@codacy/verity-cli 0.32.6 → 0.32.7

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 +16 -0
  2. package/bin/verity.js +653 -605
  3. package/package.json +2 -2
package/bin/verity.js CHANGED
@@ -10413,6 +10413,7 @@ var MAX_ITERATIONS = 2;
10413
10413
  var MAX_SPEC_FILES = 6;
10414
10414
  var MAX_SPEC_FILE_BYTES = 512e3;
10415
10415
  var MAX_TOTAL_SPEC_BYTES = 512e3;
10416
+ var MAX_EXPLICIT_SPEC_FILE_BYTES = 10240;
10416
10417
  var MAX_PLAN_FILES = 3;
10417
10418
  var MAX_PLAN_FILE_BYTES = 512e3;
10418
10419
  var MAX_INTENT_CHARS = 2e3;
@@ -10969,8 +10970,8 @@ function filterReviewable(files) {
10969
10970
  const ext = (0, import_node_path3.extname)(f).slice(1);
10970
10971
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
10971
10972
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
10972
- const basename4 = f.split("/").pop() ?? "";
10973
- if (REVIEWABLE_FILENAMES.has(basename4)) return true;
10973
+ const basename5 = f.split("/").pop() ?? "";
10974
+ if (REVIEWABLE_FILENAMES.has(basename5)) return true;
10974
10975
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
10975
10976
  return false;
10976
10977
  });
@@ -12800,12 +12801,50 @@ function resolveGuardMoments(explicit) {
12800
12801
  }
12801
12802
 
12802
12803
  // src/lib/plugin-ownership.ts
12803
- var import_node_fs6 = require("node:fs");
12804
- var import_node_os2 = require("node:os");
12804
+ var import_node_fs7 = require("node:fs");
12805
+
12806
+ // src/lib/which.ts
12807
+ var import_node_fs5 = require("node:fs");
12805
12808
  var import_node_path7 = require("node:path");
12809
+ function executableExtensions(platform, pathext) {
12810
+ if (platform !== "win32") return [""];
12811
+ const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
12812
+ const out = [];
12813
+ for (const ext of raw) {
12814
+ const lower = ext.toLowerCase();
12815
+ if (!out.includes(lower)) out.push(lower);
12816
+ if (!out.includes(ext)) out.push(ext);
12817
+ }
12818
+ return out;
12819
+ }
12820
+ function whichSync(bin, opts = {}) {
12821
+ const platform = opts.platform ?? process.platform;
12822
+ const rawPath = opts.path ?? process.env.PATH ?? "";
12823
+ if (!rawPath) return null;
12824
+ const exts = executableExtensions(platform, opts.pathext ?? process.env.PATHEXT);
12825
+ const real = opts.real ?? true;
12826
+ for (const dir of rawPath.split(import_node_path7.delimiter)) {
12827
+ if (!dir) continue;
12828
+ for (const ext of exts) {
12829
+ const candidate = (0, import_node_path7.join)(dir, bin + ext);
12830
+ try {
12831
+ if (!(0, import_node_fs5.statSync)(candidate).isFile()) continue;
12832
+ if (platform !== "win32") (0, import_node_fs5.accessSync)(candidate, import_node_fs5.constants.X_OK);
12833
+ return real ? (0, import_node_fs5.realpathSync)(candidate) : candidate;
12834
+ } catch {
12835
+ continue;
12836
+ }
12837
+ }
12838
+ }
12839
+ return null;
12840
+ }
12841
+
12842
+ // src/lib/plugin-ownership.ts
12843
+ var import_node_os2 = require("node:os");
12844
+ var import_node_path8 = require("node:path");
12806
12845
 
12807
12846
  // src/lib/stderr-log.ts
12808
- var import_node_fs5 = require("node:fs");
12847
+ var import_node_fs6 = require("node:fs");
12809
12848
  var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
12810
12849
  var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
12811
12850
  function scrub(s) {
@@ -12818,9 +12857,9 @@ function append(text) {
12818
12857
  try {
12819
12858
  const dir = projectPath(DEBUG_LOG_DIR);
12820
12859
  const file = projectPath(STDERR_LOG_FILE);
12821
- (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
12860
+ (0, import_node_fs6.mkdirSync)(dir, { recursive: true });
12822
12861
  rotateIfNeeded(file);
12823
- (0, import_node_fs5.appendFileSync)(file, text);
12862
+ (0, import_node_fs6.appendFileSync)(file, text);
12824
12863
  } catch {
12825
12864
  }
12826
12865
  }
@@ -12868,8 +12907,8 @@ function markerPath() {
12868
12907
  }
12869
12908
  function readMarker() {
12870
12909
  try {
12871
- if (!(0, import_node_fs6.existsSync)(markerPath())) return null;
12872
- const raw = JSON.parse((0, import_node_fs6.readFileSync)(markerPath(), "utf-8"));
12910
+ if (!(0, import_node_fs7.existsSync)(markerPath())) return null;
12911
+ const raw = JSON.parse((0, import_node_fs7.readFileSync)(markerPath(), "utf-8"));
12873
12912
  const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
12874
12913
  if (!pluginRoot || CONTROL_CHARS.test(pluginRoot)) return null;
12875
12914
  return {
@@ -12886,23 +12925,23 @@ function recordPluginOwnership(sessionId) {
12886
12925
  const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
12887
12926
  if (!pluginRoot) return;
12888
12927
  try {
12889
- (0, import_node_fs6.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
12928
+ (0, import_node_fs7.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
12890
12929
  const marker = {
12891
12930
  session_id: sessionId,
12892
12931
  plugin_root: pluginRoot,
12893
12932
  version: process.env.VERITY_PLUGIN_VERSION || null,
12894
12933
  ts: Math.floor(Date.now() / 1e3)
12895
12934
  };
12896
- (0, import_node_fs6.writeFileSync)(markerPath(), JSON.stringify(marker));
12935
+ (0, import_node_fs7.writeFileSync)(markerPath(), JSON.stringify(marker));
12897
12936
  } catch {
12898
12937
  }
12899
12938
  }
12900
12939
  function claudeConfigDir() {
12901
- return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path7.join)((0, import_node_os2.homedir)(), ".claude");
12940
+ return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path8.join)((0, import_node_os2.homedir)(), ".claude");
12902
12941
  }
12903
12942
  function readJsonFile(path) {
12904
12943
  try {
12905
- const parsed = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf-8"));
12944
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
12906
12945
  return parsed && typeof parsed === "object" ? parsed : null;
12907
12946
  } catch {
12908
12947
  return null;
@@ -12910,9 +12949,9 @@ function readJsonFile(path) {
12910
12949
  }
12911
12950
  function enabledPluginSetting(key) {
12912
12951
  const files = [
12913
- projectPath((0, import_node_path7.join)(".claude", "settings.local.json")),
12914
- projectPath((0, import_node_path7.join)(".claude", "settings.json")),
12915
- (0, import_node_path7.join)(claudeConfigDir(), "settings.json")
12952
+ projectPath((0, import_node_path8.join)(".claude", "settings.local.json")),
12953
+ projectPath((0, import_node_path8.join)(".claude", "settings.json")),
12954
+ (0, import_node_path8.join)(claudeConfigDir(), "settings.json")
12916
12955
  ];
12917
12956
  for (const file of files) {
12918
12957
  const map = readJsonFile(file)?.enabledPlugins;
@@ -12924,27 +12963,16 @@ function enabledPluginSetting(key) {
12924
12963
  }
12925
12964
  function marketplaceLocations() {
12926
12965
  const out = /* @__PURE__ */ new Map();
12927
- const known = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
12966
+ const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
12928
12967
  if (!known) return out;
12929
12968
  for (const [name, entry] of Object.entries(known)) {
12930
12969
  const loc2 = entry?.installLocation;
12931
- if (typeof loc2 === "string" && loc2) out.set(name, (0, import_node_path7.resolve)(loc2));
12970
+ if (typeof loc2 === "string" && loc2) out.set(name, (0, import_node_path8.resolve)(loc2));
12932
12971
  }
12933
12972
  return out;
12934
12973
  }
12935
12974
  function verityPathEntry() {
12936
- const path = process.env.PATH;
12937
- if (!path) return null;
12938
- for (const dir of path.split(import_node_path7.delimiter)) {
12939
- if (!dir) continue;
12940
- const candidate = (0, import_node_path7.join)(dir, "verity");
12941
- try {
12942
- (0, import_node_fs6.accessSync)(candidate, import_node_fs6.constants.X_OK);
12943
- return candidate;
12944
- } catch {
12945
- }
12946
- }
12947
- return null;
12975
+ return whichSync("verity", { real: false });
12948
12976
  }
12949
12977
  function verityOnPath() {
12950
12978
  return verityPathEntry() !== null;
@@ -12953,7 +12981,7 @@ function globalVerityVersion() {
12953
12981
  const entry = verityPathEntry();
12954
12982
  if (!entry) return null;
12955
12983
  try {
12956
- const pkg = readJsonFile((0, import_node_path7.join)((0, import_node_path7.dirname)((0, import_node_fs6.realpathSync)(entry)), "..", "package.json"));
12984
+ const pkg = readJsonFile((0, import_node_path8.join)((0, import_node_path8.dirname)((0, import_node_fs7.realpathSync)(entry)), "..", "package.json"));
12957
12985
  if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
12958
12986
  return pkg.version;
12959
12987
  } catch {
@@ -12965,7 +12993,7 @@ function pluginCliInvocation() {
12965
12993
  if (!root) return null;
12966
12994
  const onPath = globalVerityVersion();
12967
12995
  if (onPath !== null && onPath === activePluginVersion()) return null;
12968
- return `node ${JSON.stringify((0, import_node_path7.join)(root, "scripts", "verity.mjs"))}`;
12996
+ return `node ${JSON.stringify((0, import_node_path8.join)(root, "scripts", "verity.mjs"))}`;
12969
12997
  }
12970
12998
  function cliVersionSkew() {
12971
12999
  if (!process.env.VERITY_PLUGIN_ROOT) return null;
@@ -12984,7 +13012,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
12984
13012
  function marketplaceConflict() {
12985
13013
  const wanted = VERITY_MARKETPLACE;
12986
13014
  for (const file of ["settings.json", "settings.local.json"]) {
12987
- const path = (0, import_node_path7.join)(claudeConfigDir(), file);
13015
+ const path = (0, import_node_path8.join)(claudeConfigDir(), file);
12988
13016
  const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
12989
13017
  const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
12990
13018
  if (entry2 && typeof entry2 === "object") {
@@ -12994,7 +13022,7 @@ function marketplaceConflict() {
12994
13022
  }
12995
13023
  }
12996
13024
  }
12997
- const known = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
13025
+ const known = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
12998
13026
  const entry = known?.[wanted];
12999
13027
  if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
13000
13028
  return { name: wanted, declaredAs: describeSource(entry.source) };
@@ -13015,7 +13043,7 @@ function describeSource(src) {
13015
13043
  return target ? `${kind} \u2192 ${target}` : kind;
13016
13044
  }
13017
13045
  function legacyMarketplaceInstall() {
13018
- const plugins = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13046
+ const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13019
13047
  if (!plugins || typeof plugins !== "object") return null;
13020
13048
  for (const key of Object.keys(plugins)) {
13021
13049
  const at = key.lastIndexOf("@");
@@ -13027,13 +13055,13 @@ function legacyMarketplaceInstall() {
13027
13055
  }
13028
13056
  function realpathOr(p) {
13029
13057
  try {
13030
- return import_node_fs6.realpathSync.native(p);
13058
+ return import_node_fs7.realpathSync.native(p);
13031
13059
  } catch {
13032
- return (0, import_node_path7.resolve)(p);
13060
+ return (0, import_node_path8.resolve)(p);
13033
13061
  }
13034
13062
  }
13035
13063
  function isWithin(want, dir) {
13036
- return want === dir || want.startsWith(dir + import_node_path7.sep);
13064
+ return want === dir || want.startsWith(dir + import_node_path8.sep);
13037
13065
  }
13038
13066
  function entryAppliesHere(entry, here) {
13039
13067
  const e = entry;
@@ -13043,9 +13071,9 @@ function entryAppliesHere(entry, here) {
13043
13071
  return forProject === here;
13044
13072
  }
13045
13073
  function registrySays(pluginRoot) {
13046
- const plugins = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13074
+ const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13047
13075
  if (!plugins || typeof plugins !== "object") return "unverified";
13048
- const want = (0, import_node_path7.resolve)(pluginRoot);
13076
+ const want = (0, import_node_path8.resolve)(pluginRoot);
13049
13077
  const here = realpathOr(repoRoot());
13050
13078
  const markets = marketplaceLocations();
13051
13079
  for (const [key, value] of Object.entries(plugins)) {
@@ -13054,15 +13082,15 @@ function registrySays(pluginRoot) {
13054
13082
  const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
13055
13083
  const claims = applicable.some((entry) => {
13056
13084
  const installPath = entry?.installPath;
13057
- return typeof installPath === "string" && (0, import_node_path7.resolve)(installPath) === want;
13085
+ return typeof installPath === "string" && (0, import_node_path8.resolve)(installPath) === want;
13058
13086
  }) || source !== void 0 && applicable.length > 0 && isWithin(want, source);
13059
13087
  if (claims) {
13060
13088
  if (enabledPluginSetting(key) === false) return "gone";
13061
- return (0, import_node_fs6.existsSync)(pluginRoot) ? "live" : "gone";
13089
+ return (0, import_node_fs7.existsSync)(pluginRoot) ? "live" : "gone";
13062
13090
  }
13063
13091
  }
13064
- const managed = (0, import_node_path7.resolve)((0, import_node_path7.join)(claudeConfigDir(), "plugins", "cache"));
13065
- return want === managed || want.startsWith(managed + import_node_path7.sep) ? "gone" : "unverified";
13092
+ const managed = (0, import_node_path8.resolve)((0, import_node_path8.join)(claudeConfigDir(), "plugins", "cache"));
13093
+ return want === managed || want.startsWith(managed + import_node_path8.sep) ? "gone" : "unverified";
13066
13094
  }
13067
13095
  var _live = /* @__PURE__ */ new Map();
13068
13096
  function pluginLiveness(pluginRoot) {
@@ -13076,7 +13104,7 @@ function clearStalePluginMarker() {
13076
13104
  const marker = readMarker();
13077
13105
  if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
13078
13106
  try {
13079
- (0, import_node_fs6.rmSync)(markerPath(), { force: true });
13107
+ (0, import_node_fs7.rmSync)(markerPath(), { force: true });
13080
13108
  } catch {
13081
13109
  return null;
13082
13110
  }
@@ -13104,7 +13132,7 @@ function pluginActiveHere() {
13104
13132
  return activePluginInstall() !== null;
13105
13133
  }
13106
13134
  function registeredVerityPlugin() {
13107
- const plugins = readJsonFile((0, import_node_path7.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13135
+ const plugins = readJsonFile((0, import_node_path8.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
13108
13136
  if (!plugins || typeof plugins !== "object") return null;
13109
13137
  const here = realpathOr(repoRoot());
13110
13138
  for (const [key, value] of Object.entries(plugins)) {
@@ -13114,7 +13142,7 @@ function registeredVerityPlugin() {
13114
13142
  for (const entry of Array.isArray(value) ? value : []) {
13115
13143
  const e = entry;
13116
13144
  const installPath = typeof e.installPath === "string" ? e.installPath : "";
13117
- if (!installPath || !(0, import_node_fs6.existsSync)(installPath)) continue;
13145
+ if (!installPath || !(0, import_node_fs7.existsSync)(installPath)) continue;
13118
13146
  if (!entryAppliesHere(entry, here)) continue;
13119
13147
  return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
13120
13148
  }
@@ -13299,7 +13327,7 @@ var import_node_crypto8 = require("node:crypto");
13299
13327
 
13300
13328
  // src/lib/conversation-buffer.ts
13301
13329
  var import_promises5 = require("node:fs/promises");
13302
- var import_node_fs7 = require("node:fs");
13330
+ var import_node_fs8 = require("node:fs");
13303
13331
  var import_node_child_process5 = require("node:child_process");
13304
13332
  var import_node_crypto = require("node:crypto");
13305
13333
  function stripImageReferences(text) {
@@ -13335,7 +13363,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
13335
13363
  }
13336
13364
  async function readAndClearConversationBuffer(currentSessionId) {
13337
13365
  try {
13338
- if ((0, import_node_fs7.existsSync)(CONVERSATION_BUFFER_FILE)) {
13366
+ if ((0, import_node_fs8.existsSync)(CONVERSATION_BUFFER_FILE)) {
13339
13367
  const entries = await readBufferEntries();
13340
13368
  let mine = entries;
13341
13369
  let others = [];
@@ -13359,7 +13387,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
13359
13387
  };
13360
13388
  }
13361
13389
  }
13362
- if ((0, import_node_fs7.existsSync)(INTENT_FILE)) {
13390
+ if ((0, import_node_fs8.existsSync)(INTENT_FILE)) {
13363
13391
  try {
13364
13392
  const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
13365
13393
  await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
@@ -13652,9 +13680,9 @@ function isCommandOnlyTurn(input) {
13652
13680
 
13653
13681
  // src/lib/context-identity.ts
13654
13682
  var import_node_crypto2 = require("node:crypto");
13655
- var import_node_fs8 = require("node:fs");
13683
+ var import_node_fs9 = require("node:fs");
13656
13684
  var import_node_os3 = require("node:os");
13657
- var import_node_path8 = require("node:path");
13685
+ var import_node_path9 = require("node:path");
13658
13686
  var SHARED_SENTINELS = /* @__PURE__ */ new Set([
13659
13687
  "",
13660
13688
  "-",
@@ -13692,7 +13720,7 @@ function contextIdentity(input) {
13692
13720
  if (rawTree && !isSharedSentinel(rawTree)) {
13693
13721
  let resolved = rawTree;
13694
13722
  try {
13695
- resolved = import_node_fs8.realpathSync.native(rawTree);
13723
+ resolved = import_node_fs9.realpathSync.native(rawTree);
13696
13724
  } catch {
13697
13725
  }
13698
13726
  treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
@@ -13708,13 +13736,13 @@ function contextIdentity(input) {
13708
13736
  }
13709
13737
  function verityHome() {
13710
13738
  const override = process.env.VERITY_HOME;
13711
- return override && override.trim() ? (0, import_node_path8.resolve)(override) : (0, import_node_path8.join)((0, import_node_os3.homedir)(), ".verity");
13739
+ return override && override.trim() ? (0, import_node_path9.resolve)(override) : (0, import_node_path9.join)((0, import_node_os3.homedir)(), ".verity");
13712
13740
  }
13713
13741
  function dossierDir(identity) {
13714
- return (0, import_node_path8.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
13742
+ return (0, import_node_path9.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
13715
13743
  }
13716
13744
  function treeDir(identity) {
13717
- return (0, import_node_path8.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
13745
+ return (0, import_node_path9.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
13718
13746
  }
13719
13747
  function scopeIdentity(token, sessionId) {
13720
13748
  const t = (token ?? "").trim();
@@ -13729,8 +13757,8 @@ function sessionScopeKey(token, sessionId) {
13729
13757
 
13730
13758
  // src/lib/task-context-buffer.ts
13731
13759
  var import_promises6 = require("node:fs/promises");
13732
- var import_node_fs9 = require("node:fs");
13733
- var import_node_path9 = require("node:path");
13760
+ var import_node_fs10 = require("node:fs");
13761
+ var import_node_path10 = require("node:path");
13734
13762
  var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
13735
13763
  var MAX_BUFFER_BYTES = 500 * 1024;
13736
13764
  var MAX_PROMPT_CHARS = 2e3;
@@ -13769,7 +13797,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
13769
13797
  }
13770
13798
  async function readTaskContextBuffer(taskId) {
13771
13799
  const filePath = bufferPath(taskId);
13772
- if (!(0, import_node_fs9.existsSync)(filePath)) return null;
13800
+ if (!(0, import_node_fs10.existsSync)(filePath)) return null;
13773
13801
  try {
13774
13802
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
13775
13803
  if (!content.trim()) return null;
@@ -13803,12 +13831,12 @@ async function readTaskContextBuffer(taskId) {
13803
13831
  }
13804
13832
  async function cleanupTaskContextBuffers() {
13805
13833
  try {
13806
- if (!(0, import_node_fs9.existsSync)(TASK_CONTEXT_DIR)) return;
13834
+ if (!(0, import_node_fs10.existsSync)(TASK_CONTEXT_DIR)) return;
13807
13835
  const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
13808
13836
  const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
13809
13837
  for (const file of files) {
13810
13838
  if (!file.endsWith(".jsonl")) continue;
13811
- const filePath = (0, import_node_path9.join)(TASK_CONTEXT_DIR, file);
13839
+ const filePath = (0, import_node_path10.join)(TASK_CONTEXT_DIR, file);
13812
13840
  try {
13813
13841
  const stats = await (0, import_promises6.stat)(filePath);
13814
13842
  if (stats.mtimeMs < cutoffMs) {
@@ -13822,13 +13850,13 @@ async function cleanupTaskContextBuffers() {
13822
13850
  }
13823
13851
  function bufferPath(taskId) {
13824
13852
  const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
13825
- return (0, import_node_path9.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
13853
+ return (0, import_node_path10.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
13826
13854
  }
13827
13855
  async function appendEntry(taskId, entry) {
13828
13856
  try {
13829
13857
  await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
13830
13858
  const filePath = bufferPath(taskId);
13831
- if ((0, import_node_fs9.existsSync)(filePath)) {
13859
+ if ((0, import_node_fs10.existsSync)(filePath)) {
13832
13860
  const stats = await (0, import_promises6.stat)(filePath);
13833
13861
  if (stats.size >= MAX_BUFFER_BYTES) {
13834
13862
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
@@ -13839,7 +13867,7 @@ async function appendEntry(taskId, entry) {
13839
13867
  }
13840
13868
  }
13841
13869
  const line = JSON.stringify(entry) + "\n";
13842
- const existing = (0, import_node_fs9.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
13870
+ const existing = (0, import_node_fs10.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
13843
13871
  await (0, import_promises6.writeFile)(filePath, existing + line);
13844
13872
  } catch {
13845
13873
  }
@@ -13847,8 +13875,8 @@ async function appendEntry(taskId, entry) {
13847
13875
 
13848
13876
  // src/lib/memory-retrieval.ts
13849
13877
  var import_promises7 = require("node:fs/promises");
13850
- var import_node_fs10 = require("node:fs");
13851
- var import_node_path10 = require("node:path");
13878
+ var import_node_fs11 = require("node:fs");
13879
+ var import_node_path11 = require("node:path");
13852
13880
  var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
13853
13881
  var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
13854
13882
  var DEFAULT_BUDGET_TOKENS = 2e3;
@@ -13941,19 +13969,19 @@ function parseFrontmatter(content) {
13941
13969
  return { fm, body: match[2].trim() };
13942
13970
  }
13943
13971
  async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
13944
- if (!(0, import_node_fs10.existsSync)(memoryDir())) return null;
13972
+ if (!(0, import_node_fs11.existsSync)(memoryDir())) return null;
13945
13973
  const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
13946
13974
  const promptTokens = tokenize(promptText);
13947
13975
  const nodes = [];
13948
13976
  for (const domain of DOMAINS) {
13949
- const domainDir = (0, import_node_path10.join)(memoryDir(), domain);
13950
- if (!(0, import_node_fs10.existsSync)(domainDir)) continue;
13977
+ const domainDir = (0, import_node_path11.join)(memoryDir(), domain);
13978
+ if (!(0, import_node_fs11.existsSync)(domainDir)) continue;
13951
13979
  try {
13952
13980
  const files = await (0, import_promises7.readdir)(domainDir);
13953
13981
  for (const file of files) {
13954
13982
  if (!file.endsWith(".md")) continue;
13955
13983
  try {
13956
- const content = await (0, import_promises7.readFile)((0, import_node_path10.join)(domainDir, file), "utf-8");
13984
+ const content = await (0, import_promises7.readFile)((0, import_node_path11.join)(domainDir, file), "utf-8");
13957
13985
  const { fm, body } = parseFrontmatter(content);
13958
13986
  if (fm.status && fm.status !== "active") continue;
13959
13987
  nodes.push({
@@ -14012,13 +14040,13 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
14012
14040
 
14013
14041
  // src/lib/memory-sync.ts
14014
14042
  var import_promises8 = require("node:fs/promises");
14015
- var import_node_fs13 = require("node:fs");
14016
- var import_node_path12 = require("node:path");
14043
+ var import_node_fs14 = require("node:fs");
14044
+ var import_node_path13 = require("node:path");
14017
14045
  var import_node_crypto3 = require("node:crypto");
14018
14046
 
14019
14047
  // src/lib/gitignore.ts
14020
14048
  var import_node_child_process6 = require("node:child_process");
14021
- var import_node_fs11 = require("node:fs");
14049
+ var import_node_fs12 = require("node:fs");
14022
14050
  var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
14023
14051
  var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
14024
14052
  var VERITY_GITIGNORE_BLOCK = [
@@ -14102,7 +14130,7 @@ function fenceMemoryLines(lines) {
14102
14130
  function ensureVerityGitignore() {
14103
14131
  let content = "";
14104
14132
  try {
14105
- content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14133
+ content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14106
14134
  } catch {
14107
14135
  }
14108
14136
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14129,7 +14157,7 @@ function ensureVerityGitignore() {
14129
14157
  const sep3 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
14130
14158
  text = text + sep3 + VERITY_GITIGNORE_BLOCK;
14131
14159
  }
14132
- if (text !== content) (0, import_node_fs11.writeFileSync)(".gitignore", text);
14160
+ if (text !== content) (0, import_node_fs12.writeFileSync)(".gitignore", text);
14133
14161
  return verified(
14134
14162
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
14135
14163
  );
@@ -14149,7 +14177,7 @@ function untrackMemory() {
14149
14177
  function writeFencedBlock() {
14150
14178
  let content = "";
14151
14179
  try {
14152
- content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14180
+ content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14153
14181
  } catch {
14154
14182
  }
14155
14183
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14161,7 +14189,7 @@ function writeFencedBlock() {
14161
14189
  text = text + sep3 + VERITY_GITIGNORE_BLOCK;
14162
14190
  }
14163
14191
  try {
14164
- (0, import_node_fs11.writeFileSync)(".gitignore", text);
14192
+ (0, import_node_fs12.writeFileSync)(".gitignore", text);
14165
14193
  return true;
14166
14194
  } catch {
14167
14195
  return false;
@@ -14170,14 +14198,14 @@ function writeFencedBlock() {
14170
14198
  function fenceMemory() {
14171
14199
  let original = null;
14172
14200
  try {
14173
- original = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14201
+ original = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14174
14202
  } catch {
14175
14203
  original = null;
14176
14204
  }
14177
14205
  const restore = () => {
14178
14206
  try {
14179
- if (original === null) (0, import_node_fs11.rmSync)(".gitignore", { force: true });
14180
- else (0, import_node_fs11.writeFileSync)(".gitignore", original);
14207
+ if (original === null) (0, import_node_fs12.rmSync)(".gitignore", { force: true });
14208
+ else (0, import_node_fs12.writeFileSync)(".gitignore", original);
14181
14209
  } catch {
14182
14210
  }
14183
14211
  };
@@ -14195,7 +14223,7 @@ function fenceMemory() {
14195
14223
  }
14196
14224
  function memoryOptOut() {
14197
14225
  try {
14198
- return (0, import_node_fs11.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14226
+ return (0, import_node_fs12.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14199
14227
  } catch {
14200
14228
  return false;
14201
14229
  }
@@ -14203,13 +14231,13 @@ function memoryOptOut() {
14203
14231
  function keepMemoryTracked() {
14204
14232
  let content = "";
14205
14233
  try {
14206
- content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14234
+ content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14207
14235
  } catch {
14208
14236
  }
14209
14237
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
14210
14238
  try {
14211
14239
  const sep3 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
14212
- (0, import_node_fs11.writeFileSync)(".gitignore", content + sep3 + MEMORY_OPT_OUT_STANZA);
14240
+ (0, import_node_fs12.writeFileSync)(".gitignore", content + sep3 + MEMORY_OPT_OUT_STANZA);
14213
14241
  } catch {
14214
14242
  return "failed";
14215
14243
  }
@@ -14244,26 +14272,26 @@ function untrackVerityState() {
14244
14272
  }
14245
14273
 
14246
14274
  // src/lib/safe-path.ts
14247
- var import_node_fs12 = require("node:fs");
14248
- var import_node_path11 = require("node:path");
14275
+ var import_node_fs13 = require("node:fs");
14276
+ var import_node_path12 = require("node:path");
14249
14277
  function resolveInside(baseDir, candidate) {
14250
14278
  if (typeof candidate !== "string" || candidate.length === 0) return null;
14251
- if ((0, import_node_path11.isAbsolute)(candidate)) return null;
14252
- const baseAbs = (0, import_node_path11.resolve)(baseDir);
14253
- const full = (0, import_node_path11.resolve)(baseAbs, candidate);
14254
- const baseSep = baseAbs.endsWith(import_node_path11.sep) ? baseAbs : baseAbs + import_node_path11.sep;
14279
+ if ((0, import_node_path12.isAbsolute)(candidate)) return null;
14280
+ const baseAbs = (0, import_node_path12.resolve)(baseDir);
14281
+ const full = (0, import_node_path12.resolve)(baseAbs, candidate);
14282
+ const baseSep = baseAbs.endsWith(import_node_path12.sep) ? baseAbs : baseAbs + import_node_path12.sep;
14255
14283
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
14256
14284
  try {
14257
- if ((0, import_node_fs12.existsSync)(baseAbs)) {
14258
- const realBase = (0, import_node_fs12.realpathSync)(baseAbs);
14259
- const realBaseSep = realBase.endsWith(import_node_path11.sep) ? realBase : realBase + import_node_path11.sep;
14285
+ if ((0, import_node_fs13.existsSync)(baseAbs)) {
14286
+ const realBase = (0, import_node_fs13.realpathSync)(baseAbs);
14287
+ const realBaseSep = realBase.endsWith(import_node_path12.sep) ? realBase : realBase + import_node_path12.sep;
14260
14288
  let probe = full;
14261
- while (!(0, import_node_fs12.existsSync)(probe)) {
14262
- const parent = (0, import_node_path11.dirname)(probe);
14289
+ while (!(0, import_node_fs13.existsSync)(probe)) {
14290
+ const parent = (0, import_node_path12.dirname)(probe);
14263
14291
  if (parent === probe) break;
14264
14292
  probe = parent;
14265
14293
  }
14266
- const realProbe = (0, import_node_fs12.realpathSync)(probe);
14294
+ const realProbe = (0, import_node_fs13.realpathSync)(probe);
14267
14295
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
14268
14296
  }
14269
14297
  } catch {
@@ -14271,6 +14299,42 @@ function resolveInside(baseDir, candidate) {
14271
14299
  }
14272
14300
  return full;
14273
14301
  }
14302
+ var O_NOFOLLOW = typeof import_node_fs13.constants.O_NOFOLLOW === "number" ? import_node_fs13.constants.O_NOFOLLOW : 0;
14303
+ function readFileInside(baseDir, candidate, maxBytes) {
14304
+ const full = resolveInside(baseDir, candidate);
14305
+ if (!full) return null;
14306
+ let realParent;
14307
+ let realBase;
14308
+ try {
14309
+ realParent = (0, import_node_fs13.realpathSync)((0, import_node_path12.dirname)(full));
14310
+ realBase = (0, import_node_fs13.realpathSync)((0, import_node_path12.resolve)(baseDir));
14311
+ } catch {
14312
+ return null;
14313
+ }
14314
+ const realBaseSep = realBase.endsWith(import_node_path12.sep) ? realBase : realBase + import_node_path12.sep;
14315
+ if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
14316
+ const target = (0, import_node_path12.join)(realParent, (0, import_node_path12.basename)(full));
14317
+ let fd = null;
14318
+ try {
14319
+ fd = (0, import_node_fs13.openSync)(target, import_node_fs13.constants.O_RDONLY | O_NOFOLLOW);
14320
+ const st = (0, import_node_fs13.fstatSync)(fd);
14321
+ if (!st.isFile()) return null;
14322
+ const cap = Math.min(maxBytes, st.size);
14323
+ if (cap <= 0) return "";
14324
+ const buf = Buffer.alloc(cap);
14325
+ const bytesRead = (0, import_node_fs13.readSync)(fd, buf, 0, cap, 0);
14326
+ return buf.subarray(0, bytesRead).toString("utf-8");
14327
+ } catch {
14328
+ return null;
14329
+ } finally {
14330
+ if (fd !== null) {
14331
+ try {
14332
+ (0, import_node_fs13.closeSync)(fd);
14333
+ } catch {
14334
+ }
14335
+ }
14336
+ }
14337
+ }
14274
14338
 
14275
14339
  // src/lib/glob-match.ts
14276
14340
  function globToRegex(glob) {
@@ -14340,32 +14404,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
14340
14404
  async function ensureMemoryDir() {
14341
14405
  await (0, import_promises8.mkdir)(memoryDir2(), { recursive: true });
14342
14406
  for (const domain of DOMAINS2) {
14343
- await (0, import_promises8.mkdir)((0, import_node_path12.join)(memoryDir2(), domain), { recursive: true });
14407
+ await (0, import_promises8.mkdir)((0, import_node_path13.join)(memoryDir2(), domain), { recursive: true });
14344
14408
  }
14345
- if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"))) {
14346
- await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14409
+ if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "SCHEMA.md"))) {
14410
+ await (0, import_promises8.writeFile)((0, import_node_path13.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14347
14411
  }
14348
- if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "index.md"))) {
14349
- await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
14412
+ if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "index.md"))) {
14413
+ await (0, import_promises8.writeFile)((0, import_node_path13.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
14350
14414
  }
14351
- if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md"))) {
14352
- await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14415
+ if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "log.md"))) {
14416
+ await (0, import_promises8.writeFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14353
14417
  }
14354
14418
  }
14355
14419
  async function buildManifest() {
14356
- if (!(0, import_node_fs13.existsSync)(memoryDir2())) {
14420
+ if (!(0, import_node_fs14.existsSync)(memoryDir2())) {
14357
14421
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
14358
14422
  }
14359
14423
  const nodes = [];
14360
14424
  for (const domain of DOMAINS2) {
14361
- const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14362
- if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14425
+ const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14426
+ if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14363
14427
  try {
14364
14428
  const files = await (0, import_promises8.readdir)(domainDir);
14365
14429
  for (const file of files) {
14366
14430
  if (!file.endsWith(".md")) continue;
14367
14431
  const filePath = `${domain}/${file}`;
14368
- const fullPath = (0, import_node_path12.join)(memoryDir2(), filePath);
14432
+ const fullPath = (0, import_node_path13.join)(memoryDir2(), filePath);
14369
14433
  try {
14370
14434
  const content = await (0, import_promises8.readFile)(fullPath, "utf-8");
14371
14435
  const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
@@ -14378,13 +14442,13 @@ async function buildManifest() {
14378
14442
  }
14379
14443
  let indexHash = null;
14380
14444
  try {
14381
- const indexContent = await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "index.md"), "utf-8");
14445
+ const indexContent = await (0, import_promises8.readFile)((0, import_node_path13.join)(memoryDir2(), "index.md"), "utf-8");
14382
14446
  indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
14383
14447
  } catch {
14384
14448
  }
14385
14449
  let logLength = 0;
14386
14450
  try {
14387
- const logContent = await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8");
14451
+ const logContent = await (0, import_promises8.readFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "utf-8");
14388
14452
  logLength = logContent.split("\n").length;
14389
14453
  } catch {
14390
14454
  }
@@ -14395,15 +14459,15 @@ function hashContent(content) {
14395
14459
  }
14396
14460
  async function readOnDiskNodes() {
14397
14461
  const out = /* @__PURE__ */ new Map();
14398
- if (!(0, import_node_fs13.existsSync)(memoryDir2())) return out;
14462
+ if (!(0, import_node_fs14.existsSync)(memoryDir2())) return out;
14399
14463
  for (const domain of DOMAINS2) {
14400
- const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14401
- if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14464
+ const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14465
+ if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14402
14466
  try {
14403
14467
  for (const file of await (0, import_promises8.readdir)(domainDir)) {
14404
14468
  if (!file.endsWith(".md")) continue;
14405
14469
  try {
14406
- out.set(`${domain}/${file}`, hashContent(await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8")));
14470
+ out.set(`${domain}/${file}`, hashContent(await (0, import_promises8.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8")));
14407
14471
  } catch {
14408
14472
  }
14409
14473
  }
@@ -14449,8 +14513,8 @@ async function computeEditedNodeUploads() {
14449
14513
  const uploads = [];
14450
14514
  for (const [path, prevHash] of prev) {
14451
14515
  if (prevHash == null) continue;
14452
- const full = (0, import_node_path12.join)(memoryDir2(), path);
14453
- if (!(0, import_node_fs13.existsSync)(full)) continue;
14516
+ const full = (0, import_node_path13.join)(memoryDir2(), path);
14517
+ if (!(0, import_node_fs14.existsSync)(full)) continue;
14454
14518
  let content;
14455
14519
  try {
14456
14520
  content = await (0, import_promises8.readFile)(full, "utf-8");
@@ -14487,8 +14551,8 @@ async function applyMemoryWrites(writes, opts = {}) {
14487
14551
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
14488
14552
  for (const n of notes) logLines.push(` - ${n}`);
14489
14553
  try {
14490
- const existing = (0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14491
- await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14554
+ const existing = (0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14555
+ await (0, import_promises8.writeFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14492
14556
  } catch {
14493
14557
  }
14494
14558
  await recordSyncedNodePaths();
@@ -14508,7 +14572,7 @@ async function applyOneWrite(write, treePaths) {
14508
14572
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
14509
14573
  }
14510
14574
  }
14511
- if ((0, import_node_fs13.existsSync)(fullPath)) {
14575
+ if ((0, import_node_fs14.existsSync)(fullPath)) {
14512
14576
  let existing = "";
14513
14577
  try {
14514
14578
  existing = await (0, import_promises8.readFile)(fullPath, "utf-8");
@@ -14520,7 +14584,7 @@ async function applyOneWrite(write, treePaths) {
14520
14584
  return { written: false, notes };
14521
14585
  }
14522
14586
  }
14523
- await (0, import_promises8.mkdir)((0, import_node_path12.dirname)(fullPath), { recursive: true });
14587
+ await (0, import_promises8.mkdir)((0, import_node_path13.dirname)(fullPath), { recursive: true });
14524
14588
  await (0, import_promises8.writeFile)(fullPath, content);
14525
14589
  return { written: true, notes };
14526
14590
  }
@@ -14561,8 +14625,8 @@ async function regenerateIndex() {
14561
14625
  ];
14562
14626
  let totalNodes = 0;
14563
14627
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
14564
- const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14565
- if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14628
+ const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14629
+ if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14566
14630
  try {
14567
14631
  const files = await (0, import_promises8.readdir)(domainDir);
14568
14632
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -14572,7 +14636,7 @@ async function regenerateIndex() {
14572
14636
  for (const file of mdFiles.sort()) {
14573
14637
  const slug = file.replace(/\.md$/, "");
14574
14638
  try {
14575
- const content = await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8");
14639
+ const content = await (0, import_promises8.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8");
14576
14640
  const title = pickFrontmatter(content, "title") ?? slug;
14577
14641
  const kind = pickFrontmatter(content, "kind") ?? "-";
14578
14642
  const confidence = pickFrontmatter(content, "confidence");
@@ -14596,7 +14660,7 @@ async function regenerateIndex() {
14596
14660
  lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
14597
14661
  }
14598
14662
  const next = lines.join("\n") + "\n";
14599
- const indexPath = (0, import_node_path12.join)(memoryDir2(), "index.md");
14663
+ const indexPath = (0, import_node_path13.join)(memoryDir2(), "index.md");
14600
14664
  let existing = null;
14601
14665
  try {
14602
14666
  existing = await (0, import_promises8.readFile)(indexPath, "utf-8");
@@ -14830,9 +14894,9 @@ function hasLegacyMemoryBlock(text) {
14830
14894
  return findMarker(text, LEGACY_MD_START) !== -1;
14831
14895
  }
14832
14896
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
14833
- const claudeMdPath = (0, import_node_path12.join)(cwd, "CLAUDE.md");
14897
+ const claudeMdPath = (0, import_node_path13.join)(cwd, "CLAUDE.md");
14834
14898
  let existing = "";
14835
- if ((0, import_node_fs13.existsSync)(claudeMdPath)) {
14899
+ if ((0, import_node_fs14.existsSync)(claudeMdPath)) {
14836
14900
  existing = await (0, import_promises8.readFile)(claudeMdPath, "utf-8");
14837
14901
  }
14838
14902
  let startTag = CLAUDE_MD_START;
@@ -14971,9 +15035,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
14971
15035
  `;
14972
15036
 
14973
15037
  // src/lib/dossier-session.ts
14974
- var import_node_fs18 = require("node:fs");
15038
+ var import_node_fs19 = require("node:fs");
14975
15039
  var import_node_crypto7 = require("node:crypto");
14976
- var import_node_path15 = require("node:path");
15040
+ var import_node_path16 = require("node:path");
14977
15041
 
14978
15042
  // src/lib/pending-repeat.ts
14979
15043
  var STOP = /* @__PURE__ */ new Set([
@@ -15078,8 +15142,8 @@ function statementAnchorKey(file, patternId) {
15078
15142
 
15079
15143
  // src/lib/dossier/log.ts
15080
15144
  var import_node_crypto4 = require("node:crypto");
15081
- var import_node_fs14 = require("node:fs");
15082
- var import_node_path13 = require("node:path");
15145
+ var import_node_fs15 = require("node:fs");
15146
+ var import_node_path14 = require("node:path");
15083
15147
  var CRC_TABLE = (() => {
15084
15148
  const t = new Int32Array(256);
15085
15149
  for (let i = 0; i < 256; i++) {
@@ -15098,13 +15162,13 @@ function crc32(s) {
15098
15162
  function openDossier(identity) {
15099
15163
  try {
15100
15164
  const dir = dossierDir(identity);
15101
- (0, import_node_fs14.mkdirSync)(dir, { recursive: true, mode: 448 });
15165
+ (0, import_node_fs15.mkdirSync)(dir, { recursive: true, mode: 448 });
15102
15166
  return {
15103
15167
  dir,
15104
15168
  identity,
15105
- eventsPath: (0, import_node_path13.join)(dir, "events.jsonl"),
15106
- foldPath: (0, import_node_path13.join)(dir, "fold.json"),
15107
- rotatedDir: (0, import_node_path13.join)(dir, "rotated")
15169
+ eventsPath: (0, import_node_path14.join)(dir, "events.jsonl"),
15170
+ foldPath: (0, import_node_path14.join)(dir, "fold.json"),
15171
+ rotatedDir: (0, import_node_path14.join)(dir, "rotated")
15108
15172
  };
15109
15173
  } catch {
15110
15174
  return null;
@@ -15166,7 +15230,7 @@ function appendEvent(d, ev) {
15166
15230
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
15167
15231
  ...ev
15168
15232
  });
15169
- (0, import_node_fs14.appendFileSync)(d.eventsPath, line, { mode: 384 });
15233
+ (0, import_node_fs15.appendFileSync)(d.eventsPath, line, { mode: 384 });
15170
15234
  return true;
15171
15235
  } catch {
15172
15236
  return false;
@@ -15174,14 +15238,14 @@ function appendEvent(d, ev) {
15174
15238
  }
15175
15239
  function rotateIfNeeded2(d) {
15176
15240
  try {
15177
- if (!(0, import_node_fs14.existsSync)(d.eventsPath)) return;
15178
- if ((0, import_node_fs14.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15179
- (0, import_node_fs14.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15180
- (0, import_node_fs14.renameSync)(d.eventsPath, (0, import_node_path13.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15181
- const kept = (0, import_node_fs14.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15241
+ if (!(0, import_node_fs15.existsSync)(d.eventsPath)) return;
15242
+ if ((0, import_node_fs15.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15243
+ (0, import_node_fs15.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15244
+ (0, import_node_fs15.renameSync)(d.eventsPath, (0, import_node_path14.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15245
+ const kept = (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15182
15246
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
15183
15247
  try {
15184
- (0, import_node_fs14.renameSync)((0, import_node_path13.join)(d.rotatedDir, stale), (0, import_node_path13.join)(d.rotatedDir, `${stale}.pruned`));
15248
+ (0, import_node_fs15.renameSync)((0, import_node_path14.join)(d.rotatedDir, stale), (0, import_node_path14.join)(d.rotatedDir, `${stale}.pruned`));
15185
15249
  } catch {
15186
15250
  }
15187
15251
  }
@@ -15191,8 +15255,8 @@ function rotateIfNeeded2(d) {
15191
15255
 
15192
15256
  // src/lib/dossier/fold-dossier.ts
15193
15257
  var import_node_crypto5 = require("node:crypto");
15194
- var import_node_fs15 = require("node:fs");
15195
- var import_node_path14 = require("node:path");
15258
+ var import_node_fs16 = require("node:fs");
15259
+ var import_node_path15 = require("node:path");
15196
15260
  var EMPTY_CAPABILITIES = () => ({
15197
15261
  human_reachable: { value: "unknown", tier: "unknown" },
15198
15262
  authorship_observability: { value: "unknown", tier: "unknown" },
@@ -15243,12 +15307,12 @@ function foldDossier(d, opts = {}) {
15243
15307
  }
15244
15308
  };
15245
15309
  try {
15246
- if ((0, import_node_fs15.existsSync)(d.rotatedDir)) {
15247
- const files = (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15310
+ if ((0, import_node_fs16.existsSync)(d.rotatedDir)) {
15311
+ const files = (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15248
15312
  state.meta.rotations = files.length;
15249
15313
  for (const f of files) {
15250
15314
  try {
15251
- ingest((0, import_node_fs15.readFileSync)((0, import_node_path14.join)(d.rotatedDir, f), "utf8"));
15315
+ ingest((0, import_node_fs16.readFileSync)((0, import_node_path15.join)(d.rotatedDir, f), "utf8"));
15252
15316
  } catch {
15253
15317
  state.meta.dropped_lines++;
15254
15318
  }
@@ -15257,9 +15321,9 @@ function foldDossier(d, opts = {}) {
15257
15321
  } catch {
15258
15322
  }
15259
15323
  try {
15260
- if ((0, import_node_fs15.existsSync)(d.eventsPath)) {
15261
- state.meta.upto_offset = (0, import_node_fs15.statSync)(d.eventsPath).size;
15262
- ingest((0, import_node_fs15.readFileSync)(d.eventsPath, "utf8"));
15324
+ if ((0, import_node_fs16.existsSync)(d.eventsPath)) {
15325
+ state.meta.upto_offset = (0, import_node_fs16.statSync)(d.eventsPath).size;
15326
+ ingest((0, import_node_fs16.readFileSync)(d.eventsPath, "utf8"));
15263
15327
  }
15264
15328
  } catch {
15265
15329
  }
@@ -15530,7 +15594,7 @@ function applyBounds(state, input) {
15530
15594
  }
15531
15595
 
15532
15596
  // src/lib/dossier/cache.ts
15533
- var import_node_fs16 = require("node:fs");
15597
+ var import_node_fs17 = require("node:fs");
15534
15598
  function compactState(s) {
15535
15599
  const ms = (iso) => Date.parse(iso) || 0;
15536
15600
  return {
@@ -15659,20 +15723,20 @@ function encodeState(s) {
15659
15723
  function writeFoldCache(d, state) {
15660
15724
  try {
15661
15725
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
15662
- (0, import_node_fs16.writeFileSync)(tmp, encodeState(state), { mode: 384 });
15663
- (0, import_node_fs16.renameSync)(tmp, d.foldPath);
15726
+ (0, import_node_fs17.writeFileSync)(tmp, encodeState(state), { mode: 384 });
15727
+ (0, import_node_fs17.renameSync)(tmp, d.foldPath);
15664
15728
  } catch {
15665
15729
  }
15666
15730
  }
15667
15731
  function readFoldCache(d) {
15668
15732
  try {
15669
- if (!(0, import_node_fs16.existsSync)(d.foldPath)) return null;
15670
- const raw = JSON.parse((0, import_node_fs16.readFileSync)(d.foldPath, "utf8"));
15733
+ if (!(0, import_node_fs17.existsSync)(d.foldPath)) return null;
15734
+ const raw = JSON.parse((0, import_node_fs17.readFileSync)(d.foldPath, "utf8"));
15671
15735
  if (raw?.v !== 1) return null;
15672
15736
  const cached2 = expandState(raw);
15673
15737
  if (!cached2?.meta) return null;
15674
- const size = (0, import_node_fs16.existsSync)(d.eventsPath) ? (0, import_node_fs16.statSync)(d.eventsPath).size : 0;
15675
- const rotations = (0, import_node_fs16.existsSync)(d.rotatedDir) ? (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
15738
+ const size = (0, import_node_fs17.existsSync)(d.eventsPath) ? (0, import_node_fs17.statSync)(d.eventsPath).size : 0;
15739
+ const rotations = (0, import_node_fs17.existsSync)(d.rotatedDir) ? (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
15676
15740
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
15677
15741
  return cached2;
15678
15742
  } catch {
@@ -15723,13 +15787,13 @@ function assessContinuity(i) {
15723
15787
 
15724
15788
  // src/lib/dossier/reanchor.ts
15725
15789
  var import_node_crypto6 = require("node:crypto");
15726
- var import_node_fs17 = require("node:fs");
15790
+ var import_node_fs18 = require("node:fs");
15727
15791
  function lineSha(text) {
15728
15792
  return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
15729
15793
  }
15730
15794
  function fileHash(path) {
15731
15795
  try {
15732
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs17.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
15796
+ return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs18.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
15733
15797
  } catch {
15734
15798
  return null;
15735
15799
  }
@@ -16101,20 +16165,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
16101
16165
  let sessions = 0;
16102
16166
  try {
16103
16167
  const dir = treeDir(identity);
16104
- if (!(0, import_node_fs18.existsSync)(dir)) return { paths: [], sessions: 0 };
16105
- for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
16168
+ if (!(0, import_node_fs19.existsSync)(dir)) return { paths: [], sessions: 0 };
16169
+ for (const entry of (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true })) {
16106
16170
  if (!entry.isDirectory()) continue;
16107
16171
  if (entry.name === identity.sessionKey) continue;
16108
- const log = (0, import_node_path15.join)(dir, entry.name, "events.jsonl");
16172
+ const log = (0, import_node_path16.join)(dir, entry.name, "events.jsonl");
16109
16173
  try {
16110
- if (!(0, import_node_fs18.existsSync)(log)) continue;
16111
- if (now - (0, import_node_fs18.statSync)(log).mtimeMs > windowMs) continue;
16174
+ if (!(0, import_node_fs19.existsSync)(log)) continue;
16175
+ if (now - (0, import_node_fs19.statSync)(log).mtimeMs > windowMs) continue;
16112
16176
  const sib = {
16113
- dir: (0, import_node_path15.join)(dir, entry.name),
16177
+ dir: (0, import_node_path16.join)(dir, entry.name),
16114
16178
  identity,
16115
16179
  eventsPath: log,
16116
- foldPath: (0, import_node_path15.join)(dir, entry.name, "fold.json"),
16117
- rotatedDir: (0, import_node_path15.join)(dir, entry.name, "rotated")
16180
+ foldPath: (0, import_node_path16.join)(dir, entry.name, "fold.json"),
16181
+ rotatedDir: (0, import_node_path16.join)(dir, entry.name, "rotated")
16118
16182
  };
16119
16183
  const state = readFoldCache(sib) ?? foldDossier(sib);
16120
16184
  sessions++;
@@ -16142,25 +16206,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16142
16206
  let removed = 0;
16143
16207
  try {
16144
16208
  const mine = dossierDir(identity);
16145
- const userDir = (0, import_node_path15.dirname)((0, import_node_path15.dirname)(mine));
16146
- if (!(0, import_node_fs18.existsSync)(userDir)) return 0;
16209
+ const userDir = (0, import_node_path16.dirname)((0, import_node_path16.dirname)(mine));
16210
+ if (!(0, import_node_fs19.existsSync)(userDir)) return 0;
16147
16211
  const cutoff = Date.now() - maxAgeMs;
16148
- for (const tree of (0, import_node_fs18.readdirSync)(userDir, { withFileTypes: true })) {
16212
+ for (const tree of (0, import_node_fs19.readdirSync)(userDir, { withFileTypes: true })) {
16149
16213
  if (!tree.isDirectory()) continue;
16150
- const treePath = (0, import_node_path15.join)(userDir, tree.name);
16214
+ const treePath = (0, import_node_path16.join)(userDir, tree.name);
16151
16215
  let live = 0;
16152
- for (const entry of (0, import_node_fs18.readdirSync)(treePath, { withFileTypes: true })) {
16216
+ for (const entry of (0, import_node_fs19.readdirSync)(treePath, { withFileTypes: true })) {
16153
16217
  if (!entry.isDirectory()) continue;
16154
- const dir = (0, import_node_path15.join)(treePath, entry.name);
16218
+ const dir = (0, import_node_path16.join)(treePath, entry.name);
16155
16219
  if (dir === mine) {
16156
16220
  live++;
16157
16221
  continue;
16158
16222
  }
16159
16223
  try {
16160
- const log = (0, import_node_path15.join)(dir, "events.jsonl");
16161
- const at = (0, import_node_fs18.existsSync)(log) ? (0, import_node_fs18.statSync)(log).mtimeMs : (0, import_node_fs18.statSync)(dir).mtimeMs;
16224
+ const log = (0, import_node_path16.join)(dir, "events.jsonl");
16225
+ const at = (0, import_node_fs19.existsSync)(log) ? (0, import_node_fs19.statSync)(log).mtimeMs : (0, import_node_fs19.statSync)(dir).mtimeMs;
16162
16226
  if (at < cutoff) {
16163
- (0, import_node_fs18.rmSync)(dir, { recursive: true, force: true });
16227
+ (0, import_node_fs19.rmSync)(dir, { recursive: true, force: true });
16164
16228
  removed++;
16165
16229
  } else {
16166
16230
  live++;
@@ -16170,7 +16234,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16170
16234
  }
16171
16235
  if (live === 0) {
16172
16236
  try {
16173
- (0, import_node_fs18.rmSync)(treePath, { recursive: false, force: false });
16237
+ (0, import_node_fs19.rmSync)(treePath, { recursive: false, force: false });
16174
16238
  } catch {
16175
16239
  }
16176
16240
  }
@@ -16187,8 +16251,8 @@ function sessionDossier(token, sessionId) {
16187
16251
  }
16188
16252
  function hasActiveGoal(d) {
16189
16253
  try {
16190
- if (!(0, import_node_fs18.existsSync)(d.eventsPath)) return false;
16191
- return (0, import_node_fs18.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16254
+ if (!(0, import_node_fs19.existsSync)(d.eventsPath)) return false;
16255
+ return (0, import_node_fs19.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16192
16256
  } catch {
16193
16257
  return false;
16194
16258
  }
@@ -16212,7 +16276,7 @@ function recordTurn(d, t) {
16212
16276
  for (const a of t.authored) {
16213
16277
  const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
16214
16278
  const prior = t.known?.authored?.get(a.p);
16215
- const hash = fileHash((0, import_node_path15.join)(root, a.p));
16279
+ const hash = fileHash((0, import_node_path16.join)(root, a.p));
16216
16280
  const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
16217
16281
  const adds = Math.max(0, a.a - (prior?.adds ?? 0));
16218
16282
  const dels = Math.max(0, a.d - (prior?.dels ?? 0));
@@ -16245,7 +16309,7 @@ function recordTurn(d, t) {
16245
16309
  }
16246
16310
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
16247
16311
  for (const u of t.unobserved) {
16248
- const hash = fileHash((0, import_node_path15.join)(root, u.p));
16312
+ const hash = fileHash((0, import_node_path16.join)(root, u.p));
16249
16313
  if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
16250
16314
  appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
16251
16315
  }
@@ -16280,8 +16344,8 @@ function recordVerdict(d, v) {
16280
16344
  if (!sent.has(f.file)) continue;
16281
16345
  if (!lines.has(f.file)) {
16282
16346
  try {
16283
- const abs = (0, import_node_path15.join)(root, f.file);
16284
- lines.set(f.file, (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null);
16347
+ const abs = (0, import_node_path16.join)(root, f.file);
16348
+ lines.set(f.file, (0, import_node_fs19.existsSync)(abs) ? (0, import_node_fs19.readFileSync)(abs, "utf8").split("\n") : null);
16285
16349
  } catch {
16286
16350
  lines.set(f.file, null);
16287
16351
  }
@@ -16381,8 +16445,8 @@ function recallMemory(d, identity, opts) {
16381
16445
  budgetBytes: opts.budgetBytes,
16382
16446
  readFileLines: (file) => {
16383
16447
  try {
16384
- const abs = (0, import_node_path15.join)(root, file);
16385
- return (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null;
16448
+ const abs = (0, import_node_path16.join)(root, file);
16449
+ return (0, import_node_fs19.existsSync)(abs) ? (0, import_node_fs19.readFileSync)(abs, "utf8").split("\n") : null;
16386
16450
  } catch {
16387
16451
  return null;
16388
16452
  }
@@ -16526,22 +16590,22 @@ async function fireClassify(prompt, sessionId, globals) {
16526
16590
  }
16527
16591
 
16528
16592
  // src/commands/lifecycle.ts
16529
- var import_node_fs22 = require("node:fs");
16530
- var import_node_path19 = require("node:path");
16593
+ var import_node_fs23 = require("node:fs");
16594
+ var import_node_path20 = require("node:path");
16531
16595
 
16532
16596
  // src/lib/baseline.ts
16533
- var import_node_fs21 = require("node:fs");
16534
- var import_node_path18 = require("node:path");
16597
+ var import_node_fs22 = require("node:fs");
16598
+ var import_node_path19 = require("node:path");
16535
16599
  var import_node_crypto9 = require("node:crypto");
16536
16600
 
16537
16601
  // src/lib/snapshot.ts
16538
- var import_node_fs20 = require("node:fs");
16539
- var import_node_path17 = require("node:path");
16602
+ var import_node_fs21 = require("node:fs");
16603
+ var import_node_path18 = require("node:path");
16540
16604
  var import_node_child_process7 = require("node:child_process");
16541
16605
 
16542
16606
  // src/lib/files.ts
16543
- var import_node_fs19 = require("node:fs");
16544
- var import_node_path16 = require("node:path");
16607
+ var import_node_fs20 = require("node:fs");
16608
+ var import_node_path17 = require("node:path");
16545
16609
  var LANG_MAP = {
16546
16610
  // Analyzable (static analysis + Gemini)
16547
16611
  ts: "typescript",
@@ -16609,7 +16673,7 @@ var LANG_MAP = {
16609
16673
  mk: "make"
16610
16674
  };
16611
16675
  function detectLanguage(filepath) {
16612
- const ext = (0, import_node_path16.extname)(filepath).slice(1);
16676
+ const ext = (0, import_node_path17.extname)(filepath).slice(1);
16613
16677
  return LANG_MAP[ext] ?? ext;
16614
16678
  }
16615
16679
  function sortByMtime(files) {
@@ -16617,7 +16681,7 @@ function sortByMtime(files) {
16617
16681
  const resolved = resolveFile(f);
16618
16682
  if (!resolved) return null;
16619
16683
  try {
16620
- const stat3 = (0, import_node_fs19.statSync)(resolved);
16684
+ const stat3 = (0, import_node_fs20.statSync)(resolved);
16621
16685
  return { path: f, resolved, mtime: stat3.mtimeMs };
16622
16686
  } catch {
16623
16687
  return null;
@@ -16650,7 +16714,7 @@ function collectCodeDelta(files, opts) {
16650
16714
  }
16651
16715
  let size;
16652
16716
  try {
16653
- size = (0, import_node_fs19.statSync)(resolved).size;
16717
+ size = (0, import_node_fs20.statSync)(resolved).size;
16654
16718
  } catch {
16655
16719
  exclude(filepath, "not-stattable");
16656
16720
  continue;
@@ -16667,7 +16731,7 @@ function collectCodeDelta(files, opts) {
16667
16731
  }
16668
16732
  let content;
16669
16733
  try {
16670
- content = (0, import_node_fs19.readFileSync)(resolved, "utf-8");
16734
+ content = (0, import_node_fs20.readFileSync)(resolved, "utf-8");
16671
16735
  } catch {
16672
16736
  exclude(filepath, "not-readable");
16673
16737
  continue;
@@ -16706,16 +16770,16 @@ function collectCodeDelta(files, opts) {
16706
16770
 
16707
16771
  // src/lib/snapshot.ts
16708
16772
  function generateSnapshotDiffs(files) {
16709
- if (!(0, import_node_fs20.existsSync)(SNAPSHOT_DIR)) {
16773
+ if (!(0, import_node_fs21.existsSync)(SNAPSHOT_DIR)) {
16710
16774
  return { diffs: [], has_snapshots: false };
16711
16775
  }
16712
16776
  const diffs = [];
16713
16777
  for (const file of files) {
16714
16778
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16715
- const snapshotPath = (0, import_node_path17.join)(SNAPSHOT_DIR, file.path);
16779
+ const snapshotPath = (0, import_node_path18.join)(SNAPSHOT_DIR, file.path);
16716
16780
  const language = file.language ?? detectLanguage(file.path);
16717
- if ((0, import_node_fs20.existsSync)(snapshotPath)) {
16718
- const oldContent = (0, import_node_fs20.readFileSync)(snapshotPath, "utf-8");
16781
+ if ((0, import_node_fs21.existsSync)(snapshotPath)) {
16782
+ const oldContent = (0, import_node_fs21.readFileSync)(snapshotPath, "utf-8");
16719
16783
  if (oldContent === file.content) continue;
16720
16784
  const diff = computeDiff(oldContent, file.content, file.path);
16721
16785
  if (diff) {
@@ -16740,20 +16804,20 @@ function saveSnapshots(files) {
16740
16804
  const snapshotPaths = /* @__PURE__ */ new Set();
16741
16805
  for (const file of files) {
16742
16806
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16743
- const snapshotPath = (0, import_node_path17.join)(SNAPSHOT_DIR, file.path);
16807
+ const snapshotPath = (0, import_node_path18.join)(SNAPSHOT_DIR, file.path);
16744
16808
  snapshotPaths.add(snapshotPath);
16745
- (0, import_node_fs20.mkdirSync)((0, import_node_path17.dirname)(snapshotPath), { recursive: true });
16746
- (0, import_node_fs20.writeFileSync)(snapshotPath, file.content);
16809
+ (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(snapshotPath), { recursive: true });
16810
+ (0, import_node_fs21.writeFileSync)(snapshotPath, file.content);
16747
16811
  }
16748
16812
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
16749
16813
  }
16750
16814
  function computeDiff(oldContent, newContent, filePath) {
16751
- const tmpOld = (0, import_node_path17.join)(SNAPSHOT_DIR, ".diff-old.tmp");
16752
- const tmpNew = (0, import_node_path17.join)(SNAPSHOT_DIR, ".diff-new.tmp");
16815
+ const tmpOld = (0, import_node_path18.join)(SNAPSHOT_DIR, ".diff-old.tmp");
16816
+ const tmpNew = (0, import_node_path18.join)(SNAPSHOT_DIR, ".diff-new.tmp");
16753
16817
  try {
16754
- (0, import_node_fs20.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
16755
- (0, import_node_fs20.writeFileSync)(tmpOld, oldContent);
16756
- (0, import_node_fs20.writeFileSync)(tmpNew, newContent);
16818
+ (0, import_node_fs21.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
16819
+ (0, import_node_fs21.writeFileSync)(tmpOld, oldContent);
16820
+ (0, import_node_fs21.writeFileSync)(tmpNew, newContent);
16757
16821
  const result = (0, import_node_child_process7.execSync)(
16758
16822
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
16759
16823
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -16767,32 +16831,32 @@ function computeDiff(oldContent, newContent, filePath) {
16767
16831
  return null;
16768
16832
  } finally {
16769
16833
  try {
16770
- (0, import_node_fs20.unlinkSync)(tmpOld);
16834
+ (0, import_node_fs21.unlinkSync)(tmpOld);
16771
16835
  } catch {
16772
16836
  }
16773
16837
  try {
16774
- (0, import_node_fs20.unlinkSync)(tmpNew);
16838
+ (0, import_node_fs21.unlinkSync)(tmpNew);
16775
16839
  } catch {
16776
16840
  }
16777
16841
  }
16778
16842
  }
16779
16843
  function cleanStaleSnapshots(dir, keepSet) {
16780
- if (!(0, import_node_fs20.existsSync)(dir)) return;
16844
+ if (!(0, import_node_fs21.existsSync)(dir)) return;
16781
16845
  try {
16782
- const entries = (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true });
16846
+ const entries = (0, import_node_fs21.readdirSync)(dir, { withFileTypes: true });
16783
16847
  for (const entry of entries) {
16784
16848
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
16785
- const fullPath = (0, import_node_path17.join)(dir, entry.name);
16849
+ const fullPath = (0, import_node_path18.join)(dir, entry.name);
16786
16850
  if (entry.isDirectory()) {
16787
16851
  cleanStaleSnapshots(fullPath, keepSet);
16788
16852
  try {
16789
- const remaining = (0, import_node_fs20.readdirSync)(fullPath);
16790
- if (remaining.length === 0) (0, import_node_fs20.rmdirSync)(fullPath);
16853
+ const remaining = (0, import_node_fs21.readdirSync)(fullPath);
16854
+ if (remaining.length === 0) (0, import_node_fs21.rmdirSync)(fullPath);
16791
16855
  } catch {
16792
16856
  }
16793
16857
  } else if (!keepSet.has(fullPath)) {
16794
16858
  try {
16795
- (0, import_node_fs20.unlinkSync)(fullPath);
16859
+ (0, import_node_fs21.unlinkSync)(fullPath);
16796
16860
  } catch {
16797
16861
  }
16798
16862
  }
@@ -16811,20 +16875,20 @@ function sessionKey(sessionId) {
16811
16875
  return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
16812
16876
  }
16813
16877
  function sessionDir(key) {
16814
- return (0, import_node_path18.join)(projectPath(BASELINE_DIR), key);
16878
+ return (0, import_node_path19.join)(projectPath(BASELINE_DIR), key);
16815
16879
  }
16816
16880
  function manifestPath(dir) {
16817
- return (0, import_node_path18.join)(dir, "manifest.json");
16881
+ return (0, import_node_path19.join)(dir, "manifest.json");
16818
16882
  }
16819
16883
  function mirrorPath(dir, repoRelPath) {
16820
- return (0, import_node_path18.join)(dir, "files", repoRelPath);
16884
+ return (0, import_node_path19.join)(dir, "files", repoRelPath);
16821
16885
  }
16822
16886
  var CARRY_FILE = `${BASELINE_DIR}/.carry`;
16823
16887
  var CARRY_WINDOW_MS = 12e4;
16824
16888
  function writeCarry(sessionId, headSha) {
16825
16889
  try {
16826
- (0, import_node_fs21.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16827
- (0, import_node_fs21.writeFileSync)(
16890
+ (0, import_node_fs22.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16891
+ (0, import_node_fs22.writeFileSync)(
16828
16892
  projectPath(CARRY_FILE),
16829
16893
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
16830
16894
  );
@@ -16834,10 +16898,10 @@ function writeCarry(sessionId, headSha) {
16834
16898
  function claimCarry(newKey) {
16835
16899
  const carryPath = projectPath(CARRY_FILE);
16836
16900
  try {
16837
- if (!(0, import_node_fs21.existsSync)(carryPath)) return null;
16838
- const carry = JSON.parse((0, import_node_fs21.readFileSync)(carryPath, "utf-8"));
16901
+ if (!(0, import_node_fs22.existsSync)(carryPath)) return null;
16902
+ const carry = JSON.parse((0, import_node_fs22.readFileSync)(carryPath, "utf-8"));
16839
16903
  try {
16840
- (0, import_node_fs21.rmSync)(carryPath, { force: true });
16904
+ (0, import_node_fs22.rmSync)(carryPath, { force: true });
16841
16905
  } catch {
16842
16906
  }
16843
16907
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -16848,11 +16912,11 @@ function claimCarry(newKey) {
16848
16912
  if (!prior) return null;
16849
16913
  const toDir = sessionDir(newKey);
16850
16914
  try {
16851
- (0, import_node_fs21.rmSync)(toDir, { recursive: true, force: true });
16915
+ (0, import_node_fs22.rmSync)(toDir, { recursive: true, force: true });
16852
16916
  } catch {
16853
16917
  }
16854
- (0, import_node_fs21.renameSync)(fromDir, toDir);
16855
- (0, import_node_fs21.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16918
+ (0, import_node_fs22.renameSync)(fromDir, toDir);
16919
+ (0, import_node_fs22.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16856
16920
  return readManifest(toDir);
16857
16921
  } catch {
16858
16922
  return null;
@@ -16876,21 +16940,21 @@ function captureBaseline(opts = {}) {
16876
16940
  const head_sha = getCurrentCommit();
16877
16941
  const dirty = getDirtyFiles();
16878
16942
  try {
16879
- (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
16943
+ (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
16880
16944
  } catch {
16881
16945
  }
16882
- const filesDir = (0, import_node_path18.join)(dir, "files");
16946
+ const filesDir = (0, import_node_path19.join)(dir, "files");
16883
16947
  const mirrored = [];
16884
16948
  try {
16885
- (0, import_node_fs21.mkdirSync)(filesDir, { recursive: true });
16949
+ (0, import_node_fs22.mkdirSync)(filesDir, { recursive: true });
16886
16950
  for (const p of dirty) {
16887
16951
  if (p.includes("..")) continue;
16888
16952
  const content = safeReadForMirror(projectPath(p));
16889
16953
  if (content === null) continue;
16890
16954
  const dest = mirrorPath(dir, p);
16891
16955
  try {
16892
- (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
16893
- (0, import_node_fs21.writeFileSync)(dest, content);
16956
+ (0, import_node_fs22.mkdirSync)((0, import_node_path19.dirname)(dest), { recursive: true });
16957
+ (0, import_node_fs22.writeFileSync)(dest, content);
16894
16958
  mirrored.push(p);
16895
16959
  } catch {
16896
16960
  }
@@ -16905,8 +16969,8 @@ function captureBaseline(opts = {}) {
16905
16969
  version: BASELINE_VERSION
16906
16970
  };
16907
16971
  try {
16908
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
16909
- (0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16972
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
16973
+ (0, import_node_fs22.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16910
16974
  } catch {
16911
16975
  }
16912
16976
  pruneOldBaselines();
@@ -16917,9 +16981,9 @@ function readBaseline(sessionId) {
16917
16981
  }
16918
16982
  function readManifest(dir) {
16919
16983
  const mp = manifestPath(dir);
16920
- if (!(0, import_node_fs21.existsSync)(mp)) return null;
16984
+ if (!(0, import_node_fs22.existsSync)(mp)) return null;
16921
16985
  try {
16922
- const parsed = JSON.parse((0, import_node_fs21.readFileSync)(mp, "utf-8"));
16986
+ const parsed = JSON.parse((0, import_node_fs22.readFileSync)(mp, "utf-8"));
16923
16987
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
16924
16988
  return null;
16925
16989
  }
@@ -16950,9 +17014,9 @@ function preImage(repoRelPath, baseline) {
16950
17014
  function resolvePreImage(repoRelPath, baseline) {
16951
17015
  if (baseline.dirty_paths.includes(repoRelPath)) {
16952
17016
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
16953
- if ((0, import_node_fs21.existsSync)(mp)) {
17017
+ if ((0, import_node_fs22.existsSync)(mp)) {
16954
17018
  try {
16955
- return { content: (0, import_node_fs21.readFileSync)(mp, "utf-8"), existed: true };
17019
+ return { content: (0, import_node_fs22.readFileSync)(mp, "utf-8"), existed: true };
16956
17020
  } catch {
16957
17021
  }
16958
17022
  }
@@ -16997,8 +17061,8 @@ function absorbIntoBaseline(paths, sessionId) {
16997
17061
  const content = safeReadForMirror(projectPath(p));
16998
17062
  if (content === null) continue;
16999
17063
  const dest = mirrorPath(dir, p);
17000
- (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
17001
- (0, import_node_fs21.writeFileSync)(dest, content);
17064
+ (0, import_node_fs22.mkdirSync)((0, import_node_path19.dirname)(dest), { recursive: true });
17065
+ (0, import_node_fs22.writeFileSync)(dest, content);
17002
17066
  dirty.add(p);
17003
17067
  adopted++;
17004
17068
  } catch {
@@ -17007,7 +17071,7 @@ function absorbIntoBaseline(paths, sessionId) {
17007
17071
  if (adopted === 0) return 0;
17008
17072
  try {
17009
17073
  const updated = { ...baseline, dirty_paths: [...dirty] };
17010
- (0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17074
+ (0, import_node_fs22.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17011
17075
  preImageCache.delete(baseline);
17012
17076
  } catch {
17013
17077
  return 0;
@@ -17018,7 +17082,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
17018
17082
  const pre = preImage(repoRelPath, baseline);
17019
17083
  let current;
17020
17084
  try {
17021
- current = (0, import_node_fs21.readFileSync)(projectPath(repoRelPath), "utf-8");
17085
+ current = (0, import_node_fs22.readFileSync)(projectPath(repoRelPath), "utf-8");
17022
17086
  } catch {
17023
17087
  return pre.existed;
17024
17088
  }
@@ -17027,8 +17091,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
17027
17091
  }
17028
17092
  function safeReadForMirror(absPath) {
17029
17093
  try {
17030
- if ((0, import_node_fs21.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17031
- const buf = (0, import_node_fs21.readFileSync)(absPath);
17094
+ if ((0, import_node_fs22.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17095
+ const buf = (0, import_node_fs22.readFileSync)(absPath);
17032
17096
  if (buf.includes(0)) return null;
17033
17097
  return buf.toString("utf-8");
17034
17098
  } catch {
@@ -17039,18 +17103,18 @@ function pruneOldBaselines() {
17039
17103
  const root = projectPath(BASELINE_DIR);
17040
17104
  let entries;
17041
17105
  try {
17042
- entries = (0, import_node_fs21.readdirSync)(root);
17106
+ entries = (0, import_node_fs22.readdirSync)(root);
17043
17107
  } catch {
17044
17108
  return;
17045
17109
  }
17046
17110
  const now = Date.now();
17047
17111
  for (const name of entries) {
17048
- const dir = (0, import_node_path18.join)(root, name);
17112
+ const dir = (0, import_node_path19.join)(root, name);
17049
17113
  const manifest = readManifest(dir);
17050
17114
  if (!manifest) {
17051
17115
  try {
17052
- if (now - (0, import_node_fs21.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17053
- (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
17116
+ if (now - (0, import_node_fs22.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17117
+ (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
17054
17118
  }
17055
17119
  } catch {
17056
17120
  }
@@ -17058,7 +17122,7 @@ function pruneOldBaselines() {
17058
17122
  }
17059
17123
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
17060
17124
  try {
17061
- (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
17125
+ (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
17062
17126
  } catch {
17063
17127
  }
17064
17128
  }
@@ -17233,8 +17297,8 @@ function buildCompactionContext(session) {
17233
17297
  commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
17234
17298
  readFileLines: (file) => {
17235
17299
  try {
17236
- const abs = (0, import_node_path19.join)(root, file);
17237
- return (0, import_node_fs22.existsSync)(abs) ? (0, import_node_fs22.readFileSync)(abs, "utf8").split("\n") : null;
17300
+ const abs = (0, import_node_path20.join)(root, file);
17301
+ return (0, import_node_fs23.existsSync)(abs) ? (0, import_node_fs23.readFileSync)(abs, "utf8").split("\n") : null;
17238
17302
  } catch {
17239
17303
  return null;
17240
17304
  }
@@ -17291,24 +17355,24 @@ async function readHookStdin() {
17291
17355
 
17292
17356
  // src/commands/standard.ts
17293
17357
  var import_promises12 = require("node:fs/promises");
17294
- var import_node_fs29 = require("node:fs");
17358
+ var import_node_fs30 = require("node:fs");
17295
17359
  var import_yaml3 = __toESM(require_dist());
17296
17360
 
17297
17361
  // src/lib/synthesize.ts
17298
17362
  var import_node_child_process9 = require("node:child_process");
17299
- var import_node_fs25 = require("node:fs");
17363
+ var import_node_fs26 = require("node:fs");
17300
17364
  var import_promises9 = require("node:fs/promises");
17301
- var import_node_path22 = require("node:path");
17365
+ var import_node_path23 = require("node:path");
17302
17366
  var import_yaml = __toESM(require_dist());
17303
17367
 
17304
17368
  // src/lib/data-dir.ts
17305
- var import_node_fs23 = require("node:fs");
17306
- var import_node_path20 = require("node:path");
17369
+ var import_node_fs24 = require("node:fs");
17370
+ var import_node_path21 = require("node:path");
17307
17371
  function resolveDataDir() {
17308
17372
  const candidates2 = [
17309
- (0, import_node_path20.join)(__dirname, "..", "data"),
17373
+ (0, import_node_path21.join)(__dirname, "..", "data"),
17310
17374
  // installed: node_modules/@codacy/verity-cli/data
17311
- (0, import_node_path20.join)(__dirname, "..", "..", "data"),
17375
+ (0, import_node_path21.join)(__dirname, "..", "..", "data"),
17312
17376
  // edge case: nested resolution
17313
17377
  // THE COMMITTED SOURCE, for a source checkout that has not been built.
17314
17378
  // cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
@@ -17317,14 +17381,14 @@ function resolveDataDir() {
17317
17381
  // without this the synthesizer throws "Could not find Verity skill data"
17318
17382
  // for every test and every `verity` run from source. Resolved from this
17319
17383
  // module's own location, never the cwd: see the warning below.
17320
- (0, import_node_path20.join)(__dirname, "..", "..", "client"),
17384
+ (0, import_node_path21.join)(__dirname, "..", "..", "client"),
17321
17385
  // bundled: cli/bin/ → ../../client
17322
- (0, import_node_path20.join)(__dirname, "..", "..", "..", "client"),
17386
+ (0, import_node_path21.join)(__dirname, "..", "..", "..", "client"),
17323
17387
  // tsx: cli/src/lib/ → ../../../client
17324
17388
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
17325
17389
  ];
17326
17390
  for (const candidate of candidates2) {
17327
- if ((0, import_node_fs23.existsSync)((0, import_node_path20.join)(candidate, "skills"))) {
17391
+ if ((0, import_node_fs24.existsSync)((0, import_node_path21.join)(candidate, "skills"))) {
17328
17392
  return candidate;
17329
17393
  }
17330
17394
  }
@@ -17333,13 +17397,13 @@ function resolveDataDir() {
17333
17397
  );
17334
17398
  }
17335
17399
  function setupDataPath(file) {
17336
- return (0, import_node_path20.join)(resolveDataDir(), "skills", "verity-setup", file);
17400
+ return (0, import_node_path21.join)(resolveDataDir(), "skills", "verity-setup", file);
17337
17401
  }
17338
17402
 
17339
17403
  // src/lib/detect.ts
17340
17404
  var import_node_child_process8 = require("node:child_process");
17341
- var import_node_fs24 = require("node:fs");
17342
- var import_node_path21 = require("node:path");
17405
+ var import_node_fs25 = require("node:fs");
17406
+ var import_node_path22 = require("node:path");
17343
17407
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
17344
17408
  "typescript",
17345
17409
  "javascript",
@@ -17396,25 +17460,25 @@ function walk(root) {
17396
17460
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
17397
17461
  let entries;
17398
17462
  try {
17399
- entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
17463
+ entries = (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true });
17400
17464
  } catch {
17401
17465
  return;
17402
17466
  }
17403
17467
  for (const entry of entries) {
17404
17468
  if (found.length >= WALK_MAX_FILES) return;
17405
17469
  if (IGNORED_SEGMENTS.includes(entry.name)) continue;
17406
- const full = (0, import_node_path21.join)(dir, entry.name);
17470
+ const full = (0, import_node_path22.join)(dir, entry.name);
17407
17471
  if (entry.isDirectory()) visit(full, depth + 1);
17408
- else if (entry.isFile()) found.push((0, import_node_path21.relative)(root, full));
17472
+ else if (entry.isFile()) found.push((0, import_node_path22.relative)(root, full));
17409
17473
  }
17410
17474
  };
17411
17475
  visit(root, 0);
17412
17476
  return found;
17413
17477
  }
17414
17478
  function languageOf(path) {
17415
- const name = (0, import_node_path21.basename)(path);
17479
+ const name = (0, import_node_path22.basename)(path);
17416
17480
  if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
17417
- if (!(0, import_node_path21.extname)(name)) return null;
17481
+ if (!(0, import_node_path22.extname)(name)) return null;
17418
17482
  const lang = detectLanguage(path);
17419
17483
  return lang || null;
17420
17484
  }
@@ -17471,7 +17535,7 @@ var TOOL_CONFIG_MARKERS = [
17471
17535
  ];
17472
17536
  function readJson(path) {
17473
17537
  try {
17474
- return JSON.parse((0, import_node_fs24.readFileSync)(path, "utf-8"));
17538
+ return JSON.parse((0, import_node_fs25.readFileSync)(path, "utf-8"));
17475
17539
  } catch {
17476
17540
  return null;
17477
17541
  }
@@ -17496,17 +17560,17 @@ function declaredDependencies(root, files) {
17496
17560
  if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
17497
17561
  }
17498
17562
  };
17499
- readPackageJson((0, import_node_path21.join)(root, "package.json"));
17500
- const nested = files.filter((f) => f.includes("/") && (0, import_node_path21.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
17501
- for (const rel of nested) readPackageJson((0, import_node_path21.join)(root, rel));
17563
+ readPackageJson((0, import_node_path22.join)(root, "package.json"));
17564
+ const nested = files.filter((f) => f.includes("/") && (0, import_node_path22.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
17565
+ for (const rel of nested) readPackageJson((0, import_node_path22.join)(root, rel));
17502
17566
  const pythonManifests = [
17503
- ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path21.join)(root, f)),
17504
- ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path21.join)(root, f))
17567
+ ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path22.join)(root, f)),
17568
+ ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path22.join)(root, f))
17505
17569
  ];
17506
17570
  for (const path of pythonManifests) {
17507
- if (!(0, import_node_fs24.existsSync)(path)) continue;
17571
+ if (!(0, import_node_fs25.existsSync)(path)) continue;
17508
17572
  try {
17509
- const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17573
+ const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
17510
17574
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
17511
17575
  for (const line of text.split("\n")) {
17512
17576
  if (!/dependencies\s*=/.test(line)) continue;
@@ -17516,13 +17580,13 @@ function declaredDependencies(root, files) {
17516
17580
  }
17517
17581
  }
17518
17582
  const goMods = [
17519
- (0, import_node_path21.join)(root, "go.mod"),
17520
- ...files.filter((f) => f.includes("/") && (0, import_node_path21.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path21.join)(root, f))
17583
+ (0, import_node_path22.join)(root, "go.mod"),
17584
+ ...files.filter((f) => f.includes("/") && (0, import_node_path22.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path22.join)(root, f))
17521
17585
  ];
17522
17586
  for (const path of goMods) {
17523
- if (!(0, import_node_fs24.existsSync)(path)) continue;
17587
+ if (!(0, import_node_fs25.existsSync)(path)) continue;
17524
17588
  try {
17525
- const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17589
+ const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
17526
17590
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
17527
17591
  names2.push(m[1].replace(/^github\.com\//, ""));
17528
17592
  }
@@ -17530,10 +17594,10 @@ function declaredDependencies(root, files) {
17530
17594
  }
17531
17595
  }
17532
17596
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
17533
- const path = (0, import_node_path21.join)(root, file);
17534
- if (!(0, import_node_fs24.existsSync)(path)) continue;
17597
+ const path = (0, import_node_path22.join)(root, file);
17598
+ if (!(0, import_node_fs25.existsSync)(path)) continue;
17535
17599
  try {
17536
- const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17600
+ const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
17537
17601
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
17538
17602
  } catch {
17539
17603
  }
@@ -17541,7 +17605,7 @@ function declaredDependencies(root, files) {
17541
17605
  return names2;
17542
17606
  }
17543
17607
  function detectBuildSystem(root, files) {
17544
- const has = (f) => (0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, f)) || files.some((p) => (0, import_node_path21.basename)(p) === f);
17608
+ const has = (f) => (0, import_node_fs25.existsSync)((0, import_node_path22.join)(root, f)) || files.some((p) => (0, import_node_path22.basename)(p) === f);
17545
17609
  if (has("pnpm-lock.yaml")) return "pnpm";
17546
17610
  if (has("yarn.lock")) return "yarn";
17547
17611
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -17558,8 +17622,8 @@ function detectBuildSystem(root, files) {
17558
17622
  }
17559
17623
  function detectArchitecture(root, files) {
17560
17624
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
17561
- if (workspaceMarkers.some((m) => (0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, m)))) return "monorepo";
17562
- const pkg = readJson((0, import_node_path21.join)(root, "package.json"));
17625
+ if (workspaceMarkers.some((m) => (0, import_node_fs25.existsSync)((0, import_node_path22.join)(root, m)))) return "monorepo";
17626
+ const pkg = readJson((0, import_node_path22.join)(root, "package.json"));
17563
17627
  if (pkg && "workspaces" in pkg) return "monorepo";
17564
17628
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
17565
17629
  const nested = manifests.filter((f) => f.includes("/"));
@@ -17581,10 +17645,10 @@ function measureAvgFileLength(root, files, languages) {
17581
17645
  let total = 0;
17582
17646
  let counted = 0;
17583
17647
  for (let i = 0; i < candidates2.length; i += stride) {
17584
- const path = (0, import_node_path21.join)(root, candidates2[i]);
17648
+ const path = (0, import_node_path22.join)(root, candidates2[i]);
17585
17649
  try {
17586
- if ((0, import_node_fs24.statSync)(path).size > 2 * 1024 * 1024) continue;
17587
- total += (0, import_node_fs24.readFileSync)(path, "utf-8").split("\n").length;
17650
+ if ((0, import_node_fs25.statSync)(path).size > 2 * 1024 * 1024) continue;
17651
+ total += (0, import_node_fs25.readFileSync)(path, "utf-8").split("\n").length;
17588
17652
  counted++;
17589
17653
  } catch {
17590
17654
  }
@@ -17614,14 +17678,14 @@ function detectProject(root = repoRoot()) {
17614
17678
  const existingToolConfigs = [];
17615
17679
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
17616
17680
  for (const marker of markers) {
17617
- if ((0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, marker))) {
17681
+ if ((0, import_node_fs25.existsSync)((0, import_node_path22.join)(root, marker))) {
17618
17682
  existingToolConfigs.push({ tool, path: `./${marker}` });
17619
17683
  break;
17620
17684
  }
17621
17685
  }
17622
17686
  }
17623
17687
  return {
17624
- projectName: (0, import_node_path21.basename)(root),
17688
+ projectName: (0, import_node_path22.basename)(root),
17625
17689
  languages,
17626
17690
  languageCounts,
17627
17691
  frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
@@ -17719,8 +17783,8 @@ ${closingNote(input.origin)}
17719
17783
 
17720
17784
  // src/lib/synthesize.ts
17721
17785
  function loadCatalog() {
17722
- const catalog = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
17723
- const template = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
17786
+ const catalog = (0, import_yaml.parse)((0, import_node_fs26.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
17787
+ const template = (0, import_yaml.parse)((0, import_node_fs26.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
17724
17788
  return { catalog, template };
17725
17789
  }
17726
17790
  function selectTools(languages, intensity, catalog) {
@@ -17998,7 +18062,7 @@ function validatePatternIds() {
17998
18062
  }
17999
18063
  async function runSynthesis(opts) {
18000
18064
  const standardPath = projectPath(STANDARD_FILE);
18001
- if ((0, import_node_fs25.existsSync)(standardPath) && !opts.force) {
18065
+ if ((0, import_node_fs26.existsSync)(standardPath) && !opts.force) {
18002
18066
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
18003
18067
  }
18004
18068
  const detected = opts.detected ?? detectProject();
@@ -18065,9 +18129,9 @@ async function correctVerityMdVersion(opts) {
18065
18129
  origin: { kind: "synthesized", tools: opts.tools }
18066
18130
  }));
18067
18131
  }
18068
- async function writeFileTo(relative2, body) {
18069
- const target = projectPath(relative2);
18070
- await (0, import_promises9.mkdir)((0, import_node_path22.dirname)(target), { recursive: true });
18132
+ async function writeFileTo(relative3, body) {
18133
+ const target = projectPath(relative3);
18134
+ await (0, import_promises9.mkdir)((0, import_node_path23.dirname)(target), { recursive: true });
18071
18135
  await (0, import_promises9.writeFile)(target, body);
18072
18136
  }
18073
18137
  async function deriveConfigForStandard(standard) {
@@ -18126,11 +18190,11 @@ ${validation.detail}`);
18126
18190
 
18127
18191
  // src/lib/setup-state.ts
18128
18192
  var import_promises10 = require("node:fs/promises");
18129
- var import_node_fs26 = require("node:fs");
18193
+ var import_node_fs27 = require("node:fs");
18130
18194
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
18131
18195
  async function readSetupState() {
18132
18196
  const path = projectPath(SETUP_STATE_FILE);
18133
- if (!(0, import_node_fs26.existsSync)(path)) return null;
18197
+ if (!(0, import_node_fs27.existsSync)(path)) return null;
18134
18198
  try {
18135
18199
  const parsed = JSON.parse(await (0, import_promises10.readFile)(path, "utf-8"));
18136
18200
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -18146,12 +18210,12 @@ async function writeSetupState(patch) {
18146
18210
  }
18147
18211
 
18148
18212
  // src/lib/push-setup.ts
18149
- var import_node_fs28 = require("node:fs");
18213
+ var import_node_fs29 = require("node:fs");
18150
18214
  var import_promises11 = require("node:fs/promises");
18151
18215
  var import_yaml2 = __toESM(require_dist());
18152
18216
 
18153
18217
  // src/lib/verityignore.ts
18154
- var import_node_fs27 = require("node:fs");
18218
+ var import_node_fs28 = require("node:fs");
18155
18219
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
18156
18220
  var SECURITY_PROBES = [
18157
18221
  ".env",
@@ -18244,9 +18308,9 @@ function isIgnored3(ig, path) {
18244
18308
  }
18245
18309
  function loadVerityIgnore() {
18246
18310
  const file = projectPath(VERITYIGNORE_FILE);
18247
- if (!(0, import_node_fs27.existsSync)(file)) return EMPTY;
18311
+ if (!(0, import_node_fs28.existsSync)(file)) return EMPTY;
18248
18312
  try {
18249
- return parseVerityIgnore((0, import_node_fs27.readFileSync)(file, "utf-8"));
18313
+ return parseVerityIgnore((0, import_node_fs28.readFileSync)(file, "utf-8"));
18250
18314
  } catch {
18251
18315
  return EMPTY;
18252
18316
  }
@@ -18284,9 +18348,9 @@ function buildStandardUpload(standard, ignoreRaw) {
18284
18348
  }
18285
18349
  function readVerityIgnoreRaw() {
18286
18350
  const file = projectPath(VERITYIGNORE_FILE);
18287
- if (!(0, import_node_fs27.existsSync)(file)) return null;
18351
+ if (!(0, import_node_fs28.existsSync)(file)) return null;
18288
18352
  try {
18289
- return (0, import_node_fs27.readFileSync)(file, "utf-8");
18353
+ return (0, import_node_fs28.readFileSync)(file, "utf-8");
18290
18354
  } catch {
18291
18355
  return null;
18292
18356
  }
@@ -18314,7 +18378,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18314
18378
  }
18315
18379
  let standardVersion = null;
18316
18380
  const standardPath = projectPath(STANDARD_FILE);
18317
- if (pushStandard && (0, import_node_fs28.existsSync)(standardPath)) {
18381
+ if (pushStandard && (0, import_node_fs29.existsSync)(standardPath)) {
18318
18382
  try {
18319
18383
  const content = (0, import_yaml2.parse)(await (0, import_promises11.readFile)(standardPath, "utf-8"));
18320
18384
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -18339,7 +18403,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18339
18403
  }
18340
18404
  let configPushed = false;
18341
18405
  const configPath = projectPath(CODACY_CONFIG_FILE);
18342
- if (pushConfig && (0, import_node_fs28.existsSync)(configPath)) {
18406
+ if (pushConfig && (0, import_node_fs29.existsSync)(configPath)) {
18343
18407
  try {
18344
18408
  const content = JSON.parse(await (0, import_promises11.readFile)(configPath, "utf-8"));
18345
18409
  const result = await apiRequest({
@@ -18371,7 +18435,7 @@ function registerStandardCommands(program2) {
18371
18435
  const state = await readSetupState();
18372
18436
  if (opts.configOnly) {
18373
18437
  const standardPath = projectPath(STANDARD_FILE);
18374
- if (!(0, import_node_fs29.existsSync)(standardPath)) {
18438
+ if (!(0, import_node_fs30.existsSync)(standardPath)) {
18375
18439
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
18376
18440
  process.exit(1);
18377
18441
  }
@@ -18702,10 +18766,10 @@ function formatRunDetail(run2) {
18702
18766
  }
18703
18767
 
18704
18768
  // src/lib/ignore-declaration.ts
18705
- var import_node_fs31 = require("node:fs");
18769
+ var import_node_fs32 = require("node:fs");
18706
18770
 
18707
18771
  // src/lib/debounce.ts
18708
- var import_node_fs30 = require("node:fs");
18772
+ var import_node_fs31 = require("node:fs");
18709
18773
  var import_node_crypto10 = require("node:crypto");
18710
18774
  function scopedFile(base, sessionId) {
18711
18775
  if (!sessionId) return base;
@@ -18713,9 +18777,9 @@ function scopedFile(base, sessionId) {
18713
18777
  }
18714
18778
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18715
18779
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18716
- if (!(0, import_node_fs30.existsSync)(file)) return null;
18780
+ if (!(0, import_node_fs31.existsSync)(file)) return null;
18717
18781
  try {
18718
- const lastTs = parseInt((0, import_node_fs30.readFileSync)(file, "utf-8").trim(), 10);
18782
+ const lastTs = parseInt((0, import_node_fs31.readFileSync)(file, "utf-8").trim(), 10);
18719
18783
  const nowTs = Math.floor(Date.now() / 1e3);
18720
18784
  const elapsed = nowTs - lastTs;
18721
18785
  if (elapsed < debounceSeconds) {
@@ -18728,10 +18792,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18728
18792
  function checkMtime(files, bypassForRecentCommits, sessionId) {
18729
18793
  if (bypassForRecentCommits) return null;
18730
18794
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18731
- if (!(0, import_node_fs30.existsSync)(file)) return null;
18795
+ if (!(0, import_node_fs31.existsSync)(file)) return null;
18732
18796
  let debounceTime;
18733
18797
  try {
18734
- debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
18798
+ debounceTime = (0, import_node_fs31.statSync)(file).mtimeMs;
18735
18799
  } catch {
18736
18800
  return null;
18737
18801
  }
@@ -18739,7 +18803,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
18739
18803
  const resolved = resolveFile(f);
18740
18804
  if (!resolved) continue;
18741
18805
  try {
18742
- const stat3 = (0, import_node_fs30.statSync)(resolved);
18806
+ const stat3 = (0, import_node_fs31.statSync)(resolved);
18743
18807
  if (stat3.mtimeMs > debounceTime) {
18744
18808
  return null;
18745
18809
  }
@@ -18755,8 +18819,8 @@ function computeContentHash(files) {
18755
18819
  for (const f of sorted) {
18756
18820
  const resolved = resolveFile(f) ?? f;
18757
18821
  try {
18758
- if ((0, import_node_fs30.existsSync)(resolved)) {
18759
- hash.update((0, import_node_fs30.readFileSync)(resolved));
18822
+ if ((0, import_node_fs31.existsSync)(resolved)) {
18823
+ hash.update((0, import_node_fs31.readFileSync)(resolved));
18760
18824
  }
18761
18825
  } catch {
18762
18826
  }
@@ -18766,9 +18830,9 @@ function computeContentHash(files) {
18766
18830
  function checkContentHash(files, sessionId) {
18767
18831
  const hash = computeContentHash(files);
18768
18832
  const file = scopedFile(HASH_FILE, sessionId);
18769
- if ((0, import_node_fs30.existsSync)(file)) {
18833
+ if ((0, import_node_fs31.existsSync)(file)) {
18770
18834
  try {
18771
- const storedHash = (0, import_node_fs30.readFileSync)(file, "utf-8").trim();
18835
+ const storedHash = (0, import_node_fs31.readFileSync)(file, "utf-8").trim();
18772
18836
  if (hash === storedHash) {
18773
18837
  return { skip: "No source changes since last analysis", hash };
18774
18838
  }
@@ -18778,24 +18842,24 @@ function checkContentHash(files, sessionId) {
18778
18842
  return { skip: null, hash };
18779
18843
  }
18780
18844
  function recordAnalysisStart(sessionId) {
18781
- (0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
18782
- (0, import_node_fs30.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18845
+ (0, import_node_fs31.mkdirSync)(VERITY_DIR, { recursive: true });
18846
+ (0, import_node_fs31.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18783
18847
  }
18784
18848
  function recordPassHash(hash, sessionId) {
18785
- (0, import_node_fs30.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18849
+ (0, import_node_fs31.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18786
18850
  }
18787
18851
  function narrowToRecent(files, sessionId) {
18788
18852
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18789
- if (!(0, import_node_fs30.existsSync)(file)) return files;
18853
+ if (!(0, import_node_fs31.existsSync)(file)) return files;
18790
18854
  let debounceTime;
18791
18855
  try {
18792
- debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
18856
+ debounceTime = (0, import_node_fs31.statSync)(file).mtimeMs;
18793
18857
  } catch {
18794
18858
  return files;
18795
18859
  }
18796
18860
  const recent = files.filter((f) => {
18797
18861
  try {
18798
- return (0, import_node_fs30.existsSync)(f) && (0, import_node_fs30.statSync)(f).mtimeMs > debounceTime;
18862
+ return (0, import_node_fs31.existsSync)(f) && (0, import_node_fs31.statSync)(f).mtimeMs > debounceTime;
18799
18863
  } catch {
18800
18864
  return false;
18801
18865
  }
@@ -18808,9 +18872,9 @@ function readIteration(currentCommit, _contentHash) {
18808
18872
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
18809
18873
  function readBlockState(currentCommit, opts) {
18810
18874
  if (opts?.newUserPrompt) return NO_BLOCKS;
18811
- if (!(0, import_node_fs30.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18875
+ if (!(0, import_node_fs31.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18812
18876
  try {
18813
- const stored = (0, import_node_fs30.readFileSync)(ITERATION_FILE, "utf-8").trim();
18877
+ const stored = (0, import_node_fs31.readFileSync)(ITERATION_FILE, "utf-8").trim();
18814
18878
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
18815
18879
  if (!parsed) return NO_BLOCKS;
18816
18880
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -18856,8 +18920,8 @@ function isSameProblem(previous, current) {
18856
18920
  return current.split(",").some((k) => prev.has(k));
18857
18921
  }
18858
18922
  function writeBlockState(commit, state) {
18859
- (0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
18860
- (0, import_node_fs30.writeFileSync)(
18923
+ (0, import_node_fs31.mkdirSync)(VERITY_DIR, { recursive: true });
18924
+ (0, import_node_fs31.writeFileSync)(
18861
18925
  ITERATION_FILE,
18862
18926
  JSON.stringify({
18863
18927
  v: 2,
@@ -18962,9 +19026,9 @@ function resolveIgnoreState(keys) {
18962
19026
  }
18963
19027
  function readIgnoreState(sessionId) {
18964
19028
  const file = stateFile(sessionId);
18965
- if (!(0, import_node_fs31.existsSync)(file)) return null;
19029
+ if (!(0, import_node_fs32.existsSync)(file)) return null;
18966
19030
  try {
18967
- const o = JSON.parse((0, import_node_fs31.readFileSync)(file, "utf-8")) ?? {};
19031
+ const o = JSON.parse((0, import_node_fs32.readFileSync)(file, "utf-8")) ?? {};
18968
19032
  const spent = typeof o.spent === "number" ? o.spent : 0;
18969
19033
  const raw = o.active;
18970
19034
  let active = null;
@@ -18988,8 +19052,8 @@ function readIgnoreState(sessionId) {
18988
19052
  }
18989
19053
  function writeIgnoreState(state, sessionId) {
18990
19054
  try {
18991
- (0, import_node_fs31.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
18992
- (0, import_node_fs31.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
19055
+ (0, import_node_fs32.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
19056
+ (0, import_node_fs32.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
18993
19057
  } catch {
18994
19058
  }
18995
19059
  }
@@ -19372,7 +19436,7 @@ function createRun(opts, globals) {
19372
19436
  }
19373
19437
 
19374
19438
  // src/commands/analyze/index.ts
19375
- var import_node_fs44 = require("node:fs");
19439
+ var import_node_fs45 = require("node:fs");
19376
19440
 
19377
19441
  // src/lib/repo-context.ts
19378
19442
  var import_node_child_process10 = require("node:child_process");
@@ -20193,10 +20257,10 @@ function installRunEvidence(run2) {
20193
20257
 
20194
20258
  // src/lib/git-frame.ts
20195
20259
  var import_node_child_process11 = require("node:child_process");
20196
- var import_node_fs32 = require("node:fs");
20260
+ var import_node_fs33 = require("node:fs");
20197
20261
  var import_node_os5 = require("node:os");
20198
- var import_node_path23 = require("node:path");
20199
20262
  var import_node_path24 = require("node:path");
20263
+ var import_node_path25 = require("node:path");
20200
20264
  var VALUE_TOKEN = `(?:'[^']*'|"[^"]*"|\\S+)`;
20201
20265
  var GIT_GLOBAL_OPTS = `(?:\\s+(?:-[Cc]\\s+${VALUE_TOKEN}|--?[\\w-]+(?:=\\S+)?))*`;
20202
20266
  var COMMIT_HEAD = `git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`;
@@ -20249,8 +20313,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
20249
20313
  if (SHELL_DYNAMIC.test(raw) || raw === "-") {
20250
20314
  return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
20251
20315
  }
20252
- const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path24.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20253
- dir = (0, import_node_path23.isAbsolute)(expanded) ? expanded : (0, import_node_path23.resolve)(dir, expanded);
20316
+ const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path25.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20317
+ dir = (0, import_node_path24.isAbsolute)(expanded) ? expanded : (0, import_node_path24.resolve)(dir, expanded);
20254
20318
  }
20255
20319
  const seg = segments[segmentIndex];
20256
20320
  const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
@@ -20268,8 +20332,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
20268
20332
  if (SHELL_DYNAMIC.test(raw)) {
20269
20333
  return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
20270
20334
  }
20271
- const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path24.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20272
- dir = (0, import_node_path23.isAbsolute)(expanded) ? expanded : (0, import_node_path23.resolve)(dir, expanded);
20335
+ const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path25.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20336
+ dir = (0, import_node_path24.isAbsolute)(expanded) ? expanded : (0, import_node_path24.resolve)(dir, expanded);
20273
20337
  }
20274
20338
  }
20275
20339
  return { dir, named, unresolvable: null };
@@ -20332,14 +20396,14 @@ function gitAt(dir, args) {
20332
20396
  }
20333
20397
  function realpathOr2(p) {
20334
20398
  try {
20335
- return import_node_fs32.realpathSync.native(p);
20399
+ return import_node_fs33.realpathSync.native(p);
20336
20400
  } catch {
20337
- return (0, import_node_path23.resolve)(p);
20401
+ return (0, import_node_path24.resolve)(p);
20338
20402
  }
20339
20403
  }
20340
20404
  function resolveFrame(input) {
20341
20405
  const found = findMomentSegment(input.command, input.on);
20342
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs32.existsSync)(input.hookCwd);
20406
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs33.existsSync)(input.hookCwd);
20343
20407
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
20344
20408
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
20345
20409
  const refuse = (refusal) => ({
@@ -20362,7 +20426,7 @@ function resolveFrame(input) {
20362
20426
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
20363
20427
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
20364
20428
  if (targetDir !== baseDir) {
20365
- if (!(0, import_node_fs32.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
20429
+ if (!(0, import_node_fs33.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
20366
20430
  dir = targetDir;
20367
20431
  }
20368
20432
  }
@@ -20373,7 +20437,7 @@ function resolveFrame(input) {
20373
20437
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
20374
20438
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
20375
20439
  const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
20376
- const commonDir = commonRaw ? realpathOr2((0, import_node_path23.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path23.resolve)(dir, commonRaw)) : null;
20440
+ const commonDir = commonRaw ? realpathOr2((0, import_node_path24.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path24.resolve)(dir, commonRaw)) : null;
20377
20441
  const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
20378
20442
  return {
20379
20443
  moment: found?.moment ?? null,
@@ -20548,8 +20612,8 @@ function stagedRange(frame, command) {
20548
20612
  if (plan.kind === "unpredictable") {
20549
20613
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
20550
20614
  }
20551
- const mergeHead = frame.gitDir ? (0, import_node_path24.join)(frame.gitDir, "MERGE_HEAD") : null;
20552
- if (mergeHead && (0, import_node_fs32.existsSync)(mergeHead)) {
20615
+ const mergeHead = frame.gitDir ? (0, import_node_path25.join)(frame.gitDir, "MERGE_HEAD") : null;
20616
+ if (mergeHead && (0, import_node_fs33.existsSync)(mergeHead)) {
20553
20617
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
20554
20618
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
20555
20619
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -20683,7 +20747,7 @@ function truthy(v) {
20683
20747
  }
20684
20748
 
20685
20749
  // src/lib/transcript.ts
20686
- var import_node_fs33 = require("node:fs");
20750
+ var import_node_fs34 = require("node:fs");
20687
20751
  var MAX_READ_BYTES = 256 * 1024;
20688
20752
  var SMALL_FILE_BYTES = 64 * 1024;
20689
20753
  var MAX_FILES_LIST = 20;
@@ -20710,7 +20774,7 @@ async function extractActionSummary(transcriptPath) {
20710
20774
  function readTurnLines(transcriptPath) {
20711
20775
  let size;
20712
20776
  try {
20713
- size = (0, import_node_fs33.statSync)(transcriptPath).size;
20777
+ size = (0, import_node_fs34.statSync)(transcriptPath).size;
20714
20778
  } catch {
20715
20779
  return null;
20716
20780
  }
@@ -20718,7 +20782,7 @@ function readTurnLines(transcriptPath) {
20718
20782
  let raw;
20719
20783
  let windowed = false;
20720
20784
  if (size <= SMALL_FILE_BYTES) {
20721
- raw = (0, import_node_fs33.readFileSync)(transcriptPath, "utf-8");
20785
+ raw = (0, import_node_fs34.readFileSync)(transcriptPath, "utf-8");
20722
20786
  } else {
20723
20787
  windowed = true;
20724
20788
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -21226,7 +21290,7 @@ function channelSilence(input) {
21226
21290
  // src/lib/cli-version.ts
21227
21291
  function cliVersion() {
21228
21292
  try {
21229
- return true ? "0.32.6" : "dev";
21293
+ return true ? "0.32.7" : "dev";
21230
21294
  } catch {
21231
21295
  return "dev";
21232
21296
  }
@@ -21267,7 +21331,7 @@ async function sendSkipBeacon(ctx, reason) {
21267
21331
 
21268
21332
  // src/lib/static-analysis.ts
21269
21333
  var import_node_child_process12 = require("node:child_process");
21270
- var import_node_fs34 = require("node:fs");
21334
+ var import_node_fs35 = require("node:fs");
21271
21335
  var SEVERITY_ORDER = {
21272
21336
  Error: 0,
21273
21337
  Critical: 0,
@@ -21278,12 +21342,10 @@ var SEVERITY_ORDER = {
21278
21342
  Low: 3
21279
21343
  };
21280
21344
  function isCodacyAvailable() {
21281
- try {
21282
- (0, import_node_child_process12.execSync)("which codacy-analysis", { stdio: "pipe" });
21283
- return true;
21284
- } catch {
21285
- return false;
21286
- }
21345
+ return codacyAnalysisPath() !== null;
21346
+ }
21347
+ function codacyAnalysisPath() {
21348
+ return whichSync("codacy-analysis");
21287
21349
  }
21288
21350
  function buildAnalyzerArgv(files) {
21289
21351
  return [
@@ -21310,18 +21372,29 @@ function withFailure(kind, detail) {
21310
21372
  summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
21311
21373
  };
21312
21374
  }
21375
+ function runCodacyAnalysisIfAvailable(files) {
21376
+ if (files.length === 0) return EMPTY_RESULT;
21377
+ if (!isCodacyAvailable()) {
21378
+ return withFailure(
21379
+ "analyzer_unavailable",
21380
+ "@codacy/analysis-cli was not found on PATH \u2014 no static analysis ran"
21381
+ );
21382
+ }
21383
+ return runCodacyAnalysis(files);
21384
+ }
21313
21385
  function runCodacyAnalysis(files) {
21314
21386
  const empty = EMPTY_RESULT;
21315
21387
  if (files.length === 0) return empty;
21316
21388
  const existingFiles = files.filter((f) => {
21317
21389
  try {
21318
- return (0, import_node_fs34.existsSync)(f);
21390
+ return (0, import_node_fs35.existsSync)(f);
21319
21391
  } catch {
21320
21392
  return false;
21321
21393
  }
21322
21394
  });
21323
21395
  if (existingFiles.length === 0) return empty;
21324
- const proc = (0, import_node_child_process12.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
21396
+ const analyzer = codacyAnalysisPath() ?? "codacy-analysis";
21397
+ const proc = (0, import_node_child_process12.spawnSync)(analyzer, buildAnalyzerArgv(existingFiles), {
21325
21398
  encoding: "utf-8",
21326
21399
  maxBuffer: 10 * 1024 * 1024
21327
21400
  });
@@ -21489,11 +21562,10 @@ var EMPTY_STATIC = {
21489
21562
  summary: { total_findings: 0, by_severity: {}, tools_run: [] }
21490
21563
  };
21491
21564
  function runLocalStatic(analyzable, securityFiles, baseline, skipStatic) {
21492
- if (skipStatic || !isCodacyAvailable()) return EMPTY_STATIC;
21565
+ if (skipStatic) return EMPTY_STATIC;
21493
21566
  let scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
21494
21567
  if (baseline) scannable = scannable.filter((f) => changedSinceBaseline(f, baseline));
21495
- if (scannable.length === 0) return EMPTY_STATIC;
21496
- return runCodacyAnalysis(scannable);
21568
+ return runCodacyAnalysisIfAvailable(scannable);
21497
21569
  }
21498
21570
  function localOnlyAndExit(staticResults) {
21499
21571
  printJsonCompact({
@@ -21584,8 +21656,8 @@ async function scope(run2) {
21584
21656
  }
21585
21657
 
21586
21658
  // src/lib/specs.ts
21587
- var import_node_fs35 = require("node:fs");
21588
- var import_node_path25 = require("node:path");
21659
+ var import_node_fs36 = require("node:fs");
21660
+ var import_node_path26 = require("node:path");
21589
21661
  var SPEC_CANDIDATES = [
21590
21662
  "CLAUDE.md",
21591
21663
  "AGENTS.md",
@@ -21604,6 +21676,16 @@ var SPEC_CANDIDATES = [
21604
21676
  var DOC_EXT = /\.(md|mdx|ya?ml|txt|rst|adoc)$/i;
21605
21677
  var UNCONSULTED_FILE_BYTES = 10240;
21606
21678
  var UNCONSULTED_TOTAL_BYTES = 30720;
21679
+ function readSpecFiles(specsOpt, root) {
21680
+ const out = [];
21681
+ for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
21682
+ const candidate = (0, import_node_path26.isAbsolute)(raw) ? (0, import_node_path26.relative)(root, raw) : raw;
21683
+ const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
21684
+ if (content === null) continue;
21685
+ out.push({ path: raw, content });
21686
+ }
21687
+ return out;
21688
+ }
21607
21689
  function discoverSpecs(consulted = []) {
21608
21690
  const result = [];
21609
21691
  const seen = /* @__PURE__ */ new Set();
@@ -21616,16 +21698,16 @@ function discoverSpecs(consulted = []) {
21616
21698
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
21617
21699
  if (totalBytes >= totalCap) return false;
21618
21700
  if (seen.has(specPath)) return true;
21619
- if (!(0, import_node_fs35.existsSync)(specPath)) return true;
21701
+ if (!(0, import_node_fs36.existsSync)(specPath)) return true;
21620
21702
  seen.add(specPath);
21621
21703
  const remaining = totalCap - totalBytes;
21622
21704
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
21623
21705
  const readBytes = Math.min(fileCap, remaining);
21624
21706
  try {
21625
21707
  const buf = Buffer.alloc(readBytes);
21626
- const fd = (0, import_node_fs35.openSync)(specPath, "r");
21627
- const bytesRead = (0, import_node_fs35.readSync)(fd, buf, 0, readBytes, 0);
21628
- (0, import_node_fs35.closeSync)(fd);
21708
+ const fd = (0, import_node_fs36.openSync)(specPath, "r");
21709
+ const bytesRead = (0, import_node_fs36.readSync)(fd, buf, 0, readBytes, 0);
21710
+ (0, import_node_fs36.closeSync)(fd);
21629
21711
  const content = buf.slice(0, bytesRead).toString("utf-8");
21630
21712
  if (!content) return true;
21631
21713
  result.push({ path: specPath, content });
@@ -21641,7 +21723,7 @@ function discoverSpecs(consulted = []) {
21641
21723
  if (!addSpec(candidate)) break;
21642
21724
  }
21643
21725
  for (const dir of ["spec", "docs"]) {
21644
- if (!(0, import_node_fs35.existsSync)(dir)) continue;
21726
+ if (!(0, import_node_fs36.existsSync)(dir)) continue;
21645
21727
  try {
21646
21728
  const mdFiles = findMdFiles(dir, 2).sort();
21647
21729
  for (const mdFile of mdFiles) {
@@ -21656,9 +21738,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
21656
21738
  if (depth >= maxDepth) return [];
21657
21739
  const result = [];
21658
21740
  try {
21659
- const entries = (0, import_node_fs35.readdirSync)(dir, { withFileTypes: true });
21741
+ const entries = (0, import_node_fs36.readdirSync)(dir, { withFileTypes: true });
21660
21742
  for (const entry of entries) {
21661
- const fullPath = (0, import_node_path25.join)(dir, entry.name);
21743
+ const fullPath = (0, import_node_path26.join)(dir, entry.name);
21662
21744
  if (entry.isFile() && entry.name.endsWith(".md")) {
21663
21745
  result.push(fullPath);
21664
21746
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -21670,19 +21752,19 @@ function findMdFiles(dir, maxDepth, depth = 0) {
21670
21752
  return result;
21671
21753
  }
21672
21754
  function discoverPlans() {
21673
- const homePlansDir = (0, import_node_path25.join)(process.env.HOME ?? "", ".claude", "plans");
21755
+ const homePlansDir = (0, import_node_path26.join)(process.env.HOME ?? "", ".claude", "plans");
21674
21756
  const localPlansDir = ".claude/plans";
21675
21757
  const candidates2 = [];
21676
21758
  const seen = /* @__PURE__ */ new Set();
21677
21759
  for (const plansDir of [localPlansDir, homePlansDir]) {
21678
- if (!(0, import_node_fs35.existsSync)(plansDir)) continue;
21760
+ if (!(0, import_node_fs36.existsSync)(plansDir)) continue;
21679
21761
  try {
21680
- for (const f of (0, import_node_fs35.readdirSync)(plansDir)) {
21762
+ for (const f of (0, import_node_fs36.readdirSync)(plansDir)) {
21681
21763
  if (!f.endsWith(".md") || seen.has(f)) continue;
21682
21764
  seen.add(f);
21683
- const fullPath = (0, import_node_path25.join)(plansDir, f);
21765
+ const fullPath = (0, import_node_path26.join)(plansDir, f);
21684
21766
  try {
21685
- const stat3 = (0, import_node_fs35.statSync)(fullPath);
21767
+ const stat3 = (0, import_node_fs36.statSync)(fullPath);
21686
21768
  candidates2.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
21687
21769
  } catch {
21688
21770
  }
@@ -21695,7 +21777,7 @@ function discoverPlans() {
21695
21777
  for (const entry of candidates2.slice(0, MAX_PLAN_FILES)) {
21696
21778
  if (entry.size > MAX_PLAN_FILE_BYTES) continue;
21697
21779
  try {
21698
- const content = (0, import_node_fs35.readFileSync)(entry.path, "utf-8");
21780
+ const content = (0, import_node_fs36.readFileSync)(entry.path, "utf-8");
21699
21781
  result.push({ name: entry.name, content });
21700
21782
  } catch {
21701
21783
  }
@@ -21710,12 +21792,12 @@ function discoverGuardDocs(rangeFiles2) {
21710
21792
  if (result.length >= MAX_SPEC_FILES) break;
21711
21793
  if (!GUARD_DOC_EXT.test(path)) continue;
21712
21794
  if (path.startsWith("/") || path.includes("..")) continue;
21713
- if (!(0, import_node_fs35.existsSync)(path)) continue;
21795
+ if (!(0, import_node_fs36.existsSync)(path)) continue;
21714
21796
  try {
21715
- const stat3 = (0, import_node_fs35.statSync)(path);
21797
+ const stat3 = (0, import_node_fs36.statSync)(path);
21716
21798
  if (stat3.size > MAX_PLAN_FILE_BYTES) continue;
21717
21799
  if (totalBytes + stat3.size > MAX_TOTAL_SPEC_BYTES) continue;
21718
- const content = (0, import_node_fs35.readFileSync)(path, "utf-8");
21800
+ const content = (0, import_node_fs36.readFileSync)(path, "utf-8");
21719
21801
  if (!content) continue;
21720
21802
  result.push({ name: path, content });
21721
21803
  totalBytes += content.length;
@@ -21891,8 +21973,8 @@ async function mode(run2) {
21891
21973
  }
21892
21974
 
21893
21975
  // src/lib/fold.ts
21894
- var import_node_fs36 = require("node:fs");
21895
- var import_node_path26 = require("node:path");
21976
+ var import_node_fs37 = require("node:fs");
21977
+ var import_node_path27 = require("node:path");
21896
21978
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
21897
21979
  "user",
21898
21980
  "assistant",
@@ -22029,7 +22111,7 @@ function candidateRoots(repoRoot2) {
22029
22111
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
22030
22112
  const out = [norm];
22031
22113
  try {
22032
- const real = import_node_fs36.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
22114
+ const real = import_node_fs37.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
22033
22115
  if (real !== norm) out.push(real);
22034
22116
  } catch {
22035
22117
  }
@@ -22117,31 +22199,31 @@ function fold(transcriptPath, opts = {}) {
22117
22199
  }
22118
22200
  };
22119
22201
  try {
22120
- if (!(0, import_node_fs36.existsSync)(transcriptPath)) return result;
22121
- ingest((0, import_node_fs36.readFileSync)(transcriptPath, "utf8"), "agent");
22202
+ if (!(0, import_node_fs37.existsSync)(transcriptPath)) return result;
22203
+ ingest((0, import_node_fs37.readFileSync)(transcriptPath, "utf8"), "agent");
22122
22204
  result.coverage.complete = true;
22123
22205
  } catch {
22124
22206
  return result;
22125
22207
  }
22126
22208
  try {
22127
- const sidecarDir = (0, import_node_path26.join)(
22128
- (0, import_node_path26.dirname)(transcriptPath),
22129
- (0, import_node_path26.basename)(transcriptPath).replace(/\.jsonl$/, ""),
22209
+ const sidecarDir = (0, import_node_path27.join)(
22210
+ (0, import_node_path27.dirname)(transcriptPath),
22211
+ (0, import_node_path27.basename)(transcriptPath).replace(/\.jsonl$/, ""),
22130
22212
  "subagents"
22131
22213
  );
22132
- if ((0, import_node_fs36.existsSync)(sidecarDir)) {
22214
+ if ((0, import_node_fs37.existsSync)(sidecarDir)) {
22133
22215
  const maxFiles = opts.maxSidecars ?? 200;
22134
22216
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
22135
22217
  const found = [];
22136
22218
  const walk2 = (d, depth) => {
22137
22219
  if (depth > 4) return;
22138
- for (const e of (0, import_node_fs36.readdirSync)(d, { withFileTypes: true })) {
22139
- const p = (0, import_node_path26.join)(d, e.name);
22220
+ for (const e of (0, import_node_fs37.readdirSync)(d, { withFileTypes: true })) {
22221
+ const p = (0, import_node_path27.join)(d, e.name);
22140
22222
  if (e.isDirectory()) {
22141
22223
  walk2(p, depth + 1);
22142
22224
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
22143
22225
  try {
22144
- const st = (0, import_node_fs36.statSync)(p);
22226
+ const st = (0, import_node_fs37.statSync)(p);
22145
22227
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
22146
22228
  } catch {
22147
22229
  result.coverage.malformed++;
@@ -22158,7 +22240,7 @@ function fold(transcriptPath, opts = {}) {
22158
22240
  continue;
22159
22241
  }
22160
22242
  try {
22161
- ingest((0, import_node_fs36.readFileSync)(f.path, "utf8"), "subagent");
22243
+ ingest((0, import_node_fs37.readFileSync)(f.path, "utf8"), "subagent");
22162
22244
  bytes += f.size;
22163
22245
  result.coverage.subagentFiles++;
22164
22246
  } catch {
@@ -22193,7 +22275,7 @@ function fold(transcriptPath, opts = {}) {
22193
22275
  }
22194
22276
  function classifyUnobserved(path) {
22195
22277
  try {
22196
- const st = (0, import_node_fs36.statSync)(path);
22278
+ const st = (0, import_node_fs37.statSync)(path);
22197
22279
  if (!st.isFile()) return "unreadable";
22198
22280
  } catch {
22199
22281
  return "unreadable";
@@ -22460,14 +22542,12 @@ async function evidence(run2) {
22460
22542
  authorshipWasObservable
22461
22543
  });
22462
22544
  const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
22463
- if (!opts.skipStatic && isCodacyAvailable()) {
22545
+ if (!opts.skipStatic) {
22464
22546
  let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
22465
22547
  if (baseline) {
22466
22548
  allScannable = allScannable.filter((f) => changedSinceBaseline(f, baseline));
22467
22549
  }
22468
- if (allScannable.length > 0) {
22469
- staticResults = runCodacyAnalysis(allScannable);
22470
- }
22550
+ staticResults = runCodacyAnalysisIfAvailable(allScannable);
22471
22551
  }
22472
22552
  const deltaSet = baseline ? recentForReview.filter((f) => changedSinceBaseline(f, baseline)) : recentForReview;
22473
22553
  codeDelta = collectCodeDelta(deltaSet, {
@@ -22510,20 +22590,20 @@ async function evidence(run2) {
22510
22590
  }
22511
22591
 
22512
22592
  // src/lib/cache-cleanup.ts
22513
- var import_node_fs37 = require("node:fs");
22514
- var import_node_path27 = require("node:path");
22593
+ var import_node_fs38 = require("node:fs");
22594
+ var import_node_path28 = require("node:path");
22515
22595
  var CACHE_TTL_DAYS = 7;
22516
22596
  function pruneStaleCache() {
22517
22597
  try {
22518
22598
  const dir = projectPath(CACHE_DIR);
22519
22599
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
22520
- for (const entry of (0, import_node_fs37.readdirSync)(dir)) {
22600
+ for (const entry of (0, import_node_fs38.readdirSync)(dir)) {
22521
22601
  if (!entry.startsWith("pending-")) continue;
22522
- const path = (0, import_node_path27.join)(dir, entry);
22602
+ const path = (0, import_node_path28.join)(dir, entry);
22523
22603
  try {
22524
- const stat3 = (0, import_node_fs37.statSync)(path);
22604
+ const stat3 = (0, import_node_fs38.statSync)(path);
22525
22605
  if (stat3.mtimeMs < cutoff) {
22526
- (0, import_node_fs37.unlinkSync)(path);
22606
+ (0, import_node_fs38.unlinkSync)(path);
22527
22607
  logEvent("cache_entry_pruned", {
22528
22608
  path: entry,
22529
22609
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -22537,7 +22617,7 @@ function pruneStaleCache() {
22537
22617
  }
22538
22618
 
22539
22619
  // src/lib/context-files.ts
22540
- var import_node_fs38 = require("node:fs");
22620
+ var import_node_fs39 = require("node:fs");
22541
22621
  var import_node_os6 = require("node:os");
22542
22622
  var MAX_CONTEXT_FILES = 10;
22543
22623
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -22595,7 +22675,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
22595
22675
  continue;
22596
22676
  }
22597
22677
  try {
22598
- const content = (0, import_node_fs38.readFileSync)(safePath, "utf8");
22678
+ const content = (0, import_node_fs39.readFileSync)(safePath, "utf8");
22599
22679
  const bytes = Buffer.byteLength(content);
22600
22680
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
22601
22681
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -22686,8 +22766,8 @@ async function repoContext(run2) {
22686
22766
 
22687
22767
  // src/lib/seed-runner.ts
22688
22768
  var import_promises14 = require("node:fs/promises");
22689
- var import_node_fs39 = require("node:fs");
22690
- var import_node_path28 = require("node:path");
22769
+ var import_node_fs40 = require("node:fs");
22770
+ var import_node_path29 = require("node:path");
22691
22771
  var import_yaml4 = __toESM(require_dist());
22692
22772
 
22693
22773
  // src/lib/seed.ts
@@ -22926,7 +23006,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
22926
23006
  return fm;
22927
23007
  }
22928
23008
  async function runSeed(opts) {
22929
- if (!(0, import_node_fs39.existsSync)(STANDARD_FILE)) {
23009
+ if (!(0, import_node_fs40.existsSync)(STANDARD_FILE)) {
22930
23010
  return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
22931
23011
  }
22932
23012
  let standardDoc;
@@ -22938,7 +23018,7 @@ async function runSeed(opts) {
22938
23018
  }
22939
23019
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
22940
23020
  let readmeContent;
22941
- if ((0, import_node_fs39.existsSync)("README.md")) {
23021
+ if ((0, import_node_fs40.existsSync)("README.md")) {
22942
23022
  try {
22943
23023
  readmeContent = await (0, import_promises14.readFile)("README.md", "utf-8");
22944
23024
  } catch {
@@ -22946,7 +23026,7 @@ async function runSeed(opts) {
22946
23026
  }
22947
23027
  let claudeMdContent;
22948
23028
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
22949
- if ((0, import_node_fs39.existsSync)(p)) {
23029
+ if ((0, import_node_fs40.existsSync)(p)) {
22950
23030
  try {
22951
23031
  claudeMdContent = await (0, import_promises14.readFile)(p, "utf-8");
22952
23032
  break;
@@ -22969,8 +23049,8 @@ async function runSeed(opts) {
22969
23049
  if (candidates2.length === 0) {
22970
23050
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
22971
23051
  }
22972
- const overviewPath = (0, import_node_path28.join)(MEMORY_DIR, "domain", "project-overview.md");
22973
- if ((0, import_node_fs39.existsSync)(overviewPath) && !opts.force) {
23052
+ const overviewPath = (0, import_node_path29.join)(MEMORY_DIR, "domain", "project-overview.md");
23053
+ if ((0, import_node_fs40.existsSync)(overviewPath) && !opts.force) {
22974
23054
  return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
22975
23055
  }
22976
23056
  if (opts.dryRun) {
@@ -23012,7 +23092,7 @@ async function runSeed(opts) {
23012
23092
  continue;
23013
23093
  }
23014
23094
  try {
23015
- await (0, import_promises14.mkdir)((0, import_node_path28.dirname)(targetPath), { recursive: true });
23095
+ await (0, import_promises14.mkdir)((0, import_node_path29.dirname)(targetPath), { recursive: true });
23016
23096
  await (0, import_promises14.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
23017
23097
  created++;
23018
23098
  opts.onCreated?.(nodeId, filePathRel, c);
@@ -23025,8 +23105,8 @@ async function runSeed(opts) {
23025
23105
  }
23026
23106
 
23027
23107
  // src/commands/analyze/phases/08-memory-manifest.ts
23028
- var import_node_fs40 = require("node:fs");
23029
- var import_node_path29 = require("node:path");
23108
+ var import_node_fs41 = require("node:fs");
23109
+ var import_node_path30 = require("node:path");
23030
23110
  async function memoryManifest(run2) {
23031
23111
  const { globals } = run2;
23032
23112
  const { serviceUrl, token } = run2;
@@ -23036,9 +23116,9 @@ async function memoryManifest(run2) {
23036
23116
  let autoSeedNotice = null;
23037
23117
  try {
23038
23118
  await ensureMemoryDir();
23039
- const seedMarker = (0, import_node_path29.join)(VERITY_DIR, ".seeded");
23040
- const hasStandard = (0, import_node_fs40.existsSync)(STANDARD_FILE);
23041
- const alreadyTried = (0, import_node_fs40.existsSync)(seedMarker);
23119
+ const seedMarker = (0, import_node_path30.join)(VERITY_DIR, ".seeded");
23120
+ const hasStandard = (0, import_node_fs41.existsSync)(STANDARD_FILE);
23121
+ const alreadyTried = (0, import_node_fs41.existsSync)(seedMarker);
23042
23122
  if (hasStandard && !alreadyTried) {
23043
23123
  const preManifest = await buildManifest();
23044
23124
  if (preManifest.nodes.length === 0) {
@@ -23051,7 +23131,7 @@ async function memoryManifest(run2) {
23051
23131
  dryRun: false
23052
23132
  });
23053
23133
  if (seedResult.created > 0) {
23054
- (0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
23134
+ (0, import_node_fs41.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
23055
23135
  `);
23056
23136
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
23057
23137
  logEvent("auto_seed_ran", {
@@ -23059,7 +23139,7 @@ async function memoryManifest(run2) {
23059
23139
  failed: seedResult.failed
23060
23140
  });
23061
23141
  } else if (seedResult.skipped === "already_seeded") {
23062
- (0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
23142
+ (0, import_node_fs41.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
23063
23143
  `);
23064
23144
  } else {
23065
23145
  logEvent("auto_seed_noop", {
@@ -23154,7 +23234,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
23154
23234
  }
23155
23235
 
23156
23236
  // src/commands/analyze/phases/10-working-memory.ts
23157
- var import_node_path30 = require("node:path");
23237
+ var import_node_path31 = require("node:path");
23158
23238
  async function workingMemory(run2) {
23159
23239
  const { opts } = run2;
23160
23240
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
@@ -23166,7 +23246,7 @@ async function workingMemory(run2) {
23166
23246
  const priorState = foldForMarks(memorySession.d);
23167
23247
  incrementReport = computeIncrement(
23168
23248
  allForReview,
23169
- (p) => fileHash((0, import_node_path30.join)(repoRoot(), p)),
23249
+ (p) => fileHash((0, import_node_path31.join)(repoRoot(), p)),
23170
23250
  priorState.authored_all.map((a) => ({
23171
23251
  path: a.path,
23172
23252
  hash_at_last_verdict: a.hash_at_last_verdict
@@ -23248,7 +23328,7 @@ async function workingMemory(run2) {
23248
23328
  }
23249
23329
 
23250
23330
  // src/lib/note-budget.ts
23251
- var import_node_fs41 = require("node:fs");
23331
+ var import_node_fs42 = require("node:fs");
23252
23332
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
23253
23333
  var EPISODE_STALE_SECONDS = 30 * 60;
23254
23334
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -23270,9 +23350,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
23270
23350
  }
23271
23351
  function readAdvisoryEpisode(sessionId) {
23272
23352
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
23273
- if (!(0, import_node_fs41.existsSync)(file)) return null;
23353
+ if (!(0, import_node_fs42.existsSync)(file)) return null;
23274
23354
  try {
23275
- const o = JSON.parse((0, import_node_fs41.readFileSync)(file, "utf-8")) ?? {};
23355
+ const o = JSON.parse((0, import_node_fs42.readFileSync)(file, "utf-8")) ?? {};
23276
23356
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
23277
23357
  if (isNaN(delivered)) return null;
23278
23358
  return {
@@ -23286,8 +23366,8 @@ function readAdvisoryEpisode(sessionId) {
23286
23366
  }
23287
23367
  function writeAdvisoryEpisode(episode, sessionId) {
23288
23368
  try {
23289
- (0, import_node_fs41.mkdirSync)(VERITY_DIR, { recursive: true });
23290
- (0, import_node_fs41.writeFileSync)(
23369
+ (0, import_node_fs42.mkdirSync)(VERITY_DIR, { recursive: true });
23370
+ (0, import_node_fs42.writeFileSync)(
23291
23371
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
23292
23372
  JSON.stringify({ v: 1, ...episode })
23293
23373
  );
@@ -23604,14 +23684,14 @@ async function buildRequest(run2) {
23604
23684
  }
23605
23685
 
23606
23686
  // src/lib/offline.ts
23607
- var import_node_fs42 = require("node:fs");
23687
+ var import_node_fs43 = require("node:fs");
23608
23688
  var import_node_crypto11 = require("node:crypto");
23609
23689
  function cacheRequest(body) {
23610
23690
  try {
23611
- (0, import_node_fs42.mkdirSync)(CACHE_DIR, { recursive: true });
23691
+ (0, import_node_fs43.mkdirSync)(CACHE_DIR, { recursive: true });
23612
23692
  const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
23613
23693
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
23614
- (0, import_node_fs42.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
23694
+ (0, import_node_fs43.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
23615
23695
  } catch {
23616
23696
  }
23617
23697
  }
@@ -23730,8 +23810,8 @@ async function transmit(run2) {
23730
23810
  }
23731
23811
 
23732
23812
  // src/commands/analyze/phases/13-reconcile.ts
23733
- var import_node_fs43 = require("node:fs");
23734
- var import_node_path31 = require("node:path");
23813
+ var import_node_fs44 = require("node:fs");
23814
+ var import_node_path32 = require("node:path");
23735
23815
  async function reconcile(run2) {
23736
23816
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
23737
23817
  const sentPaths = codeDelta.files.map((f) => f.path);
@@ -23760,7 +23840,7 @@ async function reconcile(run2) {
23760
23840
  const st = foldDossier(memorySession.d);
23761
23841
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
23762
23842
  try {
23763
- const src = (0, import_node_fs43.readFileSync)((0, import_node_path31.join)(repoRoot(), file), "utf8").split("\n");
23843
+ const src = (0, import_node_fs44.readFileSync)((0, import_node_path32.join)(repoRoot(), file), "utf8").split("\n");
23764
23844
  const at = src[line - 1];
23765
23845
  return at === void 0 ? null : lineSha(at);
23766
23846
  } catch {
@@ -24425,7 +24505,7 @@ function registerAnalyzeCommand(program2) {
24425
24505
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
24426
24506
  async function runAnalyze(opts, globals) {
24427
24507
  if (!verityConfigured()) {
24428
- (0, import_node_fs44.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
24508
+ (0, import_node_fs45.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
24429
24509
  process.exit(0);
24430
24510
  }
24431
24511
  const run2 = createRun(opts, globals);
@@ -24446,11 +24526,11 @@ async function runAnalyze(opts, globals) {
24446
24526
  }
24447
24527
 
24448
24528
  // src/commands/baseline.ts
24449
- var import_node_fs46 = require("node:fs");
24529
+ var import_node_fs47 = require("node:fs");
24450
24530
 
24451
24531
  // src/lib/project-skills.ts
24452
- var import_node_fs45 = require("node:fs");
24453
- var import_node_path32 = require("node:path");
24532
+ var import_node_fs46 = require("node:fs");
24533
+ var import_node_path33 = require("node:path");
24454
24534
  var PROJECT_SKILL_NAMES = [
24455
24535
  "verity-setup",
24456
24536
  "verity-analyze",
@@ -24475,14 +24555,14 @@ var LEGACY_SKILL_NAMES = [
24475
24555
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
24476
24556
  function staleProjectSkills() {
24477
24557
  const root = projectPath(".claude/skills");
24478
- if (!(0, import_node_fs45.existsSync)(root)) return [];
24479
- return ALL.filter((name) => (0, import_node_fs45.existsSync)((0, import_node_path32.join)(root, name)));
24558
+ if (!(0, import_node_fs46.existsSync)(root)) return [];
24559
+ return ALL.filter((name) => (0, import_node_fs46.existsSync)((0, import_node_path33.join)(root, name)));
24480
24560
  }
24481
24561
  function removeProjectSkills() {
24482
24562
  const root = projectPath(".claude/skills");
24483
24563
  const removed = [];
24484
24564
  for (const name of staleProjectSkills()) {
24485
- (0, import_node_fs45.rmSync)((0, import_node_path32.join)(root, name), { recursive: true, force: true });
24565
+ (0, import_node_fs46.rmSync)((0, import_node_path33.join)(root, name), { recursive: true, force: true });
24486
24566
  removed.push(name);
24487
24567
  }
24488
24568
  return removed;
@@ -24547,13 +24627,13 @@ function registerBaselineCommands(program2) {
24547
24627
  let memoryMsg = null;
24548
24628
  let memoryAgentLine = null;
24549
24629
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
24550
- if (realStart && !(0, import_node_fs46.existsSync)(memoryNotice)) {
24630
+ if (realStart && !(0, import_node_fs47.existsSync)(memoryNotice)) {
24551
24631
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
24552
24632
  if (trackedGraph > 0) {
24553
24633
  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.`;
24554
24634
  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.`;
24555
24635
  try {
24556
- (0, import_node_fs46.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
24636
+ (0, import_node_fs47.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
24557
24637
  } catch {
24558
24638
  }
24559
24639
  }
@@ -24653,7 +24733,7 @@ function hookSource(value) {
24653
24733
  }
24654
24734
 
24655
24735
  // src/commands/review.ts
24656
- var import_node_fs47 = require("node:fs");
24736
+ var import_node_fs48 = require("node:fs");
24657
24737
  function registerReviewCommand(program2) {
24658
24738
  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) => {
24659
24739
  const globals = program2.opts();
@@ -24670,45 +24750,22 @@ async function runReview(opts, globals) {
24670
24750
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
24671
24751
  const analyzable = filterAnalyzable(allFiles);
24672
24752
  const securityFiles = filterSecurity(allFiles);
24673
- let staticResults;
24674
- if (isCodacyAvailable()) {
24675
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs47.existsSync)(f) || resolveFile(f) !== null);
24676
- staticResults = runCodacyAnalysis(scannable);
24677
- } else {
24678
- staticResults = {
24679
- tool: "@codacy/analysis-cli",
24680
- findings: [],
24681
- summary: { total_findings: 0, by_severity: {}, tools_run: [] }
24682
- };
24683
- }
24753
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs48.existsSync)(f) || resolveFile(f) !== null);
24754
+ const staticResults = runCodacyAnalysisIfAvailable(scannable);
24684
24755
  const codeDelta = collectCodeDelta(allFiles);
24685
24756
  const tokenResult = await resolveToken(globals.token);
24686
24757
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
24687
24758
  if (!tokenResult.ok || !urlResult.ok) {
24759
+ const staticFailure = staticResults.summary.failure;
24688
24760
  printJsonCompact({
24689
- gate_decision: "PASS",
24690
- systemMessage: "Verity: not authenticated \u2014 showing local static results only (no deep review, no upload). Run `verity init` to authenticate and unlock the full review.",
24761
+ gate_decision: "WARN",
24762
+ systemMessage: staticFailure ? `Verity: not authenticated, and local static analysis did not run (${staticFailure.kind}) \u2014 nothing was examined. Run \`verity init\` to authenticate and unlock the full review.` : "Verity: not authenticated \u2014 showing local static results only (no deep review, no upload). Run `verity init` to authenticate and unlock the full review.",
24691
24763
  unauthenticated: true,
24692
24764
  static_results: staticResults
24693
24765
  });
24694
24766
  process.exit(0);
24695
24767
  }
24696
- let specs;
24697
- if (opts.specs) {
24698
- const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
24699
- specs = [];
24700
- for (const p of specPaths) {
24701
- if (!(0, import_node_fs47.existsSync)(p)) continue;
24702
- try {
24703
- const { readFileSync: readFileSync27 } = await import("node:fs");
24704
- const content = readFileSync27(p, "utf-8");
24705
- specs.push({ path: p, content: content.slice(0, 10240) });
24706
- } catch {
24707
- }
24708
- }
24709
- } else {
24710
- specs = discoverSpecs();
24711
- }
24768
+ const specs = opts.specs ? readSpecFiles(opts.specs, repoRoot()) : discoverSpecs();
24712
24769
  const plans = discoverPlans();
24713
24770
  const requestBody = {
24714
24771
  static_results: staticResults,
@@ -24741,9 +24798,10 @@ async function runReview(opts, globals) {
24741
24798
  });
24742
24799
  if (!result.ok) {
24743
24800
  printError(`Service error: ${result.error}`);
24801
+ const staticFailure = staticResults.summary.failure;
24744
24802
  printJsonCompact({
24745
- gate_decision: "PASS",
24746
- systemMessage: "Verity: Service unavailable \u2014 showing static results only",
24803
+ gate_decision: "WARN",
24804
+ systemMessage: staticFailure ? `Verity: service unavailable, and local static analysis did not run (${staticFailure.kind}) \u2014 nothing was examined` : "Verity: service unavailable \u2014 showing local static results only",
24747
24805
  offline: true,
24748
24806
  static_results: staticResults
24749
24807
  });
@@ -24758,10 +24816,10 @@ async function runReview(opts, globals) {
24758
24816
  }
24759
24817
 
24760
24818
  // src/commands/guard.ts
24761
- var import_node_fs48 = require("node:fs");
24762
- var import_node_path33 = require("node:path");
24819
+ var import_node_fs49 = require("node:fs");
24820
+ var import_node_path34 = require("node:path");
24763
24821
  var GUARD_BLOCK_CAP = 2;
24764
- var GUARD_ITER_FILE = (0, import_node_path33.join)(VERITY_DIR, ".guard-iteration");
24822
+ var GUARD_ITER_FILE = (0, import_node_path34.join)(VERITY_DIR, ".guard-iteration");
24765
24823
  function readPreToolUseStdin() {
24766
24824
  const empty = { command: "", cwd: null, sessionId: null };
24767
24825
  return new Promise((resolve5) => {
@@ -24806,7 +24864,7 @@ function readPreToolUseStdin() {
24806
24864
  }
24807
24865
  function readIterMap() {
24808
24866
  try {
24809
- const raw = JSON.parse((0, import_node_fs48.readFileSync)(GUARD_ITER_FILE, "utf-8"));
24867
+ const raw = JSON.parse((0, import_node_fs49.readFileSync)(GUARD_ITER_FILE, "utf-8"));
24810
24868
  if (raw && typeof raw === "object") {
24811
24869
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
24812
24870
  return { [raw.moment]: raw.count };
@@ -24826,10 +24884,10 @@ function readIter(moment) {
24826
24884
  }
24827
24885
  function writeIter(moment, count) {
24828
24886
  try {
24829
- (0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
24887
+ (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
24830
24888
  const map = readIterMap();
24831
24889
  map[moment] = count;
24832
- (0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24890
+ (0, import_node_fs49.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24833
24891
  } catch {
24834
24892
  }
24835
24893
  }
@@ -24839,10 +24897,10 @@ function resetIter(moment) {
24839
24897
  if (!(moment in map)) return;
24840
24898
  delete map[moment];
24841
24899
  if (Object.keys(map).length === 0) {
24842
- if ((0, import_node_fs48.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs48.unlinkSync)(GUARD_ITER_FILE);
24900
+ if ((0, import_node_fs49.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs49.unlinkSync)(GUARD_ITER_FILE);
24843
24901
  } else {
24844
- (0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
24845
- (0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24902
+ (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
24903
+ (0, import_node_fs49.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24846
24904
  }
24847
24905
  } catch {
24848
24906
  }
@@ -24912,13 +24970,8 @@ function hasBlockingFinding(response, sentFiles) {
24912
24970
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
24913
24971
  const analyzable = filterAnalyzable(files);
24914
24972
  const securityFiles = filterSecurity(files);
24915
- let staticResults;
24916
- if (isCodacyAvailable()) {
24917
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs48.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
24918
- staticResults = runCodacyAnalysis(scannable);
24919
- } else {
24920
- staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
24921
- }
24973
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs49.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
24974
+ const staticResults = runCodacyAnalysisIfAvailable(scannable);
24922
24975
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
24923
24976
  const requestBody = {
24924
24977
  static_results: staticResults,
@@ -25060,7 +25113,7 @@ async function runGuard(opts, globals) {
25060
25113
  upgradeToExcerpts(repoContext2, {
25061
25114
  readFile: (rel) => {
25062
25115
  try {
25063
- return (0, import_node_fs48.readFileSync)((0, import_node_path33.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
25116
+ return (0, import_node_fs49.readFileSync)((0, import_node_path34.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
25064
25117
  } catch {
25065
25118
  return null;
25066
25119
  }
@@ -25302,7 +25355,7 @@ function registerIgnoreCommand(program2) {
25302
25355
 
25303
25356
  // src/commands/waive.ts
25304
25357
  var import_node_crypto12 = require("node:crypto");
25305
- var import_node_fs49 = require("node:fs");
25358
+ var import_node_fs50 = require("node:fs");
25306
25359
  function registerWaiveCommand(program2) {
25307
25360
  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) => {
25308
25361
  const globals = program2.opts();
@@ -25331,7 +25384,7 @@ function registerWaiveCommand(program2) {
25331
25384
  if (opts.file) {
25332
25385
  body.file = opts.file;
25333
25386
  try {
25334
- body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs49.readFileSync)(opts.file)).digest("hex");
25387
+ body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs50.readFileSync)(opts.file)).digest("hex");
25335
25388
  } catch {
25336
25389
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
25337
25390
  process.exit(1);
@@ -25356,10 +25409,10 @@ function registerWaiveCommand(program2) {
25356
25409
  }
25357
25410
 
25358
25411
  // src/commands/init.ts
25359
- var import_node_fs53 = require("node:fs");
25412
+ var import_node_fs54 = require("node:fs");
25360
25413
  var import_promises17 = require("node:fs/promises");
25361
25414
  var import_yaml6 = __toESM(require_dist());
25362
- var import_node_path36 = require("node:path");
25415
+ var import_node_path37 = require("node:path");
25363
25416
  var import_node_child_process16 = require("node:child_process");
25364
25417
 
25365
25418
  // src/lib/banner.ts
@@ -25438,18 +25491,13 @@ function printPhase(n, of, title, subtitle) {
25438
25491
  }
25439
25492
 
25440
25493
  // src/commands/doctor.ts
25441
- var import_node_fs50 = require("node:fs");
25494
+ var import_node_fs51 = require("node:fs");
25442
25495
 
25443
25496
  // src/lib/prereqs.ts
25444
25497
  var import_node_child_process14 = require("node:child_process");
25445
25498
  var MIN_NODE_MAJOR = 20;
25446
25499
  function which(bin) {
25447
- try {
25448
- const out = (0, import_node_child_process14.execSync)(`command -v ${bin}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
25449
- return out || null;
25450
- } catch {
25451
- return null;
25452
- }
25500
+ return whichSync(bin, { real: false });
25453
25501
  }
25454
25502
  function checkNode() {
25455
25503
  const version = process.version;
@@ -25650,11 +25698,11 @@ async function buildReport() {
25650
25698
  const wiring = await resolveHookWiring();
25651
25699
  const hooks = wiring.status;
25652
25700
  const telemetry = await checkTelemetry();
25653
- const hasConfig = (0, import_node_fs50.existsSync)(projectPath(CODACY_CONFIG_FILE));
25701
+ const hasConfig = (0, import_node_fs51.existsSync)(projectPath(CODACY_CONFIG_FILE));
25654
25702
  const artifacts = {
25655
- standard: (0, import_node_fs50.existsSync)(projectPath(STANDARD_FILE)),
25703
+ standard: (0, import_node_fs51.existsSync)(projectPath(STANDARD_FILE)),
25656
25704
  analysisConfig: hasConfig,
25657
- verityMd: (0, import_node_fs50.existsSync)(projectPath(VERITY_MD_FILE)),
25705
+ verityMd: (0, import_node_fs51.existsSync)(projectPath(VERITY_MD_FILE)),
25658
25706
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
25659
25707
  };
25660
25708
  const next = [];
@@ -25785,8 +25833,8 @@ function registerDoctorCommand(program2) {
25785
25833
  }
25786
25834
 
25787
25835
  // src/commands/migrate.ts
25788
- var import_node_fs51 = require("node:fs");
25789
- var import_node_path34 = require("node:path");
25836
+ var import_node_fs52 = require("node:fs");
25837
+ var import_node_path35 = require("node:path");
25790
25838
  var import_node_child_process15 = require("node:child_process");
25791
25839
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
25792
25840
  function defaultNpmRemover(pkg) {
@@ -25823,12 +25871,12 @@ async function runMigration(opts = {}) {
25823
25871
  return { actions, migrated: actions.length > 0 };
25824
25872
  }
25825
25873
  function migrateProjectDir(root, actions) {
25826
- const gateDir = (0, import_node_path34.join)(root, ".gate");
25827
- const verityDir = (0, import_node_path34.join)(root, ".verity");
25828
- if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) {
25874
+ const gateDir = (0, import_node_path35.join)(root, ".gate");
25875
+ const verityDir = (0, import_node_path35.join)(root, ".verity");
25876
+ if ((0, import_node_fs52.existsSync)(gateDir) && !(0, import_node_fs52.existsSync)(verityDir)) {
25829
25877
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
25830
25878
  }
25831
- if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
25879
+ if ((0, import_node_fs52.existsSync)(gateDir) && (0, import_node_fs52.existsSync)(verityDir)) {
25832
25880
  return migrateProjectDirCarry(gateDir, verityDir, actions);
25833
25881
  }
25834
25882
  return false;
@@ -25849,13 +25897,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
25849
25897
  }
25850
25898
  }
25851
25899
  if (moved) {
25852
- if ((0, import_node_fs51.existsSync)(gateDir)) {
25900
+ if ((0, import_node_fs52.existsSync)(gateDir)) {
25853
25901
  const carried = carryLegacyContents(gateDir, verityDir);
25854
25902
  if (carried > 0) {
25855
25903
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
25856
25904
  }
25857
25905
  try {
25858
- (0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
25906
+ (0, import_node_fs52.rmSync)(gateDir, { recursive: true, force: true });
25859
25907
  } catch {
25860
25908
  }
25861
25909
  }
@@ -25871,18 +25919,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
25871
25919
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
25872
25920
  }
25873
25921
  try {
25874
- (0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
25922
+ (0, import_node_fs52.rmSync)(gateDir, { recursive: true, force: true });
25875
25923
  } catch {
25876
25924
  }
25877
25925
  return carried > 0;
25878
25926
  }
25879
25927
  function migrateGlobalCredentials(home, actions) {
25880
25928
  if (!home) return;
25881
- const gateCreds = (0, import_node_path34.join)(home, ".gate", "credentials");
25882
- const verityCreds = (0, import_node_path34.join)(home, ".verity", "credentials");
25883
- if (!(0, import_node_fs51.existsSync)(gateCreds)) return;
25884
- if (!(0, import_node_fs51.existsSync)(verityCreds)) {
25885
- (0, import_node_fs51.mkdirSync)((0, import_node_path34.join)(home, ".verity"), { recursive: true });
25929
+ const gateCreds = (0, import_node_path35.join)(home, ".gate", "credentials");
25930
+ const verityCreds = (0, import_node_path35.join)(home, ".verity", "credentials");
25931
+ if (!(0, import_node_fs52.existsSync)(gateCreds)) return;
25932
+ if (!(0, import_node_fs52.existsSync)(verityCreds)) {
25933
+ (0, import_node_fs52.mkdirSync)((0, import_node_path35.join)(home, ".verity"), { recursive: true });
25886
25934
  moveFile(gateCreds, verityCreds);
25887
25935
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
25888
25936
  return;
@@ -25904,8 +25952,8 @@ async function migrateLegacyHooks(root, actions) {
25904
25952
  }
25905
25953
  }
25906
25954
  async function migrateClaudeMd(root, actions) {
25907
- const claudeMd = (0, import_node_path34.join)(root, "CLAUDE.md");
25908
- const hadLegacyBlock = (0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
25955
+ const claudeMd = (0, import_node_path35.join)(root, "CLAUDE.md");
25956
+ const hadLegacyBlock = (0, import_node_fs52.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
25909
25957
  if (!hadLegacyBlock) return;
25910
25958
  try {
25911
25959
  await ensureClaudeMdPointer(root);
@@ -25915,9 +25963,9 @@ async function migrateClaudeMd(root, actions) {
25915
25963
  }
25916
25964
  }
25917
25965
  function migrateStandardFile(root, actions) {
25918
- const gateMd = (0, import_node_path34.join)(root, "GATE.md");
25919
- const verityMd = (0, import_node_path34.join)(root, "VERITY.md");
25920
- if (!(0, import_node_fs51.existsSync)(gateMd) || (0, import_node_fs51.existsSync)(verityMd)) return;
25966
+ const gateMd = (0, import_node_path35.join)(root, "GATE.md");
25967
+ const verityMd = (0, import_node_path35.join)(root, "VERITY.md");
25968
+ if (!(0, import_node_fs52.existsSync)(gateMd) || (0, import_node_fs52.existsSync)(verityMd)) return;
25921
25969
  let moved = false;
25922
25970
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
25923
25971
  try {
@@ -25929,12 +25977,12 @@ function migrateStandardFile(root, actions) {
25929
25977
  if (!moved) moveFile(gateMd, verityMd);
25930
25978
  const content = readFileSyncSafe(verityMd);
25931
25979
  const refreshed = content.split("GATE.md").join("VERITY.md");
25932
- if (refreshed !== content) (0, import_node_fs51.writeFileSync)(verityMd, refreshed);
25980
+ if (refreshed !== content) (0, import_node_fs52.writeFileSync)(verityMd, refreshed);
25933
25981
  actions.push("Renamed GATE.md \u2192 VERITY.md");
25934
25982
  }
25935
25983
  async function migrateTelemetryHeaders(root, actions) {
25936
- const file = (0, import_node_path34.join)(root, ".claude", "settings.local.json");
25937
- if (!(0, import_node_fs51.existsSync)(file)) return;
25984
+ const file = (0, import_node_path35.join)(root, ".claude", "settings.local.json");
25985
+ if (!(0, import_node_fs52.existsSync)(file)) return;
25938
25986
  let settings;
25939
25987
  try {
25940
25988
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -25982,14 +26030,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
25982
26030
  }
25983
26031
  if (toAppend.length > 0) {
25984
26032
  const sep3 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
25985
- (0, import_node_fs51.writeFileSync)(verityCreds, verityContent + sep3 + toAppend.join("\n") + "\n");
26033
+ (0, import_node_fs52.writeFileSync)(verityCreds, verityContent + sep3 + toAppend.join("\n") + "\n");
25986
26034
  }
25987
- (0, import_node_fs51.rmSync)(gateCreds, { force: true });
26035
+ (0, import_node_fs52.rmSync)(gateCreds, { force: true });
25988
26036
  return toAppend.length;
25989
26037
  }
25990
26038
  function readFileSyncSafe(path) {
25991
26039
  try {
25992
- return (0, import_node_fs51.readFileSync)(path, "utf-8");
26040
+ return (0, import_node_fs52.readFileSync)(path, "utf-8");
25993
26041
  } catch {
25994
26042
  return "";
25995
26043
  }
@@ -26004,35 +26052,35 @@ function hasStagedChanges(root) {
26004
26052
  }
26005
26053
  function moveDir(from, to) {
26006
26054
  try {
26007
- (0, import_node_fs51.renameSync)(from, to);
26055
+ (0, import_node_fs52.renameSync)(from, to);
26008
26056
  } catch (err) {
26009
26057
  if (err.code !== "EXDEV") throw err;
26010
- (0, import_node_fs51.cpSync)(from, to, { recursive: true });
26011
- (0, import_node_fs51.rmSync)(from, { recursive: true, force: true });
26058
+ (0, import_node_fs52.cpSync)(from, to, { recursive: true });
26059
+ (0, import_node_fs52.rmSync)(from, { recursive: true, force: true });
26012
26060
  }
26013
26061
  }
26014
26062
  function moveFile(from, to) {
26015
26063
  try {
26016
- (0, import_node_fs51.renameSync)(from, to);
26064
+ (0, import_node_fs52.renameSync)(from, to);
26017
26065
  } catch (err) {
26018
26066
  if (err.code !== "EXDEV") throw err;
26019
- (0, import_node_fs51.cpSync)(from, to);
26020
- (0, import_node_fs51.rmSync)(from, { force: true });
26067
+ (0, import_node_fs52.cpSync)(from, to);
26068
+ (0, import_node_fs52.rmSync)(from, { force: true });
26021
26069
  }
26022
26070
  }
26023
26071
  function carryLegacyContents(gateDir, verityDir) {
26024
26072
  let copied = 0;
26025
26073
  const walk2 = (relDir) => {
26026
- const srcDir = (0, import_node_path34.join)(gateDir, relDir);
26027
- for (const entry of (0, import_node_fs51.readdirSync)(srcDir)) {
26028
- const rel = relDir ? (0, import_node_path34.join)(relDir, entry) : entry;
26029
- const src = (0, import_node_path34.join)(gateDir, rel);
26030
- const dest = (0, import_node_path34.join)(verityDir, rel);
26031
- if ((0, import_node_fs51.statSync)(src).isDirectory()) {
26074
+ const srcDir = (0, import_node_path35.join)(gateDir, relDir);
26075
+ for (const entry of (0, import_node_fs52.readdirSync)(srcDir)) {
26076
+ const rel = relDir ? (0, import_node_path35.join)(relDir, entry) : entry;
26077
+ const src = (0, import_node_path35.join)(gateDir, rel);
26078
+ const dest = (0, import_node_path35.join)(verityDir, rel);
26079
+ if ((0, import_node_fs52.statSync)(src).isDirectory()) {
26032
26080
  walk2(rel);
26033
- } else if (!(0, import_node_fs51.existsSync)(dest)) {
26034
- (0, import_node_fs51.mkdirSync)((0, import_node_path34.dirname)(dest), { recursive: true });
26035
- (0, import_node_fs51.cpSync)(src, dest);
26081
+ } else if (!(0, import_node_fs52.existsSync)(dest)) {
26082
+ (0, import_node_fs52.mkdirSync)((0, import_node_path35.dirname)(dest), { recursive: true });
26083
+ (0, import_node_fs52.cpSync)(src, dest);
26036
26084
  copied++;
26037
26085
  }
26038
26086
  }
@@ -26041,22 +26089,22 @@ function carryLegacyContents(gateDir, verityDir) {
26041
26089
  return copied;
26042
26090
  }
26043
26091
  async function needsMigration(root = repoRoot()) {
26044
- const gateDir = (0, import_node_path34.join)(root, ".gate");
26045
- const verityDir = (0, import_node_path34.join)(root, ".verity");
26046
- if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) return true;
26047
- if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
26048
- if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(gateDir, "credentials")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(verityDir, "credentials"))) {
26092
+ const gateDir = (0, import_node_path35.join)(root, ".gate");
26093
+ const verityDir = (0, import_node_path35.join)(root, ".verity");
26094
+ if ((0, import_node_fs52.existsSync)(gateDir) && !(0, import_node_fs52.existsSync)(verityDir)) return true;
26095
+ if ((0, import_node_fs52.existsSync)(gateDir) && (0, import_node_fs52.existsSync)(verityDir)) {
26096
+ if ((0, import_node_fs52.existsSync)((0, import_node_path35.join)(gateDir, "credentials")) && !(0, import_node_fs52.existsSync)((0, import_node_path35.join)(verityDir, "credentials"))) {
26049
26097
  return true;
26050
26098
  }
26051
- if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(gateDir, "memory")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(verityDir, "memory"))) {
26099
+ if ((0, import_node_fs52.existsSync)((0, import_node_path35.join)(gateDir, "memory")) && !(0, import_node_fs52.existsSync)((0, import_node_path35.join)(verityDir, "memory"))) {
26052
26100
  return true;
26053
26101
  }
26054
26102
  }
26055
- const claudeMd = (0, import_node_path34.join)(root, "CLAUDE.md");
26056
- if ((0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
26103
+ const claudeMd = (0, import_node_path35.join)(root, "CLAUDE.md");
26104
+ if ((0, import_node_fs52.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
26057
26105
  return true;
26058
26106
  }
26059
- if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(root, "GATE.md")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(root, "VERITY.md"))) {
26107
+ if ((0, import_node_fs52.existsSync)((0, import_node_path35.join)(root, "GATE.md")) && !(0, import_node_fs52.existsSync)((0, import_node_path35.join)(root, "VERITY.md"))) {
26060
26108
  return true;
26061
26109
  }
26062
26110
  if (await hasLegacyHooksAt(root)) return true;
@@ -26337,9 +26385,9 @@ async function promptMultiSelect(question, choices, fallback) {
26337
26385
  }
26338
26386
 
26339
26387
  // src/lib/remote-config.ts
26340
- var import_node_fs52 = require("node:fs");
26388
+ var import_node_fs53 = require("node:fs");
26341
26389
  var import_promises16 = require("node:fs/promises");
26342
- var import_node_path35 = require("node:path");
26390
+ var import_node_path36 = require("node:path");
26343
26391
  var import_yaml5 = __toESM(require_dist());
26344
26392
  var IGNORE_RIDER = "verityignore";
26345
26393
  async function fetchRemoteSetup(opts) {
@@ -26384,7 +26432,7 @@ async function adoptRemoteSetup(found, opts) {
26384
26432
  written.push(STANDARD_FILE);
26385
26433
  if (rider !== null) {
26386
26434
  const localIgnore = projectPath(VERITYIGNORE_FILE);
26387
- if (!(0, import_node_fs52.existsSync)(localIgnore)) {
26435
+ if (!(0, import_node_fs53.existsSync)(localIgnore)) {
26388
26436
  await writeOut(VERITYIGNORE_FILE, rider);
26389
26437
  written.push(VERITYIGNORE_FILE);
26390
26438
  } else {
@@ -26415,9 +26463,9 @@ async function adoptRemoteSetup(found, opts) {
26415
26463
  written.push(VERITY_MD_FILE);
26416
26464
  return { written, notes };
26417
26465
  }
26418
- async function writeOut(relative2, body) {
26419
- const target = projectPath(relative2);
26420
- await (0, import_promises16.mkdir)((0, import_node_path35.dirname)(target), { recursive: true });
26466
+ async function writeOut(relative3, body) {
26467
+ const target = projectPath(relative3);
26468
+ await (0, import_promises16.mkdir)((0, import_node_path36.dirname)(target), { recursive: true });
26421
26469
  await (0, import_promises16.writeFile)(target, body);
26422
26470
  }
26423
26471
  function describeRemote(found) {
@@ -26534,15 +26582,15 @@ async function runOptionalAuth(resolution, opts = {}) {
26534
26582
  }
26535
26583
  function resolveDataDir2() {
26536
26584
  const candidates2 = [
26537
- (0, import_node_path36.join)(__dirname, "..", "data"),
26585
+ (0, import_node_path37.join)(__dirname, "..", "data"),
26538
26586
  // installed: node_modules/@codacy/verity-cli/data
26539
- (0, import_node_path36.join)(__dirname, "..", "..", "data"),
26587
+ (0, import_node_path37.join)(__dirname, "..", "..", "data"),
26540
26588
  // edge case: nested resolution
26541
- (0, import_node_path36.join)(process.cwd(), "cli", "data")
26589
+ (0, import_node_path37.join)(process.cwd(), "cli", "data")
26542
26590
  // local dev: running from repo root
26543
26591
  ];
26544
26592
  for (const candidate of candidates2) {
26545
- if ((0, import_node_fs53.existsSync)((0, import_node_path36.join)(candidate, "skills"))) {
26593
+ if ((0, import_node_fs54.existsSync)((0, import_node_path37.join)(candidate, "skills"))) {
26546
26594
  return candidate;
26547
26595
  }
26548
26596
  }
@@ -26558,9 +26606,9 @@ async function skillIsCurrent(src, dest) {
26558
26606
  const list2 = (dir) => {
26559
26607
  const out = [];
26560
26608
  const walk2 = (d, prefix) => {
26561
- for (const e of (0, import_node_fs53.readdirSync)(d, { withFileTypes: true })) {
26609
+ for (const e of (0, import_node_fs54.readdirSync)(d, { withFileTypes: true })) {
26562
26610
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
26563
- if (e.isDirectory()) walk2((0, import_node_path36.join)(d, e.name), rel);
26611
+ if (e.isDirectory()) walk2((0, import_node_path37.join)(d, e.name), rel);
26564
26612
  else if (e.isFile()) out.push(rel);
26565
26613
  }
26566
26614
  };
@@ -26571,8 +26619,8 @@ async function skillIsCurrent(src, dest) {
26571
26619
  const shipped = list2(src);
26572
26620
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
26573
26621
  for (const rel of shipped) {
26574
- const a = await (0, import_promises17.readFile)((0, import_node_path36.join)(src, rel), "utf-8");
26575
- const b = await (0, import_promises17.readFile)((0, import_node_path36.join)(dest, rel), "utf-8");
26622
+ const a = await (0, import_promises17.readFile)((0, import_node_path37.join)(src, rel), "utf-8");
26623
+ const b = await (0, import_promises17.readFile)((0, import_node_path37.join)(dest, rel), "utf-8");
26576
26624
  if (a !== b) return false;
26577
26625
  }
26578
26626
  return true;
@@ -26753,7 +26801,7 @@ async function synthesizeLocally(opts) {
26753
26801
  async function healStaleAnalysisConfig(globals) {
26754
26802
  const configPath = projectPath(CODACY_CONFIG_FILE);
26755
26803
  const standardPath = projectPath(STANDARD_FILE);
26756
- if (!(0, import_node_fs53.existsSync)(configPath) || !(0, import_node_fs53.existsSync)(standardPath)) return;
26804
+ if (!(0, import_node_fs54.existsSync)(configPath) || !(0, import_node_fs54.existsSync)(standardPath)) return;
26757
26805
  const validation = validatePatternIds();
26758
26806
  if (validation.status !== "invalid") return;
26759
26807
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -26850,17 +26898,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
26850
26898
  async function installSkills(force, step) {
26851
26899
  step("Installing skills");
26852
26900
  const dataDir = resolveDataDir2();
26853
- const skillsSource = (0, import_node_path36.join)(dataDir, "skills");
26901
+ const skillsSource = (0, import_node_path37.join)(dataDir, "skills");
26854
26902
  const skillsDest = ".claude/skills";
26855
26903
  let skillsInstalled = 0;
26856
26904
  for (const skill of SKILLS) {
26857
- const src = (0, import_node_path36.join)(skillsSource, skill);
26858
- const dest = (0, import_node_path36.join)(skillsDest, skill);
26859
- if (!(0, import_node_fs53.existsSync)(src)) {
26905
+ const src = (0, import_node_path37.join)(skillsSource, skill);
26906
+ const dest = (0, import_node_path37.join)(skillsDest, skill);
26907
+ if (!(0, import_node_fs54.existsSync)(src)) {
26860
26908
  printWarn(` Skill data not found: ${skill}`);
26861
26909
  continue;
26862
26910
  }
26863
- if ((0, import_node_fs53.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
26911
+ if ((0, import_node_fs54.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
26864
26912
  skillsInstalled++;
26865
26913
  continue;
26866
26914
  }
@@ -26999,7 +27047,7 @@ function registerInitCommand(program2) {
26999
27047
  const staleMarker = clearStalePluginMarker();
27000
27048
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
27001
27049
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
27002
- const isProject = projectMarkers.some((m) => (0, import_node_fs53.existsSync)(m));
27050
+ const isProject = projectMarkers.some((m) => (0, import_node_fs54.existsSync)(m));
27003
27051
  if (!isProject) {
27004
27052
  printError("No project detected in the current directory.");
27005
27053
  printInfo('Run "verity init" from your project root.');
@@ -27089,7 +27137,7 @@ function registerInitCommand(program2) {
27089
27137
  printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
27090
27138
  }
27091
27139
  await scaffoldProject(step, defaultsOnly);
27092
- const globalVerityDir = (0, import_node_path36.join)(process.env.HOME ?? "", ".verity");
27140
+ const globalVerityDir = (0, import_node_path37.join)(process.env.HOME ?? "", ".verity");
27093
27141
  await (0, import_promises17.mkdir)(globalVerityDir, { recursive: true });
27094
27142
  console.log("");
27095
27143
  step("Wiring Claude Code hooks");
@@ -27158,7 +27206,7 @@ function registerInitCommand(program2) {
27158
27206
  }
27159
27207
  step("Your project's Standard");
27160
27208
  let haveStandard = false;
27161
- if ((0, import_node_fs53.existsSync)(projectPath(STANDARD_FILE))) {
27209
+ if ((0, import_node_fs54.existsSync)(projectPath(STANDARD_FILE))) {
27162
27210
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
27163
27211
  haveStandard = true;
27164
27212
  } else {
@@ -27188,7 +27236,7 @@ function registerInitCommand(program2) {
27188
27236
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
27189
27237
  init: {
27190
27238
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
27191
- cli_version: true ? "0.32.6" : "dev"
27239
+ cli_version: true ? "0.32.7" : "dev"
27192
27240
  }
27193
27241
  });
27194
27242
  } catch (err) {
@@ -27238,8 +27286,8 @@ function registerInitCommand(program2) {
27238
27286
  }
27239
27287
 
27240
27288
  // src/commands/uninstall.ts
27241
- var import_node_fs54 = require("node:fs");
27242
- var import_node_path37 = require("node:path");
27289
+ var import_node_fs55 = require("node:fs");
27290
+ var import_node_path38 = require("node:path");
27243
27291
  function registerUninstallCommand(program2) {
27244
27292
  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) => {
27245
27293
  const dryRun = opts.dryRun ?? false;
@@ -27248,11 +27296,11 @@ function registerUninstallCommand(program2) {
27248
27296
  const actions = [];
27249
27297
  const skillsRoot = projectPath(".claude/skills");
27250
27298
  for (const name of PROJECT_SKILL_NAMES) {
27251
- const dir = (0, import_node_path37.join)(skillsRoot, name);
27252
- if ((0, import_node_fs54.existsSync)(dir)) {
27299
+ const dir = (0, import_node_path38.join)(skillsRoot, name);
27300
+ if ((0, import_node_fs55.existsSync)(dir)) {
27253
27301
  actions.push({
27254
27302
  label: `Remove .claude/skills/${name}/`,
27255
- apply: () => (0, import_node_fs54.rmSync)(dir, { recursive: true, force: true })
27303
+ apply: () => (0, import_node_fs55.rmSync)(dir, { recursive: true, force: true })
27256
27304
  });
27257
27305
  }
27258
27306
  }
@@ -27266,24 +27314,24 @@ function registerUninstallCommand(program2) {
27266
27314
  });
27267
27315
  }
27268
27316
  const verityDir = projectPath(VERITY_DIR);
27269
- if ((0, import_node_fs54.existsSync)(verityDir)) {
27317
+ if ((0, import_node_fs55.existsSync)(verityDir)) {
27270
27318
  actions.push({
27271
27319
  label: `Remove ${VERITY_DIR}/`,
27272
- apply: () => (0, import_node_fs54.rmSync)(verityDir, { recursive: true, force: true })
27320
+ apply: () => (0, import_node_fs55.rmSync)(verityDir, { recursive: true, force: true })
27273
27321
  });
27274
27322
  }
27275
27323
  if (!keepVerityMd) {
27276
27324
  const verityMd = projectPath(VERITY_MD_FILE);
27277
- if ((0, import_node_fs54.existsSync)(verityMd)) {
27325
+ if ((0, import_node_fs55.existsSync)(verityMd)) {
27278
27326
  actions.push({
27279
27327
  label: `Remove ${VERITY_MD_FILE}`,
27280
- apply: () => (0, import_node_fs54.rmSync)(verityMd, { force: true })
27328
+ apply: () => (0, import_node_fs55.rmSync)(verityMd, { force: true })
27281
27329
  });
27282
27330
  }
27283
27331
  }
27284
27332
  const cleanupEmptyDir = (path) => {
27285
- if ((0, import_node_fs54.existsSync)(path) && (0, import_node_fs54.statSync)(path).isDirectory() && (0, import_node_fs54.readdirSync)(path).length === 0) {
27286
- (0, import_node_fs54.rmdirSync)(path);
27333
+ if ((0, import_node_fs55.existsSync)(path) && (0, import_node_fs55.statSync)(path).isDirectory() && (0, import_node_fs55.readdirSync)(path).length === 0) {
27334
+ (0, import_node_fs55.rmdirSync)(path);
27287
27335
  }
27288
27336
  };
27289
27337
  actions.push({
@@ -27294,11 +27342,11 @@ function registerUninstallCommand(program2) {
27294
27342
  }
27295
27343
  });
27296
27344
  const home = process.env.HOME ?? "";
27297
- const globalVerityDir = (0, import_node_path37.join)(home, ".verity");
27298
- if (purgeGlobal && (0, import_node_fs54.existsSync)(globalVerityDir)) {
27345
+ const globalVerityDir = (0, import_node_path38.join)(home, ".verity");
27346
+ if (purgeGlobal && (0, import_node_fs55.existsSync)(globalVerityDir)) {
27299
27347
  actions.push({
27300
27348
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
27301
- apply: () => (0, import_node_fs54.rmSync)(globalVerityDir, { recursive: true, force: true })
27349
+ apply: () => (0, import_node_fs55.rmSync)(globalVerityDir, { recursive: true, force: true })
27302
27350
  });
27303
27351
  }
27304
27352
  if (actions.length === 0) {
@@ -27492,8 +27540,8 @@ function registerTaskCommands(program2) {
27492
27540
  }
27493
27541
 
27494
27542
  // src/commands/reset.ts
27495
- var import_node_fs55 = require("node:fs");
27496
- var import_node_path38 = require("node:path");
27543
+ var import_node_fs56 = require("node:fs");
27544
+ var import_node_path39 = require("node:path");
27497
27545
  function registerResetCommand(program2) {
27498
27546
  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) => {
27499
27547
  const globals = program2.opts();
@@ -27530,11 +27578,11 @@ function registerResetCommand(program2) {
27530
27578
  }
27531
27579
  const cacheDir = projectPath(CACHE_DIR);
27532
27580
  let purged = 0;
27533
- if ((0, import_node_fs55.existsSync)(cacheDir)) {
27534
- for (const entry of (0, import_node_fs55.readdirSync)(cacheDir)) {
27581
+ if ((0, import_node_fs56.existsSync)(cacheDir)) {
27582
+ for (const entry of (0, import_node_fs56.readdirSync)(cacheDir)) {
27535
27583
  if (entry.startsWith("pending-")) {
27536
27584
  try {
27537
- (0, import_node_fs55.unlinkSync)((0, import_node_path38.join)(cacheDir, entry));
27585
+ (0, import_node_fs56.unlinkSync)((0, import_node_path39.join)(cacheDir, entry));
27538
27586
  purged++;
27539
27587
  } catch {
27540
27588
  }
@@ -27549,19 +27597,19 @@ function registerResetCommand(program2) {
27549
27597
  projectPath(`${VERITY_DIR}/.last-analysis`)
27550
27598
  ];
27551
27599
  for (const file of filesToClear) {
27552
- if ((0, import_node_fs55.existsSync)(file)) {
27600
+ if ((0, import_node_fs56.existsSync)(file)) {
27553
27601
  try {
27554
- (0, import_node_fs55.writeFileSync)(file, "");
27602
+ (0, import_node_fs56.writeFileSync)(file, "");
27555
27603
  } catch {
27556
27604
  }
27557
27605
  }
27558
27606
  }
27559
27607
  if (opts.all) {
27560
27608
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
27561
- if ((0, import_node_fs55.existsSync)(logsDir)) {
27562
- for (const entry of (0, import_node_fs55.readdirSync)(logsDir)) {
27609
+ if ((0, import_node_fs56.existsSync)(logsDir)) {
27610
+ for (const entry of (0, import_node_fs56.readdirSync)(logsDir)) {
27563
27611
  try {
27564
- (0, import_node_fs55.unlinkSync)((0, import_node_path38.join)(logsDir, entry));
27612
+ (0, import_node_fs56.unlinkSync)((0, import_node_path39.join)(logsDir, entry));
27565
27613
  } catch {
27566
27614
  }
27567
27615
  }
@@ -27921,8 +27969,8 @@ function registerTelemetryCommands(program2) {
27921
27969
  }
27922
27970
 
27923
27971
  // src/cli.ts
27924
- program.name("verity").description("CLI for Verity quality gate service").version("0.32.6").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) => {
27925
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.6");
27972
+ program.name("verity").description("CLI for Verity quality gate service").version("0.32.7").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) => {
27973
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.7");
27926
27974
  setUserNamedServiceUrl(program.opts().serviceUrl);
27927
27975
  try {
27928
27976
  await foldLegacyLocalCredential();