@codacy/verity-cli 0.33.0-experimental.d60f544 → 0.33.0

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 +852 -668
  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;
@@ -10523,7 +10524,7 @@ var SECURITY_PATTERNS = [
10523
10524
  /Dockerfile/
10524
10525
  ];
10525
10526
  var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
10526
- var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
10527
+ var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
10527
10528
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
10528
10529
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
10529
10530
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -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,20 +13875,20 @@ async function appendEntry(taskId, entry) {
13847
13875
 
13848
13876
  // src/lib/memory-retrieval.ts
13849
13877
  var import_promises8 = require("node:fs/promises");
13850
- var import_node_fs11 = require("node:fs");
13851
- var import_node_path11 = require("node:path");
13878
+ var import_node_fs12 = require("node:fs");
13879
+ var import_node_path12 = require("node:path");
13852
13880
 
13853
13881
  // src/lib/org-mirror.ts
13854
- var import_node_fs10 = require("node:fs");
13882
+ var import_node_fs11 = require("node:fs");
13855
13883
  var import_promises7 = require("node:fs/promises");
13856
- var import_node_path10 = require("node:path");
13884
+ var import_node_path11 = require("node:path");
13857
13885
  var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
13858
13886
  var STATE_FILE = ".org-pull-state.json";
13859
13887
  var BODY_MAX = 8192;
13860
13888
  function orgMirrorDir(remote = requestRemote()) {
13861
13889
  const parsed = parseRemote(remote);
13862
13890
  if (!parsed) return null;
13863
- return (0, import_node_path10.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
13891
+ return (0, import_node_path11.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
13864
13892
  }
13865
13893
  function slugify(s) {
13866
13894
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
@@ -13926,7 +13954,7 @@ function parseOrgNode(content) {
13926
13954
  }
13927
13955
  async function readState(dir) {
13928
13956
  try {
13929
- const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path10.join)(dir, STATE_FILE), "utf-8"));
13957
+ const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path11.join)(dir, STATE_FILE), "utf-8"));
13930
13958
  return {
13931
13959
  version: typeof parsed?.version === "string" ? parsed.version : null,
13932
13960
  organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
@@ -13938,7 +13966,7 @@ async function readState(dir) {
13938
13966
  }
13939
13967
  async function writeState(dir, state) {
13940
13968
  await (0, import_promises7.mkdir)(dir, { recursive: true });
13941
- await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, STATE_FILE), JSON.stringify({
13969
+ await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, STATE_FILE), JSON.stringify({
13942
13970
  ...state.version ? { version: state.version } : {},
13943
13971
  organization: state.organization,
13944
13972
  pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -14003,24 +14031,24 @@ async function pullOrgKnowledge(opts) {
14003
14031
  for (const n of nodes) {
14004
14032
  const rel = orgNodePath(n);
14005
14033
  if (written.has(rel)) continue;
14006
- await (0, import_promises7.mkdir)((0, import_node_path10.join)(dir, rel.split("/")[0]), { recursive: true });
14007
- await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
14034
+ await (0, import_promises7.mkdir)((0, import_node_path11.join)(dir, rel.split("/")[0]), { recursive: true });
14035
+ await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
14008
14036
  written.add(rel);
14009
14037
  }
14010
14038
  for (const rel of state.files) {
14011
- if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path10.join)(dir, rel), { force: true });
14039
+ if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path11.join)(dir, rel), { force: true });
14012
14040
  }
14013
- await (0, import_promises7.writeFile)((0, import_node_path10.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
14041
+ await (0, import_promises7.writeFile)((0, import_node_path11.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
14014
14042
  await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
14015
14043
  return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
14016
14044
  }
14017
14045
  async function readOrgMirror(remote = requestRemote()) {
14018
14046
  const dir = orgMirrorDir(remote);
14019
- if (!dir || !(0, import_node_fs10.existsSync)(dir)) return [];
14047
+ if (!dir || !(0, import_node_fs11.existsSync)(dir)) return [];
14020
14048
  const out = [];
14021
14049
  for (const kind of ORG_KINDS) {
14022
- const kindDir = (0, import_node_path10.join)(dir, kind);
14023
- if (!(0, import_node_fs10.existsSync)(kindDir)) continue;
14050
+ const kindDir = (0, import_node_path11.join)(dir, kind);
14051
+ if (!(0, import_node_fs11.existsSync)(kindDir)) continue;
14024
14052
  let files;
14025
14053
  try {
14026
14054
  files = await (0, import_promises7.readdir)(kindDir);
@@ -14030,7 +14058,7 @@ async function readOrgMirror(remote = requestRemote()) {
14030
14058
  for (const file of files) {
14031
14059
  if (!file.endsWith(".md")) continue;
14032
14060
  try {
14033
- const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path10.join)(kindDir, file), "utf-8"));
14061
+ const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path11.join)(kindDir, file), "utf-8"));
14034
14062
  if (node) out.push(node);
14035
14063
  } catch {
14036
14064
  }
@@ -14153,19 +14181,19 @@ function parseFrontmatter(content) {
14153
14181
  return { fm, body: match[2].trim() };
14154
14182
  }
14155
14183
  async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
14156
- const hasRepoGraph = (0, import_node_fs11.existsSync)(memoryDir());
14184
+ const hasRepoGraph = (0, import_node_fs12.existsSync)(memoryDir());
14157
14185
  const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
14158
14186
  const promptTokens = tokenize(promptText);
14159
14187
  const nodes = [];
14160
14188
  for (const domain of hasRepoGraph ? DOMAINS : []) {
14161
- const domainDir = (0, import_node_path11.join)(memoryDir(), domain);
14162
- if (!(0, import_node_fs11.existsSync)(domainDir)) continue;
14189
+ const domainDir = (0, import_node_path12.join)(memoryDir(), domain);
14190
+ if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
14163
14191
  try {
14164
14192
  const files = await (0, import_promises8.readdir)(domainDir);
14165
14193
  for (const file of files) {
14166
14194
  if (!file.endsWith(".md")) continue;
14167
14195
  try {
14168
- const content = await (0, import_promises8.readFile)((0, import_node_path11.join)(domainDir, file), "utf-8");
14196
+ const content = await (0, import_promises8.readFile)((0, import_node_path12.join)(domainDir, file), "utf-8");
14169
14197
  const { fm, body } = parseFrontmatter(content);
14170
14198
  if (fm.status && fm.status !== "active") continue;
14171
14199
  nodes.push({
@@ -14232,13 +14260,13 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
14232
14260
 
14233
14261
  // src/lib/memory-sync.ts
14234
14262
  var import_promises9 = require("node:fs/promises");
14235
- var import_node_fs14 = require("node:fs");
14236
- var import_node_path13 = require("node:path");
14263
+ var import_node_fs15 = require("node:fs");
14264
+ var import_node_path14 = require("node:path");
14237
14265
  var import_node_crypto3 = require("node:crypto");
14238
14266
 
14239
14267
  // src/lib/gitignore.ts
14240
14268
  var import_node_child_process6 = require("node:child_process");
14241
- var import_node_fs12 = require("node:fs");
14269
+ var import_node_fs13 = require("node:fs");
14242
14270
  var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
14243
14271
  var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
14244
14272
  var VERITY_GITIGNORE_BLOCK = [
@@ -14322,7 +14350,7 @@ function fenceMemoryLines(lines) {
14322
14350
  function ensureVerityGitignore() {
14323
14351
  let content = "";
14324
14352
  try {
14325
- content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14353
+ content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
14326
14354
  } catch {
14327
14355
  }
14328
14356
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14349,7 +14377,7 @@ function ensureVerityGitignore() {
14349
14377
  const sep4 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
14350
14378
  text = text + sep4 + VERITY_GITIGNORE_BLOCK;
14351
14379
  }
14352
- if (text !== content) (0, import_node_fs12.writeFileSync)(".gitignore", text);
14380
+ if (text !== content) (0, import_node_fs13.writeFileSync)(".gitignore", text);
14353
14381
  return verified(
14354
14382
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
14355
14383
  );
@@ -14369,7 +14397,7 @@ function untrackMemory() {
14369
14397
  function writeFencedBlock() {
14370
14398
  let content = "";
14371
14399
  try {
14372
- content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14400
+ content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
14373
14401
  } catch {
14374
14402
  }
14375
14403
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14381,7 +14409,7 @@ function writeFencedBlock() {
14381
14409
  text = text + sep4 + VERITY_GITIGNORE_BLOCK;
14382
14410
  }
14383
14411
  try {
14384
- (0, import_node_fs12.writeFileSync)(".gitignore", text);
14412
+ (0, import_node_fs13.writeFileSync)(".gitignore", text);
14385
14413
  return true;
14386
14414
  } catch {
14387
14415
  return false;
@@ -14390,14 +14418,14 @@ function writeFencedBlock() {
14390
14418
  function fenceMemory() {
14391
14419
  let original = null;
14392
14420
  try {
14393
- original = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14421
+ original = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
14394
14422
  } catch {
14395
14423
  original = null;
14396
14424
  }
14397
14425
  const restore = () => {
14398
14426
  try {
14399
- if (original === null) (0, import_node_fs12.rmSync)(".gitignore", { force: true });
14400
- else (0, import_node_fs12.writeFileSync)(".gitignore", original);
14427
+ if (original === null) (0, import_node_fs13.rmSync)(".gitignore", { force: true });
14428
+ else (0, import_node_fs13.writeFileSync)(".gitignore", original);
14401
14429
  } catch {
14402
14430
  }
14403
14431
  };
@@ -14415,7 +14443,7 @@ function fenceMemory() {
14415
14443
  }
14416
14444
  function memoryOptOut() {
14417
14445
  try {
14418
- return (0, import_node_fs12.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14446
+ return (0, import_node_fs13.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14419
14447
  } catch {
14420
14448
  return false;
14421
14449
  }
@@ -14423,13 +14451,13 @@ function memoryOptOut() {
14423
14451
  function keepMemoryTracked() {
14424
14452
  let content = "";
14425
14453
  try {
14426
- content = (0, import_node_fs12.readFileSync)(".gitignore", "utf-8");
14454
+ content = (0, import_node_fs13.readFileSync)(".gitignore", "utf-8");
14427
14455
  } catch {
14428
14456
  }
14429
14457
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
14430
14458
  try {
14431
14459
  const sep4 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
14432
- (0, import_node_fs12.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
14460
+ (0, import_node_fs13.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
14433
14461
  } catch {
14434
14462
  return "failed";
14435
14463
  }
@@ -14464,26 +14492,26 @@ function untrackVerityState() {
14464
14492
  }
14465
14493
 
14466
14494
  // src/lib/safe-path.ts
14467
- var import_node_fs13 = require("node:fs");
14468
- var import_node_path12 = require("node:path");
14495
+ var import_node_fs14 = require("node:fs");
14496
+ var import_node_path13 = require("node:path");
14469
14497
  function resolveInside(baseDir, candidate) {
14470
14498
  if (typeof candidate !== "string" || candidate.length === 0) return null;
14471
- if ((0, import_node_path12.isAbsolute)(candidate)) return null;
14472
- const baseAbs = (0, import_node_path12.resolve)(baseDir);
14473
- const full = (0, import_node_path12.resolve)(baseAbs, candidate);
14474
- const baseSep = baseAbs.endsWith(import_node_path12.sep) ? baseAbs : baseAbs + import_node_path12.sep;
14499
+ if ((0, import_node_path13.isAbsolute)(candidate)) return null;
14500
+ const baseAbs = (0, import_node_path13.resolve)(baseDir);
14501
+ const full = (0, import_node_path13.resolve)(baseAbs, candidate);
14502
+ const baseSep = baseAbs.endsWith(import_node_path13.sep) ? baseAbs : baseAbs + import_node_path13.sep;
14475
14503
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
14476
14504
  try {
14477
- if ((0, import_node_fs13.existsSync)(baseAbs)) {
14478
- const realBase = (0, import_node_fs13.realpathSync)(baseAbs);
14479
- const realBaseSep = realBase.endsWith(import_node_path12.sep) ? realBase : realBase + import_node_path12.sep;
14505
+ if ((0, import_node_fs14.existsSync)(baseAbs)) {
14506
+ const realBase = (0, import_node_fs14.realpathSync)(baseAbs);
14507
+ const realBaseSep = realBase.endsWith(import_node_path13.sep) ? realBase : realBase + import_node_path13.sep;
14480
14508
  let probe = full;
14481
- while (!(0, import_node_fs13.existsSync)(probe)) {
14482
- const parent = (0, import_node_path12.dirname)(probe);
14509
+ while (!(0, import_node_fs14.existsSync)(probe)) {
14510
+ const parent = (0, import_node_path13.dirname)(probe);
14483
14511
  if (parent === probe) break;
14484
14512
  probe = parent;
14485
14513
  }
14486
- const realProbe = (0, import_node_fs13.realpathSync)(probe);
14514
+ const realProbe = (0, import_node_fs14.realpathSync)(probe);
14487
14515
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
14488
14516
  }
14489
14517
  } catch {
@@ -14491,6 +14519,42 @@ function resolveInside(baseDir, candidate) {
14491
14519
  }
14492
14520
  return full;
14493
14521
  }
14522
+ var O_NOFOLLOW = typeof import_node_fs14.constants.O_NOFOLLOW === "number" ? import_node_fs14.constants.O_NOFOLLOW : 0;
14523
+ function readFileInside(baseDir, candidate, maxBytes) {
14524
+ const full = resolveInside(baseDir, candidate);
14525
+ if (!full) return null;
14526
+ let realParent;
14527
+ let realBase;
14528
+ try {
14529
+ realParent = (0, import_node_fs14.realpathSync)((0, import_node_path13.dirname)(full));
14530
+ realBase = (0, import_node_fs14.realpathSync)((0, import_node_path13.resolve)(baseDir));
14531
+ } catch {
14532
+ return null;
14533
+ }
14534
+ const realBaseSep = realBase.endsWith(import_node_path13.sep) ? realBase : realBase + import_node_path13.sep;
14535
+ if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
14536
+ const target = (0, import_node_path13.join)(realParent, (0, import_node_path13.basename)(full));
14537
+ let fd = null;
14538
+ try {
14539
+ fd = (0, import_node_fs14.openSync)(target, import_node_fs14.constants.O_RDONLY | O_NOFOLLOW);
14540
+ const st = (0, import_node_fs14.fstatSync)(fd);
14541
+ if (!st.isFile()) return null;
14542
+ const cap = Math.min(maxBytes, st.size);
14543
+ if (cap <= 0) return "";
14544
+ const buf = Buffer.alloc(cap);
14545
+ const bytesRead = (0, import_node_fs14.readSync)(fd, buf, 0, cap, 0);
14546
+ return buf.subarray(0, bytesRead).toString("utf-8");
14547
+ } catch {
14548
+ return null;
14549
+ } finally {
14550
+ if (fd !== null) {
14551
+ try {
14552
+ (0, import_node_fs14.closeSync)(fd);
14553
+ } catch {
14554
+ }
14555
+ }
14556
+ }
14557
+ }
14494
14558
 
14495
14559
  // src/lib/glob-match.ts
14496
14560
  function globToRegex(glob) {
@@ -14568,32 +14632,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
14568
14632
  async function ensureMemoryDir() {
14569
14633
  await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
14570
14634
  for (const domain of DOMAINS2) {
14571
- await (0, import_promises9.mkdir)((0, import_node_path13.join)(memoryDir2(), domain), { recursive: true });
14635
+ await (0, import_promises9.mkdir)((0, import_node_path14.join)(memoryDir2(), domain), { recursive: true });
14572
14636
  }
14573
- if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "SCHEMA.md"))) {
14574
- await (0, import_promises9.writeFile)((0, import_node_path13.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14637
+ if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "SCHEMA.md"))) {
14638
+ await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14575
14639
  }
14576
- if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "index.md"))) {
14577
- await (0, import_promises9.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");
14640
+ if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "index.md"))) {
14641
+ await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
14578
14642
  }
14579
- if (!(0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "log.md"))) {
14580
- await (0, import_promises9.writeFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14643
+ if (!(0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "log.md"))) {
14644
+ await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14581
14645
  }
14582
14646
  }
14583
14647
  async function buildManifest() {
14584
- if (!(0, import_node_fs14.existsSync)(memoryDir2())) {
14648
+ if (!(0, import_node_fs15.existsSync)(memoryDir2())) {
14585
14649
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
14586
14650
  }
14587
14651
  const nodes = [];
14588
14652
  for (const domain of DOMAINS2) {
14589
- const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14590
- if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14653
+ const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
14654
+ if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
14591
14655
  try {
14592
14656
  const files = await (0, import_promises9.readdir)(domainDir);
14593
14657
  for (const file of files) {
14594
14658
  if (!file.endsWith(".md")) continue;
14595
14659
  const filePath = `${domain}/${file}`;
14596
- const fullPath = (0, import_node_path13.join)(memoryDir2(), filePath);
14660
+ const fullPath = (0, import_node_path14.join)(memoryDir2(), filePath);
14597
14661
  try {
14598
14662
  const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
14599
14663
  const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
@@ -14606,13 +14670,13 @@ async function buildManifest() {
14606
14670
  }
14607
14671
  let indexHash = null;
14608
14672
  try {
14609
- const indexContent = await (0, import_promises9.readFile)((0, import_node_path13.join)(memoryDir2(), "index.md"), "utf-8");
14673
+ const indexContent = await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "index.md"), "utf-8");
14610
14674
  indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
14611
14675
  } catch {
14612
14676
  }
14613
14677
  let logLength = 0;
14614
14678
  try {
14615
- const logContent = await (0, import_promises9.readFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "utf-8");
14679
+ const logContent = await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "utf-8");
14616
14680
  logLength = logContent.split("\n").length;
14617
14681
  } catch {
14618
14682
  }
@@ -14623,15 +14687,15 @@ function hashContent(content) {
14623
14687
  }
14624
14688
  async function readOnDiskNodes() {
14625
14689
  const out = /* @__PURE__ */ new Map();
14626
- if (!(0, import_node_fs14.existsSync)(memoryDir2())) return out;
14690
+ if (!(0, import_node_fs15.existsSync)(memoryDir2())) return out;
14627
14691
  for (const domain of DOMAINS2) {
14628
- const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14629
- if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14692
+ const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
14693
+ if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
14630
14694
  try {
14631
14695
  for (const file of await (0, import_promises9.readdir)(domainDir)) {
14632
14696
  if (!file.endsWith(".md")) continue;
14633
14697
  try {
14634
- out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8")));
14698
+ out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path14.join)(domainDir, file), "utf-8")));
14635
14699
  } catch {
14636
14700
  }
14637
14701
  }
@@ -14668,7 +14732,7 @@ async function recordSyncedNodePaths() {
14668
14732
  }
14669
14733
  }
14670
14734
  async function writeFileAtomic(path, content) {
14671
- await (0, import_promises9.mkdir)((0, import_node_path13.dirname)(path), { recursive: true });
14735
+ await (0, import_promises9.mkdir)((0, import_node_path14.dirname)(path), { recursive: true });
14672
14736
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
14673
14737
  await (0, import_promises9.writeFile)(tmp, content);
14674
14738
  await (0, import_promises9.rename)(tmp, path);
@@ -14682,8 +14746,8 @@ async function computeEditedNodeUploads() {
14682
14746
  const uploads = [];
14683
14747
  for (const [path, prevHash] of prev) {
14684
14748
  if (prevHash == null) continue;
14685
- const full = (0, import_node_path13.join)(memoryDir2(), path);
14686
- if (!(0, import_node_fs14.existsSync)(full)) continue;
14749
+ const full = (0, import_node_path14.join)(memoryDir2(), path);
14750
+ if (!(0, import_node_fs15.existsSync)(full)) continue;
14687
14751
  let content;
14688
14752
  try {
14689
14753
  content = await (0, import_promises9.readFile)(full, "utf-8");
@@ -14727,8 +14791,8 @@ async function applyMemoryWrites(writes, opts = {}) {
14727
14791
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
14728
14792
  for (const n of notes) logLines.push(` - ${n}`);
14729
14793
  try {
14730
- const existing = (0, import_node_fs14.existsSync)((0, import_node_path13.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14731
- await (0, import_promises9.writeFile)((0, import_node_path13.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14794
+ const existing = (0, import_node_fs15.existsSync)((0, import_node_path14.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14795
+ await (0, import_promises9.writeFile)((0, import_node_path14.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14732
14796
  } catch {
14733
14797
  }
14734
14798
  if (opts.baseline === "written") await mergeSyncBaseline(synced);
@@ -14738,7 +14802,7 @@ async function applyMemoryWrites(writes, opts = {}) {
14738
14802
  async function mergeSyncBaseline(entries) {
14739
14803
  if (entries.size === 0) return;
14740
14804
  try {
14741
- if ((0, import_node_fs14.existsSync)(syncStateFile())) {
14805
+ if ((0, import_node_fs15.existsSync)(syncStateFile())) {
14742
14806
  try {
14743
14807
  JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
14744
14808
  } catch {
@@ -14766,7 +14830,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
14766
14830
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
14767
14831
  }
14768
14832
  }
14769
- if ((0, import_node_fs14.existsSync)(fullPath)) {
14833
+ if ((0, import_node_fs15.existsSync)(fullPath)) {
14770
14834
  let existing = "";
14771
14835
  try {
14772
14836
  existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
@@ -14782,7 +14846,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
14782
14846
  notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
14783
14847
  }
14784
14848
  }
14785
- await (0, import_promises9.mkdir)((0, import_node_path13.dirname)(fullPath), { recursive: true });
14849
+ await (0, import_promises9.mkdir)((0, import_node_path14.dirname)(fullPath), { recursive: true });
14786
14850
  await (0, import_promises9.writeFile)(fullPath, content);
14787
14851
  return { written: true, syncedHash: hashContent(content), notes };
14788
14852
  }
@@ -14823,8 +14887,8 @@ async function regenerateIndex() {
14823
14887
  ];
14824
14888
  let totalNodes = 0;
14825
14889
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
14826
- const domainDir = (0, import_node_path13.join)(memoryDir2(), domain);
14827
- if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14890
+ const domainDir = (0, import_node_path14.join)(memoryDir2(), domain);
14891
+ if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
14828
14892
  try {
14829
14893
  const files = await (0, import_promises9.readdir)(domainDir);
14830
14894
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -14834,7 +14898,7 @@ async function regenerateIndex() {
14834
14898
  for (const file of mdFiles.sort()) {
14835
14899
  const slug = file.replace(/\.md$/, "");
14836
14900
  try {
14837
- const content = await (0, import_promises9.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8");
14901
+ const content = await (0, import_promises9.readFile)((0, import_node_path14.join)(domainDir, file), "utf-8");
14838
14902
  const title = pickFrontmatter(content, "title") ?? slug;
14839
14903
  const kind = pickFrontmatter(content, "kind") ?? "-";
14840
14904
  const confidence = pickFrontmatter(content, "confidence");
@@ -14858,7 +14922,7 @@ async function regenerateIndex() {
14858
14922
  lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
14859
14923
  }
14860
14924
  const next = lines.join("\n") + "\n";
14861
- const indexPath = (0, import_node_path13.join)(memoryDir2(), "index.md");
14925
+ const indexPath = (0, import_node_path14.join)(memoryDir2(), "index.md");
14862
14926
  let existing = null;
14863
14927
  try {
14864
14928
  existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
@@ -15255,9 +15319,9 @@ function hasLegacyMemoryBlock(text) {
15255
15319
  return findMarker(text, LEGACY_MD_START) !== -1;
15256
15320
  }
15257
15321
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
15258
- const claudeMdPath = (0, import_node_path13.join)(cwd, "CLAUDE.md");
15322
+ const claudeMdPath = (0, import_node_path14.join)(cwd, "CLAUDE.md");
15259
15323
  let existing = "";
15260
- if ((0, import_node_fs14.existsSync)(claudeMdPath)) {
15324
+ if ((0, import_node_fs15.existsSync)(claudeMdPath)) {
15261
15325
  existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
15262
15326
  }
15263
15327
  let startTag = CLAUDE_MD_START;
@@ -15398,9 +15462,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
15398
15462
  `;
15399
15463
 
15400
15464
  // src/lib/dossier-session.ts
15401
- var import_node_fs19 = require("node:fs");
15465
+ var import_node_fs20 = require("node:fs");
15402
15466
  var import_node_crypto7 = require("node:crypto");
15403
- var import_node_path16 = require("node:path");
15467
+ var import_node_path17 = require("node:path");
15404
15468
 
15405
15469
  // src/lib/pending-repeat.ts
15406
15470
  var STOP = /* @__PURE__ */ new Set([
@@ -15505,8 +15569,8 @@ function statementAnchorKey(file, patternId) {
15505
15569
 
15506
15570
  // src/lib/dossier/log.ts
15507
15571
  var import_node_crypto4 = require("node:crypto");
15508
- var import_node_fs15 = require("node:fs");
15509
- var import_node_path14 = require("node:path");
15572
+ var import_node_fs16 = require("node:fs");
15573
+ var import_node_path15 = require("node:path");
15510
15574
  var CRC_TABLE = (() => {
15511
15575
  const t = new Int32Array(256);
15512
15576
  for (let i = 0; i < 256; i++) {
@@ -15525,13 +15589,13 @@ function crc32(s) {
15525
15589
  function openDossier(identity) {
15526
15590
  try {
15527
15591
  const dir = dossierDir(identity);
15528
- (0, import_node_fs15.mkdirSync)(dir, { recursive: true, mode: 448 });
15592
+ (0, import_node_fs16.mkdirSync)(dir, { recursive: true, mode: 448 });
15529
15593
  return {
15530
15594
  dir,
15531
15595
  identity,
15532
- eventsPath: (0, import_node_path14.join)(dir, "events.jsonl"),
15533
- foldPath: (0, import_node_path14.join)(dir, "fold.json"),
15534
- rotatedDir: (0, import_node_path14.join)(dir, "rotated")
15596
+ eventsPath: (0, import_node_path15.join)(dir, "events.jsonl"),
15597
+ foldPath: (0, import_node_path15.join)(dir, "fold.json"),
15598
+ rotatedDir: (0, import_node_path15.join)(dir, "rotated")
15535
15599
  };
15536
15600
  } catch {
15537
15601
  return null;
@@ -15593,7 +15657,7 @@ function appendEvent(d, ev) {
15593
15657
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
15594
15658
  ...ev
15595
15659
  });
15596
- (0, import_node_fs15.appendFileSync)(d.eventsPath, line, { mode: 384 });
15660
+ (0, import_node_fs16.appendFileSync)(d.eventsPath, line, { mode: 384 });
15597
15661
  return true;
15598
15662
  } catch {
15599
15663
  return false;
@@ -15601,14 +15665,14 @@ function appendEvent(d, ev) {
15601
15665
  }
15602
15666
  function rotateIfNeeded2(d) {
15603
15667
  try {
15604
- if (!(0, import_node_fs15.existsSync)(d.eventsPath)) return;
15605
- if ((0, import_node_fs15.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15606
- (0, import_node_fs15.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15607
- (0, import_node_fs15.renameSync)(d.eventsPath, (0, import_node_path14.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15608
- const kept = (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15668
+ if (!(0, import_node_fs16.existsSync)(d.eventsPath)) return;
15669
+ if ((0, import_node_fs16.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15670
+ (0, import_node_fs16.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15671
+ (0, import_node_fs16.renameSync)(d.eventsPath, (0, import_node_path15.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15672
+ const kept = (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15609
15673
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
15610
15674
  try {
15611
- (0, import_node_fs15.renameSync)((0, import_node_path14.join)(d.rotatedDir, stale), (0, import_node_path14.join)(d.rotatedDir, `${stale}.pruned`));
15675
+ (0, import_node_fs16.renameSync)((0, import_node_path15.join)(d.rotatedDir, stale), (0, import_node_path15.join)(d.rotatedDir, `${stale}.pruned`));
15612
15676
  } catch {
15613
15677
  }
15614
15678
  }
@@ -15618,8 +15682,8 @@ function rotateIfNeeded2(d) {
15618
15682
 
15619
15683
  // src/lib/dossier/fold-dossier.ts
15620
15684
  var import_node_crypto5 = require("node:crypto");
15621
- var import_node_fs16 = require("node:fs");
15622
- var import_node_path15 = require("node:path");
15685
+ var import_node_fs17 = require("node:fs");
15686
+ var import_node_path16 = require("node:path");
15623
15687
  var EMPTY_CAPABILITIES = () => ({
15624
15688
  human_reachable: { value: "unknown", tier: "unknown" },
15625
15689
  authorship_observability: { value: "unknown", tier: "unknown" },
@@ -15670,12 +15734,12 @@ function foldDossier(d, opts = {}) {
15670
15734
  }
15671
15735
  };
15672
15736
  try {
15673
- if ((0, import_node_fs16.existsSync)(d.rotatedDir)) {
15674
- const files = (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15737
+ if ((0, import_node_fs17.existsSync)(d.rotatedDir)) {
15738
+ const files = (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15675
15739
  state.meta.rotations = files.length;
15676
15740
  for (const f of files) {
15677
15741
  try {
15678
- ingest((0, import_node_fs16.readFileSync)((0, import_node_path15.join)(d.rotatedDir, f), "utf8"));
15742
+ ingest((0, import_node_fs17.readFileSync)((0, import_node_path16.join)(d.rotatedDir, f), "utf8"));
15679
15743
  } catch {
15680
15744
  state.meta.dropped_lines++;
15681
15745
  }
@@ -15684,9 +15748,9 @@ function foldDossier(d, opts = {}) {
15684
15748
  } catch {
15685
15749
  }
15686
15750
  try {
15687
- if ((0, import_node_fs16.existsSync)(d.eventsPath)) {
15688
- state.meta.upto_offset = (0, import_node_fs16.statSync)(d.eventsPath).size;
15689
- ingest((0, import_node_fs16.readFileSync)(d.eventsPath, "utf8"));
15751
+ if ((0, import_node_fs17.existsSync)(d.eventsPath)) {
15752
+ state.meta.upto_offset = (0, import_node_fs17.statSync)(d.eventsPath).size;
15753
+ ingest((0, import_node_fs17.readFileSync)(d.eventsPath, "utf8"));
15690
15754
  }
15691
15755
  } catch {
15692
15756
  }
@@ -15957,7 +16021,7 @@ function applyBounds(state, input) {
15957
16021
  }
15958
16022
 
15959
16023
  // src/lib/dossier/cache.ts
15960
- var import_node_fs17 = require("node:fs");
16024
+ var import_node_fs18 = require("node:fs");
15961
16025
  function compactState(s) {
15962
16026
  const ms = (iso) => Date.parse(iso) || 0;
15963
16027
  return {
@@ -16086,20 +16150,20 @@ function encodeState(s) {
16086
16150
  function writeFoldCache(d, state) {
16087
16151
  try {
16088
16152
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
16089
- (0, import_node_fs17.writeFileSync)(tmp, encodeState(state), { mode: 384 });
16090
- (0, import_node_fs17.renameSync)(tmp, d.foldPath);
16153
+ (0, import_node_fs18.writeFileSync)(tmp, encodeState(state), { mode: 384 });
16154
+ (0, import_node_fs18.renameSync)(tmp, d.foldPath);
16091
16155
  } catch {
16092
16156
  }
16093
16157
  }
16094
16158
  function readFoldCache(d) {
16095
16159
  try {
16096
- if (!(0, import_node_fs17.existsSync)(d.foldPath)) return null;
16097
- const raw = JSON.parse((0, import_node_fs17.readFileSync)(d.foldPath, "utf8"));
16160
+ if (!(0, import_node_fs18.existsSync)(d.foldPath)) return null;
16161
+ const raw = JSON.parse((0, import_node_fs18.readFileSync)(d.foldPath, "utf8"));
16098
16162
  if (raw?.v !== 1) return null;
16099
16163
  const cached2 = expandState(raw);
16100
16164
  if (!cached2?.meta) return null;
16101
- const size = (0, import_node_fs17.existsSync)(d.eventsPath) ? (0, import_node_fs17.statSync)(d.eventsPath).size : 0;
16102
- const rotations = (0, import_node_fs17.existsSync)(d.rotatedDir) ? (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
16165
+ const size = (0, import_node_fs18.existsSync)(d.eventsPath) ? (0, import_node_fs18.statSync)(d.eventsPath).size : 0;
16166
+ const rotations = (0, import_node_fs18.existsSync)(d.rotatedDir) ? (0, import_node_fs18.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
16103
16167
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
16104
16168
  return cached2;
16105
16169
  } catch {
@@ -16150,13 +16214,13 @@ function assessContinuity(i) {
16150
16214
 
16151
16215
  // src/lib/dossier/reanchor.ts
16152
16216
  var import_node_crypto6 = require("node:crypto");
16153
- var import_node_fs18 = require("node:fs");
16217
+ var import_node_fs19 = require("node:fs");
16154
16218
  function lineSha(text) {
16155
16219
  return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
16156
16220
  }
16157
16221
  function fileHash(path) {
16158
16222
  try {
16159
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs18.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
16223
+ return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs19.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
16160
16224
  } catch {
16161
16225
  return null;
16162
16226
  }
@@ -16528,20 +16592,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
16528
16592
  let sessions = 0;
16529
16593
  try {
16530
16594
  const dir = treeDir(identity);
16531
- if (!(0, import_node_fs19.existsSync)(dir)) return { paths: [], sessions: 0 };
16532
- for (const entry of (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true })) {
16595
+ if (!(0, import_node_fs20.existsSync)(dir)) return { paths: [], sessions: 0 };
16596
+ for (const entry of (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true })) {
16533
16597
  if (!entry.isDirectory()) continue;
16534
16598
  if (entry.name === identity.sessionKey) continue;
16535
- const log = (0, import_node_path16.join)(dir, entry.name, "events.jsonl");
16599
+ const log = (0, import_node_path17.join)(dir, entry.name, "events.jsonl");
16536
16600
  try {
16537
- if (!(0, import_node_fs19.existsSync)(log)) continue;
16538
- if (now - (0, import_node_fs19.statSync)(log).mtimeMs > windowMs) continue;
16601
+ if (!(0, import_node_fs20.existsSync)(log)) continue;
16602
+ if (now - (0, import_node_fs20.statSync)(log).mtimeMs > windowMs) continue;
16539
16603
  const sib = {
16540
- dir: (0, import_node_path16.join)(dir, entry.name),
16604
+ dir: (0, import_node_path17.join)(dir, entry.name),
16541
16605
  identity,
16542
16606
  eventsPath: log,
16543
- foldPath: (0, import_node_path16.join)(dir, entry.name, "fold.json"),
16544
- rotatedDir: (0, import_node_path16.join)(dir, entry.name, "rotated")
16607
+ foldPath: (0, import_node_path17.join)(dir, entry.name, "fold.json"),
16608
+ rotatedDir: (0, import_node_path17.join)(dir, entry.name, "rotated")
16545
16609
  };
16546
16610
  const state = readFoldCache(sib) ?? foldDossier(sib);
16547
16611
  sessions++;
@@ -16569,25 +16633,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16569
16633
  let removed = 0;
16570
16634
  try {
16571
16635
  const mine = dossierDir(identity);
16572
- const userDir = (0, import_node_path16.dirname)((0, import_node_path16.dirname)(mine));
16573
- if (!(0, import_node_fs19.existsSync)(userDir)) return 0;
16636
+ const userDir = (0, import_node_path17.dirname)((0, import_node_path17.dirname)(mine));
16637
+ if (!(0, import_node_fs20.existsSync)(userDir)) return 0;
16574
16638
  const cutoff = Date.now() - maxAgeMs;
16575
- for (const tree of (0, import_node_fs19.readdirSync)(userDir, { withFileTypes: true })) {
16639
+ for (const tree of (0, import_node_fs20.readdirSync)(userDir, { withFileTypes: true })) {
16576
16640
  if (!tree.isDirectory()) continue;
16577
- const treePath = (0, import_node_path16.join)(userDir, tree.name);
16641
+ const treePath = (0, import_node_path17.join)(userDir, tree.name);
16578
16642
  let live = 0;
16579
- for (const entry of (0, import_node_fs19.readdirSync)(treePath, { withFileTypes: true })) {
16643
+ for (const entry of (0, import_node_fs20.readdirSync)(treePath, { withFileTypes: true })) {
16580
16644
  if (!entry.isDirectory()) continue;
16581
- const dir = (0, import_node_path16.join)(treePath, entry.name);
16645
+ const dir = (0, import_node_path17.join)(treePath, entry.name);
16582
16646
  if (dir === mine) {
16583
16647
  live++;
16584
16648
  continue;
16585
16649
  }
16586
16650
  try {
16587
- const log = (0, import_node_path16.join)(dir, "events.jsonl");
16588
- const at = (0, import_node_fs19.existsSync)(log) ? (0, import_node_fs19.statSync)(log).mtimeMs : (0, import_node_fs19.statSync)(dir).mtimeMs;
16651
+ const log = (0, import_node_path17.join)(dir, "events.jsonl");
16652
+ const at = (0, import_node_fs20.existsSync)(log) ? (0, import_node_fs20.statSync)(log).mtimeMs : (0, import_node_fs20.statSync)(dir).mtimeMs;
16589
16653
  if (at < cutoff) {
16590
- (0, import_node_fs19.rmSync)(dir, { recursive: true, force: true });
16654
+ (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
16591
16655
  removed++;
16592
16656
  } else {
16593
16657
  live++;
@@ -16597,7 +16661,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16597
16661
  }
16598
16662
  if (live === 0) {
16599
16663
  try {
16600
- (0, import_node_fs19.rmSync)(treePath, { recursive: false, force: false });
16664
+ (0, import_node_fs20.rmSync)(treePath, { recursive: false, force: false });
16601
16665
  } catch {
16602
16666
  }
16603
16667
  }
@@ -16614,8 +16678,8 @@ function sessionDossier(token, sessionId) {
16614
16678
  }
16615
16679
  function hasActiveGoal(d) {
16616
16680
  try {
16617
- if (!(0, import_node_fs19.existsSync)(d.eventsPath)) return false;
16618
- return (0, import_node_fs19.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16681
+ if (!(0, import_node_fs20.existsSync)(d.eventsPath)) return false;
16682
+ return (0, import_node_fs20.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16619
16683
  } catch {
16620
16684
  return false;
16621
16685
  }
@@ -16639,7 +16703,7 @@ function recordTurn(d, t) {
16639
16703
  for (const a of t.authored) {
16640
16704
  const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
16641
16705
  const prior = t.known?.authored?.get(a.p);
16642
- const hash = fileHash((0, import_node_path16.join)(root, a.p));
16706
+ const hash = fileHash((0, import_node_path17.join)(root, a.p));
16643
16707
  const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
16644
16708
  const adds = Math.max(0, a.a - (prior?.adds ?? 0));
16645
16709
  const dels = Math.max(0, a.d - (prior?.dels ?? 0));
@@ -16672,7 +16736,7 @@ function recordTurn(d, t) {
16672
16736
  }
16673
16737
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
16674
16738
  for (const u of t.unobserved) {
16675
- const hash = fileHash((0, import_node_path16.join)(root, u.p));
16739
+ const hash = fileHash((0, import_node_path17.join)(root, u.p));
16676
16740
  if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
16677
16741
  appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
16678
16742
  }
@@ -16707,8 +16771,8 @@ function recordVerdict(d, v) {
16707
16771
  if (!sent.has(f.file)) continue;
16708
16772
  if (!lines.has(f.file)) {
16709
16773
  try {
16710
- const abs = (0, import_node_path16.join)(root, f.file);
16711
- lines.set(f.file, (0, import_node_fs19.existsSync)(abs) ? (0, import_node_fs19.readFileSync)(abs, "utf8").split("\n") : null);
16774
+ const abs = (0, import_node_path17.join)(root, f.file);
16775
+ lines.set(f.file, (0, import_node_fs20.existsSync)(abs) ? (0, import_node_fs20.readFileSync)(abs, "utf8").split("\n") : null);
16712
16776
  } catch {
16713
16777
  lines.set(f.file, null);
16714
16778
  }
@@ -16808,8 +16872,8 @@ function recallMemory(d, identity, opts) {
16808
16872
  budgetBytes: opts.budgetBytes,
16809
16873
  readFileLines: (file) => {
16810
16874
  try {
16811
- const abs = (0, import_node_path16.join)(root, file);
16812
- return (0, import_node_fs19.existsSync)(abs) ? (0, import_node_fs19.readFileSync)(abs, "utf8").split("\n") : null;
16875
+ const abs = (0, import_node_path17.join)(root, file);
16876
+ return (0, import_node_fs20.existsSync)(abs) ? (0, import_node_fs20.readFileSync)(abs, "utf8").split("\n") : null;
16813
16877
  } catch {
16814
16878
  return null;
16815
16879
  }
@@ -16953,46 +17017,46 @@ async function fireClassify(prompt, sessionId, globals) {
16953
17017
  }
16954
17018
 
16955
17019
  // src/commands/lifecycle.ts
16956
- var import_node_fs23 = require("node:fs");
16957
- var import_node_path21 = require("node:path");
17020
+ var import_node_fs24 = require("node:fs");
17021
+ var import_node_path22 = require("node:path");
16958
17022
 
16959
17023
  // src/lib/baseline.ts
16960
- var import_node_fs22 = require("node:fs");
16961
- var import_node_path20 = require("node:path");
17024
+ var import_node_fs23 = require("node:fs");
17025
+ var import_node_path21 = require("node:path");
16962
17026
  var import_node_crypto9 = require("node:crypto");
16963
17027
 
16964
17028
  // src/lib/snapshot.ts
16965
- var import_node_fs21 = require("node:fs");
16966
- var import_node_path19 = require("node:path");
17029
+ var import_node_fs22 = require("node:fs");
17030
+ var import_node_path20 = require("node:path");
16967
17031
  var import_node_child_process7 = require("node:child_process");
16968
17032
 
16969
17033
  // src/lib/files.ts
16970
- var import_node_path18 = require("node:path");
17034
+ var import_node_path19 = require("node:path");
16971
17035
 
16972
17036
  // src/lib/safe-read.ts
16973
- var import_node_fs20 = require("node:fs");
16974
- var import_node_path17 = require("node:path");
16975
- var FLAGS = import_node_fs20.constants;
17037
+ var import_node_fs21 = require("node:fs");
17038
+ var import_node_path18 = require("node:path");
17039
+ var FLAGS = import_node_fs21.constants;
16976
17040
  var NOFOLLOW = FLAGS.O_NOFOLLOW;
16977
17041
  var NONBLOCK = FLAGS.O_NONBLOCK;
16978
17042
  function closeOpened(fd) {
16979
17043
  try {
16980
- (0, import_node_fs20.closeSync)(fd);
17044
+ (0, import_node_fs21.closeSync)(fd);
16981
17045
  } catch {
16982
17046
  }
16983
17047
  }
16984
17048
  function isInsideRoot(realRoot, realPath) {
16985
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path17.sep) ? realRoot : realRoot + import_node_path17.sep);
17049
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path18.sep) ? realRoot : realRoot + import_node_path18.sep);
16986
17050
  }
16987
17051
  function sameOpenedFile(opened, current, nofollowAvailable) {
16988
17052
  if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
16989
17053
  return opened.ino === current.ino && opened.dev === current.dev;
16990
17054
  }
16991
17055
  function openRegularInRoot(root, path) {
16992
- const full = (0, import_node_path17.isAbsolute)(path) ? path : (0, import_node_path17.join)(root, path);
17056
+ const full = (0, import_node_path18.isAbsolute)(path) ? path : (0, import_node_path18.join)(root, path);
16993
17057
  let fd;
16994
17058
  try {
16995
- fd = (0, import_node_fs20.openSync)(full, import_node_fs20.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
17059
+ fd = (0, import_node_fs21.openSync)(full, import_node_fs21.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
16996
17060
  } catch (err) {
16997
17061
  const code = err.code;
16998
17062
  if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
@@ -17000,18 +17064,18 @@ function openRegularInRoot(root, path) {
17000
17064
  return { ok: false, reason: "unreadable" };
17001
17065
  }
17002
17066
  try {
17003
- const opened = (0, import_node_fs20.fstatSync)(fd, { bigint: true });
17067
+ const opened = (0, import_node_fs21.fstatSync)(fd, { bigint: true });
17004
17068
  if (!opened.isFile()) {
17005
17069
  closeOpened(fd);
17006
17070
  return { ok: false, reason: "not-regular" };
17007
17071
  }
17008
- const realRoot = import_node_fs20.realpathSync.native(root);
17009
- const realPath = import_node_fs20.realpathSync.native(full);
17072
+ const realRoot = import_node_fs21.realpathSync.native(root);
17073
+ const realPath = import_node_fs21.realpathSync.native(full);
17010
17074
  if (!isInsideRoot(realRoot, realPath)) {
17011
17075
  closeOpened(fd);
17012
17076
  return { ok: false, reason: "outside-root" };
17013
17077
  }
17014
- const current = (0, import_node_fs20.statSync)(realPath, { bigint: true });
17078
+ const current = (0, import_node_fs21.statSync)(realPath, { bigint: true });
17015
17079
  if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
17016
17080
  closeOpened(fd);
17017
17081
  return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
@@ -17033,7 +17097,7 @@ function readOpened(fd, size) {
17033
17097
  const buffer = Buffer.alloc(size);
17034
17098
  let offset = 0;
17035
17099
  while (offset < size) {
17036
- const n = (0, import_node_fs20.readSync)(fd, buffer, offset, size - offset, offset);
17100
+ const n = (0, import_node_fs21.readSync)(fd, buffer, offset, size - offset, offset);
17037
17101
  if (n === 0) break;
17038
17102
  offset += n;
17039
17103
  }
@@ -17127,7 +17191,7 @@ var LANG_MAP = {
17127
17191
  mk: "make"
17128
17192
  };
17129
17193
  function detectLanguage(filepath) {
17130
- const ext = (0, import_node_path18.extname)(filepath).slice(1);
17194
+ const ext = (0, import_node_path19.extname)(filepath).slice(1);
17131
17195
  return LANG_MAP[ext] ?? ext;
17132
17196
  }
17133
17197
  function sortByMtime(files) {
@@ -17218,16 +17282,16 @@ function collectCodeDelta(files, opts) {
17218
17282
 
17219
17283
  // src/lib/snapshot.ts
17220
17284
  function generateSnapshotDiffs(files) {
17221
- if (!(0, import_node_fs21.existsSync)(SNAPSHOT_DIR)) {
17285
+ if (!(0, import_node_fs22.existsSync)(SNAPSHOT_DIR)) {
17222
17286
  return { diffs: [], has_snapshots: false };
17223
17287
  }
17224
17288
  const diffs = [];
17225
17289
  for (const file of files) {
17226
17290
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
17227
- const snapshotPath = (0, import_node_path19.join)(SNAPSHOT_DIR, file.path);
17291
+ const snapshotPath = (0, import_node_path20.join)(SNAPSHOT_DIR, file.path);
17228
17292
  const language = file.language ?? detectLanguage(file.path);
17229
- if ((0, import_node_fs21.existsSync)(snapshotPath)) {
17230
- const oldContent = (0, import_node_fs21.readFileSync)(snapshotPath, "utf-8");
17293
+ if ((0, import_node_fs22.existsSync)(snapshotPath)) {
17294
+ const oldContent = (0, import_node_fs22.readFileSync)(snapshotPath, "utf-8");
17231
17295
  if (oldContent === file.content) continue;
17232
17296
  const diff = computeDiff(oldContent, file.content, file.path);
17233
17297
  if (diff) {
@@ -17252,20 +17316,20 @@ function saveSnapshots(files) {
17252
17316
  const snapshotPaths = /* @__PURE__ */ new Set();
17253
17317
  for (const file of files) {
17254
17318
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
17255
- const snapshotPath = (0, import_node_path19.join)(SNAPSHOT_DIR, file.path);
17319
+ const snapshotPath = (0, import_node_path20.join)(SNAPSHOT_DIR, file.path);
17256
17320
  snapshotPaths.add(snapshotPath);
17257
- (0, import_node_fs21.mkdirSync)((0, import_node_path19.dirname)(snapshotPath), { recursive: true });
17258
- (0, import_node_fs21.writeFileSync)(snapshotPath, file.content);
17321
+ (0, import_node_fs22.mkdirSync)((0, import_node_path20.dirname)(snapshotPath), { recursive: true });
17322
+ (0, import_node_fs22.writeFileSync)(snapshotPath, file.content);
17259
17323
  }
17260
17324
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
17261
17325
  }
17262
17326
  function computeDiff(oldContent, newContent, filePath) {
17263
- const tmpOld = (0, import_node_path19.join)(SNAPSHOT_DIR, ".diff-old.tmp");
17264
- const tmpNew = (0, import_node_path19.join)(SNAPSHOT_DIR, ".diff-new.tmp");
17327
+ const tmpOld = (0, import_node_path20.join)(SNAPSHOT_DIR, ".diff-old.tmp");
17328
+ const tmpNew = (0, import_node_path20.join)(SNAPSHOT_DIR, ".diff-new.tmp");
17265
17329
  try {
17266
- (0, import_node_fs21.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
17267
- (0, import_node_fs21.writeFileSync)(tmpOld, oldContent);
17268
- (0, import_node_fs21.writeFileSync)(tmpNew, newContent);
17330
+ (0, import_node_fs22.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
17331
+ (0, import_node_fs22.writeFileSync)(tmpOld, oldContent);
17332
+ (0, import_node_fs22.writeFileSync)(tmpNew, newContent);
17269
17333
  const result = (0, import_node_child_process7.execSync)(
17270
17334
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
17271
17335
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -17279,32 +17343,32 @@ function computeDiff(oldContent, newContent, filePath) {
17279
17343
  return null;
17280
17344
  } finally {
17281
17345
  try {
17282
- (0, import_node_fs21.unlinkSync)(tmpOld);
17346
+ (0, import_node_fs22.unlinkSync)(tmpOld);
17283
17347
  } catch {
17284
17348
  }
17285
17349
  try {
17286
- (0, import_node_fs21.unlinkSync)(tmpNew);
17350
+ (0, import_node_fs22.unlinkSync)(tmpNew);
17287
17351
  } catch {
17288
17352
  }
17289
17353
  }
17290
17354
  }
17291
17355
  function cleanStaleSnapshots(dir, keepSet) {
17292
- if (!(0, import_node_fs21.existsSync)(dir)) return;
17356
+ if (!(0, import_node_fs22.existsSync)(dir)) return;
17293
17357
  try {
17294
- const entries = (0, import_node_fs21.readdirSync)(dir, { withFileTypes: true });
17358
+ const entries = (0, import_node_fs22.readdirSync)(dir, { withFileTypes: true });
17295
17359
  for (const entry of entries) {
17296
17360
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
17297
- const fullPath = (0, import_node_path19.join)(dir, entry.name);
17361
+ const fullPath = (0, import_node_path20.join)(dir, entry.name);
17298
17362
  if (entry.isDirectory()) {
17299
17363
  cleanStaleSnapshots(fullPath, keepSet);
17300
17364
  try {
17301
- const remaining = (0, import_node_fs21.readdirSync)(fullPath);
17302
- if (remaining.length === 0) (0, import_node_fs21.rmdirSync)(fullPath);
17365
+ const remaining = (0, import_node_fs22.readdirSync)(fullPath);
17366
+ if (remaining.length === 0) (0, import_node_fs22.rmdirSync)(fullPath);
17303
17367
  } catch {
17304
17368
  }
17305
17369
  } else if (!keepSet.has(fullPath)) {
17306
17370
  try {
17307
- (0, import_node_fs21.unlinkSync)(fullPath);
17371
+ (0, import_node_fs22.unlinkSync)(fullPath);
17308
17372
  } catch {
17309
17373
  }
17310
17374
  }
@@ -17323,20 +17387,20 @@ function sessionKey(sessionId) {
17323
17387
  return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
17324
17388
  }
17325
17389
  function sessionDir(key) {
17326
- return (0, import_node_path20.join)(projectPath(BASELINE_DIR), key);
17390
+ return (0, import_node_path21.join)(projectPath(BASELINE_DIR), key);
17327
17391
  }
17328
17392
  function manifestPath(dir) {
17329
- return (0, import_node_path20.join)(dir, "manifest.json");
17393
+ return (0, import_node_path21.join)(dir, "manifest.json");
17330
17394
  }
17331
17395
  function mirrorPath(dir, repoRelPath) {
17332
- return (0, import_node_path20.join)(dir, "files", repoRelPath);
17396
+ return (0, import_node_path21.join)(dir, "files", repoRelPath);
17333
17397
  }
17334
17398
  var CARRY_FILE = `${BASELINE_DIR}/.carry`;
17335
17399
  var CARRY_WINDOW_MS = 12e4;
17336
17400
  function writeCarry(sessionId, headSha) {
17337
17401
  try {
17338
- (0, import_node_fs22.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
17339
- (0, import_node_fs22.writeFileSync)(
17402
+ (0, import_node_fs23.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
17403
+ (0, import_node_fs23.writeFileSync)(
17340
17404
  projectPath(CARRY_FILE),
17341
17405
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
17342
17406
  );
@@ -17346,10 +17410,10 @@ function writeCarry(sessionId, headSha) {
17346
17410
  function claimCarry(newKey) {
17347
17411
  const carryPath = projectPath(CARRY_FILE);
17348
17412
  try {
17349
- if (!(0, import_node_fs22.existsSync)(carryPath)) return null;
17350
- const carry = JSON.parse((0, import_node_fs22.readFileSync)(carryPath, "utf-8"));
17413
+ if (!(0, import_node_fs23.existsSync)(carryPath)) return null;
17414
+ const carry = JSON.parse((0, import_node_fs23.readFileSync)(carryPath, "utf-8"));
17351
17415
  try {
17352
- (0, import_node_fs22.rmSync)(carryPath, { force: true });
17416
+ (0, import_node_fs23.rmSync)(carryPath, { force: true });
17353
17417
  } catch {
17354
17418
  }
17355
17419
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -17360,11 +17424,11 @@ function claimCarry(newKey) {
17360
17424
  if (!prior) return null;
17361
17425
  const toDir = sessionDir(newKey);
17362
17426
  try {
17363
- (0, import_node_fs22.rmSync)(toDir, { recursive: true, force: true });
17427
+ (0, import_node_fs23.rmSync)(toDir, { recursive: true, force: true });
17364
17428
  } catch {
17365
17429
  }
17366
- (0, import_node_fs22.renameSync)(fromDir, toDir);
17367
- (0, import_node_fs22.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
17430
+ (0, import_node_fs23.renameSync)(fromDir, toDir);
17431
+ (0, import_node_fs23.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
17368
17432
  return readManifest(toDir);
17369
17433
  } catch {
17370
17434
  return null;
@@ -17388,21 +17452,21 @@ function captureBaseline(opts = {}) {
17388
17452
  const head_sha = getCurrentCommit();
17389
17453
  const dirty = getDirtyFiles();
17390
17454
  try {
17391
- (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
17455
+ (0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
17392
17456
  } catch {
17393
17457
  }
17394
- const filesDir = (0, import_node_path20.join)(dir, "files");
17458
+ const filesDir = (0, import_node_path21.join)(dir, "files");
17395
17459
  const mirrored = [];
17396
17460
  try {
17397
- (0, import_node_fs22.mkdirSync)(filesDir, { recursive: true });
17461
+ (0, import_node_fs23.mkdirSync)(filesDir, { recursive: true });
17398
17462
  for (const p of dirty) {
17399
17463
  if (p.includes("..")) continue;
17400
17464
  const content = safeReadForMirror(projectPath(p));
17401
17465
  if (content === null) continue;
17402
17466
  const dest = mirrorPath(dir, p);
17403
17467
  try {
17404
- (0, import_node_fs22.mkdirSync)((0, import_node_path20.dirname)(dest), { recursive: true });
17405
- (0, import_node_fs22.writeFileSync)(dest, content);
17468
+ (0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(dest), { recursive: true });
17469
+ (0, import_node_fs23.writeFileSync)(dest, content);
17406
17470
  mirrored.push(p);
17407
17471
  } catch {
17408
17472
  }
@@ -17417,8 +17481,8 @@ function captureBaseline(opts = {}) {
17417
17481
  version: BASELINE_VERSION
17418
17482
  };
17419
17483
  try {
17420
- (0, import_node_fs22.mkdirSync)(dir, { recursive: true });
17421
- (0, import_node_fs22.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
17484
+ (0, import_node_fs23.mkdirSync)(dir, { recursive: true });
17485
+ (0, import_node_fs23.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
17422
17486
  } catch {
17423
17487
  }
17424
17488
  pruneOldBaselines();
@@ -17429,9 +17493,9 @@ function readBaseline(sessionId) {
17429
17493
  }
17430
17494
  function readManifest(dir) {
17431
17495
  const mp = manifestPath(dir);
17432
- if (!(0, import_node_fs22.existsSync)(mp)) return null;
17496
+ if (!(0, import_node_fs23.existsSync)(mp)) return null;
17433
17497
  try {
17434
- const parsed = JSON.parse((0, import_node_fs22.readFileSync)(mp, "utf-8"));
17498
+ const parsed = JSON.parse((0, import_node_fs23.readFileSync)(mp, "utf-8"));
17435
17499
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
17436
17500
  return null;
17437
17501
  }
@@ -17462,9 +17526,9 @@ function preImage(repoRelPath, baseline) {
17462
17526
  function resolvePreImage(repoRelPath, baseline) {
17463
17527
  if (baseline.dirty_paths.includes(repoRelPath)) {
17464
17528
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
17465
- if ((0, import_node_fs22.existsSync)(mp)) {
17529
+ if ((0, import_node_fs23.existsSync)(mp)) {
17466
17530
  try {
17467
- return { content: (0, import_node_fs22.readFileSync)(mp, "utf-8"), existed: true };
17531
+ return { content: (0, import_node_fs23.readFileSync)(mp, "utf-8"), existed: true };
17468
17532
  } catch {
17469
17533
  }
17470
17534
  }
@@ -17509,8 +17573,8 @@ function absorbIntoBaseline(paths, sessionId) {
17509
17573
  const content = safeReadForMirror(projectPath(p));
17510
17574
  if (content === null) continue;
17511
17575
  const dest = mirrorPath(dir, p);
17512
- (0, import_node_fs22.mkdirSync)((0, import_node_path20.dirname)(dest), { recursive: true });
17513
- (0, import_node_fs22.writeFileSync)(dest, content);
17576
+ (0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(dest), { recursive: true });
17577
+ (0, import_node_fs23.writeFileSync)(dest, content);
17514
17578
  dirty.add(p);
17515
17579
  adopted++;
17516
17580
  } catch {
@@ -17519,7 +17583,7 @@ function absorbIntoBaseline(paths, sessionId) {
17519
17583
  if (adopted === 0) return 0;
17520
17584
  try {
17521
17585
  const updated = { ...baseline, dirty_paths: [...dirty] };
17522
- (0, import_node_fs22.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17586
+ (0, import_node_fs23.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17523
17587
  preImageCache.delete(baseline);
17524
17588
  } catch {
17525
17589
  return 0;
@@ -17530,7 +17594,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
17530
17594
  const pre = preImage(repoRelPath, baseline);
17531
17595
  let current;
17532
17596
  try {
17533
- current = (0, import_node_fs22.readFileSync)(projectPath(repoRelPath), "utf-8");
17597
+ current = (0, import_node_fs23.readFileSync)(projectPath(repoRelPath), "utf-8");
17534
17598
  } catch {
17535
17599
  return pre.existed;
17536
17600
  }
@@ -17539,8 +17603,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
17539
17603
  }
17540
17604
  function safeReadForMirror(absPath) {
17541
17605
  try {
17542
- if ((0, import_node_fs22.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17543
- const buf = (0, import_node_fs22.readFileSync)(absPath);
17606
+ if ((0, import_node_fs23.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17607
+ const buf = (0, import_node_fs23.readFileSync)(absPath);
17544
17608
  if (buf.includes(0)) return null;
17545
17609
  return buf.toString("utf-8");
17546
17610
  } catch {
@@ -17551,18 +17615,18 @@ function pruneOldBaselines() {
17551
17615
  const root = projectPath(BASELINE_DIR);
17552
17616
  let entries;
17553
17617
  try {
17554
- entries = (0, import_node_fs22.readdirSync)(root);
17618
+ entries = (0, import_node_fs23.readdirSync)(root);
17555
17619
  } catch {
17556
17620
  return;
17557
17621
  }
17558
17622
  const now = Date.now();
17559
17623
  for (const name of entries) {
17560
- const dir = (0, import_node_path20.join)(root, name);
17624
+ const dir = (0, import_node_path21.join)(root, name);
17561
17625
  const manifest = readManifest(dir);
17562
17626
  if (!manifest) {
17563
17627
  try {
17564
- if (now - (0, import_node_fs22.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17565
- (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
17628
+ if (now - (0, import_node_fs23.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17629
+ (0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
17566
17630
  }
17567
17631
  } catch {
17568
17632
  }
@@ -17570,7 +17634,7 @@ function pruneOldBaselines() {
17570
17634
  }
17571
17635
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
17572
17636
  try {
17573
- (0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
17637
+ (0, import_node_fs23.rmSync)(dir, { recursive: true, force: true });
17574
17638
  } catch {
17575
17639
  }
17576
17640
  }
@@ -17745,8 +17809,8 @@ function buildCompactionContext(session) {
17745
17809
  commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
17746
17810
  readFileLines: (file) => {
17747
17811
  try {
17748
- const abs = (0, import_node_path21.join)(root, file);
17749
- return (0, import_node_fs23.existsSync)(abs) ? (0, import_node_fs23.readFileSync)(abs, "utf8").split("\n") : null;
17812
+ const abs = (0, import_node_path22.join)(root, file);
17813
+ return (0, import_node_fs24.existsSync)(abs) ? (0, import_node_fs24.readFileSync)(abs, "utf8").split("\n") : null;
17750
17814
  } catch {
17751
17815
  return null;
17752
17816
  }
@@ -17803,24 +17867,24 @@ async function readHookStdin() {
17803
17867
 
17804
17868
  // src/commands/standard.ts
17805
17869
  var import_promises13 = require("node:fs/promises");
17806
- var import_node_fs30 = require("node:fs");
17870
+ var import_node_fs31 = require("node:fs");
17807
17871
  var import_yaml3 = __toESM(require_dist());
17808
17872
 
17809
17873
  // src/lib/synthesize.ts
17810
17874
  var import_node_child_process9 = require("node:child_process");
17811
- var import_node_fs26 = require("node:fs");
17875
+ var import_node_fs27 = require("node:fs");
17812
17876
  var import_promises10 = require("node:fs/promises");
17813
- var import_node_path24 = require("node:path");
17877
+ var import_node_path25 = require("node:path");
17814
17878
  var import_yaml = __toESM(require_dist());
17815
17879
 
17816
17880
  // src/lib/data-dir.ts
17817
- var import_node_fs24 = require("node:fs");
17818
- var import_node_path22 = require("node:path");
17881
+ var import_node_fs25 = require("node:fs");
17882
+ var import_node_path23 = require("node:path");
17819
17883
  function resolveDataDir() {
17820
17884
  const candidates2 = [
17821
- (0, import_node_path22.join)(__dirname, "..", "data"),
17885
+ (0, import_node_path23.join)(__dirname, "..", "data"),
17822
17886
  // installed: node_modules/@codacy/verity-cli/data
17823
- (0, import_node_path22.join)(__dirname, "..", "..", "data"),
17887
+ (0, import_node_path23.join)(__dirname, "..", "..", "data"),
17824
17888
  // edge case: nested resolution
17825
17889
  // THE COMMITTED SOURCE, for a source checkout that has not been built.
17826
17890
  // cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
@@ -17829,14 +17893,14 @@ function resolveDataDir() {
17829
17893
  // without this the synthesizer throws "Could not find Verity skill data"
17830
17894
  // for every test and every `verity` run from source. Resolved from this
17831
17895
  // module's own location, never the cwd: see the warning below.
17832
- (0, import_node_path22.join)(__dirname, "..", "..", "client"),
17896
+ (0, import_node_path23.join)(__dirname, "..", "..", "client"),
17833
17897
  // bundled: cli/bin/ → ../../client
17834
- (0, import_node_path22.join)(__dirname, "..", "..", "..", "client"),
17898
+ (0, import_node_path23.join)(__dirname, "..", "..", "..", "client"),
17835
17899
  // tsx: cli/src/lib/ → ../../../client
17836
17900
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
17837
17901
  ];
17838
17902
  for (const candidate of candidates2) {
17839
- if ((0, import_node_fs24.existsSync)((0, import_node_path22.join)(candidate, "skills"))) {
17903
+ if ((0, import_node_fs25.existsSync)((0, import_node_path23.join)(candidate, "skills"))) {
17840
17904
  return candidate;
17841
17905
  }
17842
17906
  }
@@ -17845,13 +17909,13 @@ function resolveDataDir() {
17845
17909
  );
17846
17910
  }
17847
17911
  function setupDataPath(file) {
17848
- return (0, import_node_path22.join)(resolveDataDir(), "skills", "verity-setup", file);
17912
+ return (0, import_node_path23.join)(resolveDataDir(), "skills", "verity-setup", file);
17849
17913
  }
17850
17914
 
17851
17915
  // src/lib/detect.ts
17852
17916
  var import_node_child_process8 = require("node:child_process");
17853
- var import_node_fs25 = require("node:fs");
17854
- var import_node_path23 = require("node:path");
17917
+ var import_node_fs26 = require("node:fs");
17918
+ var import_node_path24 = require("node:path");
17855
17919
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
17856
17920
  "typescript",
17857
17921
  "javascript",
@@ -17908,25 +17972,25 @@ function walk(root) {
17908
17972
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
17909
17973
  let entries;
17910
17974
  try {
17911
- entries = (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true });
17975
+ entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
17912
17976
  } catch {
17913
17977
  return;
17914
17978
  }
17915
17979
  for (const entry of entries) {
17916
17980
  if (found.length >= WALK_MAX_FILES) return;
17917
17981
  if (IGNORED_SEGMENTS.includes(entry.name)) continue;
17918
- const full = (0, import_node_path23.join)(dir, entry.name);
17982
+ const full = (0, import_node_path24.join)(dir, entry.name);
17919
17983
  if (entry.isDirectory()) visit(full, depth + 1);
17920
- else if (entry.isFile()) found.push((0, import_node_path23.relative)(root, full));
17984
+ else if (entry.isFile()) found.push((0, import_node_path24.relative)(root, full));
17921
17985
  }
17922
17986
  };
17923
17987
  visit(root, 0);
17924
17988
  return found;
17925
17989
  }
17926
17990
  function languageOf(path) {
17927
- const name = (0, import_node_path23.basename)(path);
17991
+ const name = (0, import_node_path24.basename)(path);
17928
17992
  if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
17929
- if (!(0, import_node_path23.extname)(name)) return null;
17993
+ if (!(0, import_node_path24.extname)(name)) return null;
17930
17994
  const lang = detectLanguage(path);
17931
17995
  return lang || null;
17932
17996
  }
@@ -17983,7 +18047,7 @@ var TOOL_CONFIG_MARKERS = [
17983
18047
  ];
17984
18048
  function readJson(path) {
17985
18049
  try {
17986
- return JSON.parse((0, import_node_fs25.readFileSync)(path, "utf-8"));
18050
+ return JSON.parse((0, import_node_fs26.readFileSync)(path, "utf-8"));
17987
18051
  } catch {
17988
18052
  return null;
17989
18053
  }
@@ -18008,17 +18072,17 @@ function declaredDependencies(root, files) {
18008
18072
  if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
18009
18073
  }
18010
18074
  };
18011
- readPackageJson((0, import_node_path23.join)(root, "package.json"));
18012
- const nested = files.filter((f) => f.includes("/") && (0, import_node_path23.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
18013
- for (const rel of nested) readPackageJson((0, import_node_path23.join)(root, rel));
18075
+ readPackageJson((0, import_node_path24.join)(root, "package.json"));
18076
+ const nested = files.filter((f) => f.includes("/") && (0, import_node_path24.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
18077
+ for (const rel of nested) readPackageJson((0, import_node_path24.join)(root, rel));
18014
18078
  const pythonManifests = [
18015
- ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path23.join)(root, f)),
18016
- ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path23.join)(root, f))
18079
+ ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path24.join)(root, f)),
18080
+ ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path24.join)(root, f))
18017
18081
  ];
18018
18082
  for (const path of pythonManifests) {
18019
- if (!(0, import_node_fs25.existsSync)(path)) continue;
18083
+ if (!(0, import_node_fs26.existsSync)(path)) continue;
18020
18084
  try {
18021
- const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
18085
+ const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
18022
18086
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
18023
18087
  for (const line of text.split("\n")) {
18024
18088
  if (!/dependencies\s*=/.test(line)) continue;
@@ -18028,13 +18092,13 @@ function declaredDependencies(root, files) {
18028
18092
  }
18029
18093
  }
18030
18094
  const goMods = [
18031
- (0, import_node_path23.join)(root, "go.mod"),
18032
- ...files.filter((f) => f.includes("/") && (0, import_node_path23.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path23.join)(root, f))
18095
+ (0, import_node_path24.join)(root, "go.mod"),
18096
+ ...files.filter((f) => f.includes("/") && (0, import_node_path24.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path24.join)(root, f))
18033
18097
  ];
18034
18098
  for (const path of goMods) {
18035
- if (!(0, import_node_fs25.existsSync)(path)) continue;
18099
+ if (!(0, import_node_fs26.existsSync)(path)) continue;
18036
18100
  try {
18037
- const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
18101
+ const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
18038
18102
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
18039
18103
  names2.push(m[1].replace(/^github\.com\//, ""));
18040
18104
  }
@@ -18042,10 +18106,10 @@ function declaredDependencies(root, files) {
18042
18106
  }
18043
18107
  }
18044
18108
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
18045
- const path = (0, import_node_path23.join)(root, file);
18046
- if (!(0, import_node_fs25.existsSync)(path)) continue;
18109
+ const path = (0, import_node_path24.join)(root, file);
18110
+ if (!(0, import_node_fs26.existsSync)(path)) continue;
18047
18111
  try {
18048
- const text = (0, import_node_fs25.readFileSync)(path, "utf-8");
18112
+ const text = (0, import_node_fs26.readFileSync)(path, "utf-8");
18049
18113
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
18050
18114
  } catch {
18051
18115
  }
@@ -18053,7 +18117,7 @@ function declaredDependencies(root, files) {
18053
18117
  return names2;
18054
18118
  }
18055
18119
  function detectBuildSystem(root, files) {
18056
- const has = (f) => (0, import_node_fs25.existsSync)((0, import_node_path23.join)(root, f)) || files.some((p) => (0, import_node_path23.basename)(p) === f);
18120
+ const has = (f) => (0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, f)) || files.some((p) => (0, import_node_path24.basename)(p) === f);
18057
18121
  if (has("pnpm-lock.yaml")) return "pnpm";
18058
18122
  if (has("yarn.lock")) return "yarn";
18059
18123
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -18070,8 +18134,8 @@ function detectBuildSystem(root, files) {
18070
18134
  }
18071
18135
  function detectArchitecture(root, files) {
18072
18136
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
18073
- if (workspaceMarkers.some((m) => (0, import_node_fs25.existsSync)((0, import_node_path23.join)(root, m)))) return "monorepo";
18074
- const pkg = readJson((0, import_node_path23.join)(root, "package.json"));
18137
+ if (workspaceMarkers.some((m) => (0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, m)))) return "monorepo";
18138
+ const pkg = readJson((0, import_node_path24.join)(root, "package.json"));
18075
18139
  if (pkg && "workspaces" in pkg) return "monorepo";
18076
18140
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
18077
18141
  const nested = manifests.filter((f) => f.includes("/"));
@@ -18093,10 +18157,10 @@ function measureAvgFileLength(root, files, languages) {
18093
18157
  let total = 0;
18094
18158
  let counted = 0;
18095
18159
  for (let i = 0; i < candidates2.length; i += stride) {
18096
- const path = (0, import_node_path23.join)(root, candidates2[i]);
18160
+ const path = (0, import_node_path24.join)(root, candidates2[i]);
18097
18161
  try {
18098
- if ((0, import_node_fs25.statSync)(path).size > 2 * 1024 * 1024) continue;
18099
- total += (0, import_node_fs25.readFileSync)(path, "utf-8").split("\n").length;
18162
+ if ((0, import_node_fs26.statSync)(path).size > 2 * 1024 * 1024) continue;
18163
+ total += (0, import_node_fs26.readFileSync)(path, "utf-8").split("\n").length;
18100
18164
  counted++;
18101
18165
  } catch {
18102
18166
  }
@@ -18126,14 +18190,14 @@ function detectProject(root = repoRoot()) {
18126
18190
  const existingToolConfigs = [];
18127
18191
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
18128
18192
  for (const marker of markers) {
18129
- if ((0, import_node_fs25.existsSync)((0, import_node_path23.join)(root, marker))) {
18193
+ if ((0, import_node_fs26.existsSync)((0, import_node_path24.join)(root, marker))) {
18130
18194
  existingToolConfigs.push({ tool, path: `./${marker}` });
18131
18195
  break;
18132
18196
  }
18133
18197
  }
18134
18198
  }
18135
18199
  return {
18136
- projectName: (0, import_node_path23.basename)(root),
18200
+ projectName: (0, import_node_path24.basename)(root),
18137
18201
  languages,
18138
18202
  languageCounts,
18139
18203
  frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
@@ -18231,8 +18295,8 @@ ${closingNote(input.origin)}
18231
18295
 
18232
18296
  // src/lib/synthesize.ts
18233
18297
  function loadCatalog() {
18234
- const catalog = (0, import_yaml.parse)((0, import_node_fs26.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
18235
- const template = (0, import_yaml.parse)((0, import_node_fs26.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
18298
+ const catalog = (0, import_yaml.parse)((0, import_node_fs27.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
18299
+ const template = (0, import_yaml.parse)((0, import_node_fs27.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
18236
18300
  return { catalog, template };
18237
18301
  }
18238
18302
  function selectTools(languages, intensity, catalog) {
@@ -18510,7 +18574,7 @@ function validatePatternIds() {
18510
18574
  }
18511
18575
  async function runSynthesis(opts) {
18512
18576
  const standardPath = projectPath(STANDARD_FILE);
18513
- if ((0, import_node_fs26.existsSync)(standardPath) && !opts.force) {
18577
+ if ((0, import_node_fs27.existsSync)(standardPath) && !opts.force) {
18514
18578
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
18515
18579
  }
18516
18580
  const detected = opts.detected ?? detectProject();
@@ -18577,9 +18641,9 @@ async function correctVerityMdVersion(opts) {
18577
18641
  origin: { kind: "synthesized", tools: opts.tools }
18578
18642
  }));
18579
18643
  }
18580
- async function writeFileTo(relative2, body) {
18581
- const target = projectPath(relative2);
18582
- await (0, import_promises10.mkdir)((0, import_node_path24.dirname)(target), { recursive: true });
18644
+ async function writeFileTo(relative3, body) {
18645
+ const target = projectPath(relative3);
18646
+ await (0, import_promises10.mkdir)((0, import_node_path25.dirname)(target), { recursive: true });
18583
18647
  await (0, import_promises10.writeFile)(target, body);
18584
18648
  }
18585
18649
  async function deriveConfigForStandard(standard) {
@@ -18638,11 +18702,11 @@ ${validation.detail}`);
18638
18702
 
18639
18703
  // src/lib/setup-state.ts
18640
18704
  var import_promises11 = require("node:fs/promises");
18641
- var import_node_fs27 = require("node:fs");
18705
+ var import_node_fs28 = require("node:fs");
18642
18706
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
18643
18707
  async function readSetupState() {
18644
18708
  const path = projectPath(SETUP_STATE_FILE);
18645
- if (!(0, import_node_fs27.existsSync)(path)) return null;
18709
+ if (!(0, import_node_fs28.existsSync)(path)) return null;
18646
18710
  try {
18647
18711
  const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
18648
18712
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -18658,12 +18722,12 @@ async function writeSetupState(patch) {
18658
18722
  }
18659
18723
 
18660
18724
  // src/lib/push-setup.ts
18661
- var import_node_fs29 = require("node:fs");
18725
+ var import_node_fs30 = require("node:fs");
18662
18726
  var import_promises12 = require("node:fs/promises");
18663
18727
  var import_yaml2 = __toESM(require_dist());
18664
18728
 
18665
18729
  // src/lib/verityignore.ts
18666
- var import_node_fs28 = require("node:fs");
18730
+ var import_node_fs29 = require("node:fs");
18667
18731
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
18668
18732
  var SECURITY_PROBES = [
18669
18733
  ".env",
@@ -18756,9 +18820,9 @@ function isIgnored3(ig, path) {
18756
18820
  }
18757
18821
  function loadVerityIgnore() {
18758
18822
  const file = projectPath(VERITYIGNORE_FILE);
18759
- if (!(0, import_node_fs28.existsSync)(file)) return EMPTY;
18823
+ if (!(0, import_node_fs29.existsSync)(file)) return EMPTY;
18760
18824
  try {
18761
- return parseVerityIgnore((0, import_node_fs28.readFileSync)(file, "utf-8"));
18825
+ return parseVerityIgnore((0, import_node_fs29.readFileSync)(file, "utf-8"));
18762
18826
  } catch {
18763
18827
  return EMPTY;
18764
18828
  }
@@ -18796,9 +18860,9 @@ function buildStandardUpload(standard, ignoreRaw) {
18796
18860
  }
18797
18861
  function readVerityIgnoreRaw() {
18798
18862
  const file = projectPath(VERITYIGNORE_FILE);
18799
- if (!(0, import_node_fs28.existsSync)(file)) return null;
18863
+ if (!(0, import_node_fs29.existsSync)(file)) return null;
18800
18864
  try {
18801
- return (0, import_node_fs28.readFileSync)(file, "utf-8");
18865
+ return (0, import_node_fs29.readFileSync)(file, "utf-8");
18802
18866
  } catch {
18803
18867
  return null;
18804
18868
  }
@@ -18826,7 +18890,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18826
18890
  }
18827
18891
  let standardVersion = null;
18828
18892
  const standardPath = projectPath(STANDARD_FILE);
18829
- if (pushStandard && (0, import_node_fs29.existsSync)(standardPath)) {
18893
+ if (pushStandard && (0, import_node_fs30.existsSync)(standardPath)) {
18830
18894
  try {
18831
18895
  const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
18832
18896
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -18851,7 +18915,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18851
18915
  }
18852
18916
  let configPushed = false;
18853
18917
  const configPath = projectPath(CODACY_CONFIG_FILE);
18854
- if (pushConfig && (0, import_node_fs29.existsSync)(configPath)) {
18918
+ if (pushConfig && (0, import_node_fs30.existsSync)(configPath)) {
18855
18919
  try {
18856
18920
  const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
18857
18921
  const result = await apiRequest({
@@ -18883,7 +18947,7 @@ function registerStandardCommands(program2) {
18883
18947
  const state = await readSetupState();
18884
18948
  if (opts.configOnly) {
18885
18949
  const standardPath = projectPath(STANDARD_FILE);
18886
- if (!(0, import_node_fs30.existsSync)(standardPath)) {
18950
+ if (!(0, import_node_fs31.existsSync)(standardPath)) {
18887
18951
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
18888
18952
  process.exit(1);
18889
18953
  }
@@ -19195,7 +19259,9 @@ function formatRunDetail(run2) {
19195
19259
  if (f.description && f.description !== title) lines.push(` ${f.description}`);
19196
19260
  const fix = f.fix?.description ?? f.suggestion;
19197
19261
  if (fix) lines.push(` \u21B3 fix: ${fix}`);
19198
- if (f.scope === "pre-existing") lines.push(" (pre-existing)");
19262
+ if (f.scope === "pre-existing") {
19263
+ lines.push(f.provenance === "caused-elsewhere" ? " (caused elsewhere \u2014 not by this change)" : " (pre-existing)");
19264
+ }
19199
19265
  }
19200
19266
  }
19201
19267
  const pending = run2.pending_items ?? [];
@@ -19214,10 +19280,10 @@ function formatRunDetail(run2) {
19214
19280
  }
19215
19281
 
19216
19282
  // src/lib/ignore-declaration.ts
19217
- var import_node_fs32 = require("node:fs");
19283
+ var import_node_fs33 = require("node:fs");
19218
19284
 
19219
19285
  // src/lib/debounce.ts
19220
- var import_node_fs31 = require("node:fs");
19286
+ var import_node_fs32 = require("node:fs");
19221
19287
  var import_node_crypto10 = require("node:crypto");
19222
19288
  function scopedFile(base, sessionId) {
19223
19289
  if (!sessionId) return base;
@@ -19225,9 +19291,9 @@ function scopedFile(base, sessionId) {
19225
19291
  }
19226
19292
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
19227
19293
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19228
- if (!(0, import_node_fs31.existsSync)(file)) return null;
19294
+ if (!(0, import_node_fs32.existsSync)(file)) return null;
19229
19295
  try {
19230
- const lastTs = parseInt((0, import_node_fs31.readFileSync)(file, "utf-8").trim(), 10);
19296
+ const lastTs = parseInt((0, import_node_fs32.readFileSync)(file, "utf-8").trim(), 10);
19231
19297
  const nowTs = Math.floor(Date.now() / 1e3);
19232
19298
  const elapsed = nowTs - lastTs;
19233
19299
  if (elapsed < debounceSeconds) {
@@ -19240,10 +19306,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
19240
19306
  function checkMtime(files, bypassForRecentCommits, sessionId) {
19241
19307
  if (bypassForRecentCommits) return null;
19242
19308
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19243
- if (!(0, import_node_fs31.existsSync)(file)) return null;
19309
+ if (!(0, import_node_fs32.existsSync)(file)) return null;
19244
19310
  let debounceTime;
19245
19311
  try {
19246
- debounceTime = (0, import_node_fs31.statSync)(file).mtimeMs;
19312
+ debounceTime = (0, import_node_fs32.statSync)(file).mtimeMs;
19247
19313
  } catch {
19248
19314
  return null;
19249
19315
  }
@@ -19251,7 +19317,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
19251
19317
  const resolved = resolveFile(f);
19252
19318
  if (!resolved) continue;
19253
19319
  try {
19254
- const stat3 = (0, import_node_fs31.statSync)(resolved);
19320
+ const stat3 = (0, import_node_fs32.statSync)(resolved);
19255
19321
  if (stat3.mtimeMs > debounceTime) {
19256
19322
  return null;
19257
19323
  }
@@ -19267,8 +19333,8 @@ function computeContentHash(files) {
19267
19333
  for (const f of sorted) {
19268
19334
  const resolved = resolveFile(f) ?? f;
19269
19335
  try {
19270
- if ((0, import_node_fs31.existsSync)(resolved)) {
19271
- hash.update((0, import_node_fs31.readFileSync)(resolved));
19336
+ if ((0, import_node_fs32.existsSync)(resolved)) {
19337
+ hash.update((0, import_node_fs32.readFileSync)(resolved));
19272
19338
  }
19273
19339
  } catch {
19274
19340
  }
@@ -19278,9 +19344,9 @@ function computeContentHash(files) {
19278
19344
  function checkContentHash(files, sessionId) {
19279
19345
  const hash = computeContentHash(files);
19280
19346
  const file = scopedFile(HASH_FILE, sessionId);
19281
- if ((0, import_node_fs31.existsSync)(file)) {
19347
+ if ((0, import_node_fs32.existsSync)(file)) {
19282
19348
  try {
19283
- const storedHash = (0, import_node_fs31.readFileSync)(file, "utf-8").trim();
19349
+ const storedHash = (0, import_node_fs32.readFileSync)(file, "utf-8").trim();
19284
19350
  if (hash === storedHash) {
19285
19351
  return { skip: "No source changes since last analysis", hash };
19286
19352
  }
@@ -19290,24 +19356,24 @@ function checkContentHash(files, sessionId) {
19290
19356
  return { skip: null, hash };
19291
19357
  }
19292
19358
  function recordAnalysisStart(sessionId) {
19293
- (0, import_node_fs31.mkdirSync)(VERITY_DIR, { recursive: true });
19294
- (0, import_node_fs31.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
19359
+ (0, import_node_fs32.mkdirSync)(VERITY_DIR, { recursive: true });
19360
+ (0, import_node_fs32.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
19295
19361
  }
19296
19362
  function recordPassHash(hash, sessionId) {
19297
- (0, import_node_fs31.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
19363
+ (0, import_node_fs32.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
19298
19364
  }
19299
19365
  function narrowToRecent(files, sessionId) {
19300
19366
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19301
- if (!(0, import_node_fs31.existsSync)(file)) return files;
19367
+ if (!(0, import_node_fs32.existsSync)(file)) return files;
19302
19368
  let debounceTime;
19303
19369
  try {
19304
- debounceTime = (0, import_node_fs31.statSync)(file).mtimeMs;
19370
+ debounceTime = (0, import_node_fs32.statSync)(file).mtimeMs;
19305
19371
  } catch {
19306
19372
  return files;
19307
19373
  }
19308
19374
  const recent = files.filter((f) => {
19309
19375
  try {
19310
- return (0, import_node_fs31.existsSync)(f) && (0, import_node_fs31.statSync)(f).mtimeMs > debounceTime;
19376
+ return (0, import_node_fs32.existsSync)(f) && (0, import_node_fs32.statSync)(f).mtimeMs > debounceTime;
19311
19377
  } catch {
19312
19378
  return false;
19313
19379
  }
@@ -19320,9 +19386,9 @@ function readIteration(currentCommit, _contentHash) {
19320
19386
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
19321
19387
  function readBlockState(currentCommit, opts) {
19322
19388
  if (opts?.newUserPrompt) return NO_BLOCKS;
19323
- if (!(0, import_node_fs31.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
19389
+ if (!(0, import_node_fs32.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
19324
19390
  try {
19325
- const stored = (0, import_node_fs31.readFileSync)(ITERATION_FILE, "utf-8").trim();
19391
+ const stored = (0, import_node_fs32.readFileSync)(ITERATION_FILE, "utf-8").trim();
19326
19392
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
19327
19393
  if (!parsed) return NO_BLOCKS;
19328
19394
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -19368,8 +19434,8 @@ function isSameProblem(previous, current) {
19368
19434
  return current.split(",").some((k) => prev.has(k));
19369
19435
  }
19370
19436
  function writeBlockState(commit, state) {
19371
- (0, import_node_fs31.mkdirSync)(VERITY_DIR, { recursive: true });
19372
- (0, import_node_fs31.writeFileSync)(
19437
+ (0, import_node_fs32.mkdirSync)(VERITY_DIR, { recursive: true });
19438
+ (0, import_node_fs32.writeFileSync)(
19373
19439
  ITERATION_FILE,
19374
19440
  JSON.stringify({
19375
19441
  v: 2,
@@ -19474,9 +19540,9 @@ function resolveIgnoreState(keys) {
19474
19540
  }
19475
19541
  function readIgnoreState(sessionId) {
19476
19542
  const file = stateFile(sessionId);
19477
- if (!(0, import_node_fs32.existsSync)(file)) return null;
19543
+ if (!(0, import_node_fs33.existsSync)(file)) return null;
19478
19544
  try {
19479
- const o = JSON.parse((0, import_node_fs32.readFileSync)(file, "utf-8")) ?? {};
19545
+ const o = JSON.parse((0, import_node_fs33.readFileSync)(file, "utf-8")) ?? {};
19480
19546
  const spent = typeof o.spent === "number" ? o.spent : 0;
19481
19547
  const raw = o.active;
19482
19548
  let active = null;
@@ -19500,8 +19566,8 @@ function readIgnoreState(sessionId) {
19500
19566
  }
19501
19567
  function writeIgnoreState(state, sessionId) {
19502
19568
  try {
19503
- (0, import_node_fs32.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
19504
- (0, import_node_fs32.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
19569
+ (0, import_node_fs33.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
19570
+ (0, import_node_fs33.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
19505
19571
  } catch {
19506
19572
  }
19507
19573
  }
@@ -19884,7 +19950,7 @@ function createRun(opts, globals) {
19884
19950
  }
19885
19951
 
19886
19952
  // src/commands/analyze/index.ts
19887
- var import_node_fs45 = require("node:fs");
19953
+ var import_node_fs46 = require("node:fs");
19888
19954
 
19889
19955
  // src/lib/repo-context.ts
19890
19956
  var import_node_child_process10 = require("node:child_process");
@@ -20395,6 +20461,112 @@ function partitionSites(rgLines, symbols, opts) {
20395
20461
  while (callers.length + tests.length > MAX_SITES) callers.pop();
20396
20462
  return { callers, tests, dropped };
20397
20463
  }
20464
+ var MAX_IMPORTERS = 12;
20465
+ var MAX_IMPORTERS_PER_FILE = 2;
20466
+ function moduleKey(path) {
20467
+ return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
20468
+ }
20469
+ function importSpecifier(text) {
20470
+ const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text);
20471
+ return m?.[1] ?? null;
20472
+ }
20473
+ function resolveSpecifier(fromFile, spec) {
20474
+ if (!spec.startsWith(".")) return null;
20475
+ const dir = fromFile.includes("/") ? fromFile.slice(0, fromFile.lastIndexOf("/")) : "";
20476
+ const out = [];
20477
+ for (const part of (dir ? dir.split("/") : []).concat(spec.split("/"))) {
20478
+ if (part === "" || part === ".") continue;
20479
+ if (part === "..") {
20480
+ if (out.length === 0) return null;
20481
+ out.pop();
20482
+ continue;
20483
+ }
20484
+ out.push(part);
20485
+ }
20486
+ return out.length > 0 ? moduleKey(out.join("/")) : null;
20487
+ }
20488
+ function partitionImporters(rgLines, changedPaths, opts) {
20489
+ const changedByKey = /* @__PURE__ */ new Map();
20490
+ for (const p of changedPaths) changedByKey.set(moduleKey(p), p);
20491
+ const hits = rgLines.map(parseRgLine).filter((h) => h !== null);
20492
+ hits.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line);
20493
+ const perFile = /* @__PURE__ */ new Map();
20494
+ const out = [];
20495
+ for (const h of hits) {
20496
+ if (out.length >= MAX_IMPORTERS) break;
20497
+ if (opts.sentPaths.has(h.file)) continue;
20498
+ if (opts.isExcluded(h.file)) continue;
20499
+ if (!isCodeSiteFile(h.file)) continue;
20500
+ const spec = importSpecifier(h.text);
20501
+ if (!spec) continue;
20502
+ const resolved = resolveSpecifier(h.file, spec);
20503
+ if (!resolved) continue;
20504
+ const changed = changedByKey.get(resolved);
20505
+ if (!changed) continue;
20506
+ const used = perFile.get(h.file) ?? 0;
20507
+ if (used >= MAX_IMPORTERS_PER_FILE) continue;
20508
+ perFile.set(h.file, used + 1);
20509
+ out.push({ file: h.file, line: h.line, text: h.text.trim().slice(0, SITE_TEXT_MAX), symbol: changed });
20510
+ }
20511
+ return out;
20512
+ }
20513
+ function runRg(args, cwd, timeoutMs) {
20514
+ let res = null;
20515
+ for (const inv of rgInvocations()) {
20516
+ res = (0, import_node_child_process10.spawnSync)(inv.cmd, args, {
20517
+ ...inv.argv0 ? { argv0: inv.argv0 } : {},
20518
+ cwd,
20519
+ env: ripgrepEnv(),
20520
+ timeout: timeoutMs,
20521
+ maxBuffer: 4 * 1024 * 1024,
20522
+ encoding: "utf8"
20523
+ });
20524
+ if (res.error?.code !== "ENOENT") break;
20525
+ }
20526
+ if (!res || res.error?.code === "ENOENT") {
20527
+ return { ok: false, reason: "no-tool" };
20528
+ }
20529
+ if (res.error) {
20530
+ const code = res.error.code;
20531
+ return { ok: false, reason: code === "ETIMEDOUT" ? "timeout" : "error" };
20532
+ }
20533
+ if (res.signal) return { ok: false, reason: "timeout" };
20534
+ if (res.status !== 0 && res.status !== 1) return { ok: false, reason: "error" };
20535
+ return { ok: true, lines: (res.stdout ?? "").split("\n").map((l) => l.replace(/^\.\//, "")).filter(Boolean) };
20536
+ }
20537
+ function findImporters(input) {
20538
+ const basenames = [
20539
+ ...new Set(input.changedPaths.map((p) => moduleKey(p).split("/").pop() ?? "").filter((b) => b.length > 0))
20540
+ ].slice(0, MAX_SYMBOLS);
20541
+ if (basenames.length === 0) return [];
20542
+ const res = runRg(
20543
+ [
20544
+ "--no-config",
20545
+ "-n",
20546
+ "-w",
20547
+ "-F",
20548
+ "--no-heading",
20549
+ "--color",
20550
+ "never",
20551
+ "-m",
20552
+ "8",
20553
+ "--max-columns",
20554
+ "300",
20555
+ "--max-columns-preview",
20556
+ ...basenames.flatMap((b) => ["-e", b]),
20557
+ "-g",
20558
+ "!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
20559
+ "./"
20560
+ ],
20561
+ input.cwd,
20562
+ input.timeoutMs
20563
+ );
20564
+ if (!res.ok) return [];
20565
+ return partitionImporters(res.lines, input.changedPaths, {
20566
+ sentPaths: input.sentPaths,
20567
+ isExcluded: input.isExcluded
20568
+ });
20569
+ }
20398
20570
  function buildRepoContext(input) {
20399
20571
  const started = Date.now();
20400
20572
  let signalsByPath;
@@ -20429,7 +20601,18 @@ function buildRepoContext(input) {
20429
20601
  const unsupportedExts = [...unsupported].sort().slice(0, 8);
20430
20602
  const audit = unsupportedExts.length > 0 ? { unsupported_exts: unsupportedExts } : {};
20431
20603
  const symbols = rankSymbols([...new Set(collected)]);
20604
+ const changedPaths = [.../* @__PURE__ */ new Set([...signalsByPath.keys(), ...input.deltaFiles.map((f) => f.path)])];
20605
+ const importers = findImporters({
20606
+ changedPaths,
20607
+ sentPaths: input.sentPaths,
20608
+ isExcluded: input.isExcluded,
20609
+ cwd: input.cwd ?? process.cwd(),
20610
+ timeoutMs: input.timeoutMs ?? RG_TIMEOUT_MS
20611
+ });
20432
20612
  if (symbols.length === 0) {
20613
+ if (importers.length > 0) {
20614
+ return { state: "ok", symbols: [], ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
20615
+ }
20433
20616
  const everySupportedFileFoundNothing = unsupportedExts.length > 0;
20434
20617
  return {
20435
20618
  state: "absent",
@@ -20468,34 +20651,19 @@ function buildRepoContext(input) {
20468
20651
  "!**/{dist,build,out,vendor,node_modules,.git,coverage,target,__pycache__}/**",
20469
20652
  "./"
20470
20653
  ];
20471
- let res = null;
20472
- for (const inv of rgInvocations()) {
20473
- res = (0, import_node_child_process10.spawnSync)(inv.cmd, args, {
20474
- ...inv.argv0 ? { argv0: inv.argv0 } : {},
20475
- cwd: input.cwd ?? process.cwd(),
20476
- env: ripgrepEnv(),
20477
- timeout: input.timeoutMs ?? RG_TIMEOUT_MS,
20478
- maxBuffer: 4 * 1024 * 1024,
20479
- encoding: "utf8"
20480
- });
20481
- if (res.error?.code !== "ENOENT") break;
20482
- }
20483
- if (!res || res.error?.code === "ENOENT") {
20484
- return { state: "absent", reason: "no-tool", symbols, ...audit };
20485
- }
20486
- if (res.error) {
20487
- const code = res.error.code;
20488
- if (code === "ETIMEDOUT") return { state: "absent", reason: "timeout", symbols, ...audit };
20489
- return { state: "absent", reason: "error", symbols, ...audit };
20654
+ const res = runRg(args, input.cwd ?? process.cwd(), input.timeoutMs ?? RG_TIMEOUT_MS);
20655
+ if (!res.ok) {
20656
+ if (importers.length > 0) {
20657
+ return { state: "ok", symbols, ...audit, callers: [], tests: [], importers, elapsed_ms: Date.now() - started };
20658
+ }
20659
+ return { state: "absent", reason: res.reason, symbols, ...audit };
20490
20660
  }
20491
- if (res.signal) return { state: "absent", reason: "timeout", symbols, ...audit };
20492
- if (res.status !== 0 && res.status !== 1) return { state: "absent", reason: "error", symbols, ...audit };
20493
- const lines = (res.stdout ?? "").split("\n").map((l) => l.replace(/^\.\//, "")).filter(Boolean);
20661
+ const lines = res.lines;
20494
20662
  const { callers, tests, dropped } = partitionSites(lines, symbols, {
20495
20663
  sentPaths: input.sentPaths,
20496
20664
  isExcluded: input.isExcluded
20497
20665
  });
20498
- if (callers.length === 0 && tests.length === 0) {
20666
+ if (callers.length === 0 && tests.length === 0 && importers.length === 0) {
20499
20667
  return {
20500
20668
  state: "absent",
20501
20669
  reason: "no-sites",
@@ -20512,6 +20680,7 @@ function buildRepoContext(input) {
20512
20680
  ...audit,
20513
20681
  callers,
20514
20682
  tests,
20683
+ ...importers.length > 0 ? { importers } : {},
20515
20684
  elapsed_ms: Date.now() - started
20516
20685
  };
20517
20686
  }
@@ -20579,12 +20748,17 @@ function upgradeToExcerpts(rc, opts) {
20579
20748
  }
20580
20749
  function describeRepoContext(rc) {
20581
20750
  if (rc.state !== "ok") {
20582
- const exts = rc.unsupported_exts?.length ? ` \xB7 no rules for: ${rc.unsupported_exts.join(", ")}` : "";
20583
- return `absent (${rc.reason ?? "unknown"})${exts}`;
20751
+ const bits = [
20752
+ rc.symbols?.length ? `searched: ${rc.symbols.join(", ")}` : "",
20753
+ rc.dropped_symbols?.length ? `dropped too-common: ${rc.dropped_symbols.join(", ")}` : "",
20754
+ rc.unsupported_exts?.length ? `no rules for: ${rc.unsupported_exts.join(", ")}` : ""
20755
+ ].filter(Boolean);
20756
+ return `absent (${rc.reason ?? "unknown"})${bits.length > 0 ? ` \xB7 ${bits.join(" \xB7 ")}` : ""}`;
20584
20757
  }
20585
20758
  const parts = [
20586
20759
  `${rc.symbols?.length ?? 0} symbol(s) \u2192 ${rc.callers?.length ?? 0} caller(s) \xB7 ${rc.tests?.length ?? 0} test(s)`
20587
20760
  ];
20761
+ if (rc.importers?.length) parts.push(`${rc.importers.length} importer(s)`);
20588
20762
  if (rc.excerpts?.length) parts.push(`${rc.excerpts.length} excerpt(s)`);
20589
20763
  if (rc.dropped_symbols?.length) parts.push(`dropped too-common: ${rc.dropped_symbols.join(", ")}`);
20590
20764
  if (rc.unsupported_exts?.length) parts.push(`no rules for: ${rc.unsupported_exts.join(", ")}`);
@@ -20712,10 +20886,10 @@ function installRunEvidence(run2) {
20712
20886
  }
20713
20887
 
20714
20888
  // src/lib/git-frame.ts
20715
- var import_node_fs33 = require("node:fs");
20889
+ var import_node_fs34 = require("node:fs");
20716
20890
  var import_node_os5 = require("node:os");
20717
- var import_node_path25 = require("node:path");
20718
20891
  var import_node_path26 = require("node:path");
20892
+ var import_node_path27 = require("node:path");
20719
20893
 
20720
20894
  // src/lib/hardened-git.ts
20721
20895
  var import_node_child_process11 = require("node:child_process");
@@ -20877,8 +21051,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
20877
21051
  if (SHELL_DYNAMIC.test(raw) || raw === "-") {
20878
21052
  return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
20879
21053
  }
20880
- const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path26.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20881
- dir = (0, import_node_path25.isAbsolute)(expanded) ? expanded : (0, import_node_path25.resolve)(dir, expanded);
21054
+ const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path27.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
21055
+ dir = (0, import_node_path26.isAbsolute)(expanded) ? expanded : (0, import_node_path26.resolve)(dir, expanded);
20882
21056
  }
20883
21057
  const seg = segments[segmentIndex];
20884
21058
  const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
@@ -20896,8 +21070,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
20896
21070
  if (SHELL_DYNAMIC.test(raw)) {
20897
21071
  return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
20898
21072
  }
20899
- const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path26.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
20900
- dir = (0, import_node_path25.isAbsolute)(expanded) ? expanded : (0, import_node_path25.resolve)(dir, expanded);
21073
+ const expanded = raw === "~" ? (0, import_node_os5.homedir)() : raw.startsWith("~/") ? (0, import_node_path27.join)((0, import_node_os5.homedir)(), raw.slice(2)) : raw;
21074
+ dir = (0, import_node_path26.isAbsolute)(expanded) ? expanded : (0, import_node_path26.resolve)(dir, expanded);
20901
21075
  }
20902
21076
  }
20903
21077
  return { dir, named, unresolvable: null };
@@ -20957,14 +21131,14 @@ function gitAt(dir, args) {
20957
21131
  }
20958
21132
  function realpathOr2(p) {
20959
21133
  try {
20960
- return import_node_fs33.realpathSync.native(p);
21134
+ return import_node_fs34.realpathSync.native(p);
20961
21135
  } catch {
20962
- return (0, import_node_path25.resolve)(p);
21136
+ return (0, import_node_path26.resolve)(p);
20963
21137
  }
20964
21138
  }
20965
21139
  function resolveFrame(input) {
20966
21140
  const found = findMomentSegment(input.command, input.on);
20967
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs33.existsSync)(input.hookCwd);
21141
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs34.existsSync)(input.hookCwd);
20968
21142
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
20969
21143
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
20970
21144
  const refuse = (refusal) => ({
@@ -20987,7 +21161,7 @@ function resolveFrame(input) {
20987
21161
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
20988
21162
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
20989
21163
  if (targetDir !== baseDir) {
20990
- if (!(0, import_node_fs33.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
21164
+ if (!(0, import_node_fs34.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
20991
21165
  dir = targetDir;
20992
21166
  }
20993
21167
  }
@@ -20998,7 +21172,7 @@ function resolveFrame(input) {
20998
21172
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
20999
21173
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
21000
21174
  const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
21001
- const commonDir = commonRaw ? realpathOr2((0, import_node_path25.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path25.resolve)(dir, commonRaw)) : null;
21175
+ const commonDir = commonRaw ? realpathOr2((0, import_node_path26.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path26.resolve)(dir, commonRaw)) : null;
21002
21176
  const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
21003
21177
  return {
21004
21178
  moment: found?.moment ?? null,
@@ -21173,8 +21347,8 @@ function stagedRange(frame, command) {
21173
21347
  if (plan.kind === "unpredictable") {
21174
21348
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
21175
21349
  }
21176
- const mergeHead = frame.gitDir ? (0, import_node_path26.join)(frame.gitDir, "MERGE_HEAD") : null;
21177
- if (mergeHead && (0, import_node_fs33.existsSync)(mergeHead)) {
21350
+ const mergeHead = frame.gitDir ? (0, import_node_path27.join)(frame.gitDir, "MERGE_HEAD") : null;
21351
+ if (mergeHead && (0, import_node_fs34.existsSync)(mergeHead)) {
21178
21352
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
21179
21353
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
21180
21354
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -21308,7 +21482,7 @@ function truthy(v) {
21308
21482
  }
21309
21483
 
21310
21484
  // src/lib/transcript.ts
21311
- var import_node_fs34 = require("node:fs");
21485
+ var import_node_fs35 = require("node:fs");
21312
21486
  var MAX_READ_BYTES = 256 * 1024;
21313
21487
  var SMALL_FILE_BYTES = 64 * 1024;
21314
21488
  var MAX_FILES_LIST = 20;
@@ -21335,7 +21509,7 @@ async function extractActionSummary(transcriptPath) {
21335
21509
  function readTurnLines(transcriptPath) {
21336
21510
  let size;
21337
21511
  try {
21338
- size = (0, import_node_fs34.statSync)(transcriptPath).size;
21512
+ size = (0, import_node_fs35.statSync)(transcriptPath).size;
21339
21513
  } catch {
21340
21514
  return null;
21341
21515
  }
@@ -21343,7 +21517,7 @@ function readTurnLines(transcriptPath) {
21343
21517
  let raw;
21344
21518
  let windowed = false;
21345
21519
  if (size <= SMALL_FILE_BYTES) {
21346
- raw = (0, import_node_fs34.readFileSync)(transcriptPath, "utf-8");
21520
+ raw = (0, import_node_fs35.readFileSync)(transcriptPath, "utf-8");
21347
21521
  } else {
21348
21522
  windowed = true;
21349
21523
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -21851,7 +22025,7 @@ function channelSilence(input) {
21851
22025
  // src/lib/cli-version.ts
21852
22026
  function cliVersion() {
21853
22027
  try {
21854
- return true ? "0.33.0-experimental.d60f544" : "dev";
22028
+ return true ? "0.33.0" : "dev";
21855
22029
  } catch {
21856
22030
  return "dev";
21857
22031
  }
@@ -21892,7 +22066,7 @@ async function sendSkipBeacon(ctx, reason) {
21892
22066
 
21893
22067
  // src/lib/static-analysis.ts
21894
22068
  var import_node_child_process12 = require("node:child_process");
21895
- var import_node_fs35 = require("node:fs");
22069
+ var import_node_fs36 = require("node:fs");
21896
22070
  var SEVERITY_ORDER = {
21897
22071
  Error: 0,
21898
22072
  Critical: 0,
@@ -21903,12 +22077,10 @@ var SEVERITY_ORDER = {
21903
22077
  Low: 3
21904
22078
  };
21905
22079
  function isCodacyAvailable() {
21906
- try {
21907
- (0, import_node_child_process12.execSync)("which codacy-analysis", { stdio: "pipe" });
21908
- return true;
21909
- } catch {
21910
- return false;
21911
- }
22080
+ return codacyAnalysisPath() !== null;
22081
+ }
22082
+ function codacyAnalysisPath() {
22083
+ return whichSync("codacy-analysis");
21912
22084
  }
21913
22085
  function buildAnalyzerArgv(files) {
21914
22086
  return [
@@ -21935,18 +22107,29 @@ function withFailure(kind, detail) {
21935
22107
  summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
21936
22108
  };
21937
22109
  }
22110
+ function runCodacyAnalysisIfAvailable(files) {
22111
+ if (files.length === 0) return EMPTY_RESULT;
22112
+ if (!isCodacyAvailable()) {
22113
+ return withFailure(
22114
+ "analyzer_unavailable",
22115
+ "@codacy/analysis-cli was not found on PATH \u2014 no static analysis ran"
22116
+ );
22117
+ }
22118
+ return runCodacyAnalysis(files);
22119
+ }
21938
22120
  function runCodacyAnalysis(files) {
21939
22121
  const empty = EMPTY_RESULT;
21940
22122
  if (files.length === 0) return empty;
21941
22123
  const existingFiles = files.filter((f) => {
21942
22124
  try {
21943
- return (0, import_node_fs35.existsSync)(f);
22125
+ return (0, import_node_fs36.existsSync)(f);
21944
22126
  } catch {
21945
22127
  return false;
21946
22128
  }
21947
22129
  });
21948
22130
  if (existingFiles.length === 0) return empty;
21949
- const proc = (0, import_node_child_process12.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
22131
+ const analyzer = codacyAnalysisPath() ?? "codacy-analysis";
22132
+ const proc = (0, import_node_child_process12.spawnSync)(analyzer, buildAnalyzerArgv(existingFiles), {
21950
22133
  encoding: "utf-8",
21951
22134
  maxBuffer: 10 * 1024 * 1024
21952
22135
  });
@@ -22114,11 +22297,10 @@ var EMPTY_STATIC = {
22114
22297
  summary: { total_findings: 0, by_severity: {}, tools_run: [] }
22115
22298
  };
22116
22299
  function runLocalStatic(analyzable, securityFiles, baseline, skipStatic) {
22117
- if (skipStatic || !isCodacyAvailable()) return EMPTY_STATIC;
22300
+ if (skipStatic) return EMPTY_STATIC;
22118
22301
  let scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
22119
22302
  if (baseline) scannable = scannable.filter((f) => changedSinceBaseline(f, baseline));
22120
- if (scannable.length === 0) return EMPTY_STATIC;
22121
- return runCodacyAnalysis(scannable);
22303
+ return runCodacyAnalysisIfAvailable(scannable);
22122
22304
  }
22123
22305
  function localOnlyAndExit(staticResults) {
22124
22306
  printJsonCompact({
@@ -22209,8 +22391,8 @@ async function scope(run2) {
22209
22391
  }
22210
22392
 
22211
22393
  // src/lib/specs.ts
22212
- var import_node_fs36 = require("node:fs");
22213
- var import_node_path27 = require("node:path");
22394
+ var import_node_fs37 = require("node:fs");
22395
+ var import_node_path28 = require("node:path");
22214
22396
  var SPEC_CANDIDATES = [
22215
22397
  "CLAUDE.md",
22216
22398
  "AGENTS.md",
@@ -22229,6 +22411,16 @@ var SPEC_CANDIDATES = [
22229
22411
  var DOC_EXT = /\.(md|mdx|ya?ml|txt|rst|adoc)$/i;
22230
22412
  var UNCONSULTED_FILE_BYTES = 10240;
22231
22413
  var UNCONSULTED_TOTAL_BYTES = 30720;
22414
+ function readSpecFiles(specsOpt, root) {
22415
+ const out = [];
22416
+ for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
22417
+ const candidate = (0, import_node_path28.isAbsolute)(raw) ? (0, import_node_path28.relative)(root, raw) : raw;
22418
+ const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
22419
+ if (content === null) continue;
22420
+ out.push({ path: raw, content });
22421
+ }
22422
+ return out;
22423
+ }
22232
22424
  function discoverSpecs(consulted = []) {
22233
22425
  const result = [];
22234
22426
  const seen = /* @__PURE__ */ new Set();
@@ -22241,7 +22433,7 @@ function discoverSpecs(consulted = []) {
22241
22433
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
22242
22434
  if (totalBytes >= totalCap) return false;
22243
22435
  if (seen.has(specPath)) return true;
22244
- if (!(0, import_node_fs36.existsSync)(specPath)) return true;
22436
+ if (!(0, import_node_fs37.existsSync)(specPath)) return true;
22245
22437
  seen.add(specPath);
22246
22438
  const remaining = totalCap - totalBytes;
22247
22439
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
@@ -22264,7 +22456,7 @@ function discoverSpecs(consulted = []) {
22264
22456
  if (!addSpec(candidate)) break;
22265
22457
  }
22266
22458
  for (const dir of ["spec", "docs"]) {
22267
- if (!(0, import_node_fs36.existsSync)(dir)) continue;
22459
+ if (!(0, import_node_fs37.existsSync)(dir)) continue;
22268
22460
  try {
22269
22461
  const mdFiles = findMdFiles(dir, 2).sort();
22270
22462
  for (const mdFile of mdFiles) {
@@ -22279,9 +22471,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
22279
22471
  if (depth >= maxDepth) return [];
22280
22472
  const result = [];
22281
22473
  try {
22282
- const entries = (0, import_node_fs36.readdirSync)(dir, { withFileTypes: true });
22474
+ const entries = (0, import_node_fs37.readdirSync)(dir, { withFileTypes: true });
22283
22475
  for (const entry of entries) {
22284
- const fullPath = (0, import_node_path27.join)(dir, entry.name);
22476
+ const fullPath = (0, import_node_path28.join)(dir, entry.name);
22285
22477
  if (entry.isFile() && entry.name.endsWith(".md")) {
22286
22478
  result.push(fullPath);
22287
22479
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -22294,25 +22486,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
22294
22486
  }
22295
22487
  function discoverPlans() {
22296
22488
  const home = process.env.HOME ?? "";
22297
- const homePlansDir = (0, import_node_path27.join)(home, ".claude", "plans");
22489
+ const homePlansDir = (0, import_node_path28.join)(home, ".claude", "plans");
22298
22490
  const sources = [];
22299
22491
  if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
22300
- sources.push({ root: process.cwd(), prefix: (0, import_node_path27.join)(".claude", "plans") });
22492
+ sources.push({ root: process.cwd(), prefix: (0, import_node_path28.join)(".claude", "plans") });
22301
22493
  }
22302
- if (home && (0, import_node_fs36.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
22494
+ if (home && (0, import_node_fs37.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
22303
22495
  const candidates2 = [];
22304
22496
  const seen = /* @__PURE__ */ new Set();
22305
22497
  for (const source of sources) {
22306
22498
  let names2;
22307
22499
  try {
22308
- names2 = (0, import_node_fs36.readdirSync)(source.prefix ? (0, import_node_path27.join)(source.root, source.prefix) : source.root);
22500
+ names2 = (0, import_node_fs37.readdirSync)(source.prefix ? (0, import_node_path28.join)(source.root, source.prefix) : source.root);
22309
22501
  } catch {
22310
22502
  continue;
22311
22503
  }
22312
22504
  for (const f of names2) {
22313
22505
  if (!f.endsWith(".md") || seen.has(f)) continue;
22314
22506
  seen.add(f);
22315
- const relPath = source.prefix ? (0, import_node_path27.join)(source.prefix, f) : f;
22507
+ const relPath = source.prefix ? (0, import_node_path28.join)(source.prefix, f) : f;
22316
22508
  const stat3 = statRegularInRoot(source.root, relPath);
22317
22509
  if (!stat3.ok) continue;
22318
22510
  candidates2.push({ name: f, root: source.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
@@ -22330,9 +22522,9 @@ function discoverPlans() {
22330
22522
  function isRealDirectoryChain(root, parts) {
22331
22523
  let current = root;
22332
22524
  for (const part of parts) {
22333
- current = (0, import_node_path27.join)(current, part);
22525
+ current = (0, import_node_path28.join)(current, part);
22334
22526
  try {
22335
- if (!(0, import_node_fs36.lstatSync)(current).isDirectory()) return false;
22527
+ if (!(0, import_node_fs37.lstatSync)(current).isDirectory()) return false;
22336
22528
  } catch {
22337
22529
  return false;
22338
22530
  }
@@ -22347,7 +22539,7 @@ function discoverGuardDocs(rangeFiles2) {
22347
22539
  if (result.length >= MAX_SPEC_FILES) break;
22348
22540
  if (!GUARD_DOC_EXT.test(path)) continue;
22349
22541
  if (path.startsWith("/") || path.includes("..")) continue;
22350
- if (!(0, import_node_fs36.existsSync)(path)) continue;
22542
+ if (!(0, import_node_fs37.existsSync)(path)) continue;
22351
22543
  const opened = openRegularInRoot(process.cwd(), path);
22352
22544
  if (!opened.ok) continue;
22353
22545
  if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
@@ -22533,8 +22725,8 @@ async function mode(run2) {
22533
22725
  }
22534
22726
 
22535
22727
  // src/lib/fold.ts
22536
- var import_node_fs37 = require("node:fs");
22537
- var import_node_path28 = require("node:path");
22728
+ var import_node_fs38 = require("node:fs");
22729
+ var import_node_path29 = require("node:path");
22538
22730
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
22539
22731
  "user",
22540
22732
  "assistant",
@@ -22671,7 +22863,7 @@ function candidateRoots(repoRoot2) {
22671
22863
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
22672
22864
  const out = [norm];
22673
22865
  try {
22674
- const real = import_node_fs37.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
22866
+ const real = import_node_fs38.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
22675
22867
  if (real !== norm) out.push(real);
22676
22868
  } catch {
22677
22869
  }
@@ -22759,31 +22951,31 @@ function fold(transcriptPath, opts = {}) {
22759
22951
  }
22760
22952
  };
22761
22953
  try {
22762
- if (!(0, import_node_fs37.existsSync)(transcriptPath)) return result;
22763
- ingest((0, import_node_fs37.readFileSync)(transcriptPath, "utf8"), "agent");
22954
+ if (!(0, import_node_fs38.existsSync)(transcriptPath)) return result;
22955
+ ingest((0, import_node_fs38.readFileSync)(transcriptPath, "utf8"), "agent");
22764
22956
  result.coverage.complete = true;
22765
22957
  } catch {
22766
22958
  return result;
22767
22959
  }
22768
22960
  try {
22769
- const sidecarDir = (0, import_node_path28.join)(
22770
- (0, import_node_path28.dirname)(transcriptPath),
22771
- (0, import_node_path28.basename)(transcriptPath).replace(/\.jsonl$/, ""),
22961
+ const sidecarDir = (0, import_node_path29.join)(
22962
+ (0, import_node_path29.dirname)(transcriptPath),
22963
+ (0, import_node_path29.basename)(transcriptPath).replace(/\.jsonl$/, ""),
22772
22964
  "subagents"
22773
22965
  );
22774
- if ((0, import_node_fs37.existsSync)(sidecarDir)) {
22966
+ if ((0, import_node_fs38.existsSync)(sidecarDir)) {
22775
22967
  const maxFiles = opts.maxSidecars ?? 200;
22776
22968
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
22777
22969
  const found = [];
22778
22970
  const walk2 = (d, depth) => {
22779
22971
  if (depth > 4) return;
22780
- for (const e of (0, import_node_fs37.readdirSync)(d, { withFileTypes: true })) {
22781
- const p = (0, import_node_path28.join)(d, e.name);
22972
+ for (const e of (0, import_node_fs38.readdirSync)(d, { withFileTypes: true })) {
22973
+ const p = (0, import_node_path29.join)(d, e.name);
22782
22974
  if (e.isDirectory()) {
22783
22975
  walk2(p, depth + 1);
22784
22976
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
22785
22977
  try {
22786
- const st = (0, import_node_fs37.statSync)(p);
22978
+ const st = (0, import_node_fs38.statSync)(p);
22787
22979
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
22788
22980
  } catch {
22789
22981
  result.coverage.malformed++;
@@ -22800,7 +22992,7 @@ function fold(transcriptPath, opts = {}) {
22800
22992
  continue;
22801
22993
  }
22802
22994
  try {
22803
- ingest((0, import_node_fs37.readFileSync)(f.path, "utf8"), "subagent");
22995
+ ingest((0, import_node_fs38.readFileSync)(f.path, "utf8"), "subagent");
22804
22996
  bytes += f.size;
22805
22997
  result.coverage.subagentFiles++;
22806
22998
  } catch {
@@ -22835,7 +23027,7 @@ function fold(transcriptPath, opts = {}) {
22835
23027
  }
22836
23028
  function classifyUnobserved(path) {
22837
23029
  try {
22838
- const st = (0, import_node_fs37.statSync)(path);
23030
+ const st = (0, import_node_fs38.statSync)(path);
22839
23031
  if (!st.isFile()) return "unreadable";
22840
23032
  } catch {
22841
23033
  return "unreadable";
@@ -23102,14 +23294,12 @@ async function evidence(run2) {
23102
23294
  authorshipWasObservable
23103
23295
  });
23104
23296
  const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
23105
- if (!opts.skipStatic && isCodacyAvailable()) {
23297
+ if (!opts.skipStatic) {
23106
23298
  let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
23107
23299
  if (baseline) {
23108
23300
  allScannable = allScannable.filter((f) => changedSinceBaseline(f, baseline));
23109
23301
  }
23110
- if (allScannable.length > 0) {
23111
- staticResults = runCodacyAnalysis(allScannable);
23112
- }
23302
+ staticResults = runCodacyAnalysisIfAvailable(allScannable);
23113
23303
  }
23114
23304
  const deltaSet = baseline ? recentForReview.filter((f) => changedSinceBaseline(f, baseline)) : recentForReview;
23115
23305
  codeDelta = collectCodeDelta(deltaSet, {
@@ -23152,20 +23342,20 @@ async function evidence(run2) {
23152
23342
  }
23153
23343
 
23154
23344
  // src/lib/cache-cleanup.ts
23155
- var import_node_fs38 = require("node:fs");
23156
- var import_node_path29 = require("node:path");
23345
+ var import_node_fs39 = require("node:fs");
23346
+ var import_node_path30 = require("node:path");
23157
23347
  var CACHE_TTL_DAYS = 7;
23158
23348
  function pruneStaleCache() {
23159
23349
  try {
23160
23350
  const dir = projectPath(CACHE_DIR);
23161
23351
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
23162
- for (const entry of (0, import_node_fs38.readdirSync)(dir)) {
23352
+ for (const entry of (0, import_node_fs39.readdirSync)(dir)) {
23163
23353
  if (!entry.startsWith("pending-")) continue;
23164
- const path = (0, import_node_path29.join)(dir, entry);
23354
+ const path = (0, import_node_path30.join)(dir, entry);
23165
23355
  try {
23166
- const stat3 = (0, import_node_fs38.statSync)(path);
23356
+ const stat3 = (0, import_node_fs39.statSync)(path);
23167
23357
  if (stat3.mtimeMs < cutoff) {
23168
- (0, import_node_fs38.unlinkSync)(path);
23358
+ (0, import_node_fs39.unlinkSync)(path);
23169
23359
  logEvent("cache_entry_pruned", {
23170
23360
  path: entry,
23171
23361
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -23179,7 +23369,7 @@ function pruneStaleCache() {
23179
23369
  }
23180
23370
 
23181
23371
  // src/lib/context-files.ts
23182
- var import_node_fs39 = require("node:fs");
23372
+ var import_node_fs40 = require("node:fs");
23183
23373
  var import_node_os6 = require("node:os");
23184
23374
  var MAX_CONTEXT_FILES = 10;
23185
23375
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -23237,7 +23427,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
23237
23427
  continue;
23238
23428
  }
23239
23429
  try {
23240
- const content = (0, import_node_fs39.readFileSync)(safePath, "utf8");
23430
+ const content = (0, import_node_fs40.readFileSync)(safePath, "utf8");
23241
23431
  const bytes = Buffer.byteLength(content);
23242
23432
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
23243
23433
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -23322,14 +23512,15 @@ async function repoContext(run2) {
23322
23512
  dropped: run2.repoContext.dropped_symbols?.length ?? 0,
23323
23513
  callers: run2.repoContext.callers?.length ?? 0,
23324
23514
  tests: run2.repoContext.tests?.length ?? 0,
23515
+ importers: run2.repoContext.importers?.length ?? 0,
23325
23516
  elapsed_ms: run2.repoContext.elapsed_ms ?? null
23326
23517
  });
23327
23518
  }
23328
23519
 
23329
23520
  // src/lib/seed-runner.ts
23330
23521
  var import_promises15 = require("node:fs/promises");
23331
- var import_node_fs40 = require("node:fs");
23332
- var import_node_path30 = require("node:path");
23522
+ var import_node_fs41 = require("node:fs");
23523
+ var import_node_path31 = require("node:path");
23333
23524
  var import_yaml4 = __toESM(require_dist());
23334
23525
 
23335
23526
  // src/lib/seed.ts
@@ -23568,7 +23759,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
23568
23759
  return fm;
23569
23760
  }
23570
23761
  async function runSeed(opts) {
23571
- if (!(0, import_node_fs40.existsSync)(STANDARD_FILE)) {
23762
+ if (!(0, import_node_fs41.existsSync)(STANDARD_FILE)) {
23572
23763
  return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
23573
23764
  }
23574
23765
  let standardDoc;
@@ -23580,7 +23771,7 @@ async function runSeed(opts) {
23580
23771
  }
23581
23772
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
23582
23773
  let readmeContent;
23583
- if ((0, import_node_fs40.existsSync)("README.md")) {
23774
+ if ((0, import_node_fs41.existsSync)("README.md")) {
23584
23775
  try {
23585
23776
  readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
23586
23777
  } catch {
@@ -23588,7 +23779,7 @@ async function runSeed(opts) {
23588
23779
  }
23589
23780
  let claudeMdContent;
23590
23781
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
23591
- if ((0, import_node_fs40.existsSync)(p)) {
23782
+ if ((0, import_node_fs41.existsSync)(p)) {
23592
23783
  try {
23593
23784
  claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
23594
23785
  break;
@@ -23611,8 +23802,8 @@ async function runSeed(opts) {
23611
23802
  if (candidates2.length === 0) {
23612
23803
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
23613
23804
  }
23614
- const overviewPath = (0, import_node_path30.join)(MEMORY_DIR, "domain", "project-overview.md");
23615
- if ((0, import_node_fs40.existsSync)(overviewPath) && !opts.force) {
23805
+ const overviewPath = (0, import_node_path31.join)(MEMORY_DIR, "domain", "project-overview.md");
23806
+ if ((0, import_node_fs41.existsSync)(overviewPath) && !opts.force) {
23616
23807
  return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
23617
23808
  }
23618
23809
  if (opts.dryRun) {
@@ -23654,7 +23845,7 @@ async function runSeed(opts) {
23654
23845
  continue;
23655
23846
  }
23656
23847
  try {
23657
- await (0, import_promises15.mkdir)((0, import_node_path30.dirname)(targetPath), { recursive: true });
23848
+ await (0, import_promises15.mkdir)((0, import_node_path31.dirname)(targetPath), { recursive: true });
23658
23849
  await (0, import_promises15.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
23659
23850
  created++;
23660
23851
  opts.onCreated?.(nodeId, filePathRel, c);
@@ -23667,8 +23858,8 @@ async function runSeed(opts) {
23667
23858
  }
23668
23859
 
23669
23860
  // src/commands/analyze/phases/08-memory-manifest.ts
23670
- var import_node_fs41 = require("node:fs");
23671
- var import_node_path31 = require("node:path");
23861
+ var import_node_fs42 = require("node:fs");
23862
+ var import_node_path32 = require("node:path");
23672
23863
  async function memoryManifest(run2) {
23673
23864
  const { globals } = run2;
23674
23865
  const { serviceUrl, token } = run2;
@@ -23678,9 +23869,9 @@ async function memoryManifest(run2) {
23678
23869
  let autoSeedNotice = null;
23679
23870
  try {
23680
23871
  await ensureMemoryDir();
23681
- const seedMarker = (0, import_node_path31.join)(VERITY_DIR, ".seeded");
23682
- const hasStandard = (0, import_node_fs41.existsSync)(STANDARD_FILE);
23683
- const alreadyTried = (0, import_node_fs41.existsSync)(seedMarker);
23872
+ const seedMarker = (0, import_node_path32.join)(VERITY_DIR, ".seeded");
23873
+ const hasStandard = (0, import_node_fs42.existsSync)(STANDARD_FILE);
23874
+ const alreadyTried = (0, import_node_fs42.existsSync)(seedMarker);
23684
23875
  if (hasStandard && !alreadyTried) {
23685
23876
  const preManifest = await buildManifest();
23686
23877
  if (preManifest.nodes.length === 0) {
@@ -23693,7 +23884,7 @@ async function memoryManifest(run2) {
23693
23884
  dryRun: false
23694
23885
  });
23695
23886
  if (seedResult.created > 0) {
23696
- (0, import_node_fs41.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
23887
+ (0, import_node_fs42.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
23697
23888
  `);
23698
23889
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
23699
23890
  logEvent("auto_seed_ran", {
@@ -23701,7 +23892,7 @@ async function memoryManifest(run2) {
23701
23892
  failed: seedResult.failed
23702
23893
  });
23703
23894
  } else if (seedResult.skipped === "already_seeded") {
23704
- (0, import_node_fs41.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
23895
+ (0, import_node_fs42.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
23705
23896
  `);
23706
23897
  } else {
23707
23898
  logEvent("auto_seed_noop", {
@@ -23796,7 +23987,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
23796
23987
  }
23797
23988
 
23798
23989
  // src/commands/analyze/phases/10-working-memory.ts
23799
- var import_node_path32 = require("node:path");
23990
+ var import_node_path33 = require("node:path");
23800
23991
  async function workingMemory(run2) {
23801
23992
  const { opts } = run2;
23802
23993
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
@@ -23808,7 +23999,7 @@ async function workingMemory(run2) {
23808
23999
  const priorState = foldForMarks(memorySession.d);
23809
24000
  incrementReport = computeIncrement(
23810
24001
  allForReview,
23811
- (p) => fileHash((0, import_node_path32.join)(repoRoot(), p)),
24002
+ (p) => fileHash((0, import_node_path33.join)(repoRoot(), p)),
23812
24003
  priorState.authored_all.map((a) => ({
23813
24004
  path: a.path,
23814
24005
  hash_at_last_verdict: a.hash_at_last_verdict
@@ -23890,7 +24081,7 @@ async function workingMemory(run2) {
23890
24081
  }
23891
24082
 
23892
24083
  // src/lib/note-budget.ts
23893
- var import_node_fs42 = require("node:fs");
24084
+ var import_node_fs43 = require("node:fs");
23894
24085
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
23895
24086
  var EPISODE_STALE_SECONDS = 30 * 60;
23896
24087
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -23912,9 +24103,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
23912
24103
  }
23913
24104
  function readAdvisoryEpisode(sessionId) {
23914
24105
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
23915
- if (!(0, import_node_fs42.existsSync)(file)) return null;
24106
+ if (!(0, import_node_fs43.existsSync)(file)) return null;
23916
24107
  try {
23917
- const o = JSON.parse((0, import_node_fs42.readFileSync)(file, "utf-8")) ?? {};
24108
+ const o = JSON.parse((0, import_node_fs43.readFileSync)(file, "utf-8")) ?? {};
23918
24109
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
23919
24110
  if (isNaN(delivered)) return null;
23920
24111
  return {
@@ -23928,8 +24119,8 @@ function readAdvisoryEpisode(sessionId) {
23928
24119
  }
23929
24120
  function writeAdvisoryEpisode(episode, sessionId) {
23930
24121
  try {
23931
- (0, import_node_fs42.mkdirSync)(VERITY_DIR, { recursive: true });
23932
- (0, import_node_fs42.writeFileSync)(
24122
+ (0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
24123
+ (0, import_node_fs43.writeFileSync)(
23933
24124
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
23934
24125
  JSON.stringify({ v: 1, ...episode })
23935
24126
  );
@@ -24237,14 +24428,14 @@ async function buildRequest(run2) {
24237
24428
  }
24238
24429
 
24239
24430
  // src/lib/offline.ts
24240
- var import_node_fs43 = require("node:fs");
24431
+ var import_node_fs44 = require("node:fs");
24241
24432
  var import_node_crypto11 = require("node:crypto");
24242
24433
  function cacheRequest(body) {
24243
24434
  try {
24244
- (0, import_node_fs43.mkdirSync)(CACHE_DIR, { recursive: true });
24435
+ (0, import_node_fs44.mkdirSync)(CACHE_DIR, { recursive: true });
24245
24436
  const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
24246
24437
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
24247
- (0, import_node_fs43.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
24438
+ (0, import_node_fs44.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
24248
24439
  } catch {
24249
24440
  }
24250
24441
  }
@@ -24363,8 +24554,8 @@ async function transmit(run2) {
24363
24554
  }
24364
24555
 
24365
24556
  // src/commands/analyze/phases/13-reconcile.ts
24366
- var import_node_fs44 = require("node:fs");
24367
- var import_node_path33 = require("node:path");
24557
+ var import_node_fs45 = require("node:fs");
24558
+ var import_node_path34 = require("node:path");
24368
24559
  async function reconcile(run2) {
24369
24560
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
24370
24561
  const sentPaths = codeDelta.files.map((f) => f.path);
@@ -24393,7 +24584,7 @@ async function reconcile(run2) {
24393
24584
  const st = foldDossier(memorySession.d);
24394
24585
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
24395
24586
  try {
24396
- const src = (0, import_node_fs44.readFileSync)((0, import_node_path33.join)(repoRoot(), file), "utf8").split("\n");
24587
+ const src = (0, import_node_fs45.readFileSync)((0, import_node_path34.join)(repoRoot(), file), "utf8").split("\n");
24397
24588
  const at = src[line - 1];
24398
24589
  return at === void 0 ? null : lineSha(at);
24399
24590
  } catch {
@@ -24679,12 +24870,20 @@ async function pullRepoMemory(opts) {
24679
24870
  let version = null;
24680
24871
  let cursor = null;
24681
24872
  let pages = 0;
24682
- const remember = (complete) => writePullState({
24683
- version: complete ? version : null,
24684
- // A complete pull saw every file the server holds, so its ledger replaces the
24685
- // old one (a path that stopped arriving was archived). A partial one only adds.
24686
- served: complete ? served : new Map([...state.served, ...served])
24687
- });
24873
+ const remember = async (complete) => {
24874
+ const onDisk = await readPullState();
24875
+ const meanwhile = /* @__PURE__ */ new Map();
24876
+ for (const [path, hash] of onDisk.served) {
24877
+ if (state.served.get(path) !== hash) meanwhile.set(path, hash);
24878
+ }
24879
+ await writePullState({
24880
+ version: complete ? version : null,
24881
+ // A complete pull saw every file the server holds, so its ledger replaces
24882
+ // the old one (a path that stopped arriving was archived) — except for what
24883
+ // another writer recorded while it ran. A partial one only adds.
24884
+ served: complete ? new Map([...served, ...meanwhile]) : new Map([...state.served, ...served, ...meanwhile])
24885
+ });
24886
+ };
24688
24887
  do {
24689
24888
  const params = new URLSearchParams({ limit: String(PAGE_SIZE) });
24690
24889
  if (cursor) params.set("cursor", cursor);
@@ -24757,7 +24956,7 @@ async function readPullState() {
24757
24956
  async function writePullState(state) {
24758
24957
  try {
24759
24958
  await (0, import_promises16.mkdir)(projectPath(VERITY_DIR), { recursive: true });
24760
- await (0, import_promises16.writeFile)(pullStateFile(), JSON.stringify({
24959
+ await writeFileAtomic(pullStateFile(), JSON.stringify({
24761
24960
  ...state.version ? { version: state.version } : {},
24762
24961
  pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
24763
24962
  served: Object.fromEntries(state.served)
@@ -25200,7 +25399,7 @@ function registerAnalyzeCommand(program2) {
25200
25399
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
25201
25400
  async function runAnalyze(opts, globals) {
25202
25401
  if (!verityConfigured()) {
25203
- (0, import_node_fs45.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
25402
+ (0, import_node_fs46.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
25204
25403
  process.exit(0);
25205
25404
  }
25206
25405
  const run2 = createRun(opts, globals);
@@ -25221,11 +25420,11 @@ async function runAnalyze(opts, globals) {
25221
25420
  }
25222
25421
 
25223
25422
  // src/commands/baseline.ts
25224
- var import_node_fs47 = require("node:fs");
25423
+ var import_node_fs48 = require("node:fs");
25225
25424
 
25226
25425
  // src/lib/project-skills.ts
25227
- var import_node_fs46 = require("node:fs");
25228
- var import_node_path34 = require("node:path");
25426
+ var import_node_fs47 = require("node:fs");
25427
+ var import_node_path35 = require("node:path");
25229
25428
  var PROJECT_SKILL_NAMES = [
25230
25429
  "verity-setup",
25231
25430
  "verity-analyze",
@@ -25250,14 +25449,14 @@ var LEGACY_SKILL_NAMES = [
25250
25449
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
25251
25450
  function staleProjectSkills() {
25252
25451
  const root = projectPath(".claude/skills");
25253
- if (!(0, import_node_fs46.existsSync)(root)) return [];
25254
- return ALL.filter((name) => (0, import_node_fs46.existsSync)((0, import_node_path34.join)(root, name)));
25452
+ if (!(0, import_node_fs47.existsSync)(root)) return [];
25453
+ return ALL.filter((name) => (0, import_node_fs47.existsSync)((0, import_node_path35.join)(root, name)));
25255
25454
  }
25256
25455
  function removeProjectSkills() {
25257
25456
  const root = projectPath(".claude/skills");
25258
25457
  const removed = [];
25259
25458
  for (const name of staleProjectSkills()) {
25260
- (0, import_node_fs46.rmSync)((0, import_node_path34.join)(root, name), { recursive: true, force: true });
25459
+ (0, import_node_fs47.rmSync)((0, import_node_path35.join)(root, name), { recursive: true, force: true });
25261
25460
  removed.push(name);
25262
25461
  }
25263
25462
  return removed;
@@ -25322,13 +25521,13 @@ function registerBaselineCommands(program2) {
25322
25521
  let memoryMsg = null;
25323
25522
  let memoryAgentLine = null;
25324
25523
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
25325
- if (realStart && !(0, import_node_fs47.existsSync)(memoryNotice)) {
25524
+ if (realStart && !(0, import_node_fs48.existsSync)(memoryNotice)) {
25326
25525
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
25327
25526
  if (trackedGraph > 0) {
25328
25527
  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.`;
25329
25528
  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.`;
25330
25529
  try {
25331
- (0, import_node_fs47.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
25530
+ (0, import_node_fs48.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
25332
25531
  } catch {
25333
25532
  }
25334
25533
  }
@@ -25429,7 +25628,7 @@ function hookSource(value) {
25429
25628
  }
25430
25629
 
25431
25630
  // src/commands/review.ts
25432
- var import_node_fs48 = require("node:fs");
25631
+ var import_node_fs49 = require("node:fs");
25433
25632
  function registerReviewCommand(program2) {
25434
25633
  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) => {
25435
25634
  const globals = program2.opts();
@@ -25446,45 +25645,22 @@ async function runReview(opts, globals) {
25446
25645
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
25447
25646
  const analyzable = filterAnalyzable(allFiles);
25448
25647
  const securityFiles = filterSecurity(allFiles);
25449
- let staticResults;
25450
- if (isCodacyAvailable()) {
25451
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs48.existsSync)(f) || resolveFile(f) !== null);
25452
- staticResults = runCodacyAnalysis(scannable);
25453
- } else {
25454
- staticResults = {
25455
- tool: "@codacy/analysis-cli",
25456
- findings: [],
25457
- summary: { total_findings: 0, by_severity: {}, tools_run: [] }
25458
- };
25459
- }
25648
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs49.existsSync)(f) || resolveFile(f) !== null);
25649
+ const staticResults = runCodacyAnalysisIfAvailable(scannable);
25460
25650
  const codeDelta = collectCodeDelta(allFiles);
25461
25651
  const tokenResult = await resolveToken(globals.token);
25462
25652
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
25463
25653
  if (!tokenResult.ok || !urlResult.ok) {
25654
+ const staticFailure = staticResults.summary.failure;
25464
25655
  printJsonCompact({
25465
- gate_decision: "PASS",
25466
- 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.",
25656
+ gate_decision: "WARN",
25657
+ 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.",
25467
25658
  unauthenticated: true,
25468
25659
  static_results: staticResults
25469
25660
  });
25470
25661
  process.exit(0);
25471
25662
  }
25472
- let specs;
25473
- if (opts.specs) {
25474
- const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
25475
- specs = [];
25476
- for (const p of specPaths) {
25477
- if (!(0, import_node_fs48.existsSync)(p)) continue;
25478
- try {
25479
- const { readFileSync: readFileSync26 } = await import("node:fs");
25480
- const content = readFileSync26(p, "utf-8");
25481
- specs.push({ path: p, content: content.slice(0, 10240) });
25482
- } catch {
25483
- }
25484
- }
25485
- } else {
25486
- specs = discoverSpecs();
25487
- }
25663
+ const specs = opts.specs ? readSpecFiles(opts.specs, repoRoot()) : discoverSpecs();
25488
25664
  const plans = discoverPlans();
25489
25665
  const requestBody = {
25490
25666
  static_results: staticResults,
@@ -25517,9 +25693,10 @@ async function runReview(opts, globals) {
25517
25693
  });
25518
25694
  if (!result.ok) {
25519
25695
  printError(`Service error: ${result.error}`);
25696
+ const staticFailure = staticResults.summary.failure;
25520
25697
  printJsonCompact({
25521
- gate_decision: "PASS",
25522
- systemMessage: "Verity: Service unavailable \u2014 showing static results only",
25698
+ gate_decision: "WARN",
25699
+ 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",
25523
25700
  offline: true,
25524
25701
  static_results: staticResults
25525
25702
  });
@@ -25534,8 +25711,8 @@ async function runReview(opts, globals) {
25534
25711
  }
25535
25712
 
25536
25713
  // src/commands/guard.ts
25537
- var import_node_fs49 = require("node:fs");
25538
- var import_node_path35 = require("node:path");
25714
+ var import_node_fs50 = require("node:fs");
25715
+ var import_node_path36 = require("node:path");
25539
25716
 
25540
25717
  // src/lib/terminal-text.ts
25541
25718
  var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
@@ -25910,7 +26087,7 @@ async function buildAgentDiffs(ctx, paths, limits = { perFileChars: 24e3, totalC
25910
26087
  // src/commands/guard.ts
25911
26088
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
25912
26089
  var GUARD_BLOCK_CAP = 2;
25913
- var GUARD_ITER_FILE = (0, import_node_path35.join)(VERITY_DIR, ".guard-iteration");
26090
+ var GUARD_ITER_FILE = (0, import_node_path36.join)(VERITY_DIR, ".guard-iteration");
25914
26091
  function readPreToolUseStdin() {
25915
26092
  const empty = { command: "", cwd: null, sessionId: null };
25916
26093
  return new Promise((resolve6) => {
@@ -25955,7 +26132,7 @@ function readPreToolUseStdin() {
25955
26132
  }
25956
26133
  function readIterMap() {
25957
26134
  try {
25958
- const raw = JSON.parse((0, import_node_fs49.readFileSync)(GUARD_ITER_FILE, "utf-8"));
26135
+ const raw = JSON.parse((0, import_node_fs50.readFileSync)(GUARD_ITER_FILE, "utf-8"));
25959
26136
  if (raw && typeof raw === "object") {
25960
26137
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
25961
26138
  return { [raw.moment]: raw.count };
@@ -25975,10 +26152,10 @@ function readIter(moment) {
25975
26152
  }
25976
26153
  function writeIter(moment, count) {
25977
26154
  try {
25978
- (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
26155
+ (0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
25979
26156
  const map = readIterMap();
25980
26157
  map[moment] = count;
25981
- (0, import_node_fs49.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26158
+ (0, import_node_fs50.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
25982
26159
  } catch {
25983
26160
  }
25984
26161
  }
@@ -25988,10 +26165,10 @@ function resetIter(moment) {
25988
26165
  if (!(moment in map)) return;
25989
26166
  delete map[moment];
25990
26167
  if (Object.keys(map).length === 0) {
25991
- if ((0, import_node_fs49.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs49.unlinkSync)(GUARD_ITER_FILE);
26168
+ if ((0, import_node_fs50.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs50.unlinkSync)(GUARD_ITER_FILE);
25992
26169
  } else {
25993
- (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
25994
- (0, import_node_fs49.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26170
+ (0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
26171
+ (0, import_node_fs50.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
25995
26172
  }
25996
26173
  } catch {
25997
26174
  }
@@ -26061,13 +26238,8 @@ function hasBlockingFinding(response, sentFiles) {
26061
26238
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
26062
26239
  const analyzable = filterAnalyzable(files);
26063
26240
  const securityFiles = filterSecurity(files);
26064
- let staticResults;
26065
- if (isCodacyAvailable()) {
26066
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs49.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
26067
- staticResults = runCodacyAnalysis(scannable);
26068
- } else {
26069
- staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
26070
- }
26241
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs50.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
26242
+ const staticResults = runCodacyAnalysisIfAvailable(scannable);
26071
26243
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
26072
26244
  const requestBody = {
26073
26245
  static_results: staticResults,
@@ -26143,6 +26315,9 @@ function worstGate(...gates) {
26143
26315
  };
26144
26316
  return GATES[Math.max(...gates.map(rank2))];
26145
26317
  }
26318
+ function oneShotLostOutcome(input) {
26319
+ return input.agentGate === "FAIL" && input.agentBlocking ? "block" : "allow-without-review";
26320
+ }
26146
26321
  function withAgentVerdict(oneShot, agent) {
26147
26322
  if (agent.one_shot_source === "none" && typeof oneShot.gate_decision === "string") {
26148
26323
  const added = agent.findings.filter((f) => f.agent_added === true);
@@ -26311,6 +26486,7 @@ async function runGuard(opts, globals) {
26311
26486
  symbols: repoContext2.symbols?.length ?? 0,
26312
26487
  callers: repoContext2.callers?.length ?? 0,
26313
26488
  tests: repoContext2.tests?.length ?? 0,
26489
+ importers: repoContext2.importers?.length ?? 0,
26314
26490
  excerpts: repoContext2.excerpts?.length ?? 0,
26315
26491
  elapsed_ms: repoContext2.elapsed_ms ?? null
26316
26492
  });
@@ -26357,13 +26533,6 @@ async function runGuard(opts, globals) {
26357
26533
  const agentOutcome = agent ? await agent : null;
26358
26534
  const agentVerdict = agentOutcome?.kind === "finished" && agentOutcome.response.gate_decision ? agentOutcome.response : null;
26359
26535
  const reviewSecs = Math.max(1, Math.round((Date.now() - reviewStart) / 1e3));
26360
- if (!result.ok && !agentVerdict) {
26361
- const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
26362
- emitAllowNotice(
26363
- `\u26A0 Verity ${moment}: ${authRemedy ? "not authorized" : "service offline"} \u2014 ${verb}ed WITHOUT review${authRemedy}`,
26364
- `Verity ${moment}: ${authRemedy ? "not authorized" : "service unavailable"} (${result.error}); the ${verb} was allowed WITHOUT a Verity review.${authRemedy}`
26365
- );
26366
- }
26367
26536
  const oneShotResponse = result.ok ? result.data : {};
26368
26537
  const response = agentVerdict ? withAgentVerdict(oneShotResponse, agentVerdict) : oneShotResponse;
26369
26538
  if (opts.json) process.stderr.write(JSON.stringify(response) + "\n");
@@ -26375,6 +26544,19 @@ async function runGuard(opts, globals) {
26375
26544
  const covDetail = agentLine ? `${coverageBlock(coverage)}
26376
26545
  ${agentLine}` : coverageBlock(coverage);
26377
26546
  const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
26547
+ if (!result.ok) {
26548
+ const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
26549
+ if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
26550
+ writeIter(moment, iter + 1);
26551
+ writeBlockMessage(moment, response, covDetail);
26552
+ process.exit(2);
26553
+ }
26554
+ const agentNote = agentLine ? ` ${agentLine}, but it reviewed only part of the change.` : "";
26555
+ emitAllowNotice(
26556
+ `\u26A0 Verity ${moment}: ${authRemedy ? "not authorized" : "no single-pass review"} \u2014 ${verb}ed WITHOUT review${authRemedy}`,
26557
+ `Verity ${moment}: the single-pass review did not come back (${result.error}); the ${verb} was allowed WITHOUT a Verity review.${agentNote}${authRemedy}`
26558
+ );
26559
+ }
26378
26560
  if (decision === "FAIL" && hasBlockingFinding(response, witnessed)) {
26379
26561
  writeIter(moment, iter + 1);
26380
26562
  writeBlockMessage(moment, response, covDetail);
@@ -26566,7 +26748,7 @@ function registerIgnoreCommand(program2) {
26566
26748
 
26567
26749
  // src/commands/waive.ts
26568
26750
  var import_node_crypto12 = require("node:crypto");
26569
- var import_node_fs50 = require("node:fs");
26751
+ var import_node_fs51 = require("node:fs");
26570
26752
  function registerWaiveCommand(program2) {
26571
26753
  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) => {
26572
26754
  const globals = program2.opts();
@@ -26595,7 +26777,7 @@ function registerWaiveCommand(program2) {
26595
26777
  if (opts.file) {
26596
26778
  body.file = opts.file;
26597
26779
  try {
26598
- body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs50.readFileSync)(opts.file)).digest("hex");
26780
+ body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs51.readFileSync)(opts.file)).digest("hex");
26599
26781
  } catch {
26600
26782
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
26601
26783
  process.exit(1);
@@ -26620,10 +26802,10 @@ function registerWaiveCommand(program2) {
26620
26802
  }
26621
26803
 
26622
26804
  // src/commands/init.ts
26623
- var import_node_fs54 = require("node:fs");
26805
+ var import_node_fs55 = require("node:fs");
26624
26806
  var import_promises19 = require("node:fs/promises");
26625
26807
  var import_yaml6 = __toESM(require_dist());
26626
- var import_node_path38 = require("node:path");
26808
+ var import_node_path39 = require("node:path");
26627
26809
  var import_node_child_process17 = require("node:child_process");
26628
26810
 
26629
26811
  // src/lib/banner.ts
@@ -26702,18 +26884,13 @@ function printPhase(n, of, title, subtitle) {
26702
26884
  }
26703
26885
 
26704
26886
  // src/commands/doctor.ts
26705
- var import_node_fs51 = require("node:fs");
26887
+ var import_node_fs52 = require("node:fs");
26706
26888
 
26707
26889
  // src/lib/prereqs.ts
26708
26890
  var import_node_child_process15 = require("node:child_process");
26709
26891
  var MIN_NODE_MAJOR = 20;
26710
26892
  function which(bin) {
26711
- try {
26712
- const out = (0, import_node_child_process15.execSync)(`command -v ${bin}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
26713
- return out || null;
26714
- } catch {
26715
- return null;
26716
- }
26893
+ return whichSync(bin, { real: false });
26717
26894
  }
26718
26895
  function checkNode() {
26719
26896
  const version = process.version;
@@ -26914,11 +27091,11 @@ async function buildReport() {
26914
27091
  const wiring = await resolveHookWiring();
26915
27092
  const hooks = wiring.status;
26916
27093
  const telemetry = await checkTelemetry();
26917
- const hasConfig = (0, import_node_fs51.existsSync)(projectPath(CODACY_CONFIG_FILE));
27094
+ const hasConfig = (0, import_node_fs52.existsSync)(projectPath(CODACY_CONFIG_FILE));
26918
27095
  const artifacts = {
26919
- standard: (0, import_node_fs51.existsSync)(projectPath(STANDARD_FILE)),
27096
+ standard: (0, import_node_fs52.existsSync)(projectPath(STANDARD_FILE)),
26920
27097
  analysisConfig: hasConfig,
26921
- verityMd: (0, import_node_fs51.existsSync)(projectPath(VERITY_MD_FILE)),
27098
+ verityMd: (0, import_node_fs52.existsSync)(projectPath(VERITY_MD_FILE)),
26922
27099
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
26923
27100
  };
26924
27101
  const next = [];
@@ -27049,8 +27226,8 @@ function registerDoctorCommand(program2) {
27049
27226
  }
27050
27227
 
27051
27228
  // src/commands/migrate.ts
27052
- var import_node_fs52 = require("node:fs");
27053
- var import_node_path36 = require("node:path");
27229
+ var import_node_fs53 = require("node:fs");
27230
+ var import_node_path37 = require("node:path");
27054
27231
  var import_node_child_process16 = require("node:child_process");
27055
27232
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
27056
27233
  function defaultNpmRemover(pkg) {
@@ -27087,12 +27264,12 @@ async function runMigration(opts = {}) {
27087
27264
  return { actions, migrated: actions.length > 0 };
27088
27265
  }
27089
27266
  function migrateProjectDir(root, actions) {
27090
- const gateDir = (0, import_node_path36.join)(root, ".gate");
27091
- const verityDir = (0, import_node_path36.join)(root, ".verity");
27092
- if ((0, import_node_fs52.existsSync)(gateDir) && !(0, import_node_fs52.existsSync)(verityDir)) {
27267
+ const gateDir = (0, import_node_path37.join)(root, ".gate");
27268
+ const verityDir = (0, import_node_path37.join)(root, ".verity");
27269
+ if ((0, import_node_fs53.existsSync)(gateDir) && !(0, import_node_fs53.existsSync)(verityDir)) {
27093
27270
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
27094
27271
  }
27095
- if ((0, import_node_fs52.existsSync)(gateDir) && (0, import_node_fs52.existsSync)(verityDir)) {
27272
+ if ((0, import_node_fs53.existsSync)(gateDir) && (0, import_node_fs53.existsSync)(verityDir)) {
27096
27273
  return migrateProjectDirCarry(gateDir, verityDir, actions);
27097
27274
  }
27098
27275
  return false;
@@ -27113,13 +27290,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
27113
27290
  }
27114
27291
  }
27115
27292
  if (moved) {
27116
- if ((0, import_node_fs52.existsSync)(gateDir)) {
27293
+ if ((0, import_node_fs53.existsSync)(gateDir)) {
27117
27294
  const carried = carryLegacyContents(gateDir, verityDir);
27118
27295
  if (carried > 0) {
27119
27296
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
27120
27297
  }
27121
27298
  try {
27122
- (0, import_node_fs52.rmSync)(gateDir, { recursive: true, force: true });
27299
+ (0, import_node_fs53.rmSync)(gateDir, { recursive: true, force: true });
27123
27300
  } catch {
27124
27301
  }
27125
27302
  }
@@ -27135,18 +27312,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
27135
27312
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
27136
27313
  }
27137
27314
  try {
27138
- (0, import_node_fs52.rmSync)(gateDir, { recursive: true, force: true });
27315
+ (0, import_node_fs53.rmSync)(gateDir, { recursive: true, force: true });
27139
27316
  } catch {
27140
27317
  }
27141
27318
  return carried > 0;
27142
27319
  }
27143
27320
  function migrateGlobalCredentials(home, actions) {
27144
27321
  if (!home) return;
27145
- const gateCreds = (0, import_node_path36.join)(home, ".gate", "credentials");
27146
- const verityCreds = (0, import_node_path36.join)(home, ".verity", "credentials");
27147
- if (!(0, import_node_fs52.existsSync)(gateCreds)) return;
27148
- if (!(0, import_node_fs52.existsSync)(verityCreds)) {
27149
- (0, import_node_fs52.mkdirSync)((0, import_node_path36.join)(home, ".verity"), { recursive: true });
27322
+ const gateCreds = (0, import_node_path37.join)(home, ".gate", "credentials");
27323
+ const verityCreds = (0, import_node_path37.join)(home, ".verity", "credentials");
27324
+ if (!(0, import_node_fs53.existsSync)(gateCreds)) return;
27325
+ if (!(0, import_node_fs53.existsSync)(verityCreds)) {
27326
+ (0, import_node_fs53.mkdirSync)((0, import_node_path37.join)(home, ".verity"), { recursive: true });
27150
27327
  moveFile(gateCreds, verityCreds);
27151
27328
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
27152
27329
  return;
@@ -27168,8 +27345,8 @@ async function migrateLegacyHooks(root, actions) {
27168
27345
  }
27169
27346
  }
27170
27347
  async function migrateClaudeMd(root, actions) {
27171
- const claudeMd = (0, import_node_path36.join)(root, "CLAUDE.md");
27172
- const hadLegacyBlock = (0, import_node_fs52.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
27348
+ const claudeMd = (0, import_node_path37.join)(root, "CLAUDE.md");
27349
+ const hadLegacyBlock = (0, import_node_fs53.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
27173
27350
  if (!hadLegacyBlock) return;
27174
27351
  try {
27175
27352
  await ensureClaudeMdPointer(root);
@@ -27179,9 +27356,9 @@ async function migrateClaudeMd(root, actions) {
27179
27356
  }
27180
27357
  }
27181
27358
  function migrateStandardFile(root, actions) {
27182
- const gateMd = (0, import_node_path36.join)(root, "GATE.md");
27183
- const verityMd = (0, import_node_path36.join)(root, "VERITY.md");
27184
- if (!(0, import_node_fs52.existsSync)(gateMd) || (0, import_node_fs52.existsSync)(verityMd)) return;
27359
+ const gateMd = (0, import_node_path37.join)(root, "GATE.md");
27360
+ const verityMd = (0, import_node_path37.join)(root, "VERITY.md");
27361
+ if (!(0, import_node_fs53.existsSync)(gateMd) || (0, import_node_fs53.existsSync)(verityMd)) return;
27185
27362
  let moved = false;
27186
27363
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
27187
27364
  try {
@@ -27193,12 +27370,12 @@ function migrateStandardFile(root, actions) {
27193
27370
  if (!moved) moveFile(gateMd, verityMd);
27194
27371
  const content = readFileSyncSafe(verityMd);
27195
27372
  const refreshed = content.split("GATE.md").join("VERITY.md");
27196
- if (refreshed !== content) (0, import_node_fs52.writeFileSync)(verityMd, refreshed);
27373
+ if (refreshed !== content) (0, import_node_fs53.writeFileSync)(verityMd, refreshed);
27197
27374
  actions.push("Renamed GATE.md \u2192 VERITY.md");
27198
27375
  }
27199
27376
  async function migrateTelemetryHeaders(root, actions) {
27200
- const file = (0, import_node_path36.join)(root, ".claude", "settings.local.json");
27201
- if (!(0, import_node_fs52.existsSync)(file)) return;
27377
+ const file = (0, import_node_path37.join)(root, ".claude", "settings.local.json");
27378
+ if (!(0, import_node_fs53.existsSync)(file)) return;
27202
27379
  let settings;
27203
27380
  try {
27204
27381
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -27246,14 +27423,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
27246
27423
  }
27247
27424
  if (toAppend.length > 0) {
27248
27425
  const sep4 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
27249
- (0, import_node_fs52.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
27426
+ (0, import_node_fs53.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
27250
27427
  }
27251
- (0, import_node_fs52.rmSync)(gateCreds, { force: true });
27428
+ (0, import_node_fs53.rmSync)(gateCreds, { force: true });
27252
27429
  return toAppend.length;
27253
27430
  }
27254
27431
  function readFileSyncSafe(path) {
27255
27432
  try {
27256
- return (0, import_node_fs52.readFileSync)(path, "utf-8");
27433
+ return (0, import_node_fs53.readFileSync)(path, "utf-8");
27257
27434
  } catch {
27258
27435
  return "";
27259
27436
  }
@@ -27268,35 +27445,35 @@ function hasStagedChanges(root) {
27268
27445
  }
27269
27446
  function moveDir(from, to) {
27270
27447
  try {
27271
- (0, import_node_fs52.renameSync)(from, to);
27448
+ (0, import_node_fs53.renameSync)(from, to);
27272
27449
  } catch (err) {
27273
27450
  if (err.code !== "EXDEV") throw err;
27274
- (0, import_node_fs52.cpSync)(from, to, { recursive: true });
27275
- (0, import_node_fs52.rmSync)(from, { recursive: true, force: true });
27451
+ (0, import_node_fs53.cpSync)(from, to, { recursive: true });
27452
+ (0, import_node_fs53.rmSync)(from, { recursive: true, force: true });
27276
27453
  }
27277
27454
  }
27278
27455
  function moveFile(from, to) {
27279
27456
  try {
27280
- (0, import_node_fs52.renameSync)(from, to);
27457
+ (0, import_node_fs53.renameSync)(from, to);
27281
27458
  } catch (err) {
27282
27459
  if (err.code !== "EXDEV") throw err;
27283
- (0, import_node_fs52.cpSync)(from, to);
27284
- (0, import_node_fs52.rmSync)(from, { force: true });
27460
+ (0, import_node_fs53.cpSync)(from, to);
27461
+ (0, import_node_fs53.rmSync)(from, { force: true });
27285
27462
  }
27286
27463
  }
27287
27464
  function carryLegacyContents(gateDir, verityDir) {
27288
27465
  let copied = 0;
27289
27466
  const walk2 = (relDir) => {
27290
- const srcDir = (0, import_node_path36.join)(gateDir, relDir);
27291
- for (const entry of (0, import_node_fs52.readdirSync)(srcDir)) {
27292
- const rel = relDir ? (0, import_node_path36.join)(relDir, entry) : entry;
27293
- const src = (0, import_node_path36.join)(gateDir, rel);
27294
- const dest = (0, import_node_path36.join)(verityDir, rel);
27295
- if ((0, import_node_fs52.statSync)(src).isDirectory()) {
27467
+ const srcDir = (0, import_node_path37.join)(gateDir, relDir);
27468
+ for (const entry of (0, import_node_fs53.readdirSync)(srcDir)) {
27469
+ const rel = relDir ? (0, import_node_path37.join)(relDir, entry) : entry;
27470
+ const src = (0, import_node_path37.join)(gateDir, rel);
27471
+ const dest = (0, import_node_path37.join)(verityDir, rel);
27472
+ if ((0, import_node_fs53.statSync)(src).isDirectory()) {
27296
27473
  walk2(rel);
27297
- } else if (!(0, import_node_fs52.existsSync)(dest)) {
27298
- (0, import_node_fs52.mkdirSync)((0, import_node_path36.dirname)(dest), { recursive: true });
27299
- (0, import_node_fs52.cpSync)(src, dest);
27474
+ } else if (!(0, import_node_fs53.existsSync)(dest)) {
27475
+ (0, import_node_fs53.mkdirSync)((0, import_node_path37.dirname)(dest), { recursive: true });
27476
+ (0, import_node_fs53.cpSync)(src, dest);
27300
27477
  copied++;
27301
27478
  }
27302
27479
  }
@@ -27305,22 +27482,22 @@ function carryLegacyContents(gateDir, verityDir) {
27305
27482
  return copied;
27306
27483
  }
27307
27484
  async function needsMigration(root = repoRoot()) {
27308
- const gateDir = (0, import_node_path36.join)(root, ".gate");
27309
- const verityDir = (0, import_node_path36.join)(root, ".verity");
27310
- if ((0, import_node_fs52.existsSync)(gateDir) && !(0, import_node_fs52.existsSync)(verityDir)) return true;
27311
- if ((0, import_node_fs52.existsSync)(gateDir) && (0, import_node_fs52.existsSync)(verityDir)) {
27312
- if ((0, import_node_fs52.existsSync)((0, import_node_path36.join)(gateDir, "credentials")) && !(0, import_node_fs52.existsSync)((0, import_node_path36.join)(verityDir, "credentials"))) {
27485
+ const gateDir = (0, import_node_path37.join)(root, ".gate");
27486
+ const verityDir = (0, import_node_path37.join)(root, ".verity");
27487
+ if ((0, import_node_fs53.existsSync)(gateDir) && !(0, import_node_fs53.existsSync)(verityDir)) return true;
27488
+ if ((0, import_node_fs53.existsSync)(gateDir) && (0, import_node_fs53.existsSync)(verityDir)) {
27489
+ if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(gateDir, "credentials")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(verityDir, "credentials"))) {
27313
27490
  return true;
27314
27491
  }
27315
- if ((0, import_node_fs52.existsSync)((0, import_node_path36.join)(gateDir, "memory")) && !(0, import_node_fs52.existsSync)((0, import_node_path36.join)(verityDir, "memory"))) {
27492
+ if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(gateDir, "memory")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(verityDir, "memory"))) {
27316
27493
  return true;
27317
27494
  }
27318
27495
  }
27319
- const claudeMd = (0, import_node_path36.join)(root, "CLAUDE.md");
27320
- if ((0, import_node_fs52.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
27496
+ const claudeMd = (0, import_node_path37.join)(root, "CLAUDE.md");
27497
+ if ((0, import_node_fs53.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
27321
27498
  return true;
27322
27499
  }
27323
- if ((0, import_node_fs52.existsSync)((0, import_node_path36.join)(root, "GATE.md")) && !(0, import_node_fs52.existsSync)((0, import_node_path36.join)(root, "VERITY.md"))) {
27500
+ if ((0, import_node_fs53.existsSync)((0, import_node_path37.join)(root, "GATE.md")) && !(0, import_node_fs53.existsSync)((0, import_node_path37.join)(root, "VERITY.md"))) {
27324
27501
  return true;
27325
27502
  }
27326
27503
  if (await hasLegacyHooksAt(root)) return true;
@@ -27601,9 +27778,9 @@ async function promptMultiSelect(question, choices, fallback) {
27601
27778
  }
27602
27779
 
27603
27780
  // src/lib/remote-config.ts
27604
- var import_node_fs53 = require("node:fs");
27781
+ var import_node_fs54 = require("node:fs");
27605
27782
  var import_promises18 = require("node:fs/promises");
27606
- var import_node_path37 = require("node:path");
27783
+ var import_node_path38 = require("node:path");
27607
27784
  var import_yaml5 = __toESM(require_dist());
27608
27785
  var IGNORE_RIDER = "verityignore";
27609
27786
  async function fetchRemoteSetup(opts) {
@@ -27648,7 +27825,7 @@ async function adoptRemoteSetup(found, opts) {
27648
27825
  written.push(STANDARD_FILE);
27649
27826
  if (rider !== null) {
27650
27827
  const localIgnore = projectPath(VERITYIGNORE_FILE);
27651
- if (!(0, import_node_fs53.existsSync)(localIgnore)) {
27828
+ if (!(0, import_node_fs54.existsSync)(localIgnore)) {
27652
27829
  await writeOut(VERITYIGNORE_FILE, rider);
27653
27830
  written.push(VERITYIGNORE_FILE);
27654
27831
  } else {
@@ -27679,9 +27856,9 @@ async function adoptRemoteSetup(found, opts) {
27679
27856
  written.push(VERITY_MD_FILE);
27680
27857
  return { written, notes };
27681
27858
  }
27682
- async function writeOut(relative2, body) {
27683
- const target = projectPath(relative2);
27684
- await (0, import_promises18.mkdir)((0, import_node_path37.dirname)(target), { recursive: true });
27859
+ async function writeOut(relative3, body) {
27860
+ const target = projectPath(relative3);
27861
+ await (0, import_promises18.mkdir)((0, import_node_path38.dirname)(target), { recursive: true });
27685
27862
  await (0, import_promises18.writeFile)(target, body);
27686
27863
  }
27687
27864
  function describeRemote(found) {
@@ -27798,15 +27975,15 @@ async function runOptionalAuth(resolution, opts = {}) {
27798
27975
  }
27799
27976
  function resolveDataDir2() {
27800
27977
  const candidates2 = [
27801
- (0, import_node_path38.join)(__dirname, "..", "data"),
27978
+ (0, import_node_path39.join)(__dirname, "..", "data"),
27802
27979
  // installed: node_modules/@codacy/verity-cli/data
27803
- (0, import_node_path38.join)(__dirname, "..", "..", "data"),
27980
+ (0, import_node_path39.join)(__dirname, "..", "..", "data"),
27804
27981
  // edge case: nested resolution
27805
- (0, import_node_path38.join)(process.cwd(), "cli", "data")
27982
+ (0, import_node_path39.join)(process.cwd(), "cli", "data")
27806
27983
  // local dev: running from repo root
27807
27984
  ];
27808
27985
  for (const candidate of candidates2) {
27809
- if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(candidate, "skills"))) {
27986
+ if ((0, import_node_fs55.existsSync)((0, import_node_path39.join)(candidate, "skills"))) {
27810
27987
  return candidate;
27811
27988
  }
27812
27989
  }
@@ -27822,9 +27999,9 @@ async function skillIsCurrent(src, dest) {
27822
27999
  const list2 = (dir) => {
27823
28000
  const out = [];
27824
28001
  const walk2 = (d, prefix) => {
27825
- for (const e of (0, import_node_fs54.readdirSync)(d, { withFileTypes: true })) {
28002
+ for (const e of (0, import_node_fs55.readdirSync)(d, { withFileTypes: true })) {
27826
28003
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
27827
- if (e.isDirectory()) walk2((0, import_node_path38.join)(d, e.name), rel);
28004
+ if (e.isDirectory()) walk2((0, import_node_path39.join)(d, e.name), rel);
27828
28005
  else if (e.isFile()) out.push(rel);
27829
28006
  }
27830
28007
  };
@@ -27835,8 +28012,8 @@ async function skillIsCurrent(src, dest) {
27835
28012
  const shipped = list2(src);
27836
28013
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
27837
28014
  for (const rel of shipped) {
27838
- const a = await (0, import_promises19.readFile)((0, import_node_path38.join)(src, rel), "utf-8");
27839
- const b = await (0, import_promises19.readFile)((0, import_node_path38.join)(dest, rel), "utf-8");
28015
+ const a = await (0, import_promises19.readFile)((0, import_node_path39.join)(src, rel), "utf-8");
28016
+ const b = await (0, import_promises19.readFile)((0, import_node_path39.join)(dest, rel), "utf-8");
27840
28017
  if (a !== b) return false;
27841
28018
  }
27842
28019
  return true;
@@ -28017,7 +28194,7 @@ async function synthesizeLocally(opts) {
28017
28194
  async function healStaleAnalysisConfig(globals) {
28018
28195
  const configPath = projectPath(CODACY_CONFIG_FILE);
28019
28196
  const standardPath = projectPath(STANDARD_FILE);
28020
- if (!(0, import_node_fs54.existsSync)(configPath) || !(0, import_node_fs54.existsSync)(standardPath)) return;
28197
+ if (!(0, import_node_fs55.existsSync)(configPath) || !(0, import_node_fs55.existsSync)(standardPath)) return;
28021
28198
  const validation = validatePatternIds();
28022
28199
  if (validation.status !== "invalid") return;
28023
28200
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -28114,17 +28291,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
28114
28291
  async function installSkills(force, step) {
28115
28292
  step("Installing skills");
28116
28293
  const dataDir = resolveDataDir2();
28117
- const skillsSource = (0, import_node_path38.join)(dataDir, "skills");
28294
+ const skillsSource = (0, import_node_path39.join)(dataDir, "skills");
28118
28295
  const skillsDest = ".claude/skills";
28119
28296
  let skillsInstalled = 0;
28120
28297
  for (const skill of SKILLS) {
28121
- const src = (0, import_node_path38.join)(skillsSource, skill);
28122
- const dest = (0, import_node_path38.join)(skillsDest, skill);
28123
- if (!(0, import_node_fs54.existsSync)(src)) {
28298
+ const src = (0, import_node_path39.join)(skillsSource, skill);
28299
+ const dest = (0, import_node_path39.join)(skillsDest, skill);
28300
+ if (!(0, import_node_fs55.existsSync)(src)) {
28124
28301
  printWarn(` Skill data not found: ${skill}`);
28125
28302
  continue;
28126
28303
  }
28127
- if ((0, import_node_fs54.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
28304
+ if ((0, import_node_fs55.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
28128
28305
  skillsInstalled++;
28129
28306
  continue;
28130
28307
  }
@@ -28263,7 +28440,7 @@ function registerInitCommand(program2) {
28263
28440
  const staleMarker = clearStalePluginMarker();
28264
28441
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
28265
28442
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
28266
- const isProject = projectMarkers.some((m) => (0, import_node_fs54.existsSync)(m));
28443
+ const isProject = projectMarkers.some((m) => (0, import_node_fs55.existsSync)(m));
28267
28444
  if (!isProject) {
28268
28445
  printError("No project detected in the current directory.");
28269
28446
  printInfo('Run "verity init" from your project root.');
@@ -28353,7 +28530,7 @@ function registerInitCommand(program2) {
28353
28530
  printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
28354
28531
  }
28355
28532
  await scaffoldProject(step, defaultsOnly);
28356
- const globalVerityDir = (0, import_node_path38.join)(process.env.HOME ?? "", ".verity");
28533
+ const globalVerityDir = (0, import_node_path39.join)(process.env.HOME ?? "", ".verity");
28357
28534
  await (0, import_promises19.mkdir)(globalVerityDir, { recursive: true });
28358
28535
  console.log("");
28359
28536
  step("Wiring Claude Code hooks");
@@ -28422,7 +28599,7 @@ function registerInitCommand(program2) {
28422
28599
  }
28423
28600
  step("Your project's Standard");
28424
28601
  let haveStandard = false;
28425
- if ((0, import_node_fs54.existsSync)(projectPath(STANDARD_FILE))) {
28602
+ if ((0, import_node_fs55.existsSync)(projectPath(STANDARD_FILE))) {
28426
28603
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
28427
28604
  haveStandard = true;
28428
28605
  } else {
@@ -28452,7 +28629,7 @@ function registerInitCommand(program2) {
28452
28629
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
28453
28630
  init: {
28454
28631
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
28455
- cli_version: true ? "0.33.0-experimental.d60f544" : "dev"
28632
+ cli_version: true ? "0.33.0" : "dev"
28456
28633
  }
28457
28634
  });
28458
28635
  } catch (err) {
@@ -28502,8 +28679,8 @@ function registerInitCommand(program2) {
28502
28679
  }
28503
28680
 
28504
28681
  // src/commands/uninstall.ts
28505
- var import_node_fs55 = require("node:fs");
28506
- var import_node_path39 = require("node:path");
28682
+ var import_node_fs56 = require("node:fs");
28683
+ var import_node_path40 = require("node:path");
28507
28684
  function registerUninstallCommand(program2) {
28508
28685
  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) => {
28509
28686
  const dryRun = opts.dryRun ?? false;
@@ -28512,11 +28689,11 @@ function registerUninstallCommand(program2) {
28512
28689
  const actions = [];
28513
28690
  const skillsRoot = projectPath(".claude/skills");
28514
28691
  for (const name of PROJECT_SKILL_NAMES) {
28515
- const dir = (0, import_node_path39.join)(skillsRoot, name);
28516
- if ((0, import_node_fs55.existsSync)(dir)) {
28692
+ const dir = (0, import_node_path40.join)(skillsRoot, name);
28693
+ if ((0, import_node_fs56.existsSync)(dir)) {
28517
28694
  actions.push({
28518
28695
  label: `Remove .claude/skills/${name}/`,
28519
- apply: () => (0, import_node_fs55.rmSync)(dir, { recursive: true, force: true })
28696
+ apply: () => (0, import_node_fs56.rmSync)(dir, { recursive: true, force: true })
28520
28697
  });
28521
28698
  }
28522
28699
  }
@@ -28530,24 +28707,24 @@ function registerUninstallCommand(program2) {
28530
28707
  });
28531
28708
  }
28532
28709
  const verityDir = projectPath(VERITY_DIR);
28533
- if ((0, import_node_fs55.existsSync)(verityDir)) {
28710
+ if ((0, import_node_fs56.existsSync)(verityDir)) {
28534
28711
  actions.push({
28535
28712
  label: `Remove ${VERITY_DIR}/`,
28536
- apply: () => (0, import_node_fs55.rmSync)(verityDir, { recursive: true, force: true })
28713
+ apply: () => (0, import_node_fs56.rmSync)(verityDir, { recursive: true, force: true })
28537
28714
  });
28538
28715
  }
28539
28716
  if (!keepVerityMd) {
28540
28717
  const verityMd = projectPath(VERITY_MD_FILE);
28541
- if ((0, import_node_fs55.existsSync)(verityMd)) {
28718
+ if ((0, import_node_fs56.existsSync)(verityMd)) {
28542
28719
  actions.push({
28543
28720
  label: `Remove ${VERITY_MD_FILE}`,
28544
- apply: () => (0, import_node_fs55.rmSync)(verityMd, { force: true })
28721
+ apply: () => (0, import_node_fs56.rmSync)(verityMd, { force: true })
28545
28722
  });
28546
28723
  }
28547
28724
  }
28548
28725
  const cleanupEmptyDir = (path) => {
28549
- if ((0, import_node_fs55.existsSync)(path) && (0, import_node_fs55.statSync)(path).isDirectory() && (0, import_node_fs55.readdirSync)(path).length === 0) {
28550
- (0, import_node_fs55.rmdirSync)(path);
28726
+ if ((0, import_node_fs56.existsSync)(path) && (0, import_node_fs56.statSync)(path).isDirectory() && (0, import_node_fs56.readdirSync)(path).length === 0) {
28727
+ (0, import_node_fs56.rmdirSync)(path);
28551
28728
  }
28552
28729
  };
28553
28730
  actions.push({
@@ -28558,11 +28735,11 @@ function registerUninstallCommand(program2) {
28558
28735
  }
28559
28736
  });
28560
28737
  const home = process.env.HOME ?? "";
28561
- const globalVerityDir = (0, import_node_path39.join)(home, ".verity");
28562
- if (purgeGlobal && (0, import_node_fs55.existsSync)(globalVerityDir)) {
28738
+ const globalVerityDir = (0, import_node_path40.join)(home, ".verity");
28739
+ if (purgeGlobal && (0, import_node_fs56.existsSync)(globalVerityDir)) {
28563
28740
  actions.push({
28564
28741
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
28565
- apply: () => (0, import_node_fs55.rmSync)(globalVerityDir, { recursive: true, force: true })
28742
+ apply: () => (0, import_node_fs56.rmSync)(globalVerityDir, { recursive: true, force: true })
28566
28743
  });
28567
28744
  }
28568
28745
  if (actions.length === 0) {
@@ -28756,8 +28933,8 @@ function registerTaskCommands(program2) {
28756
28933
  }
28757
28934
 
28758
28935
  // src/commands/reset.ts
28759
- var import_node_fs56 = require("node:fs");
28760
- var import_node_path40 = require("node:path");
28936
+ var import_node_fs57 = require("node:fs");
28937
+ var import_node_path41 = require("node:path");
28761
28938
  function registerResetCommand(program2) {
28762
28939
  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) => {
28763
28940
  const globals = program2.opts();
@@ -28794,11 +28971,11 @@ function registerResetCommand(program2) {
28794
28971
  }
28795
28972
  const cacheDir = projectPath(CACHE_DIR);
28796
28973
  let purged = 0;
28797
- if ((0, import_node_fs56.existsSync)(cacheDir)) {
28798
- for (const entry of (0, import_node_fs56.readdirSync)(cacheDir)) {
28974
+ if ((0, import_node_fs57.existsSync)(cacheDir)) {
28975
+ for (const entry of (0, import_node_fs57.readdirSync)(cacheDir)) {
28799
28976
  if (entry.startsWith("pending-")) {
28800
28977
  try {
28801
- (0, import_node_fs56.unlinkSync)((0, import_node_path40.join)(cacheDir, entry));
28978
+ (0, import_node_fs57.unlinkSync)((0, import_node_path41.join)(cacheDir, entry));
28802
28979
  purged++;
28803
28980
  } catch {
28804
28981
  }
@@ -28813,19 +28990,19 @@ function registerResetCommand(program2) {
28813
28990
  projectPath(`${VERITY_DIR}/.last-analysis`)
28814
28991
  ];
28815
28992
  for (const file of filesToClear) {
28816
- if ((0, import_node_fs56.existsSync)(file)) {
28993
+ if ((0, import_node_fs57.existsSync)(file)) {
28817
28994
  try {
28818
- (0, import_node_fs56.writeFileSync)(file, "");
28995
+ (0, import_node_fs57.writeFileSync)(file, "");
28819
28996
  } catch {
28820
28997
  }
28821
28998
  }
28822
28999
  }
28823
29000
  if (opts.all) {
28824
29001
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
28825
- if ((0, import_node_fs56.existsSync)(logsDir)) {
28826
- for (const entry of (0, import_node_fs56.readdirSync)(logsDir)) {
29002
+ if ((0, import_node_fs57.existsSync)(logsDir)) {
29003
+ for (const entry of (0, import_node_fs57.readdirSync)(logsDir)) {
28827
29004
  try {
28828
- (0, import_node_fs56.unlinkSync)((0, import_node_path40.join)(logsDir, entry));
29005
+ (0, import_node_fs57.unlinkSync)((0, import_node_path41.join)(logsDir, entry));
28829
29006
  } catch {
28830
29007
  }
28831
29008
  }
@@ -28837,7 +29014,7 @@ function registerResetCommand(program2) {
28837
29014
  }
28838
29015
 
28839
29016
  // src/commands/reflect.ts
28840
- var import_node_fs57 = require("node:fs");
29017
+ var import_node_fs58 = require("node:fs");
28841
29018
 
28842
29019
  // src/lib/reflection-globs.ts
28843
29020
  var MAX_GLOBS = 6;
@@ -28875,7 +29052,7 @@ async function writeNodeToDisk(args) {
28875
29052
  { treePaths: listTrackedFiles(), recordBaseline: false }
28876
29053
  );
28877
29054
  if (written === 0) return false;
28878
- return (0, import_node_fs57.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
29055
+ return (0, import_node_fs58.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
28879
29056
  } catch {
28880
29057
  return false;
28881
29058
  }
@@ -28954,7 +29131,7 @@ function registerReflectCommand(program2) {
28954
29131
  const fileGlobs = explicitGlobs.length > 0 ? explicitGlobs : derivedGlobs.length > 0 ? derivedGlobs : inheritedGlobs;
28955
29132
  const result = await apiRequest({
28956
29133
  method: "POST",
28957
- path: "/compound/memory/nodes",
29134
+ path: "/compound/reflect",
28958
29135
  serviceUrl,
28959
29136
  token,
28960
29137
  body: {
@@ -28987,6 +29164,8 @@ function registerReflectCommand(program2) {
28987
29164
  const nodeId = result.data.node_id;
28988
29165
  const filePath = result.data.file_path;
28989
29166
  const viewUrl = typeof result.data.view_url === "string" ? result.data.view_url : null;
29167
+ const recordedSource = typeof result.data.source === "string" ? result.data.source : source;
29168
+ const recordedAsUser = recordedSource === "user";
28990
29169
  const content = typeof result.data.content === "string" ? result.data.content : null;
28991
29170
  const synced = content !== null && await writeNodeToDisk({ filePath, content, nodeId });
28992
29171
  printInfo(
@@ -28994,8 +29173,13 @@ function registerReflectCommand(program2) {
28994
29173
  );
28995
29174
  if (viewUrl) printInfo(` ${viewUrl}`);
28996
29175
  printInfo(
28997
- confirmed ? " Recorded as yours (source: user)." : " Auto-recorded from this task \u2014 nobody reviewed it. Edit or delete the file if it is wrong."
29176
+ recordedAsUser ? " Recorded as yours (source: user)." : " Auto-recorded from this task \u2014 nobody reviewed it. Edit or delete the file if it is wrong."
28998
29177
  );
29178
+ if (recordedSource !== source) {
29179
+ printWarn(
29180
+ `Provenance mismatch: sent source "${source}", the service recorded "${recordedSource}". Correct ${nodeId} on the dashboard \u2014 a draft stored as human-authored cannot be told apart later.`
29181
+ );
29182
+ }
28999
29183
  if (fileGlobs.length === 0) {
29000
29184
  printWarn(
29001
29185
  'No files matched \u2014 this reflection will not surface in future reviews. Cite a path in the text, or pass --file-globs "<path or glob>".'
@@ -29367,8 +29551,8 @@ function registerTelemetryCommands(program2) {
29367
29551
  }
29368
29552
 
29369
29553
  // src/cli.ts
29370
- program.name("verity").description("CLI for Verity quality gate service").version("0.33.0-experimental.d60f544").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) => {
29371
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.0-experimental.d60f544");
29554
+ program.name("verity").description("CLI for Verity quality gate service").version("0.33.0").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) => {
29555
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.0");
29372
29556
  setUserNamedServiceUrl(program.opts().serviceUrl);
29373
29557
  try {
29374
29558
  await foldLegacyLocalCredential();