@codacy/verity-cli 0.32.5-experimental.4d91ca0 → 0.32.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/verity.js CHANGED
@@ -10523,7 +10523,7 @@ var SECURITY_PATTERNS = [
10523
10523
  /Dockerfile/
10524
10524
  ];
10525
10525
  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;
10526
+ var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
10527
10527
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
10528
10528
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
10529
10529
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -14012,12 +14012,239 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
14012
14012
 
14013
14013
  // src/lib/memory-sync.ts
14014
14014
  var import_promises8 = require("node:fs/promises");
14015
- var import_node_fs12 = require("node:fs");
14015
+ var import_node_fs13 = require("node:fs");
14016
14016
  var import_node_path12 = require("node:path");
14017
14017
  var import_node_crypto3 = require("node:crypto");
14018
14018
 
14019
- // src/lib/safe-path.ts
14019
+ // src/lib/gitignore.ts
14020
+ var import_node_child_process6 = require("node:child_process");
14020
14021
  var import_node_fs11 = require("node:fs");
14022
+ var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
14023
+ var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
14024
+ var VERITY_GITIGNORE_BLOCK = [
14025
+ "# Verity \u2014 machine-local state. Everything in .verity/ is ignored except the",
14026
+ "# shared standard, which is meant to be committed. The knowledge graph under",
14027
+ "# .verity/memory/ is machine-local too: the service rebuilds it, and committing",
14028
+ "# it puts generated notes in every diff and pull request.",
14029
+ ".verity/*",
14030
+ "!.verity/standard.yaml",
14031
+ SETTINGS_LOCAL_IGNORE_ENTRY,
14032
+ ""
14033
+ ].join("\n");
14034
+ var MEMORY_OPT_OUT_MARKER = "# Verity: this project commits its knowledge graph on purpose.";
14035
+ var MEMORY_OPT_OUT_STANZA = [
14036
+ MEMORY_OPT_OUT_MARKER,
14037
+ '# Remove these three lines (or run "verity memory untrack") to stop tracking it.',
14038
+ "!.verity/memory/",
14039
+ ".verity/memory/log.md",
14040
+ ""
14041
+ ].join("\n");
14042
+ var BREAKING_ENTRIES = /* @__PURE__ */ new Set([".verity/", ".verity"]);
14043
+ var SUPERSEDED_COMMENT = "# shared standard and the knowledge graph, which are meant to be committed.";
14044
+ var MEMORY_COMMENT = [
14045
+ "# shared standard, which is meant to be committed. The knowledge graph under",
14046
+ "# .verity/memory/ is machine-local too: the service rebuilds it, and committing",
14047
+ "# it puts generated notes in every diff and pull request."
14048
+ ];
14049
+ var SUPERSEDED_MEMORY_LINES = /* @__PURE__ */ new Set([
14050
+ "!.verity/memory/",
14051
+ "!.verity/memory",
14052
+ ".verity/memory/log.md",
14053
+ SUPERSEDED_COMMENT
14054
+ ]);
14055
+ function isIgnored(path) {
14056
+ try {
14057
+ (0, import_node_child_process6.execSync)(`git check-ignore -q -- "${path}"`, { stdio: "pipe" });
14058
+ return true;
14059
+ } catch (err) {
14060
+ return err.status === 1 ? false : null;
14061
+ }
14062
+ }
14063
+ function semanticsHold() {
14064
+ const snapshot = isIgnored(".verity/.snapshot/__probe__");
14065
+ const standard = isIgnored(".verity/standard.yaml");
14066
+ const futureState = isIgnored(".verity/.__probe-future-state__");
14067
+ if (snapshot === null || standard === null || futureState === null) return null;
14068
+ return snapshot === true && futureState === true && standard === false;
14069
+ }
14070
+ function memoryPosture() {
14071
+ const ignored = isIgnored(".verity/memory/domain/__probe__.md");
14072
+ if (ignored === null) return "unknown";
14073
+ return ignored ? "ignored" : "committable";
14074
+ }
14075
+ function committedMemoryFiles() {
14076
+ try {
14077
+ return (0, import_node_child_process6.execSync)("git ls-files -z -- .verity/memory", {
14078
+ encoding: "utf-8",
14079
+ stdio: ["pipe", "pipe", "pipe"]
14080
+ }).split("\0").filter(Boolean);
14081
+ } catch {
14082
+ return [];
14083
+ }
14084
+ }
14085
+ var OPT_OUT_COMMENT_LINES = /* @__PURE__ */ new Set([
14086
+ MEMORY_OPT_OUT_MARKER,
14087
+ '# Remove these three lines (or run "verity memory untrack") to stop tracking it.'
14088
+ ]);
14089
+ function fenceMemoryLines(lines) {
14090
+ const out = [];
14091
+ for (const line of lines) {
14092
+ const trimmed = line.trim();
14093
+ if (trimmed === SUPERSEDED_COMMENT) {
14094
+ out.push(...MEMORY_COMMENT);
14095
+ continue;
14096
+ }
14097
+ if (SUPERSEDED_MEMORY_LINES.has(trimmed) || OPT_OUT_COMMENT_LINES.has(trimmed)) continue;
14098
+ out.push(line);
14099
+ }
14100
+ return out;
14101
+ }
14102
+ function ensureVerityGitignore() {
14103
+ let content = "";
14104
+ try {
14105
+ content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14106
+ } catch {
14107
+ }
14108
+ const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
14109
+ const optedOut = content.includes(MEMORY_OPT_OUT_MARKER);
14110
+ const lines = content.split("\n");
14111
+ const needsRepair = lines.some((l) => BREAKING_ENTRIES.has(l.trim()));
14112
+ const hasSupersededMemory = hasMarker && !optedOut && lines.some((l) => SUPERSEDED_MEMORY_LINES.has(l.trim()));
14113
+ const memoryIsCommitted = hasSupersededMemory && committedMemoryFiles().length > 0;
14114
+ const verified = (result) => semanticsHold() === false ? "conflict" : result;
14115
+ if (hasMarker && !needsRepair && !hasSupersededMemory) return verified("covered");
14116
+ if (!hasMarker && !needsRepair) {
14117
+ if (semanticsHold() === true) return "covered";
14118
+ }
14119
+ try {
14120
+ let next = lines;
14121
+ if (needsRepair) {
14122
+ next = next.map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
14123
+ }
14124
+ if (hasSupersededMemory && !memoryIsCommitted) {
14125
+ next = fenceMemoryLines(next);
14126
+ }
14127
+ let text = next.join("\n");
14128
+ if (!hasMarker) {
14129
+ const sep3 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
14130
+ text = text + sep3 + VERITY_GITIGNORE_BLOCK;
14131
+ }
14132
+ if (text !== content) (0, import_node_fs11.writeFileSync)(".gitignore", text);
14133
+ return verified(
14134
+ memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
14135
+ );
14136
+ } catch {
14137
+ return "failed";
14138
+ }
14139
+ }
14140
+ function untrackMemory() {
14141
+ if (committedMemoryFiles().length === 0) return "none";
14142
+ try {
14143
+ (0, import_node_child_process6.execSync)("git rm -r --cached --quiet -- .verity/memory", { stdio: "pipe" });
14144
+ return "untracked";
14145
+ } catch {
14146
+ return "failed";
14147
+ }
14148
+ }
14149
+ function writeFencedBlock() {
14150
+ let content = "";
14151
+ try {
14152
+ content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14153
+ } catch {
14154
+ }
14155
+ const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
14156
+ let lines = content.split("\n").map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
14157
+ lines = fenceMemoryLines(lines);
14158
+ let text = lines.join("\n");
14159
+ if (!hasMarker) {
14160
+ const sep3 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
14161
+ text = text + sep3 + VERITY_GITIGNORE_BLOCK;
14162
+ }
14163
+ try {
14164
+ (0, import_node_fs11.writeFileSync)(".gitignore", text);
14165
+ return true;
14166
+ } catch {
14167
+ return false;
14168
+ }
14169
+ }
14170
+ function fenceMemory() {
14171
+ let original = null;
14172
+ try {
14173
+ original = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14174
+ } catch {
14175
+ original = null;
14176
+ }
14177
+ const restore = () => {
14178
+ try {
14179
+ if (original === null) (0, import_node_fs11.rmSync)(".gitignore", { force: true });
14180
+ else (0, import_node_fs11.writeFileSync)(".gitignore", original);
14181
+ } catch {
14182
+ }
14183
+ };
14184
+ if (!writeFencedBlock()) return { untracked: 0, ok: false };
14185
+ if (memoryPosture() !== "ignored") {
14186
+ restore();
14187
+ return { untracked: 0, ok: false };
14188
+ }
14189
+ const tracked = committedMemoryFiles().length;
14190
+ if (tracked > 0 && untrackMemory() === "failed") {
14191
+ restore();
14192
+ return { untracked: 0, ok: false };
14193
+ }
14194
+ return { untracked: tracked, ok: true };
14195
+ }
14196
+ function memoryOptOut() {
14197
+ try {
14198
+ return (0, import_node_fs11.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14199
+ } catch {
14200
+ return false;
14201
+ }
14202
+ }
14203
+ function keepMemoryTracked() {
14204
+ let content = "";
14205
+ try {
14206
+ content = (0, import_node_fs11.readFileSync)(".gitignore", "utf-8");
14207
+ } catch {
14208
+ }
14209
+ if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
14210
+ try {
14211
+ const sep3 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
14212
+ (0, import_node_fs11.writeFileSync)(".gitignore", content + sep3 + MEMORY_OPT_OUT_STANZA);
14213
+ } catch {
14214
+ return "failed";
14215
+ }
14216
+ return memoryPosture() === "ignored" ? "refused" : "recorded";
14217
+ }
14218
+ function committedVerityState() {
14219
+ let out = "";
14220
+ try {
14221
+ out = (0, import_node_child_process6.execSync)("git ls-files -z -- .verity", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
14222
+ } catch {
14223
+ return [];
14224
+ }
14225
+ return out.split("\0").filter(Boolean).filter((p) => p !== ".verity/standard.yaml" && !p.startsWith(".verity/memory/"));
14226
+ }
14227
+ function untrackVerityState() {
14228
+ const tracked = committedVerityState();
14229
+ if (tracked.length === 0) return "none";
14230
+ try {
14231
+ (0, import_node_child_process6.execSync)("git rm -r --cached --quiet -- .verity", { stdio: "pipe" });
14232
+ const keeps = [".verity/standard.yaml"];
14233
+ if (memoryPosture() === "committable") keeps.push(".verity/memory");
14234
+ for (const keep of keeps) {
14235
+ try {
14236
+ (0, import_node_child_process6.execSync)(`git add -- "${keep}"`, { stdio: "pipe" });
14237
+ } catch {
14238
+ }
14239
+ }
14240
+ return "untracked";
14241
+ } catch {
14242
+ return "failed";
14243
+ }
14244
+ }
14245
+
14246
+ // src/lib/safe-path.ts
14247
+ var import_node_fs12 = require("node:fs");
14021
14248
  var import_node_path11 = require("node:path");
14022
14249
  function resolveInside(baseDir, candidate) {
14023
14250
  if (typeof candidate !== "string" || candidate.length === 0) return null;
@@ -14027,16 +14254,16 @@ function resolveInside(baseDir, candidate) {
14027
14254
  const baseSep = baseAbs.endsWith(import_node_path11.sep) ? baseAbs : baseAbs + import_node_path11.sep;
14028
14255
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
14029
14256
  try {
14030
- if ((0, import_node_fs11.existsSync)(baseAbs)) {
14031
- const realBase = (0, import_node_fs11.realpathSync)(baseAbs);
14257
+ if ((0, import_node_fs12.existsSync)(baseAbs)) {
14258
+ const realBase = (0, import_node_fs12.realpathSync)(baseAbs);
14032
14259
  const realBaseSep = realBase.endsWith(import_node_path11.sep) ? realBase : realBase + import_node_path11.sep;
14033
14260
  let probe = full;
14034
- while (!(0, import_node_fs11.existsSync)(probe)) {
14261
+ while (!(0, import_node_fs12.existsSync)(probe)) {
14035
14262
  const parent = (0, import_node_path11.dirname)(probe);
14036
14263
  if (parent === probe) break;
14037
14264
  probe = parent;
14038
14265
  }
14039
- const realProbe = (0, import_node_fs11.realpathSync)(probe);
14266
+ const realProbe = (0, import_node_fs12.realpathSync)(probe);
14040
14267
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
14041
14268
  }
14042
14269
  } catch {
@@ -14115,24 +14342,24 @@ async function ensureMemoryDir() {
14115
14342
  for (const domain of DOMAINS2) {
14116
14343
  await (0, import_promises8.mkdir)((0, import_node_path12.join)(memoryDir2(), domain), { recursive: true });
14117
14344
  }
14118
- if (!(0, import_node_fs12.existsSync)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"))) {
14345
+ if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"))) {
14119
14346
  await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14120
14347
  }
14121
- if (!(0, import_node_fs12.existsSync)((0, import_node_path12.join)(memoryDir2(), "index.md"))) {
14348
+ if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "index.md"))) {
14122
14349
  await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
14123
14350
  }
14124
- if (!(0, import_node_fs12.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md"))) {
14351
+ if (!(0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md"))) {
14125
14352
  await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14126
14353
  }
14127
14354
  }
14128
14355
  async function buildManifest() {
14129
- if (!(0, import_node_fs12.existsSync)(memoryDir2())) {
14356
+ if (!(0, import_node_fs13.existsSync)(memoryDir2())) {
14130
14357
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
14131
14358
  }
14132
14359
  const nodes = [];
14133
14360
  for (const domain of DOMAINS2) {
14134
14361
  const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14135
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
14362
+ if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14136
14363
  try {
14137
14364
  const files = await (0, import_promises8.readdir)(domainDir);
14138
14365
  for (const file of files) {
@@ -14168,10 +14395,10 @@ function hashContent(content) {
14168
14395
  }
14169
14396
  async function readOnDiskNodes() {
14170
14397
  const out = /* @__PURE__ */ new Map();
14171
- if (!(0, import_node_fs12.existsSync)(memoryDir2())) return out;
14398
+ if (!(0, import_node_fs13.existsSync)(memoryDir2())) return out;
14172
14399
  for (const domain of DOMAINS2) {
14173
14400
  const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14174
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
14401
+ if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14175
14402
  try {
14176
14403
  for (const file of await (0, import_promises8.readdir)(domainDir)) {
14177
14404
  if (!file.endsWith(".md")) continue;
@@ -14223,7 +14450,7 @@ async function computeEditedNodeUploads() {
14223
14450
  for (const [path, prevHash] of prev) {
14224
14451
  if (prevHash == null) continue;
14225
14452
  const full = (0, import_node_path12.join)(memoryDir2(), path);
14226
- if (!(0, import_node_fs12.existsSync)(full)) continue;
14453
+ if (!(0, import_node_fs13.existsSync)(full)) continue;
14227
14454
  let content;
14228
14455
  try {
14229
14456
  content = await (0, import_promises8.readFile)(full, "utf-8");
@@ -14238,6 +14465,7 @@ async function computeDeletedNodePaths() {
14238
14465
  const prev = await readSyncBaseline();
14239
14466
  if (prev.size === 0) return [];
14240
14467
  const current = await readOnDiskNodes();
14468
+ if (current.size === 0 && memoryPosture() === "ignored") return [];
14241
14469
  return [...prev.keys()].filter((p) => !current.has(p));
14242
14470
  }
14243
14471
  async function applyMemoryWrites(writes, opts = {}) {
@@ -14259,7 +14487,7 @@ async function applyMemoryWrites(writes, opts = {}) {
14259
14487
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
14260
14488
  for (const n of notes) logLines.push(` - ${n}`);
14261
14489
  try {
14262
- const existing = (0, import_node_fs12.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14490
+ const existing = (0, import_node_fs13.existsSync)((0, import_node_path12.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14263
14491
  await (0, import_promises8.writeFile)((0, import_node_path12.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14264
14492
  } catch {
14265
14493
  }
@@ -14280,7 +14508,7 @@ async function applyOneWrite(write, treePaths) {
14280
14508
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
14281
14509
  }
14282
14510
  }
14283
- if ((0, import_node_fs12.existsSync)(fullPath)) {
14511
+ if ((0, import_node_fs13.existsSync)(fullPath)) {
14284
14512
  let existing = "";
14285
14513
  try {
14286
14514
  existing = await (0, import_promises8.readFile)(fullPath, "utf-8");
@@ -14334,7 +14562,7 @@ async function regenerateIndex() {
14334
14562
  let totalNodes = 0;
14335
14563
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
14336
14564
  const domainDir = (0, import_node_path12.join)(memoryDir2(), domain);
14337
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
14565
+ if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14338
14566
  try {
14339
14567
  const files = await (0, import_promises8.readdir)(domainDir);
14340
14568
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -14604,7 +14832,7 @@ function hasLegacyMemoryBlock(text) {
14604
14832
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
14605
14833
  const claudeMdPath = (0, import_node_path12.join)(cwd, "CLAUDE.md");
14606
14834
  let existing = "";
14607
- if ((0, import_node_fs12.existsSync)(claudeMdPath)) {
14835
+ if ((0, import_node_fs13.existsSync)(claudeMdPath)) {
14608
14836
  existing = await (0, import_promises8.readFile)(claudeMdPath, "utf-8");
14609
14837
  }
14610
14838
  let startTag = CLAUDE_MD_START;
@@ -14706,6 +14934,9 @@ file_globs: ["src/auth/**"]
14706
14934
  confidence: 0.5-1.0
14707
14935
  status: active | archived | superseded | orphan_flagged
14708
14936
  source: extractor | user | imported
14937
+ session: "<session key that produced this node>" # absent = unattributed
14938
+ task: "<task id it was extracted from>"
14939
+ run: "<run id that produced it>"
14709
14940
  # ... (see full schema in MEMORY-GRAPH-PRD \xA76.3)
14710
14941
  ---
14711
14942
 
@@ -14740,7 +14971,7 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
14740
14971
  `;
14741
14972
 
14742
14973
  // src/lib/dossier-session.ts
14743
- var import_node_fs17 = require("node:fs");
14974
+ var import_node_fs18 = require("node:fs");
14744
14975
  var import_node_crypto7 = require("node:crypto");
14745
14976
  var import_node_path15 = require("node:path");
14746
14977
 
@@ -14847,7 +15078,7 @@ function statementAnchorKey(file, patternId) {
14847
15078
 
14848
15079
  // src/lib/dossier/log.ts
14849
15080
  var import_node_crypto4 = require("node:crypto");
14850
- var import_node_fs13 = require("node:fs");
15081
+ var import_node_fs14 = require("node:fs");
14851
15082
  var import_node_path13 = require("node:path");
14852
15083
  var CRC_TABLE = (() => {
14853
15084
  const t = new Int32Array(256);
@@ -14867,7 +15098,7 @@ function crc32(s) {
14867
15098
  function openDossier(identity) {
14868
15099
  try {
14869
15100
  const dir = dossierDir(identity);
14870
- (0, import_node_fs13.mkdirSync)(dir, { recursive: true, mode: 448 });
15101
+ (0, import_node_fs14.mkdirSync)(dir, { recursive: true, mode: 448 });
14871
15102
  return {
14872
15103
  dir,
14873
15104
  identity,
@@ -14935,7 +15166,7 @@ function appendEvent(d, ev) {
14935
15166
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
14936
15167
  ...ev
14937
15168
  });
14938
- (0, import_node_fs13.appendFileSync)(d.eventsPath, line, { mode: 384 });
15169
+ (0, import_node_fs14.appendFileSync)(d.eventsPath, line, { mode: 384 });
14939
15170
  return true;
14940
15171
  } catch {
14941
15172
  return false;
@@ -14943,14 +15174,14 @@ function appendEvent(d, ev) {
14943
15174
  }
14944
15175
  function rotateIfNeeded2(d) {
14945
15176
  try {
14946
- if (!(0, import_node_fs13.existsSync)(d.eventsPath)) return;
14947
- if ((0, import_node_fs13.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
14948
- (0, import_node_fs13.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
14949
- (0, import_node_fs13.renameSync)(d.eventsPath, (0, import_node_path13.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
14950
- const kept = (0, import_node_fs13.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15177
+ if (!(0, import_node_fs14.existsSync)(d.eventsPath)) return;
15178
+ if ((0, import_node_fs14.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15179
+ (0, import_node_fs14.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15180
+ (0, import_node_fs14.renameSync)(d.eventsPath, (0, import_node_path13.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15181
+ const kept = (0, import_node_fs14.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
14951
15182
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
14952
15183
  try {
14953
- (0, import_node_fs13.renameSync)((0, import_node_path13.join)(d.rotatedDir, stale), (0, import_node_path13.join)(d.rotatedDir, `${stale}.pruned`));
15184
+ (0, import_node_fs14.renameSync)((0, import_node_path13.join)(d.rotatedDir, stale), (0, import_node_path13.join)(d.rotatedDir, `${stale}.pruned`));
14954
15185
  } catch {
14955
15186
  }
14956
15187
  }
@@ -14960,7 +15191,7 @@ function rotateIfNeeded2(d) {
14960
15191
 
14961
15192
  // src/lib/dossier/fold-dossier.ts
14962
15193
  var import_node_crypto5 = require("node:crypto");
14963
- var import_node_fs14 = require("node:fs");
15194
+ var import_node_fs15 = require("node:fs");
14964
15195
  var import_node_path14 = require("node:path");
14965
15196
  var EMPTY_CAPABILITIES = () => ({
14966
15197
  human_reachable: { value: "unknown", tier: "unknown" },
@@ -15012,12 +15243,12 @@ function foldDossier(d, opts = {}) {
15012
15243
  }
15013
15244
  };
15014
15245
  try {
15015
- if ((0, import_node_fs14.existsSync)(d.rotatedDir)) {
15016
- const files = (0, import_node_fs14.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15246
+ if ((0, import_node_fs15.existsSync)(d.rotatedDir)) {
15247
+ const files = (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15017
15248
  state.meta.rotations = files.length;
15018
15249
  for (const f of files) {
15019
15250
  try {
15020
- ingest((0, import_node_fs14.readFileSync)((0, import_node_path14.join)(d.rotatedDir, f), "utf8"));
15251
+ ingest((0, import_node_fs15.readFileSync)((0, import_node_path14.join)(d.rotatedDir, f), "utf8"));
15021
15252
  } catch {
15022
15253
  state.meta.dropped_lines++;
15023
15254
  }
@@ -15026,9 +15257,9 @@ function foldDossier(d, opts = {}) {
15026
15257
  } catch {
15027
15258
  }
15028
15259
  try {
15029
- if ((0, import_node_fs14.existsSync)(d.eventsPath)) {
15030
- state.meta.upto_offset = (0, import_node_fs14.statSync)(d.eventsPath).size;
15031
- ingest((0, import_node_fs14.readFileSync)(d.eventsPath, "utf8"));
15260
+ if ((0, import_node_fs15.existsSync)(d.eventsPath)) {
15261
+ state.meta.upto_offset = (0, import_node_fs15.statSync)(d.eventsPath).size;
15262
+ ingest((0, import_node_fs15.readFileSync)(d.eventsPath, "utf8"));
15032
15263
  }
15033
15264
  } catch {
15034
15265
  }
@@ -15299,7 +15530,7 @@ function applyBounds(state, input) {
15299
15530
  }
15300
15531
 
15301
15532
  // src/lib/dossier/cache.ts
15302
- var import_node_fs15 = require("node:fs");
15533
+ var import_node_fs16 = require("node:fs");
15303
15534
  function compactState(s) {
15304
15535
  const ms = (iso) => Date.parse(iso) || 0;
15305
15536
  return {
@@ -15428,20 +15659,20 @@ function encodeState(s) {
15428
15659
  function writeFoldCache(d, state) {
15429
15660
  try {
15430
15661
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
15431
- (0, import_node_fs15.writeFileSync)(tmp, encodeState(state), { mode: 384 });
15432
- (0, import_node_fs15.renameSync)(tmp, d.foldPath);
15662
+ (0, import_node_fs16.writeFileSync)(tmp, encodeState(state), { mode: 384 });
15663
+ (0, import_node_fs16.renameSync)(tmp, d.foldPath);
15433
15664
  } catch {
15434
15665
  }
15435
15666
  }
15436
15667
  function readFoldCache(d) {
15437
15668
  try {
15438
- if (!(0, import_node_fs15.existsSync)(d.foldPath)) return null;
15439
- const raw = JSON.parse((0, import_node_fs15.readFileSync)(d.foldPath, "utf8"));
15669
+ if (!(0, import_node_fs16.existsSync)(d.foldPath)) return null;
15670
+ const raw = JSON.parse((0, import_node_fs16.readFileSync)(d.foldPath, "utf8"));
15440
15671
  if (raw?.v !== 1) return null;
15441
15672
  const cached2 = expandState(raw);
15442
15673
  if (!cached2?.meta) return null;
15443
- const size = (0, import_node_fs15.existsSync)(d.eventsPath) ? (0, import_node_fs15.statSync)(d.eventsPath).size : 0;
15444
- const rotations = (0, import_node_fs15.existsSync)(d.rotatedDir) ? (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
15674
+ const size = (0, import_node_fs16.existsSync)(d.eventsPath) ? (0, import_node_fs16.statSync)(d.eventsPath).size : 0;
15675
+ const rotations = (0, import_node_fs16.existsSync)(d.rotatedDir) ? (0, import_node_fs16.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
15445
15676
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
15446
15677
  return cached2;
15447
15678
  } catch {
@@ -15492,13 +15723,13 @@ function assessContinuity(i) {
15492
15723
 
15493
15724
  // src/lib/dossier/reanchor.ts
15494
15725
  var import_node_crypto6 = require("node:crypto");
15495
- var import_node_fs16 = require("node:fs");
15726
+ var import_node_fs17 = require("node:fs");
15496
15727
  function lineSha(text) {
15497
15728
  return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
15498
15729
  }
15499
15730
  function fileHash(path) {
15500
15731
  try {
15501
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs16.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
15732
+ return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs17.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
15502
15733
  } catch {
15503
15734
  return null;
15504
15735
  }
@@ -15870,14 +16101,14 @@ function foreignAuthoredPaths(identity, opts = {}) {
15870
16101
  let sessions = 0;
15871
16102
  try {
15872
16103
  const dir = treeDir(identity);
15873
- if (!(0, import_node_fs17.existsSync)(dir)) return { paths: [], sessions: 0 };
15874
- for (const entry of (0, import_node_fs17.readdirSync)(dir, { withFileTypes: true })) {
16104
+ if (!(0, import_node_fs18.existsSync)(dir)) return { paths: [], sessions: 0 };
16105
+ for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
15875
16106
  if (!entry.isDirectory()) continue;
15876
16107
  if (entry.name === identity.sessionKey) continue;
15877
16108
  const log = (0, import_node_path15.join)(dir, entry.name, "events.jsonl");
15878
16109
  try {
15879
- if (!(0, import_node_fs17.existsSync)(log)) continue;
15880
- if (now - (0, import_node_fs17.statSync)(log).mtimeMs > windowMs) continue;
16110
+ if (!(0, import_node_fs18.existsSync)(log)) continue;
16111
+ if (now - (0, import_node_fs18.statSync)(log).mtimeMs > windowMs) continue;
15881
16112
  const sib = {
15882
16113
  dir: (0, import_node_path15.join)(dir, entry.name),
15883
16114
  identity,
@@ -15912,13 +16143,13 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15912
16143
  try {
15913
16144
  const mine = dossierDir(identity);
15914
16145
  const userDir = (0, import_node_path15.dirname)((0, import_node_path15.dirname)(mine));
15915
- if (!(0, import_node_fs17.existsSync)(userDir)) return 0;
16146
+ if (!(0, import_node_fs18.existsSync)(userDir)) return 0;
15916
16147
  const cutoff = Date.now() - maxAgeMs;
15917
- for (const tree of (0, import_node_fs17.readdirSync)(userDir, { withFileTypes: true })) {
16148
+ for (const tree of (0, import_node_fs18.readdirSync)(userDir, { withFileTypes: true })) {
15918
16149
  if (!tree.isDirectory()) continue;
15919
16150
  const treePath = (0, import_node_path15.join)(userDir, tree.name);
15920
16151
  let live = 0;
15921
- for (const entry of (0, import_node_fs17.readdirSync)(treePath, { withFileTypes: true })) {
16152
+ for (const entry of (0, import_node_fs18.readdirSync)(treePath, { withFileTypes: true })) {
15922
16153
  if (!entry.isDirectory()) continue;
15923
16154
  const dir = (0, import_node_path15.join)(treePath, entry.name);
15924
16155
  if (dir === mine) {
@@ -15927,9 +16158,9 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15927
16158
  }
15928
16159
  try {
15929
16160
  const log = (0, import_node_path15.join)(dir, "events.jsonl");
15930
- const at = (0, import_node_fs17.existsSync)(log) ? (0, import_node_fs17.statSync)(log).mtimeMs : (0, import_node_fs17.statSync)(dir).mtimeMs;
16161
+ const at = (0, import_node_fs18.existsSync)(log) ? (0, import_node_fs18.statSync)(log).mtimeMs : (0, import_node_fs18.statSync)(dir).mtimeMs;
15931
16162
  if (at < cutoff) {
15932
- (0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
16163
+ (0, import_node_fs18.rmSync)(dir, { recursive: true, force: true });
15933
16164
  removed++;
15934
16165
  } else {
15935
16166
  live++;
@@ -15939,7 +16170,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15939
16170
  }
15940
16171
  if (live === 0) {
15941
16172
  try {
15942
- (0, import_node_fs17.rmSync)(treePath, { recursive: false, force: false });
16173
+ (0, import_node_fs18.rmSync)(treePath, { recursive: false, force: false });
15943
16174
  } catch {
15944
16175
  }
15945
16176
  }
@@ -15956,8 +16187,8 @@ function sessionDossier(token, sessionId) {
15956
16187
  }
15957
16188
  function hasActiveGoal(d) {
15958
16189
  try {
15959
- if (!(0, import_node_fs17.existsSync)(d.eventsPath)) return false;
15960
- return (0, import_node_fs17.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16190
+ if (!(0, import_node_fs18.existsSync)(d.eventsPath)) return false;
16191
+ return (0, import_node_fs18.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
15961
16192
  } catch {
15962
16193
  return false;
15963
16194
  }
@@ -16050,7 +16281,7 @@ function recordVerdict(d, v) {
16050
16281
  if (!lines.has(f.file)) {
16051
16282
  try {
16052
16283
  const abs = (0, import_node_path15.join)(root, f.file);
16053
- lines.set(f.file, (0, import_node_fs17.existsSync)(abs) ? (0, import_node_fs17.readFileSync)(abs, "utf8").split("\n") : null);
16284
+ lines.set(f.file, (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null);
16054
16285
  } catch {
16055
16286
  lines.set(f.file, null);
16056
16287
  }
@@ -16151,7 +16382,7 @@ function recallMemory(d, identity, opts) {
16151
16382
  readFileLines: (file) => {
16152
16383
  try {
16153
16384
  const abs = (0, import_node_path15.join)(root, file);
16154
- return (0, import_node_fs17.existsSync)(abs) ? (0, import_node_fs17.readFileSync)(abs, "utf8").split("\n") : null;
16385
+ return (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null;
16155
16386
  } catch {
16156
16387
  return null;
16157
16388
  }
@@ -16295,21 +16526,21 @@ async function fireClassify(prompt, sessionId, globals) {
16295
16526
  }
16296
16527
 
16297
16528
  // src/commands/lifecycle.ts
16298
- var import_node_fs21 = require("node:fs");
16529
+ var import_node_fs22 = require("node:fs");
16299
16530
  var import_node_path19 = require("node:path");
16300
16531
 
16301
16532
  // src/lib/baseline.ts
16302
- var import_node_fs20 = require("node:fs");
16533
+ var import_node_fs21 = require("node:fs");
16303
16534
  var import_node_path18 = require("node:path");
16304
16535
  var import_node_crypto9 = require("node:crypto");
16305
16536
 
16306
16537
  // src/lib/snapshot.ts
16307
- var import_node_fs19 = require("node:fs");
16538
+ var import_node_fs20 = require("node:fs");
16308
16539
  var import_node_path17 = require("node:path");
16309
- var import_node_child_process6 = require("node:child_process");
16540
+ var import_node_child_process7 = require("node:child_process");
16310
16541
 
16311
16542
  // src/lib/files.ts
16312
- var import_node_fs18 = require("node:fs");
16543
+ var import_node_fs19 = require("node:fs");
16313
16544
  var import_node_path16 = require("node:path");
16314
16545
  var LANG_MAP = {
16315
16546
  // Analyzable (static analysis + Gemini)
@@ -16386,7 +16617,7 @@ function sortByMtime(files) {
16386
16617
  const resolved = resolveFile(f);
16387
16618
  if (!resolved) return null;
16388
16619
  try {
16389
- const stat3 = (0, import_node_fs18.statSync)(resolved);
16620
+ const stat3 = (0, import_node_fs19.statSync)(resolved);
16390
16621
  return { path: f, resolved, mtime: stat3.mtimeMs };
16391
16622
  } catch {
16392
16623
  return null;
@@ -16419,7 +16650,7 @@ function collectCodeDelta(files, opts) {
16419
16650
  }
16420
16651
  let size;
16421
16652
  try {
16422
- size = (0, import_node_fs18.statSync)(resolved).size;
16653
+ size = (0, import_node_fs19.statSync)(resolved).size;
16423
16654
  } catch {
16424
16655
  exclude(filepath, "not-stattable");
16425
16656
  continue;
@@ -16436,7 +16667,7 @@ function collectCodeDelta(files, opts) {
16436
16667
  }
16437
16668
  let content;
16438
16669
  try {
16439
- content = (0, import_node_fs18.readFileSync)(resolved, "utf-8");
16670
+ content = (0, import_node_fs19.readFileSync)(resolved, "utf-8");
16440
16671
  } catch {
16441
16672
  exclude(filepath, "not-readable");
16442
16673
  continue;
@@ -16475,7 +16706,7 @@ function collectCodeDelta(files, opts) {
16475
16706
 
16476
16707
  // src/lib/snapshot.ts
16477
16708
  function generateSnapshotDiffs(files) {
16478
- if (!(0, import_node_fs19.existsSync)(SNAPSHOT_DIR)) {
16709
+ if (!(0, import_node_fs20.existsSync)(SNAPSHOT_DIR)) {
16479
16710
  return { diffs: [], has_snapshots: false };
16480
16711
  }
16481
16712
  const diffs = [];
@@ -16483,8 +16714,8 @@ function generateSnapshotDiffs(files) {
16483
16714
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16484
16715
  const snapshotPath = (0, import_node_path17.join)(SNAPSHOT_DIR, file.path);
16485
16716
  const language = file.language ?? detectLanguage(file.path);
16486
- if ((0, import_node_fs19.existsSync)(snapshotPath)) {
16487
- const oldContent = (0, import_node_fs19.readFileSync)(snapshotPath, "utf-8");
16717
+ if ((0, import_node_fs20.existsSync)(snapshotPath)) {
16718
+ const oldContent = (0, import_node_fs20.readFileSync)(snapshotPath, "utf-8");
16488
16719
  if (oldContent === file.content) continue;
16489
16720
  const diff = computeDiff(oldContent, file.content, file.path);
16490
16721
  if (diff) {
@@ -16511,8 +16742,8 @@ function saveSnapshots(files) {
16511
16742
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16512
16743
  const snapshotPath = (0, import_node_path17.join)(SNAPSHOT_DIR, file.path);
16513
16744
  snapshotPaths.add(snapshotPath);
16514
- (0, import_node_fs19.mkdirSync)((0, import_node_path17.dirname)(snapshotPath), { recursive: true });
16515
- (0, import_node_fs19.writeFileSync)(snapshotPath, file.content);
16745
+ (0, import_node_fs20.mkdirSync)((0, import_node_path17.dirname)(snapshotPath), { recursive: true });
16746
+ (0, import_node_fs20.writeFileSync)(snapshotPath, file.content);
16516
16747
  }
16517
16748
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
16518
16749
  }
@@ -16520,10 +16751,10 @@ function computeDiff(oldContent, newContent, filePath) {
16520
16751
  const tmpOld = (0, import_node_path17.join)(SNAPSHOT_DIR, ".diff-old.tmp");
16521
16752
  const tmpNew = (0, import_node_path17.join)(SNAPSHOT_DIR, ".diff-new.tmp");
16522
16753
  try {
16523
- (0, import_node_fs19.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
16524
- (0, import_node_fs19.writeFileSync)(tmpOld, oldContent);
16525
- (0, import_node_fs19.writeFileSync)(tmpNew, newContent);
16526
- const result = (0, import_node_child_process6.execSync)(
16754
+ (0, import_node_fs20.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
16755
+ (0, import_node_fs20.writeFileSync)(tmpOld, oldContent);
16756
+ (0, import_node_fs20.writeFileSync)(tmpNew, newContent);
16757
+ const result = (0, import_node_child_process7.execSync)(
16527
16758
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
16528
16759
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
16529
16760
  );
@@ -16536,32 +16767,32 @@ function computeDiff(oldContent, newContent, filePath) {
16536
16767
  return null;
16537
16768
  } finally {
16538
16769
  try {
16539
- (0, import_node_fs19.unlinkSync)(tmpOld);
16770
+ (0, import_node_fs20.unlinkSync)(tmpOld);
16540
16771
  } catch {
16541
16772
  }
16542
16773
  try {
16543
- (0, import_node_fs19.unlinkSync)(tmpNew);
16774
+ (0, import_node_fs20.unlinkSync)(tmpNew);
16544
16775
  } catch {
16545
16776
  }
16546
16777
  }
16547
16778
  }
16548
16779
  function cleanStaleSnapshots(dir, keepSet) {
16549
- if (!(0, import_node_fs19.existsSync)(dir)) return;
16780
+ if (!(0, import_node_fs20.existsSync)(dir)) return;
16550
16781
  try {
16551
- const entries = (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true });
16782
+ const entries = (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true });
16552
16783
  for (const entry of entries) {
16553
16784
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
16554
16785
  const fullPath = (0, import_node_path17.join)(dir, entry.name);
16555
16786
  if (entry.isDirectory()) {
16556
16787
  cleanStaleSnapshots(fullPath, keepSet);
16557
16788
  try {
16558
- const remaining = (0, import_node_fs19.readdirSync)(fullPath);
16559
- if (remaining.length === 0) (0, import_node_fs19.rmdirSync)(fullPath);
16789
+ const remaining = (0, import_node_fs20.readdirSync)(fullPath);
16790
+ if (remaining.length === 0) (0, import_node_fs20.rmdirSync)(fullPath);
16560
16791
  } catch {
16561
16792
  }
16562
16793
  } else if (!keepSet.has(fullPath)) {
16563
16794
  try {
16564
- (0, import_node_fs19.unlinkSync)(fullPath);
16795
+ (0, import_node_fs20.unlinkSync)(fullPath);
16565
16796
  } catch {
16566
16797
  }
16567
16798
  }
@@ -16592,8 +16823,8 @@ var CARRY_FILE = `${BASELINE_DIR}/.carry`;
16592
16823
  var CARRY_WINDOW_MS = 12e4;
16593
16824
  function writeCarry(sessionId, headSha) {
16594
16825
  try {
16595
- (0, import_node_fs20.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16596
- (0, import_node_fs20.writeFileSync)(
16826
+ (0, import_node_fs21.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16827
+ (0, import_node_fs21.writeFileSync)(
16597
16828
  projectPath(CARRY_FILE),
16598
16829
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
16599
16830
  );
@@ -16603,10 +16834,10 @@ function writeCarry(sessionId, headSha) {
16603
16834
  function claimCarry(newKey) {
16604
16835
  const carryPath = projectPath(CARRY_FILE);
16605
16836
  try {
16606
- if (!(0, import_node_fs20.existsSync)(carryPath)) return null;
16607
- const carry = JSON.parse((0, import_node_fs20.readFileSync)(carryPath, "utf-8"));
16837
+ if (!(0, import_node_fs21.existsSync)(carryPath)) return null;
16838
+ const carry = JSON.parse((0, import_node_fs21.readFileSync)(carryPath, "utf-8"));
16608
16839
  try {
16609
- (0, import_node_fs20.rmSync)(carryPath, { force: true });
16840
+ (0, import_node_fs21.rmSync)(carryPath, { force: true });
16610
16841
  } catch {
16611
16842
  }
16612
16843
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -16617,11 +16848,11 @@ function claimCarry(newKey) {
16617
16848
  if (!prior) return null;
16618
16849
  const toDir = sessionDir(newKey);
16619
16850
  try {
16620
- (0, import_node_fs20.rmSync)(toDir, { recursive: true, force: true });
16851
+ (0, import_node_fs21.rmSync)(toDir, { recursive: true, force: true });
16621
16852
  } catch {
16622
16853
  }
16623
- (0, import_node_fs20.renameSync)(fromDir, toDir);
16624
- (0, import_node_fs20.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16854
+ (0, import_node_fs21.renameSync)(fromDir, toDir);
16855
+ (0, import_node_fs21.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16625
16856
  return readManifest(toDir);
16626
16857
  } catch {
16627
16858
  return null;
@@ -16645,21 +16876,21 @@ function captureBaseline(opts = {}) {
16645
16876
  const head_sha = getCurrentCommit();
16646
16877
  const dirty = getDirtyFiles();
16647
16878
  try {
16648
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
16879
+ (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
16649
16880
  } catch {
16650
16881
  }
16651
16882
  const filesDir = (0, import_node_path18.join)(dir, "files");
16652
16883
  const mirrored = [];
16653
16884
  try {
16654
- (0, import_node_fs20.mkdirSync)(filesDir, { recursive: true });
16885
+ (0, import_node_fs21.mkdirSync)(filesDir, { recursive: true });
16655
16886
  for (const p of dirty) {
16656
16887
  if (p.includes("..")) continue;
16657
16888
  const content = safeReadForMirror(projectPath(p));
16658
16889
  if (content === null) continue;
16659
16890
  const dest = mirrorPath(dir, p);
16660
16891
  try {
16661
- (0, import_node_fs20.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
16662
- (0, import_node_fs20.writeFileSync)(dest, content);
16892
+ (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
16893
+ (0, import_node_fs21.writeFileSync)(dest, content);
16663
16894
  mirrored.push(p);
16664
16895
  } catch {
16665
16896
  }
@@ -16674,8 +16905,8 @@ function captureBaseline(opts = {}) {
16674
16905
  version: BASELINE_VERSION
16675
16906
  };
16676
16907
  try {
16677
- (0, import_node_fs20.mkdirSync)(dir, { recursive: true });
16678
- (0, import_node_fs20.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16908
+ (0, import_node_fs21.mkdirSync)(dir, { recursive: true });
16909
+ (0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16679
16910
  } catch {
16680
16911
  }
16681
16912
  pruneOldBaselines();
@@ -16686,9 +16917,9 @@ function readBaseline(sessionId) {
16686
16917
  }
16687
16918
  function readManifest(dir) {
16688
16919
  const mp = manifestPath(dir);
16689
- if (!(0, import_node_fs20.existsSync)(mp)) return null;
16920
+ if (!(0, import_node_fs21.existsSync)(mp)) return null;
16690
16921
  try {
16691
- const parsed = JSON.parse((0, import_node_fs20.readFileSync)(mp, "utf-8"));
16922
+ const parsed = JSON.parse((0, import_node_fs21.readFileSync)(mp, "utf-8"));
16692
16923
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
16693
16924
  return null;
16694
16925
  }
@@ -16719,9 +16950,9 @@ function preImage(repoRelPath, baseline) {
16719
16950
  function resolvePreImage(repoRelPath, baseline) {
16720
16951
  if (baseline.dirty_paths.includes(repoRelPath)) {
16721
16952
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
16722
- if ((0, import_node_fs20.existsSync)(mp)) {
16953
+ if ((0, import_node_fs21.existsSync)(mp)) {
16723
16954
  try {
16724
- return { content: (0, import_node_fs20.readFileSync)(mp, "utf-8"), existed: true };
16955
+ return { content: (0, import_node_fs21.readFileSync)(mp, "utf-8"), existed: true };
16725
16956
  } catch {
16726
16957
  }
16727
16958
  }
@@ -16766,8 +16997,8 @@ function absorbIntoBaseline(paths, sessionId) {
16766
16997
  const content = safeReadForMirror(projectPath(p));
16767
16998
  if (content === null) continue;
16768
16999
  const dest = mirrorPath(dir, p);
16769
- (0, import_node_fs20.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
16770
- (0, import_node_fs20.writeFileSync)(dest, content);
17000
+ (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
17001
+ (0, import_node_fs21.writeFileSync)(dest, content);
16771
17002
  dirty.add(p);
16772
17003
  adopted++;
16773
17004
  } catch {
@@ -16776,7 +17007,7 @@ function absorbIntoBaseline(paths, sessionId) {
16776
17007
  if (adopted === 0) return 0;
16777
17008
  try {
16778
17009
  const updated = { ...baseline, dirty_paths: [...dirty] };
16779
- (0, import_node_fs20.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17010
+ (0, import_node_fs21.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
16780
17011
  preImageCache.delete(baseline);
16781
17012
  } catch {
16782
17013
  return 0;
@@ -16787,7 +17018,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
16787
17018
  const pre = preImage(repoRelPath, baseline);
16788
17019
  let current;
16789
17020
  try {
16790
- current = (0, import_node_fs20.readFileSync)(projectPath(repoRelPath), "utf-8");
17021
+ current = (0, import_node_fs21.readFileSync)(projectPath(repoRelPath), "utf-8");
16791
17022
  } catch {
16792
17023
  return pre.existed;
16793
17024
  }
@@ -16796,8 +17027,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
16796
17027
  }
16797
17028
  function safeReadForMirror(absPath) {
16798
17029
  try {
16799
- if ((0, import_node_fs20.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
16800
- const buf = (0, import_node_fs20.readFileSync)(absPath);
17030
+ if ((0, import_node_fs21.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17031
+ const buf = (0, import_node_fs21.readFileSync)(absPath);
16801
17032
  if (buf.includes(0)) return null;
16802
17033
  return buf.toString("utf-8");
16803
17034
  } catch {
@@ -16808,7 +17039,7 @@ function pruneOldBaselines() {
16808
17039
  const root = projectPath(BASELINE_DIR);
16809
17040
  let entries;
16810
17041
  try {
16811
- entries = (0, import_node_fs20.readdirSync)(root);
17042
+ entries = (0, import_node_fs21.readdirSync)(root);
16812
17043
  } catch {
16813
17044
  return;
16814
17045
  }
@@ -16818,8 +17049,8 @@ function pruneOldBaselines() {
16818
17049
  const manifest = readManifest(dir);
16819
17050
  if (!manifest) {
16820
17051
  try {
16821
- if (now - (0, import_node_fs20.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
16822
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
17052
+ if (now - (0, import_node_fs21.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17053
+ (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
16823
17054
  }
16824
17055
  } catch {
16825
17056
  }
@@ -16827,7 +17058,7 @@ function pruneOldBaselines() {
16827
17058
  }
16828
17059
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
16829
17060
  try {
16830
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
17061
+ (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
16831
17062
  } catch {
16832
17063
  }
16833
17064
  }
@@ -17003,7 +17234,7 @@ function buildCompactionContext(session) {
17003
17234
  readFileLines: (file) => {
17004
17235
  try {
17005
17236
  const abs = (0, import_node_path19.join)(root, file);
17006
- return (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null;
17237
+ return (0, import_node_fs22.existsSync)(abs) ? (0, import_node_fs22.readFileSync)(abs, "utf8").split("\n") : null;
17007
17238
  } catch {
17008
17239
  return null;
17009
17240
  }
@@ -17060,18 +17291,18 @@ async function readHookStdin() {
17060
17291
 
17061
17292
  // src/commands/standard.ts
17062
17293
  var import_promises12 = require("node:fs/promises");
17063
- var import_node_fs28 = require("node:fs");
17294
+ var import_node_fs29 = require("node:fs");
17064
17295
  var import_yaml3 = __toESM(require_dist());
17065
17296
 
17066
17297
  // src/lib/synthesize.ts
17067
- var import_node_child_process8 = require("node:child_process");
17068
- var import_node_fs24 = require("node:fs");
17298
+ var import_node_child_process9 = require("node:child_process");
17299
+ var import_node_fs25 = require("node:fs");
17069
17300
  var import_promises9 = require("node:fs/promises");
17070
17301
  var import_node_path22 = require("node:path");
17071
17302
  var import_yaml = __toESM(require_dist());
17072
17303
 
17073
17304
  // src/lib/data-dir.ts
17074
- var import_node_fs22 = require("node:fs");
17305
+ var import_node_fs23 = require("node:fs");
17075
17306
  var import_node_path20 = require("node:path");
17076
17307
  function resolveDataDir() {
17077
17308
  const candidates2 = [
@@ -17093,7 +17324,7 @@ function resolveDataDir() {
17093
17324
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
17094
17325
  ];
17095
17326
  for (const candidate of candidates2) {
17096
- if ((0, import_node_fs22.existsSync)((0, import_node_path20.join)(candidate, "skills"))) {
17327
+ if ((0, import_node_fs23.existsSync)((0, import_node_path20.join)(candidate, "skills"))) {
17097
17328
  return candidate;
17098
17329
  }
17099
17330
  }
@@ -17106,8 +17337,8 @@ function setupDataPath(file) {
17106
17337
  }
17107
17338
 
17108
17339
  // src/lib/detect.ts
17109
- var import_node_child_process7 = require("node:child_process");
17110
- var import_node_fs23 = require("node:fs");
17340
+ var import_node_child_process8 = require("node:child_process");
17341
+ var import_node_fs24 = require("node:fs");
17111
17342
  var import_node_path21 = require("node:path");
17112
17343
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
17113
17344
  "typescript",
@@ -17139,19 +17370,19 @@ var IGNORED_SEGMENTS = [
17139
17370
  ".verity",
17140
17371
  ".codacy"
17141
17372
  ];
17142
- function isIgnored(path) {
17373
+ function isIgnored2(path) {
17143
17374
  const parts = path.split("/");
17144
17375
  return parts.some((p) => IGNORED_SEGMENTS.includes(p));
17145
17376
  }
17146
17377
  function listProjectFiles(root) {
17147
17378
  try {
17148
- const out = (0, import_node_child_process7.execSync)("git ls-files -z", {
17379
+ const out = (0, import_node_child_process8.execSync)("git ls-files -z", {
17149
17380
  cwd: root,
17150
17381
  encoding: "utf-8",
17151
17382
  maxBuffer: 32 * 1024 * 1024,
17152
17383
  stdio: ["pipe", "pipe", "pipe"]
17153
17384
  });
17154
- const tracked = out.split("\0").filter(Boolean).filter((p) => !isIgnored(p));
17385
+ const tracked = out.split("\0").filter(Boolean).filter((p) => !isIgnored2(p));
17155
17386
  if (tracked.length > 0) return tracked;
17156
17387
  } catch {
17157
17388
  }
@@ -17165,7 +17396,7 @@ function walk(root) {
17165
17396
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
17166
17397
  let entries;
17167
17398
  try {
17168
- entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
17399
+ entries = (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true });
17169
17400
  } catch {
17170
17401
  return;
17171
17402
  }
@@ -17240,7 +17471,7 @@ var TOOL_CONFIG_MARKERS = [
17240
17471
  ];
17241
17472
  function readJson(path) {
17242
17473
  try {
17243
- return JSON.parse((0, import_node_fs23.readFileSync)(path, "utf-8"));
17474
+ return JSON.parse((0, import_node_fs24.readFileSync)(path, "utf-8"));
17244
17475
  } catch {
17245
17476
  return null;
17246
17477
  }
@@ -17273,9 +17504,9 @@ function declaredDependencies(root, files) {
17273
17504
  ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path21.join)(root, f))
17274
17505
  ];
17275
17506
  for (const path of pythonManifests) {
17276
- if (!(0, import_node_fs23.existsSync)(path)) continue;
17507
+ if (!(0, import_node_fs24.existsSync)(path)) continue;
17277
17508
  try {
17278
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
17509
+ const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17279
17510
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
17280
17511
  for (const line of text.split("\n")) {
17281
17512
  if (!/dependencies\s*=/.test(line)) continue;
@@ -17289,9 +17520,9 @@ function declaredDependencies(root, files) {
17289
17520
  ...files.filter((f) => f.includes("/") && (0, import_node_path21.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path21.join)(root, f))
17290
17521
  ];
17291
17522
  for (const path of goMods) {
17292
- if (!(0, import_node_fs23.existsSync)(path)) continue;
17523
+ if (!(0, import_node_fs24.existsSync)(path)) continue;
17293
17524
  try {
17294
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
17525
+ const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17295
17526
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
17296
17527
  names2.push(m[1].replace(/^github\.com\//, ""));
17297
17528
  }
@@ -17300,9 +17531,9 @@ function declaredDependencies(root, files) {
17300
17531
  }
17301
17532
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
17302
17533
  const path = (0, import_node_path21.join)(root, file);
17303
- if (!(0, import_node_fs23.existsSync)(path)) continue;
17534
+ if (!(0, import_node_fs24.existsSync)(path)) continue;
17304
17535
  try {
17305
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
17536
+ const text = (0, import_node_fs24.readFileSync)(path, "utf-8");
17306
17537
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
17307
17538
  } catch {
17308
17539
  }
@@ -17310,7 +17541,7 @@ function declaredDependencies(root, files) {
17310
17541
  return names2;
17311
17542
  }
17312
17543
  function detectBuildSystem(root, files) {
17313
- const has = (f) => (0, import_node_fs23.existsSync)((0, import_node_path21.join)(root, f)) || files.some((p) => (0, import_node_path21.basename)(p) === f);
17544
+ const has = (f) => (0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, f)) || files.some((p) => (0, import_node_path21.basename)(p) === f);
17314
17545
  if (has("pnpm-lock.yaml")) return "pnpm";
17315
17546
  if (has("yarn.lock")) return "yarn";
17316
17547
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -17327,7 +17558,7 @@ function detectBuildSystem(root, files) {
17327
17558
  }
17328
17559
  function detectArchitecture(root, files) {
17329
17560
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
17330
- if (workspaceMarkers.some((m) => (0, import_node_fs23.existsSync)((0, import_node_path21.join)(root, m)))) return "monorepo";
17561
+ if (workspaceMarkers.some((m) => (0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, m)))) return "monorepo";
17331
17562
  const pkg = readJson((0, import_node_path21.join)(root, "package.json"));
17332
17563
  if (pkg && "workspaces" in pkg) return "monorepo";
17333
17564
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
@@ -17352,8 +17583,8 @@ function measureAvgFileLength(root, files, languages) {
17352
17583
  for (let i = 0; i < candidates2.length; i += stride) {
17353
17584
  const path = (0, import_node_path21.join)(root, candidates2[i]);
17354
17585
  try {
17355
- if ((0, import_node_fs23.statSync)(path).size > 2 * 1024 * 1024) continue;
17356
- total += (0, import_node_fs23.readFileSync)(path, "utf-8").split("\n").length;
17586
+ if ((0, import_node_fs24.statSync)(path).size > 2 * 1024 * 1024) continue;
17587
+ total += (0, import_node_fs24.readFileSync)(path, "utf-8").split("\n").length;
17357
17588
  counted++;
17358
17589
  } catch {
17359
17590
  }
@@ -17383,7 +17614,7 @@ function detectProject(root = repoRoot()) {
17383
17614
  const existingToolConfigs = [];
17384
17615
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
17385
17616
  for (const marker of markers) {
17386
- if ((0, import_node_fs23.existsSync)((0, import_node_path21.join)(root, marker))) {
17617
+ if ((0, import_node_fs24.existsSync)((0, import_node_path21.join)(root, marker))) {
17387
17618
  existingToolConfigs.push({ tool, path: `./${marker}` });
17388
17619
  break;
17389
17620
  }
@@ -17488,8 +17719,8 @@ ${closingNote(input.origin)}
17488
17719
 
17489
17720
  // src/lib/synthesize.ts
17490
17721
  function loadCatalog() {
17491
- const catalog = (0, import_yaml.parse)((0, import_node_fs24.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
17492
- const template = (0, import_yaml.parse)((0, import_node_fs24.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
17722
+ const catalog = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
17723
+ const template = (0, import_yaml.parse)((0, import_node_fs25.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
17493
17724
  return { catalog, template };
17494
17725
  }
17495
17726
  function selectTools(languages, intensity, catalog) {
@@ -17540,7 +17771,7 @@ var TRIVY_BY_INTENSITY = {
17540
17771
  };
17541
17772
  function adapterPatternIds(toolId) {
17542
17773
  try {
17543
- const out = (0, import_node_child_process8.execFileSync)(
17774
+ const out = (0, import_node_child_process9.execFileSync)(
17544
17775
  process.execPath,
17545
17776
  [setupDataPath("validate-patterns.mjs"), "--list", toolId],
17546
17777
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
@@ -17570,7 +17801,7 @@ function resolvePatternId(toolId, curatedId, adapterIds) {
17570
17801
  }
17571
17802
  function trivyPatterns(intensity) {
17572
17803
  try {
17573
- const out = (0, import_node_child_process8.execFileSync)(
17804
+ const out = (0, import_node_child_process9.execFileSync)(
17574
17805
  process.execPath,
17575
17806
  [setupDataPath("validate-patterns.mjs"), "--emit", "Trivy", TRIVY_BY_INTENSITY[intensity].emit],
17576
17807
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 3e4 }
@@ -17750,7 +17981,7 @@ export default tseslint.config(
17750
17981
  function validatePatternIds() {
17751
17982
  const configPath = projectPath(CODACY_CONFIG_FILE);
17752
17983
  try {
17753
- (0, import_node_child_process8.execFileSync)(process.execPath, [setupDataPath("validate-patterns.mjs"), configPath], {
17984
+ (0, import_node_child_process9.execFileSync)(process.execPath, [setupDataPath("validate-patterns.mjs"), configPath], {
17754
17985
  encoding: "utf-8",
17755
17986
  stdio: ["pipe", "pipe", "pipe"],
17756
17987
  timeout: 6e4
@@ -17767,7 +17998,7 @@ function validatePatternIds() {
17767
17998
  }
17768
17999
  async function runSynthesis(opts) {
17769
18000
  const standardPath = projectPath(STANDARD_FILE);
17770
- if ((0, import_node_fs24.existsSync)(standardPath) && !opts.force) {
18001
+ if ((0, import_node_fs25.existsSync)(standardPath) && !opts.force) {
17771
18002
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
17772
18003
  }
17773
18004
  const detected = opts.detected ?? detectProject();
@@ -17895,11 +18126,11 @@ ${validation.detail}`);
17895
18126
 
17896
18127
  // src/lib/setup-state.ts
17897
18128
  var import_promises10 = require("node:fs/promises");
17898
- var import_node_fs25 = require("node:fs");
18129
+ var import_node_fs26 = require("node:fs");
17899
18130
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
17900
18131
  async function readSetupState() {
17901
18132
  const path = projectPath(SETUP_STATE_FILE);
17902
- if (!(0, import_node_fs25.existsSync)(path)) return null;
18133
+ if (!(0, import_node_fs26.existsSync)(path)) return null;
17903
18134
  try {
17904
18135
  const parsed = JSON.parse(await (0, import_promises10.readFile)(path, "utf-8"));
17905
18136
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -17915,12 +18146,12 @@ async function writeSetupState(patch) {
17915
18146
  }
17916
18147
 
17917
18148
  // src/lib/push-setup.ts
17918
- var import_node_fs27 = require("node:fs");
18149
+ var import_node_fs28 = require("node:fs");
17919
18150
  var import_promises11 = require("node:fs/promises");
17920
18151
  var import_yaml2 = __toESM(require_dist());
17921
18152
 
17922
18153
  // src/lib/verityignore.ts
17923
- var import_node_fs26 = require("node:fs");
18154
+ var import_node_fs27 = require("node:fs");
17924
18155
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
17925
18156
  var SECURITY_PROBES = [
17926
18157
  ".env",
@@ -18008,14 +18239,14 @@ function decide(rules, path) {
18008
18239
  }
18009
18240
  return excluded;
18010
18241
  }
18011
- function isIgnored2(ig, path) {
18242
+ function isIgnored3(ig, path) {
18012
18243
  return decide(ig.rules, path);
18013
18244
  }
18014
18245
  function loadVerityIgnore() {
18015
18246
  const file = projectPath(VERITYIGNORE_FILE);
18016
- if (!(0, import_node_fs26.existsSync)(file)) return EMPTY;
18247
+ if (!(0, import_node_fs27.existsSync)(file)) return EMPTY;
18017
18248
  try {
18018
- return parseVerityIgnore((0, import_node_fs26.readFileSync)(file, "utf-8"));
18249
+ return parseVerityIgnore((0, import_node_fs27.readFileSync)(file, "utf-8"));
18019
18250
  } catch {
18020
18251
  return EMPTY;
18021
18252
  }
@@ -18028,7 +18259,7 @@ function partitionIgnored(paths, ig) {
18028
18259
  const kept = [];
18029
18260
  const ignored = [];
18030
18261
  for (const p of paths) {
18031
- if (p !== VERITYIGNORE_FILE && isIgnored2(ig, p)) ignored.push(p);
18262
+ if (p !== VERITYIGNORE_FILE && isIgnored3(ig, p)) ignored.push(p);
18032
18263
  else kept.push(p);
18033
18264
  }
18034
18265
  return {
@@ -18053,9 +18284,9 @@ function buildStandardUpload(standard, ignoreRaw) {
18053
18284
  }
18054
18285
  function readVerityIgnoreRaw() {
18055
18286
  const file = projectPath(VERITYIGNORE_FILE);
18056
- if (!(0, import_node_fs26.existsSync)(file)) return null;
18287
+ if (!(0, import_node_fs27.existsSync)(file)) return null;
18057
18288
  try {
18058
- return (0, import_node_fs26.readFileSync)(file, "utf-8");
18289
+ return (0, import_node_fs27.readFileSync)(file, "utf-8");
18059
18290
  } catch {
18060
18291
  return null;
18061
18292
  }
@@ -18083,7 +18314,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18083
18314
  }
18084
18315
  let standardVersion = null;
18085
18316
  const standardPath = projectPath(STANDARD_FILE);
18086
- if (pushStandard && (0, import_node_fs27.existsSync)(standardPath)) {
18317
+ if (pushStandard && (0, import_node_fs28.existsSync)(standardPath)) {
18087
18318
  try {
18088
18319
  const content = (0, import_yaml2.parse)(await (0, import_promises11.readFile)(standardPath, "utf-8"));
18089
18320
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -18108,7 +18339,7 @@ async function pushStandardAndConfig(globals, what = {}) {
18108
18339
  }
18109
18340
  let configPushed = false;
18110
18341
  const configPath = projectPath(CODACY_CONFIG_FILE);
18111
- if (pushConfig && (0, import_node_fs27.existsSync)(configPath)) {
18342
+ if (pushConfig && (0, import_node_fs28.existsSync)(configPath)) {
18112
18343
  try {
18113
18344
  const content = JSON.parse(await (0, import_promises11.readFile)(configPath, "utf-8"));
18114
18345
  const result = await apiRequest({
@@ -18140,7 +18371,7 @@ function registerStandardCommands(program2) {
18140
18371
  const state = await readSetupState();
18141
18372
  if (opts.configOnly) {
18142
18373
  const standardPath = projectPath(STANDARD_FILE);
18143
- if (!(0, import_node_fs28.existsSync)(standardPath)) {
18374
+ if (!(0, import_node_fs29.existsSync)(standardPath)) {
18144
18375
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
18145
18376
  process.exit(1);
18146
18377
  }
@@ -18471,10 +18702,10 @@ function formatRunDetail(run2) {
18471
18702
  }
18472
18703
 
18473
18704
  // src/lib/ignore-declaration.ts
18474
- var import_node_fs30 = require("node:fs");
18705
+ var import_node_fs31 = require("node:fs");
18475
18706
 
18476
18707
  // src/lib/debounce.ts
18477
- var import_node_fs29 = require("node:fs");
18708
+ var import_node_fs30 = require("node:fs");
18478
18709
  var import_node_crypto10 = require("node:crypto");
18479
18710
  function scopedFile(base, sessionId) {
18480
18711
  if (!sessionId) return base;
@@ -18482,9 +18713,9 @@ function scopedFile(base, sessionId) {
18482
18713
  }
18483
18714
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18484
18715
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18485
- if (!(0, import_node_fs29.existsSync)(file)) return null;
18716
+ if (!(0, import_node_fs30.existsSync)(file)) return null;
18486
18717
  try {
18487
- const lastTs = parseInt((0, import_node_fs29.readFileSync)(file, "utf-8").trim(), 10);
18718
+ const lastTs = parseInt((0, import_node_fs30.readFileSync)(file, "utf-8").trim(), 10);
18488
18719
  const nowTs = Math.floor(Date.now() / 1e3);
18489
18720
  const elapsed = nowTs - lastTs;
18490
18721
  if (elapsed < debounceSeconds) {
@@ -18497,10 +18728,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18497
18728
  function checkMtime(files, bypassForRecentCommits, sessionId) {
18498
18729
  if (bypassForRecentCommits) return null;
18499
18730
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18500
- if (!(0, import_node_fs29.existsSync)(file)) return null;
18731
+ if (!(0, import_node_fs30.existsSync)(file)) return null;
18501
18732
  let debounceTime;
18502
18733
  try {
18503
- debounceTime = (0, import_node_fs29.statSync)(file).mtimeMs;
18734
+ debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
18504
18735
  } catch {
18505
18736
  return null;
18506
18737
  }
@@ -18508,7 +18739,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
18508
18739
  const resolved = resolveFile(f);
18509
18740
  if (!resolved) continue;
18510
18741
  try {
18511
- const stat3 = (0, import_node_fs29.statSync)(resolved);
18742
+ const stat3 = (0, import_node_fs30.statSync)(resolved);
18512
18743
  if (stat3.mtimeMs > debounceTime) {
18513
18744
  return null;
18514
18745
  }
@@ -18524,8 +18755,8 @@ function computeContentHash(files) {
18524
18755
  for (const f of sorted) {
18525
18756
  const resolved = resolveFile(f) ?? f;
18526
18757
  try {
18527
- if ((0, import_node_fs29.existsSync)(resolved)) {
18528
- hash.update((0, import_node_fs29.readFileSync)(resolved));
18758
+ if ((0, import_node_fs30.existsSync)(resolved)) {
18759
+ hash.update((0, import_node_fs30.readFileSync)(resolved));
18529
18760
  }
18530
18761
  } catch {
18531
18762
  }
@@ -18535,9 +18766,9 @@ function computeContentHash(files) {
18535
18766
  function checkContentHash(files, sessionId) {
18536
18767
  const hash = computeContentHash(files);
18537
18768
  const file = scopedFile(HASH_FILE, sessionId);
18538
- if ((0, import_node_fs29.existsSync)(file)) {
18769
+ if ((0, import_node_fs30.existsSync)(file)) {
18539
18770
  try {
18540
- const storedHash = (0, import_node_fs29.readFileSync)(file, "utf-8").trim();
18771
+ const storedHash = (0, import_node_fs30.readFileSync)(file, "utf-8").trim();
18541
18772
  if (hash === storedHash) {
18542
18773
  return { skip: "No source changes since last analysis", hash };
18543
18774
  }
@@ -18547,24 +18778,24 @@ function checkContentHash(files, sessionId) {
18547
18778
  return { skip: null, hash };
18548
18779
  }
18549
18780
  function recordAnalysisStart(sessionId) {
18550
- (0, import_node_fs29.mkdirSync)(VERITY_DIR, { recursive: true });
18551
- (0, import_node_fs29.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18781
+ (0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
18782
+ (0, import_node_fs30.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18552
18783
  }
18553
18784
  function recordPassHash(hash, sessionId) {
18554
- (0, import_node_fs29.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18785
+ (0, import_node_fs30.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18555
18786
  }
18556
18787
  function narrowToRecent(files, sessionId) {
18557
18788
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18558
- if (!(0, import_node_fs29.existsSync)(file)) return files;
18789
+ if (!(0, import_node_fs30.existsSync)(file)) return files;
18559
18790
  let debounceTime;
18560
18791
  try {
18561
- debounceTime = (0, import_node_fs29.statSync)(file).mtimeMs;
18792
+ debounceTime = (0, import_node_fs30.statSync)(file).mtimeMs;
18562
18793
  } catch {
18563
18794
  return files;
18564
18795
  }
18565
18796
  const recent = files.filter((f) => {
18566
18797
  try {
18567
- return (0, import_node_fs29.existsSync)(f) && (0, import_node_fs29.statSync)(f).mtimeMs > debounceTime;
18798
+ return (0, import_node_fs30.existsSync)(f) && (0, import_node_fs30.statSync)(f).mtimeMs > debounceTime;
18568
18799
  } catch {
18569
18800
  return false;
18570
18801
  }
@@ -18577,9 +18808,9 @@ function readIteration(currentCommit, _contentHash) {
18577
18808
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
18578
18809
  function readBlockState(currentCommit, opts) {
18579
18810
  if (opts?.newUserPrompt) return NO_BLOCKS;
18580
- if (!(0, import_node_fs29.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18811
+ if (!(0, import_node_fs30.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18581
18812
  try {
18582
- const stored = (0, import_node_fs29.readFileSync)(ITERATION_FILE, "utf-8").trim();
18813
+ const stored = (0, import_node_fs30.readFileSync)(ITERATION_FILE, "utf-8").trim();
18583
18814
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
18584
18815
  if (!parsed) return NO_BLOCKS;
18585
18816
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -18625,8 +18856,8 @@ function isSameProblem(previous, current) {
18625
18856
  return current.split(",").some((k) => prev.has(k));
18626
18857
  }
18627
18858
  function writeBlockState(commit, state) {
18628
- (0, import_node_fs29.mkdirSync)(VERITY_DIR, { recursive: true });
18629
- (0, import_node_fs29.writeFileSync)(
18859
+ (0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
18860
+ (0, import_node_fs30.writeFileSync)(
18630
18861
  ITERATION_FILE,
18631
18862
  JSON.stringify({
18632
18863
  v: 2,
@@ -18731,9 +18962,9 @@ function resolveIgnoreState(keys) {
18731
18962
  }
18732
18963
  function readIgnoreState(sessionId) {
18733
18964
  const file = stateFile(sessionId);
18734
- if (!(0, import_node_fs30.existsSync)(file)) return null;
18965
+ if (!(0, import_node_fs31.existsSync)(file)) return null;
18735
18966
  try {
18736
- const o = JSON.parse((0, import_node_fs30.readFileSync)(file, "utf-8")) ?? {};
18967
+ const o = JSON.parse((0, import_node_fs31.readFileSync)(file, "utf-8")) ?? {};
18737
18968
  const spent = typeof o.spent === "number" ? o.spent : 0;
18738
18969
  const raw = o.active;
18739
18970
  let active = null;
@@ -18757,8 +18988,8 @@ function readIgnoreState(sessionId) {
18757
18988
  }
18758
18989
  function writeIgnoreState(state, sessionId) {
18759
18990
  try {
18760
- (0, import_node_fs30.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
18761
- (0, import_node_fs30.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
18991
+ (0, import_node_fs31.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
18992
+ (0, import_node_fs31.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
18762
18993
  } catch {
18763
18994
  }
18764
18995
  }
@@ -19141,10 +19372,10 @@ function createRun(opts, globals) {
19141
19372
  }
19142
19373
 
19143
19374
  // src/commands/analyze/index.ts
19144
- var import_node_fs43 = require("node:fs");
19375
+ var import_node_fs44 = require("node:fs");
19145
19376
 
19146
19377
  // src/lib/repo-context.ts
19147
- var import_node_child_process9 = require("node:child_process");
19378
+ var import_node_child_process10 = require("node:child_process");
19148
19379
  var import_node_os4 = require("node:os");
19149
19380
  function rgInvocations(env = process.env) {
19150
19381
  const out = [{ cmd: "rg" }];
@@ -19720,7 +19951,7 @@ function buildRepoContext(input) {
19720
19951
  ];
19721
19952
  let res = null;
19722
19953
  for (const inv of rgInvocations()) {
19723
- res = (0, import_node_child_process9.spawnSync)(inv.cmd, args, {
19954
+ res = (0, import_node_child_process10.spawnSync)(inv.cmd, args, {
19724
19955
  ...inv.argv0 ? { argv0: inv.argv0 } : {},
19725
19956
  cwd: input.cwd ?? process.cwd(),
19726
19957
  timeout: input.timeoutMs ?? RG_TIMEOUT_MS,
@@ -19961,8 +20192,8 @@ function installRunEvidence(run2) {
19961
20192
  }
19962
20193
 
19963
20194
  // src/lib/git-frame.ts
19964
- var import_node_child_process10 = require("node:child_process");
19965
- var import_node_fs31 = require("node:fs");
20195
+ var import_node_child_process11 = require("node:child_process");
20196
+ var import_node_fs32 = require("node:fs");
19966
20197
  var import_node_os5 = require("node:os");
19967
20198
  var import_node_path23 = require("node:path");
19968
20199
  var import_node_path24 = require("node:path");
@@ -20094,21 +20325,21 @@ function parsePushTarget(segment) {
20094
20325
  }
20095
20326
  function gitAt(dir, args) {
20096
20327
  try {
20097
- return (0, import_node_child_process10.execFileSync)("git", args, { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
20328
+ return (0, import_node_child_process11.execFileSync)("git", args, { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
20098
20329
  } catch {
20099
20330
  return "";
20100
20331
  }
20101
20332
  }
20102
20333
  function realpathOr2(p) {
20103
20334
  try {
20104
- return import_node_fs31.realpathSync.native(p);
20335
+ return import_node_fs32.realpathSync.native(p);
20105
20336
  } catch {
20106
20337
  return (0, import_node_path23.resolve)(p);
20107
20338
  }
20108
20339
  }
20109
20340
  function resolveFrame(input) {
20110
20341
  const found = findMomentSegment(input.command, input.on);
20111
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs31.existsSync)(input.hookCwd);
20342
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs32.existsSync)(input.hookCwd);
20112
20343
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
20113
20344
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
20114
20345
  const refuse = (refusal) => ({
@@ -20131,7 +20362,7 @@ function resolveFrame(input) {
20131
20362
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
20132
20363
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
20133
20364
  if (targetDir !== baseDir) {
20134
- if (!(0, import_node_fs31.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
20365
+ if (!(0, import_node_fs32.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
20135
20366
  dir = targetDir;
20136
20367
  }
20137
20368
  }
@@ -20318,7 +20549,7 @@ function stagedRange(frame, command) {
20318
20549
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
20319
20550
  }
20320
20551
  const mergeHead = frame.gitDir ? (0, import_node_path24.join)(frame.gitDir, "MERGE_HEAD") : null;
20321
- if (mergeHead && (0, import_node_fs31.existsSync)(mergeHead)) {
20552
+ if (mergeHead && (0, import_node_fs32.existsSync)(mergeHead)) {
20322
20553
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
20323
20554
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
20324
20555
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -20452,7 +20683,7 @@ function truthy(v) {
20452
20683
  }
20453
20684
 
20454
20685
  // src/lib/transcript.ts
20455
- var import_node_fs32 = require("node:fs");
20686
+ var import_node_fs33 = require("node:fs");
20456
20687
  var MAX_READ_BYTES = 256 * 1024;
20457
20688
  var SMALL_FILE_BYTES = 64 * 1024;
20458
20689
  var MAX_FILES_LIST = 20;
@@ -20479,7 +20710,7 @@ async function extractActionSummary(transcriptPath) {
20479
20710
  function readTurnLines(transcriptPath) {
20480
20711
  let size;
20481
20712
  try {
20482
- size = (0, import_node_fs32.statSync)(transcriptPath).size;
20713
+ size = (0, import_node_fs33.statSync)(transcriptPath).size;
20483
20714
  } catch {
20484
20715
  return null;
20485
20716
  }
@@ -20487,7 +20718,7 @@ function readTurnLines(transcriptPath) {
20487
20718
  let raw;
20488
20719
  let windowed = false;
20489
20720
  if (size <= SMALL_FILE_BYTES) {
20490
- raw = (0, import_node_fs32.readFileSync)(transcriptPath, "utf-8");
20721
+ raw = (0, import_node_fs33.readFileSync)(transcriptPath, "utf-8");
20491
20722
  } else {
20492
20723
  windowed = true;
20493
20724
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -20995,7 +21226,7 @@ function channelSilence(input) {
20995
21226
  // src/lib/cli-version.ts
20996
21227
  function cliVersion() {
20997
21228
  try {
20998
- return true ? "0.32.5-experimental.4d91ca0" : "dev";
21229
+ return true ? "0.32.6" : "dev";
20999
21230
  } catch {
21000
21231
  return "dev";
21001
21232
  }
@@ -21035,8 +21266,8 @@ async function sendSkipBeacon(ctx, reason) {
21035
21266
  }
21036
21267
 
21037
21268
  // src/lib/static-analysis.ts
21038
- var import_node_child_process11 = require("node:child_process");
21039
- var import_node_fs33 = require("node:fs");
21269
+ var import_node_child_process12 = require("node:child_process");
21270
+ var import_node_fs34 = require("node:fs");
21040
21271
  var SEVERITY_ORDER = {
21041
21272
  Error: 0,
21042
21273
  Critical: 0,
@@ -21048,7 +21279,7 @@ var SEVERITY_ORDER = {
21048
21279
  };
21049
21280
  function isCodacyAvailable() {
21050
21281
  try {
21051
- (0, import_node_child_process11.execSync)("which codacy-analysis", { stdio: "pipe" });
21282
+ (0, import_node_child_process12.execSync)("which codacy-analysis", { stdio: "pipe" });
21052
21283
  return true;
21053
21284
  } catch {
21054
21285
  return false;
@@ -21084,13 +21315,13 @@ function runCodacyAnalysis(files) {
21084
21315
  if (files.length === 0) return empty;
21085
21316
  const existingFiles = files.filter((f) => {
21086
21317
  try {
21087
- return (0, import_node_fs33.existsSync)(f);
21318
+ return (0, import_node_fs34.existsSync)(f);
21088
21319
  } catch {
21089
21320
  return false;
21090
21321
  }
21091
21322
  });
21092
21323
  if (existingFiles.length === 0) return empty;
21093
- const proc = (0, import_node_child_process11.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
21324
+ const proc = (0, import_node_child_process12.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
21094
21325
  encoding: "utf-8",
21095
21326
  maxBuffer: 10 * 1024 * 1024
21096
21327
  });
@@ -21353,7 +21584,7 @@ async function scope(run2) {
21353
21584
  }
21354
21585
 
21355
21586
  // src/lib/specs.ts
21356
- var import_node_fs34 = require("node:fs");
21587
+ var import_node_fs35 = require("node:fs");
21357
21588
  var import_node_path25 = require("node:path");
21358
21589
  var SPEC_CANDIDATES = [
21359
21590
  "CLAUDE.md",
@@ -21385,16 +21616,16 @@ function discoverSpecs(consulted = []) {
21385
21616
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
21386
21617
  if (totalBytes >= totalCap) return false;
21387
21618
  if (seen.has(specPath)) return true;
21388
- if (!(0, import_node_fs34.existsSync)(specPath)) return true;
21619
+ if (!(0, import_node_fs35.existsSync)(specPath)) return true;
21389
21620
  seen.add(specPath);
21390
21621
  const remaining = totalCap - totalBytes;
21391
21622
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
21392
21623
  const readBytes = Math.min(fileCap, remaining);
21393
21624
  try {
21394
21625
  const buf = Buffer.alloc(readBytes);
21395
- const fd = (0, import_node_fs34.openSync)(specPath, "r");
21396
- const bytesRead = (0, import_node_fs34.readSync)(fd, buf, 0, readBytes, 0);
21397
- (0, import_node_fs34.closeSync)(fd);
21626
+ const fd = (0, import_node_fs35.openSync)(specPath, "r");
21627
+ const bytesRead = (0, import_node_fs35.readSync)(fd, buf, 0, readBytes, 0);
21628
+ (0, import_node_fs35.closeSync)(fd);
21398
21629
  const content = buf.slice(0, bytesRead).toString("utf-8");
21399
21630
  if (!content) return true;
21400
21631
  result.push({ path: specPath, content });
@@ -21410,7 +21641,7 @@ function discoverSpecs(consulted = []) {
21410
21641
  if (!addSpec(candidate)) break;
21411
21642
  }
21412
21643
  for (const dir of ["spec", "docs"]) {
21413
- if (!(0, import_node_fs34.existsSync)(dir)) continue;
21644
+ if (!(0, import_node_fs35.existsSync)(dir)) continue;
21414
21645
  try {
21415
21646
  const mdFiles = findMdFiles(dir, 2).sort();
21416
21647
  for (const mdFile of mdFiles) {
@@ -21425,7 +21656,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
21425
21656
  if (depth >= maxDepth) return [];
21426
21657
  const result = [];
21427
21658
  try {
21428
- const entries = (0, import_node_fs34.readdirSync)(dir, { withFileTypes: true });
21659
+ const entries = (0, import_node_fs35.readdirSync)(dir, { withFileTypes: true });
21429
21660
  for (const entry of entries) {
21430
21661
  const fullPath = (0, import_node_path25.join)(dir, entry.name);
21431
21662
  if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -21444,14 +21675,14 @@ function discoverPlans() {
21444
21675
  const candidates2 = [];
21445
21676
  const seen = /* @__PURE__ */ new Set();
21446
21677
  for (const plansDir of [localPlansDir, homePlansDir]) {
21447
- if (!(0, import_node_fs34.existsSync)(plansDir)) continue;
21678
+ if (!(0, import_node_fs35.existsSync)(plansDir)) continue;
21448
21679
  try {
21449
- for (const f of (0, import_node_fs34.readdirSync)(plansDir)) {
21680
+ for (const f of (0, import_node_fs35.readdirSync)(plansDir)) {
21450
21681
  if (!f.endsWith(".md") || seen.has(f)) continue;
21451
21682
  seen.add(f);
21452
21683
  const fullPath = (0, import_node_path25.join)(plansDir, f);
21453
21684
  try {
21454
- const stat3 = (0, import_node_fs34.statSync)(fullPath);
21685
+ const stat3 = (0, import_node_fs35.statSync)(fullPath);
21455
21686
  candidates2.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
21456
21687
  } catch {
21457
21688
  }
@@ -21464,7 +21695,7 @@ function discoverPlans() {
21464
21695
  for (const entry of candidates2.slice(0, MAX_PLAN_FILES)) {
21465
21696
  if (entry.size > MAX_PLAN_FILE_BYTES) continue;
21466
21697
  try {
21467
- const content = (0, import_node_fs34.readFileSync)(entry.path, "utf-8");
21698
+ const content = (0, import_node_fs35.readFileSync)(entry.path, "utf-8");
21468
21699
  result.push({ name: entry.name, content });
21469
21700
  } catch {
21470
21701
  }
@@ -21479,12 +21710,12 @@ function discoverGuardDocs(rangeFiles2) {
21479
21710
  if (result.length >= MAX_SPEC_FILES) break;
21480
21711
  if (!GUARD_DOC_EXT.test(path)) continue;
21481
21712
  if (path.startsWith("/") || path.includes("..")) continue;
21482
- if (!(0, import_node_fs34.existsSync)(path)) continue;
21713
+ if (!(0, import_node_fs35.existsSync)(path)) continue;
21483
21714
  try {
21484
- const stat3 = (0, import_node_fs34.statSync)(path);
21715
+ const stat3 = (0, import_node_fs35.statSync)(path);
21485
21716
  if (stat3.size > MAX_PLAN_FILE_BYTES) continue;
21486
21717
  if (totalBytes + stat3.size > MAX_TOTAL_SPEC_BYTES) continue;
21487
- const content = (0, import_node_fs34.readFileSync)(path, "utf-8");
21718
+ const content = (0, import_node_fs35.readFileSync)(path, "utf-8");
21488
21719
  if (!content) continue;
21489
21720
  result.push({ name: path, content });
21490
21721
  totalBytes += content.length;
@@ -21660,7 +21891,7 @@ async function mode(run2) {
21660
21891
  }
21661
21892
 
21662
21893
  // src/lib/fold.ts
21663
- var import_node_fs35 = require("node:fs");
21894
+ var import_node_fs36 = require("node:fs");
21664
21895
  var import_node_path26 = require("node:path");
21665
21896
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
21666
21897
  "user",
@@ -21798,7 +22029,7 @@ function candidateRoots(repoRoot2) {
21798
22029
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
21799
22030
  const out = [norm];
21800
22031
  try {
21801
- const real = import_node_fs35.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
22032
+ const real = import_node_fs36.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
21802
22033
  if (real !== norm) out.push(real);
21803
22034
  } catch {
21804
22035
  }
@@ -21886,8 +22117,8 @@ function fold(transcriptPath, opts = {}) {
21886
22117
  }
21887
22118
  };
21888
22119
  try {
21889
- if (!(0, import_node_fs35.existsSync)(transcriptPath)) return result;
21890
- ingest((0, import_node_fs35.readFileSync)(transcriptPath, "utf8"), "agent");
22120
+ if (!(0, import_node_fs36.existsSync)(transcriptPath)) return result;
22121
+ ingest((0, import_node_fs36.readFileSync)(transcriptPath, "utf8"), "agent");
21891
22122
  result.coverage.complete = true;
21892
22123
  } catch {
21893
22124
  return result;
@@ -21898,19 +22129,19 @@ function fold(transcriptPath, opts = {}) {
21898
22129
  (0, import_node_path26.basename)(transcriptPath).replace(/\.jsonl$/, ""),
21899
22130
  "subagents"
21900
22131
  );
21901
- if ((0, import_node_fs35.existsSync)(sidecarDir)) {
22132
+ if ((0, import_node_fs36.existsSync)(sidecarDir)) {
21902
22133
  const maxFiles = opts.maxSidecars ?? 200;
21903
22134
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
21904
22135
  const found = [];
21905
22136
  const walk2 = (d, depth) => {
21906
22137
  if (depth > 4) return;
21907
- for (const e of (0, import_node_fs35.readdirSync)(d, { withFileTypes: true })) {
22138
+ for (const e of (0, import_node_fs36.readdirSync)(d, { withFileTypes: true })) {
21908
22139
  const p = (0, import_node_path26.join)(d, e.name);
21909
22140
  if (e.isDirectory()) {
21910
22141
  walk2(p, depth + 1);
21911
22142
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
21912
22143
  try {
21913
- const st = (0, import_node_fs35.statSync)(p);
22144
+ const st = (0, import_node_fs36.statSync)(p);
21914
22145
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
21915
22146
  } catch {
21916
22147
  result.coverage.malformed++;
@@ -21927,7 +22158,7 @@ function fold(transcriptPath, opts = {}) {
21927
22158
  continue;
21928
22159
  }
21929
22160
  try {
21930
- ingest((0, import_node_fs35.readFileSync)(f.path, "utf8"), "subagent");
22161
+ ingest((0, import_node_fs36.readFileSync)(f.path, "utf8"), "subagent");
21931
22162
  bytes += f.size;
21932
22163
  result.coverage.subagentFiles++;
21933
22164
  } catch {
@@ -21962,7 +22193,7 @@ function fold(transcriptPath, opts = {}) {
21962
22193
  }
21963
22194
  function classifyUnobserved(path) {
21964
22195
  try {
21965
- const st = (0, import_node_fs35.statSync)(path);
22196
+ const st = (0, import_node_fs36.statSync)(path);
21966
22197
  if (!st.isFile()) return "unreadable";
21967
22198
  } catch {
21968
22199
  return "unreadable";
@@ -22279,20 +22510,20 @@ async function evidence(run2) {
22279
22510
  }
22280
22511
 
22281
22512
  // src/lib/cache-cleanup.ts
22282
- var import_node_fs36 = require("node:fs");
22513
+ var import_node_fs37 = require("node:fs");
22283
22514
  var import_node_path27 = require("node:path");
22284
22515
  var CACHE_TTL_DAYS = 7;
22285
22516
  function pruneStaleCache() {
22286
22517
  try {
22287
22518
  const dir = projectPath(CACHE_DIR);
22288
22519
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
22289
- for (const entry of (0, import_node_fs36.readdirSync)(dir)) {
22520
+ for (const entry of (0, import_node_fs37.readdirSync)(dir)) {
22290
22521
  if (!entry.startsWith("pending-")) continue;
22291
22522
  const path = (0, import_node_path27.join)(dir, entry);
22292
22523
  try {
22293
- const stat3 = (0, import_node_fs36.statSync)(path);
22524
+ const stat3 = (0, import_node_fs37.statSync)(path);
22294
22525
  if (stat3.mtimeMs < cutoff) {
22295
- (0, import_node_fs36.unlinkSync)(path);
22526
+ (0, import_node_fs37.unlinkSync)(path);
22296
22527
  logEvent("cache_entry_pruned", {
22297
22528
  path: entry,
22298
22529
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -22306,7 +22537,7 @@ function pruneStaleCache() {
22306
22537
  }
22307
22538
 
22308
22539
  // src/lib/context-files.ts
22309
- var import_node_fs37 = require("node:fs");
22540
+ var import_node_fs38 = require("node:fs");
22310
22541
  var import_node_os6 = require("node:os");
22311
22542
  var MAX_CONTEXT_FILES = 10;
22312
22543
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -22364,7 +22595,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
22364
22595
  continue;
22365
22596
  }
22366
22597
  try {
22367
- const content = (0, import_node_fs37.readFileSync)(safePath, "utf8");
22598
+ const content = (0, import_node_fs38.readFileSync)(safePath, "utf8");
22368
22599
  const bytes = Buffer.byteLength(content);
22369
22600
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
22370
22601
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -22414,7 +22645,7 @@ async function contextFiles(run2) {
22414
22645
  const readSet = readSetContextPaths(run2.actionSummary, codeDelta.files);
22415
22646
  const { kept: externalContext } = partitionVerityOwned(readSet);
22416
22647
  const ig = loadVerityIgnore();
22417
- const unfenced = run2.verityIgnored.suspended ? externalContext : externalContext.filter((p) => !isIgnored2(ig, p));
22648
+ const unfenced = run2.verityIgnored.suspended ? externalContext : externalContext.filter((p) => !isIgnored3(ig, p));
22418
22649
  const contextFiles2 = gatherContextFiles(unfenced, codeDelta.files, {
22419
22650
  maxFiles: MAX_FILES - codeDelta.files.length
22420
22651
  });
@@ -22435,7 +22666,7 @@ async function repoContext(run2) {
22435
22666
  const deltaFiles = codeDelta.files.filter((f) => f.role !== "context");
22436
22667
  const sentPaths = new Set(codeDelta.files.map((f) => f.path));
22437
22668
  const ig = loadVerityIgnore();
22438
- const isExcluded = (p) => isVerityOwnedPath(p) || !run2.verityIgnored.suspended && isIgnored2(ig, p);
22669
+ const isExcluded = (p) => isVerityOwnedPath(p) || !run2.verityIgnored.suspended && isIgnored3(ig, p);
22439
22670
  run2.repoContext = buildRepoContext({
22440
22671
  deltaFiles,
22441
22672
  diffs: snapshotResult.diffs,
@@ -22455,7 +22686,7 @@ async function repoContext(run2) {
22455
22686
 
22456
22687
  // src/lib/seed-runner.ts
22457
22688
  var import_promises14 = require("node:fs/promises");
22458
- var import_node_fs38 = require("node:fs");
22689
+ var import_node_fs39 = require("node:fs");
22459
22690
  var import_node_path28 = require("node:path");
22460
22691
  var import_yaml4 = __toESM(require_dist());
22461
22692
 
@@ -22695,7 +22926,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
22695
22926
  return fm;
22696
22927
  }
22697
22928
  async function runSeed(opts) {
22698
- if (!(0, import_node_fs38.existsSync)(STANDARD_FILE)) {
22929
+ if (!(0, import_node_fs39.existsSync)(STANDARD_FILE)) {
22699
22930
  return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
22700
22931
  }
22701
22932
  let standardDoc;
@@ -22707,7 +22938,7 @@ async function runSeed(opts) {
22707
22938
  }
22708
22939
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
22709
22940
  let readmeContent;
22710
- if ((0, import_node_fs38.existsSync)("README.md")) {
22941
+ if ((0, import_node_fs39.existsSync)("README.md")) {
22711
22942
  try {
22712
22943
  readmeContent = await (0, import_promises14.readFile)("README.md", "utf-8");
22713
22944
  } catch {
@@ -22715,7 +22946,7 @@ async function runSeed(opts) {
22715
22946
  }
22716
22947
  let claudeMdContent;
22717
22948
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
22718
- if ((0, import_node_fs38.existsSync)(p)) {
22949
+ if ((0, import_node_fs39.existsSync)(p)) {
22719
22950
  try {
22720
22951
  claudeMdContent = await (0, import_promises14.readFile)(p, "utf-8");
22721
22952
  break;
@@ -22739,7 +22970,7 @@ async function runSeed(opts) {
22739
22970
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
22740
22971
  }
22741
22972
  const overviewPath = (0, import_node_path28.join)(MEMORY_DIR, "domain", "project-overview.md");
22742
- if ((0, import_node_fs38.existsSync)(overviewPath) && !opts.force) {
22973
+ if ((0, import_node_fs39.existsSync)(overviewPath) && !opts.force) {
22743
22974
  return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
22744
22975
  }
22745
22976
  if (opts.dryRun) {
@@ -22794,7 +23025,7 @@ async function runSeed(opts) {
22794
23025
  }
22795
23026
 
22796
23027
  // src/commands/analyze/phases/08-memory-manifest.ts
22797
- var import_node_fs39 = require("node:fs");
23028
+ var import_node_fs40 = require("node:fs");
22798
23029
  var import_node_path29 = require("node:path");
22799
23030
  async function memoryManifest(run2) {
22800
23031
  const { globals } = run2;
@@ -22806,8 +23037,8 @@ async function memoryManifest(run2) {
22806
23037
  try {
22807
23038
  await ensureMemoryDir();
22808
23039
  const seedMarker = (0, import_node_path29.join)(VERITY_DIR, ".seeded");
22809
- const hasStandard = (0, import_node_fs39.existsSync)(STANDARD_FILE);
22810
- const alreadyTried = (0, import_node_fs39.existsSync)(seedMarker);
23040
+ const hasStandard = (0, import_node_fs40.existsSync)(STANDARD_FILE);
23041
+ const alreadyTried = (0, import_node_fs40.existsSync)(seedMarker);
22811
23042
  if (hasStandard && !alreadyTried) {
22812
23043
  const preManifest = await buildManifest();
22813
23044
  if (preManifest.nodes.length === 0) {
@@ -22820,7 +23051,7 @@ async function memoryManifest(run2) {
22820
23051
  dryRun: false
22821
23052
  });
22822
23053
  if (seedResult.created > 0) {
22823
- (0, import_node_fs39.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
23054
+ (0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
22824
23055
  `);
22825
23056
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
22826
23057
  logEvent("auto_seed_ran", {
@@ -22828,7 +23059,7 @@ async function memoryManifest(run2) {
22828
23059
  failed: seedResult.failed
22829
23060
  });
22830
23061
  } else if (seedResult.skipped === "already_seeded") {
22831
- (0, import_node_fs39.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
23062
+ (0, import_node_fs40.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
22832
23063
  `);
22833
23064
  } else {
22834
23065
  logEvent("auto_seed_noop", {
@@ -23017,7 +23248,7 @@ async function workingMemory(run2) {
23017
23248
  }
23018
23249
 
23019
23250
  // src/lib/note-budget.ts
23020
- var import_node_fs40 = require("node:fs");
23251
+ var import_node_fs41 = require("node:fs");
23021
23252
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
23022
23253
  var EPISODE_STALE_SECONDS = 30 * 60;
23023
23254
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -23039,9 +23270,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
23039
23270
  }
23040
23271
  function readAdvisoryEpisode(sessionId) {
23041
23272
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
23042
- if (!(0, import_node_fs40.existsSync)(file)) return null;
23273
+ if (!(0, import_node_fs41.existsSync)(file)) return null;
23043
23274
  try {
23044
- const o = JSON.parse((0, import_node_fs40.readFileSync)(file, "utf-8")) ?? {};
23275
+ const o = JSON.parse((0, import_node_fs41.readFileSync)(file, "utf-8")) ?? {};
23045
23276
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
23046
23277
  if (isNaN(delivered)) return null;
23047
23278
  return {
@@ -23055,8 +23286,8 @@ function readAdvisoryEpisode(sessionId) {
23055
23286
  }
23056
23287
  function writeAdvisoryEpisode(episode, sessionId) {
23057
23288
  try {
23058
- (0, import_node_fs40.mkdirSync)(VERITY_DIR, { recursive: true });
23059
- (0, import_node_fs40.writeFileSync)(
23289
+ (0, import_node_fs41.mkdirSync)(VERITY_DIR, { recursive: true });
23290
+ (0, import_node_fs41.writeFileSync)(
23060
23291
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
23061
23292
  JSON.stringify({ v: 1, ...episode })
23062
23293
  );
@@ -23086,7 +23317,7 @@ function isExplicitlyAutonomous(env = process.env) {
23086
23317
  }
23087
23318
 
23088
23319
  // src/lib/task-context.ts
23089
- var import_node_child_process12 = require("node:child_process");
23320
+ var import_node_child_process13 = require("node:child_process");
23090
23321
  var CLOSING_RE = /\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b[\s:]*#(\d+)/i;
23091
23322
  var BRANCH_RE = /(?:^|[/_-])(?:issue|gh|fix)[-_/]?(\d+)\b/i;
23092
23323
  function parseLinkedIssue(sources) {
@@ -23102,7 +23333,7 @@ function parseLinkedIssue(sources) {
23102
23333
  }
23103
23334
  function safeExec(cmd, timeout) {
23104
23335
  try {
23105
- return (0, import_node_child_process12.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
23336
+ return (0, import_node_child_process13.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
23106
23337
  } catch {
23107
23338
  return "";
23108
23339
  }
@@ -23373,14 +23604,14 @@ async function buildRequest(run2) {
23373
23604
  }
23374
23605
 
23375
23606
  // src/lib/offline.ts
23376
- var import_node_fs41 = require("node:fs");
23607
+ var import_node_fs42 = require("node:fs");
23377
23608
  var import_node_crypto11 = require("node:crypto");
23378
23609
  function cacheRequest(body) {
23379
23610
  try {
23380
- (0, import_node_fs41.mkdirSync)(CACHE_DIR, { recursive: true });
23611
+ (0, import_node_fs42.mkdirSync)(CACHE_DIR, { recursive: true });
23381
23612
  const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
23382
23613
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
23383
- (0, import_node_fs41.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
23614
+ (0, import_node_fs42.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
23384
23615
  } catch {
23385
23616
  }
23386
23617
  }
@@ -23499,7 +23730,7 @@ async function transmit(run2) {
23499
23730
  }
23500
23731
 
23501
23732
  // src/commands/analyze/phases/13-reconcile.ts
23502
- var import_node_fs42 = require("node:fs");
23733
+ var import_node_fs43 = require("node:fs");
23503
23734
  var import_node_path31 = require("node:path");
23504
23735
  async function reconcile(run2) {
23505
23736
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
@@ -23529,7 +23760,7 @@ async function reconcile(run2) {
23529
23760
  const st = foldDossier(memorySession.d);
23530
23761
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
23531
23762
  try {
23532
- const src = (0, import_node_fs42.readFileSync)((0, import_node_path31.join)(repoRoot(), file), "utf8").split("\n");
23763
+ const src = (0, import_node_fs43.readFileSync)((0, import_node_path31.join)(repoRoot(), file), "utf8").split("\n");
23533
23764
  const at = src[line - 1];
23534
23765
  return at === void 0 ? null : lineSha(at);
23535
23766
  } catch {
@@ -24194,7 +24425,7 @@ function registerAnalyzeCommand(program2) {
24194
24425
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
24195
24426
  async function runAnalyze(opts, globals) {
24196
24427
  if (!verityConfigured()) {
24197
- (0, import_node_fs43.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
24428
+ (0, import_node_fs44.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
24198
24429
  process.exit(0);
24199
24430
  }
24200
24431
  const run2 = createRun(opts, globals);
@@ -24214,8 +24445,11 @@ async function runAnalyze(opts, globals) {
24214
24445
  }
24215
24446
  }
24216
24447
 
24448
+ // src/commands/baseline.ts
24449
+ var import_node_fs46 = require("node:fs");
24450
+
24217
24451
  // src/lib/project-skills.ts
24218
- var import_node_fs44 = require("node:fs");
24452
+ var import_node_fs45 = require("node:fs");
24219
24453
  var import_node_path32 = require("node:path");
24220
24454
  var PROJECT_SKILL_NAMES = [
24221
24455
  "verity-setup",
@@ -24241,14 +24475,14 @@ var LEGACY_SKILL_NAMES = [
24241
24475
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
24242
24476
  function staleProjectSkills() {
24243
24477
  const root = projectPath(".claude/skills");
24244
- if (!(0, import_node_fs44.existsSync)(root)) return [];
24245
- return ALL.filter((name) => (0, import_node_fs44.existsSync)((0, import_node_path32.join)(root, name)));
24478
+ if (!(0, import_node_fs45.existsSync)(root)) return [];
24479
+ return ALL.filter((name) => (0, import_node_fs45.existsSync)((0, import_node_path32.join)(root, name)));
24246
24480
  }
24247
24481
  function removeProjectSkills() {
24248
24482
  const root = projectPath(".claude/skills");
24249
24483
  const removed = [];
24250
24484
  for (const name of staleProjectSkills()) {
24251
- (0, import_node_fs44.rmSync)((0, import_node_path32.join)(root, name), { recursive: true, force: true });
24485
+ (0, import_node_fs45.rmSync)((0, import_node_path32.join)(root, name), { recursive: true, force: true });
24252
24486
  removed.push(name);
24253
24487
  }
24254
24488
  return removed;
@@ -24310,6 +24544,20 @@ function registerBaselineCommands(program2) {
24310
24544
  process.exit(0);
24311
24545
  }
24312
24546
  const realStart = source === void 0 || source === "startup" || source === "clear";
24547
+ let memoryMsg = null;
24548
+ let memoryAgentLine = null;
24549
+ const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
24550
+ if (realStart && !(0, import_node_fs46.existsSync)(memoryNotice)) {
24551
+ const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
24552
+ if (trackedGraph > 0) {
24553
+ memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
24554
+ memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
24555
+ try {
24556
+ (0, import_node_fs46.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
24557
+ } catch {
24558
+ }
24559
+ }
24560
+ }
24313
24561
  if (isPluginInvocation() && realStart) {
24314
24562
  const installed2 = activePluginVersion();
24315
24563
  const state = await readSetupState().catch(() => null);
@@ -24332,10 +24580,11 @@ function registerBaselineCommands(program2) {
24332
24580
  );
24333
24581
  }
24334
24582
  }
24583
+ if (memoryAgentLine) notices.push(memoryAgentLine);
24335
24584
  if (notices.length > 0) {
24336
24585
  process.stdout.write(
24337
24586
  JSON.stringify({
24338
- ...userMsg || skewMsg ? { systemMessage: [skewMsg, userMsg].filter(Boolean).join("\n") } : {},
24587
+ ...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
24339
24588
  hookSpecificOutput: {
24340
24589
  hookEventName: "SessionStart",
24341
24590
  additionalContext: notices.join("\n")
@@ -24343,6 +24592,16 @@ function registerBaselineCommands(program2) {
24343
24592
  }) + "\n"
24344
24593
  );
24345
24594
  }
24595
+ } else if (memoryMsg) {
24596
+ process.stdout.write(
24597
+ JSON.stringify({
24598
+ systemMessage: memoryMsg,
24599
+ hookSpecificOutput: {
24600
+ hookEventName: "SessionStart",
24601
+ ...memoryAgentLine ? { additionalContext: memoryAgentLine } : {}
24602
+ }
24603
+ }) + "\n"
24604
+ );
24346
24605
  }
24347
24606
  if (deferredToPlugin("baseline capture", session ?? null)) {
24348
24607
  process.exit(0);
@@ -24394,7 +24653,7 @@ function hookSource(value) {
24394
24653
  }
24395
24654
 
24396
24655
  // src/commands/review.ts
24397
- var import_node_fs45 = require("node:fs");
24656
+ var import_node_fs47 = require("node:fs");
24398
24657
  function registerReviewCommand(program2) {
24399
24658
  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) => {
24400
24659
  const globals = program2.opts();
@@ -24413,7 +24672,7 @@ async function runReview(opts, globals) {
24413
24672
  const securityFiles = filterSecurity(allFiles);
24414
24673
  let staticResults;
24415
24674
  if (isCodacyAvailable()) {
24416
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs45.existsSync)(f) || resolveFile(f) !== null);
24675
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs47.existsSync)(f) || resolveFile(f) !== null);
24417
24676
  staticResults = runCodacyAnalysis(scannable);
24418
24677
  } else {
24419
24678
  staticResults = {
@@ -24439,7 +24698,7 @@ async function runReview(opts, globals) {
24439
24698
  const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
24440
24699
  specs = [];
24441
24700
  for (const p of specPaths) {
24442
- if (!(0, import_node_fs45.existsSync)(p)) continue;
24701
+ if (!(0, import_node_fs47.existsSync)(p)) continue;
24443
24702
  try {
24444
24703
  const { readFileSync: readFileSync27 } = await import("node:fs");
24445
24704
  const content = readFileSync27(p, "utf-8");
@@ -24499,7 +24758,7 @@ async function runReview(opts, globals) {
24499
24758
  }
24500
24759
 
24501
24760
  // src/commands/guard.ts
24502
- var import_node_fs46 = require("node:fs");
24761
+ var import_node_fs48 = require("node:fs");
24503
24762
  var import_node_path33 = require("node:path");
24504
24763
  var GUARD_BLOCK_CAP = 2;
24505
24764
  var GUARD_ITER_FILE = (0, import_node_path33.join)(VERITY_DIR, ".guard-iteration");
@@ -24547,7 +24806,7 @@ function readPreToolUseStdin() {
24547
24806
  }
24548
24807
  function readIterMap() {
24549
24808
  try {
24550
- const raw = JSON.parse((0, import_node_fs46.readFileSync)(GUARD_ITER_FILE, "utf-8"));
24809
+ const raw = JSON.parse((0, import_node_fs48.readFileSync)(GUARD_ITER_FILE, "utf-8"));
24551
24810
  if (raw && typeof raw === "object") {
24552
24811
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
24553
24812
  return { [raw.moment]: raw.count };
@@ -24567,10 +24826,10 @@ function readIter(moment) {
24567
24826
  }
24568
24827
  function writeIter(moment, count) {
24569
24828
  try {
24570
- (0, import_node_fs46.mkdirSync)(VERITY_DIR, { recursive: true });
24829
+ (0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
24571
24830
  const map = readIterMap();
24572
24831
  map[moment] = count;
24573
- (0, import_node_fs46.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24832
+ (0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24574
24833
  } catch {
24575
24834
  }
24576
24835
  }
@@ -24580,10 +24839,10 @@ function resetIter(moment) {
24580
24839
  if (!(moment in map)) return;
24581
24840
  delete map[moment];
24582
24841
  if (Object.keys(map).length === 0) {
24583
- if ((0, import_node_fs46.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs46.unlinkSync)(GUARD_ITER_FILE);
24842
+ if ((0, import_node_fs48.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs48.unlinkSync)(GUARD_ITER_FILE);
24584
24843
  } else {
24585
- (0, import_node_fs46.mkdirSync)(VERITY_DIR, { recursive: true });
24586
- (0, import_node_fs46.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24844
+ (0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
24845
+ (0, import_node_fs48.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
24587
24846
  }
24588
24847
  } catch {
24589
24848
  }
@@ -24655,7 +24914,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
24655
24914
  const securityFiles = filterSecurity(files);
24656
24915
  let staticResults;
24657
24916
  if (isCodacyAvailable()) {
24658
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs46.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
24917
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs48.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
24659
24918
  staticResults = runCodacyAnalysis(scannable);
24660
24919
  } else {
24661
24920
  staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
@@ -24795,13 +25054,13 @@ async function runGuard(opts, globals) {
24795
25054
  diffs: [],
24796
25055
  signalsByPath: rangeChangeSignals(frame, range, codeDelta.files.map((f) => f.path)),
24797
25056
  sentPaths: new Set(codeDelta.files.map((f) => f.path)),
24798
- isExcluded: (p) => isVerityOwnedPath(p) || isIgnored2(ig, p),
25057
+ isExcluded: (p) => isVerityOwnedPath(p) || isIgnored3(ig, p),
24799
25058
  cwd: frame.worktreeRoot ?? process.cwd()
24800
25059
  });
24801
25060
  upgradeToExcerpts(repoContext2, {
24802
25061
  readFile: (rel) => {
24803
25062
  try {
24804
- return (0, import_node_fs46.readFileSync)((0, import_node_path33.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
25063
+ return (0, import_node_fs48.readFileSync)((0, import_node_path33.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
24805
25064
  } catch {
24806
25065
  return null;
24807
25066
  }
@@ -25043,7 +25302,7 @@ function registerIgnoreCommand(program2) {
25043
25302
 
25044
25303
  // src/commands/waive.ts
25045
25304
  var import_node_crypto12 = require("node:crypto");
25046
- var import_node_fs47 = require("node:fs");
25305
+ var import_node_fs49 = require("node:fs");
25047
25306
  function registerWaiveCommand(program2) {
25048
25307
  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) => {
25049
25308
  const globals = program2.opts();
@@ -25072,7 +25331,7 @@ function registerWaiveCommand(program2) {
25072
25331
  if (opts.file) {
25073
25332
  body.file = opts.file;
25074
25333
  try {
25075
- body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs47.readFileSync)(opts.file)).digest("hex");
25334
+ body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs49.readFileSync)(opts.file)).digest("hex");
25076
25335
  } catch {
25077
25336
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
25078
25337
  process.exit(1);
@@ -25097,7 +25356,7 @@ function registerWaiveCommand(program2) {
25097
25356
  }
25098
25357
 
25099
25358
  // src/commands/init.ts
25100
- var import_node_fs52 = require("node:fs");
25359
+ var import_node_fs53 = require("node:fs");
25101
25360
  var import_promises17 = require("node:fs/promises");
25102
25361
  var import_yaml6 = __toESM(require_dist());
25103
25362
  var import_node_path36 = require("node:path");
@@ -25179,14 +25438,14 @@ function printPhase(n, of, title, subtitle) {
25179
25438
  }
25180
25439
 
25181
25440
  // src/commands/doctor.ts
25182
- var import_node_fs49 = require("node:fs");
25441
+ var import_node_fs50 = require("node:fs");
25183
25442
 
25184
25443
  // src/lib/prereqs.ts
25185
- var import_node_child_process13 = require("node:child_process");
25444
+ var import_node_child_process14 = require("node:child_process");
25186
25445
  var MIN_NODE_MAJOR = 20;
25187
25446
  function which(bin) {
25188
25447
  try {
25189
- const out = (0, import_node_child_process13.execSync)(`command -v ${bin}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
25448
+ const out = (0, import_node_child_process14.execSync)(`command -v ${bin}`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
25190
25449
  return out || null;
25191
25450
  } catch {
25192
25451
  return null;
@@ -25208,7 +25467,7 @@ function checkNode() {
25208
25467
  function checkGit() {
25209
25468
  let detail = "";
25210
25469
  try {
25211
- detail = (0, import_node_child_process13.execSync)("git --version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
25470
+ detail = (0, import_node_child_process14.execSync)("git --version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
25212
25471
  } catch {
25213
25472
  return {
25214
25473
  id: "git",
@@ -25246,7 +25505,7 @@ function checkAnalysisCli() {
25246
25505
  var INSTALL_TIMEOUT_MS = 12e4;
25247
25506
  function run(command, args, opts = {}) {
25248
25507
  return new Promise((resolve5) => {
25249
- const child = (0, import_node_child_process13.spawn)(command, args, {
25508
+ const child = (0, import_node_child_process14.spawn)(command, args, {
25250
25509
  stdio: opts.inherit ? "inherit" : "pipe",
25251
25510
  timeout: INSTALL_TIMEOUT_MS
25252
25511
  });
@@ -25296,96 +25555,6 @@ async function checkPrereqs(opts = {}) {
25296
25555
 
25297
25556
  // src/lib/telemetry.ts
25298
25557
  var import_promises15 = require("node:fs/promises");
25299
-
25300
- // src/lib/gitignore.ts
25301
- var import_node_child_process14 = require("node:child_process");
25302
- var import_node_fs48 = require("node:fs");
25303
- var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
25304
- var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
25305
- var VERITY_GITIGNORE_BLOCK = [
25306
- "# Verity \u2014 machine-local state. Everything in .verity/ is ignored EXCEPT the",
25307
- "# shared standard and the knowledge graph, which are meant to be committed.",
25308
- ".verity/*",
25309
- "!.verity/standard.yaml",
25310
- "!.verity/memory/",
25311
- ".verity/memory/log.md",
25312
- SETTINGS_LOCAL_IGNORE_ENTRY,
25313
- ""
25314
- ].join("\n");
25315
- var BREAKING_ENTRIES = /* @__PURE__ */ new Set([".verity/", ".verity"]);
25316
- function isIgnored3(path) {
25317
- try {
25318
- (0, import_node_child_process14.execSync)(`git check-ignore -q -- "${path}"`, { stdio: "pipe" });
25319
- return true;
25320
- } catch (err) {
25321
- return err.status === 1 ? false : null;
25322
- }
25323
- }
25324
- function semanticsHold() {
25325
- const snapshot = isIgnored3(".verity/.snapshot/__probe__");
25326
- const standard = isIgnored3(".verity/standard.yaml");
25327
- const node = isIgnored3(".verity/memory/domain/__probe__.md");
25328
- const futureState = isIgnored3(".verity/.__probe-future-state__");
25329
- if (snapshot === null || standard === null || node === null || futureState === null) return null;
25330
- return snapshot === true && futureState === true && standard === false && node === false;
25331
- }
25332
- function ensureVerityGitignore() {
25333
- let content = "";
25334
- try {
25335
- content = (0, import_node_fs48.readFileSync)(".gitignore", "utf-8");
25336
- } catch {
25337
- }
25338
- const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
25339
- const lines = content.split("\n");
25340
- const breakingCount = lines.filter((l) => BREAKING_ENTRIES.has(l.trim())).length;
25341
- const needsRepair = breakingCount > 0;
25342
- const verified = (result) => semanticsHold() === false ? "conflict" : result;
25343
- if (hasMarker && !needsRepair) return verified("covered");
25344
- if (!hasMarker && !needsRepair) {
25345
- if (semanticsHold() === true) return "covered";
25346
- }
25347
- try {
25348
- let next = content;
25349
- if (needsRepair) {
25350
- next = lines.map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l).join("\n");
25351
- }
25352
- if (!hasMarker) {
25353
- const sep3 = next === "" ? "" : next.endsWith("\n") ? "\n" : "\n\n";
25354
- next = next + sep3 + VERITY_GITIGNORE_BLOCK;
25355
- }
25356
- (0, import_node_fs48.writeFileSync)(".gitignore", next);
25357
- return verified(needsRepair ? "repaired" : "added");
25358
- } catch {
25359
- return "failed";
25360
- }
25361
- }
25362
- function committedVerityState() {
25363
- let out = "";
25364
- try {
25365
- out = (0, import_node_child_process14.execSync)("git ls-files -z -- .verity", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
25366
- } catch {
25367
- return [];
25368
- }
25369
- return out.split("\0").filter(Boolean).filter((p) => p !== ".verity/standard.yaml" && !(p.startsWith(".verity/memory/") && p !== ".verity/memory/log.md"));
25370
- }
25371
- function untrackVerityState() {
25372
- const tracked = committedVerityState();
25373
- if (tracked.length === 0) return "none";
25374
- try {
25375
- (0, import_node_child_process14.execSync)("git rm -r --cached --quiet -- .verity", { stdio: "pipe" });
25376
- for (const keep of [".verity/standard.yaml", ".verity/memory"]) {
25377
- try {
25378
- (0, import_node_child_process14.execSync)(`git add -- "${keep}"`, { stdio: "pipe" });
25379
- } catch {
25380
- }
25381
- }
25382
- return "untracked";
25383
- } catch {
25384
- return "failed";
25385
- }
25386
- }
25387
-
25388
- // src/lib/telemetry.ts
25389
25558
  var SETTINGS_LOCAL_FILE2 = ".claude/settings.local.json";
25390
25559
  var GITIGNORE_FILE = ".gitignore";
25391
25560
  var GITIGNORE_ENTRY = SETTINGS_LOCAL_IGNORE_ENTRY;
@@ -25481,11 +25650,11 @@ async function buildReport() {
25481
25650
  const wiring = await resolveHookWiring();
25482
25651
  const hooks = wiring.status;
25483
25652
  const telemetry = await checkTelemetry();
25484
- const hasConfig = (0, import_node_fs49.existsSync)(projectPath(CODACY_CONFIG_FILE));
25653
+ const hasConfig = (0, import_node_fs50.existsSync)(projectPath(CODACY_CONFIG_FILE));
25485
25654
  const artifacts = {
25486
- standard: (0, import_node_fs49.existsSync)(projectPath(STANDARD_FILE)),
25655
+ standard: (0, import_node_fs50.existsSync)(projectPath(STANDARD_FILE)),
25487
25656
  analysisConfig: hasConfig,
25488
- verityMd: (0, import_node_fs49.existsSync)(projectPath(VERITY_MD_FILE)),
25657
+ verityMd: (0, import_node_fs50.existsSync)(projectPath(VERITY_MD_FILE)),
25489
25658
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
25490
25659
  };
25491
25660
  const next = [];
@@ -25526,6 +25695,12 @@ async function buildReport() {
25526
25695
  if (state?.telemetry === "deferred") {
25527
25696
  next.push('Telemetry was requested but needs a token \u2014 run "verity login", then "verity telemetry install".');
25528
25697
  }
25698
+ const memory = { posture: memoryPosture(), trackedFiles: committedMemoryFiles().length };
25699
+ if (memory.trackedFiles > 0 && !memoryOptOut()) {
25700
+ next.push(
25701
+ `${memory.trackedFiles} knowledge-graph file(s) under .verity/memory/ are tracked in git, so Verity's generated notes appear in every diff and pull request. Run "verity memory untrack" to stop that (the files stay on disk), or "verity memory track" if this project commits them on purpose.`
25702
+ );
25703
+ }
25529
25704
  const conflict = marketplaceConflict();
25530
25705
  if (conflict) {
25531
25706
  next.push(
@@ -25558,11 +25733,16 @@ async function buildReport() {
25558
25733
  },
25559
25734
  telemetry: { enabled: telemetry.enabled, endpoint: telemetry.endpoint },
25560
25735
  artifacts,
25736
+ memory,
25561
25737
  next
25562
25738
  };
25563
25739
  }
25564
25740
  function registerDoctorCommand(program2) {
25565
25741
  program2.command("doctor").description("Report prerequisites, setup phase, hooks, and what is still missing").option("--json", "Output the full report as JSON (what /verity-setup reads)").action(async (opts) => {
25742
+ try {
25743
+ process.chdir(repoRoot());
25744
+ } catch {
25745
+ }
25566
25746
  const report = await buildReport();
25567
25747
  if (opts.json) {
25568
25748
  printJson(report);
@@ -25590,6 +25770,9 @@ function registerDoctorCommand(program2) {
25590
25770
  const idNote = idState === "valid" ? "\u2713" : idState === "invalid" ? "\u26A0 ids do not resolve" : idState === "unchecked" ? "\u2713 (ids unverified \u2014 no adapter)" : "";
25591
25771
  printInfo(` .codacy/codacy.config.json: ${report.artifacts.analysisConfig ? idNote : "missing"}`);
25592
25772
  printInfo(` VERITY.md: ${report.artifacts.verityMd ? "\u2713" : "missing"}`);
25773
+ printInfo(
25774
+ ` .verity/memory/: ${report.memory.trackedFiles > 0 ? `${report.memory.trackedFiles} file(s) tracked in git \u2014 they appear in every diff` : report.memory.posture === "ignored" ? "machine-local \u2713" : "not tracked"}`
25775
+ );
25593
25776
  if (report.next.length > 0) {
25594
25777
  console.log("");
25595
25778
  printWarn("Next:");
@@ -25602,7 +25785,7 @@ function registerDoctorCommand(program2) {
25602
25785
  }
25603
25786
 
25604
25787
  // src/commands/migrate.ts
25605
- var import_node_fs50 = require("node:fs");
25788
+ var import_node_fs51 = require("node:fs");
25606
25789
  var import_node_path34 = require("node:path");
25607
25790
  var import_node_child_process15 = require("node:child_process");
25608
25791
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
@@ -25642,10 +25825,10 @@ async function runMigration(opts = {}) {
25642
25825
  function migrateProjectDir(root, actions) {
25643
25826
  const gateDir = (0, import_node_path34.join)(root, ".gate");
25644
25827
  const verityDir = (0, import_node_path34.join)(root, ".verity");
25645
- if ((0, import_node_fs50.existsSync)(gateDir) && !(0, import_node_fs50.existsSync)(verityDir)) {
25828
+ if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) {
25646
25829
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
25647
25830
  }
25648
- if ((0, import_node_fs50.existsSync)(gateDir) && (0, import_node_fs50.existsSync)(verityDir)) {
25831
+ if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
25649
25832
  return migrateProjectDirCarry(gateDir, verityDir, actions);
25650
25833
  }
25651
25834
  return false;
@@ -25666,13 +25849,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
25666
25849
  }
25667
25850
  }
25668
25851
  if (moved) {
25669
- if ((0, import_node_fs50.existsSync)(gateDir)) {
25852
+ if ((0, import_node_fs51.existsSync)(gateDir)) {
25670
25853
  const carried = carryLegacyContents(gateDir, verityDir);
25671
25854
  if (carried > 0) {
25672
25855
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
25673
25856
  }
25674
25857
  try {
25675
- (0, import_node_fs50.rmSync)(gateDir, { recursive: true, force: true });
25858
+ (0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
25676
25859
  } catch {
25677
25860
  }
25678
25861
  }
@@ -25688,7 +25871,7 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
25688
25871
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
25689
25872
  }
25690
25873
  try {
25691
- (0, import_node_fs50.rmSync)(gateDir, { recursive: true, force: true });
25874
+ (0, import_node_fs51.rmSync)(gateDir, { recursive: true, force: true });
25692
25875
  } catch {
25693
25876
  }
25694
25877
  return carried > 0;
@@ -25697,9 +25880,9 @@ function migrateGlobalCredentials(home, actions) {
25697
25880
  if (!home) return;
25698
25881
  const gateCreds = (0, import_node_path34.join)(home, ".gate", "credentials");
25699
25882
  const verityCreds = (0, import_node_path34.join)(home, ".verity", "credentials");
25700
- if (!(0, import_node_fs50.existsSync)(gateCreds)) return;
25701
- if (!(0, import_node_fs50.existsSync)(verityCreds)) {
25702
- (0, import_node_fs50.mkdirSync)((0, import_node_path34.join)(home, ".verity"), { recursive: true });
25883
+ if (!(0, import_node_fs51.existsSync)(gateCreds)) return;
25884
+ if (!(0, import_node_fs51.existsSync)(verityCreds)) {
25885
+ (0, import_node_fs51.mkdirSync)((0, import_node_path34.join)(home, ".verity"), { recursive: true });
25703
25886
  moveFile(gateCreds, verityCreds);
25704
25887
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
25705
25888
  return;
@@ -25722,7 +25905,7 @@ async function migrateLegacyHooks(root, actions) {
25722
25905
  }
25723
25906
  async function migrateClaudeMd(root, actions) {
25724
25907
  const claudeMd = (0, import_node_path34.join)(root, "CLAUDE.md");
25725
- const hadLegacyBlock = (0, import_node_fs50.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
25908
+ const hadLegacyBlock = (0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
25726
25909
  if (!hadLegacyBlock) return;
25727
25910
  try {
25728
25911
  await ensureClaudeMdPointer(root);
@@ -25734,7 +25917,7 @@ async function migrateClaudeMd(root, actions) {
25734
25917
  function migrateStandardFile(root, actions) {
25735
25918
  const gateMd = (0, import_node_path34.join)(root, "GATE.md");
25736
25919
  const verityMd = (0, import_node_path34.join)(root, "VERITY.md");
25737
- if (!(0, import_node_fs50.existsSync)(gateMd) || (0, import_node_fs50.existsSync)(verityMd)) return;
25920
+ if (!(0, import_node_fs51.existsSync)(gateMd) || (0, import_node_fs51.existsSync)(verityMd)) return;
25738
25921
  let moved = false;
25739
25922
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
25740
25923
  try {
@@ -25746,12 +25929,12 @@ function migrateStandardFile(root, actions) {
25746
25929
  if (!moved) moveFile(gateMd, verityMd);
25747
25930
  const content = readFileSyncSafe(verityMd);
25748
25931
  const refreshed = content.split("GATE.md").join("VERITY.md");
25749
- if (refreshed !== content) (0, import_node_fs50.writeFileSync)(verityMd, refreshed);
25932
+ if (refreshed !== content) (0, import_node_fs51.writeFileSync)(verityMd, refreshed);
25750
25933
  actions.push("Renamed GATE.md \u2192 VERITY.md");
25751
25934
  }
25752
25935
  async function migrateTelemetryHeaders(root, actions) {
25753
25936
  const file = (0, import_node_path34.join)(root, ".claude", "settings.local.json");
25754
- if (!(0, import_node_fs50.existsSync)(file)) return;
25937
+ if (!(0, import_node_fs51.existsSync)(file)) return;
25755
25938
  let settings;
25756
25939
  try {
25757
25940
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -25799,14 +25982,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
25799
25982
  }
25800
25983
  if (toAppend.length > 0) {
25801
25984
  const sep3 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
25802
- (0, import_node_fs50.writeFileSync)(verityCreds, verityContent + sep3 + toAppend.join("\n") + "\n");
25985
+ (0, import_node_fs51.writeFileSync)(verityCreds, verityContent + sep3 + toAppend.join("\n") + "\n");
25803
25986
  }
25804
- (0, import_node_fs50.rmSync)(gateCreds, { force: true });
25987
+ (0, import_node_fs51.rmSync)(gateCreds, { force: true });
25805
25988
  return toAppend.length;
25806
25989
  }
25807
25990
  function readFileSyncSafe(path) {
25808
25991
  try {
25809
- return (0, import_node_fs50.readFileSync)(path, "utf-8");
25992
+ return (0, import_node_fs51.readFileSync)(path, "utf-8");
25810
25993
  } catch {
25811
25994
  return "";
25812
25995
  }
@@ -25821,35 +26004,35 @@ function hasStagedChanges(root) {
25821
26004
  }
25822
26005
  function moveDir(from, to) {
25823
26006
  try {
25824
- (0, import_node_fs50.renameSync)(from, to);
26007
+ (0, import_node_fs51.renameSync)(from, to);
25825
26008
  } catch (err) {
25826
26009
  if (err.code !== "EXDEV") throw err;
25827
- (0, import_node_fs50.cpSync)(from, to, { recursive: true });
25828
- (0, import_node_fs50.rmSync)(from, { recursive: true, force: true });
26010
+ (0, import_node_fs51.cpSync)(from, to, { recursive: true });
26011
+ (0, import_node_fs51.rmSync)(from, { recursive: true, force: true });
25829
26012
  }
25830
26013
  }
25831
26014
  function moveFile(from, to) {
25832
26015
  try {
25833
- (0, import_node_fs50.renameSync)(from, to);
26016
+ (0, import_node_fs51.renameSync)(from, to);
25834
26017
  } catch (err) {
25835
26018
  if (err.code !== "EXDEV") throw err;
25836
- (0, import_node_fs50.cpSync)(from, to);
25837
- (0, import_node_fs50.rmSync)(from, { force: true });
26019
+ (0, import_node_fs51.cpSync)(from, to);
26020
+ (0, import_node_fs51.rmSync)(from, { force: true });
25838
26021
  }
25839
26022
  }
25840
26023
  function carryLegacyContents(gateDir, verityDir) {
25841
26024
  let copied = 0;
25842
26025
  const walk2 = (relDir) => {
25843
26026
  const srcDir = (0, import_node_path34.join)(gateDir, relDir);
25844
- for (const entry of (0, import_node_fs50.readdirSync)(srcDir)) {
26027
+ for (const entry of (0, import_node_fs51.readdirSync)(srcDir)) {
25845
26028
  const rel = relDir ? (0, import_node_path34.join)(relDir, entry) : entry;
25846
26029
  const src = (0, import_node_path34.join)(gateDir, rel);
25847
26030
  const dest = (0, import_node_path34.join)(verityDir, rel);
25848
- if ((0, import_node_fs50.statSync)(src).isDirectory()) {
26031
+ if ((0, import_node_fs51.statSync)(src).isDirectory()) {
25849
26032
  walk2(rel);
25850
- } else if (!(0, import_node_fs50.existsSync)(dest)) {
25851
- (0, import_node_fs50.mkdirSync)((0, import_node_path34.dirname)(dest), { recursive: true });
25852
- (0, import_node_fs50.cpSync)(src, dest);
26033
+ } else if (!(0, import_node_fs51.existsSync)(dest)) {
26034
+ (0, import_node_fs51.mkdirSync)((0, import_node_path34.dirname)(dest), { recursive: true });
26035
+ (0, import_node_fs51.cpSync)(src, dest);
25853
26036
  copied++;
25854
26037
  }
25855
26038
  }
@@ -25860,20 +26043,20 @@ function carryLegacyContents(gateDir, verityDir) {
25860
26043
  async function needsMigration(root = repoRoot()) {
25861
26044
  const gateDir = (0, import_node_path34.join)(root, ".gate");
25862
26045
  const verityDir = (0, import_node_path34.join)(root, ".verity");
25863
- if ((0, import_node_fs50.existsSync)(gateDir) && !(0, import_node_fs50.existsSync)(verityDir)) return true;
25864
- if ((0, import_node_fs50.existsSync)(gateDir) && (0, import_node_fs50.existsSync)(verityDir)) {
25865
- if ((0, import_node_fs50.existsSync)((0, import_node_path34.join)(gateDir, "credentials")) && !(0, import_node_fs50.existsSync)((0, import_node_path34.join)(verityDir, "credentials"))) {
26046
+ if ((0, import_node_fs51.existsSync)(gateDir) && !(0, import_node_fs51.existsSync)(verityDir)) return true;
26047
+ if ((0, import_node_fs51.existsSync)(gateDir) && (0, import_node_fs51.existsSync)(verityDir)) {
26048
+ if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(gateDir, "credentials")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(verityDir, "credentials"))) {
25866
26049
  return true;
25867
26050
  }
25868
- if ((0, import_node_fs50.existsSync)((0, import_node_path34.join)(gateDir, "memory")) && !(0, import_node_fs50.existsSync)((0, import_node_path34.join)(verityDir, "memory"))) {
26051
+ if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(gateDir, "memory")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(verityDir, "memory"))) {
25869
26052
  return true;
25870
26053
  }
25871
26054
  }
25872
26055
  const claudeMd = (0, import_node_path34.join)(root, "CLAUDE.md");
25873
- if ((0, import_node_fs50.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
26056
+ if ((0, import_node_fs51.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
25874
26057
  return true;
25875
26058
  }
25876
- if ((0, import_node_fs50.existsSync)((0, import_node_path34.join)(root, "GATE.md")) && !(0, import_node_fs50.existsSync)((0, import_node_path34.join)(root, "VERITY.md"))) {
26059
+ if ((0, import_node_fs51.existsSync)((0, import_node_path34.join)(root, "GATE.md")) && !(0, import_node_fs51.existsSync)((0, import_node_path34.join)(root, "VERITY.md"))) {
25877
26060
  return true;
25878
26061
  }
25879
26062
  if (await hasLegacyHooksAt(root)) return true;
@@ -26154,7 +26337,7 @@ async function promptMultiSelect(question, choices, fallback) {
26154
26337
  }
26155
26338
 
26156
26339
  // src/lib/remote-config.ts
26157
- var import_node_fs51 = require("node:fs");
26340
+ var import_node_fs52 = require("node:fs");
26158
26341
  var import_promises16 = require("node:fs/promises");
26159
26342
  var import_node_path35 = require("node:path");
26160
26343
  var import_yaml5 = __toESM(require_dist());
@@ -26201,7 +26384,7 @@ async function adoptRemoteSetup(found, opts) {
26201
26384
  written.push(STANDARD_FILE);
26202
26385
  if (rider !== null) {
26203
26386
  const localIgnore = projectPath(VERITYIGNORE_FILE);
26204
- if (!(0, import_node_fs51.existsSync)(localIgnore)) {
26387
+ if (!(0, import_node_fs52.existsSync)(localIgnore)) {
26205
26388
  await writeOut(VERITYIGNORE_FILE, rider);
26206
26389
  written.push(VERITYIGNORE_FILE);
26207
26390
  } else {
@@ -26359,7 +26542,7 @@ function resolveDataDir2() {
26359
26542
  // local dev: running from repo root
26360
26543
  ];
26361
26544
  for (const candidate of candidates2) {
26362
- if ((0, import_node_fs52.existsSync)((0, import_node_path36.join)(candidate, "skills"))) {
26545
+ if ((0, import_node_fs53.existsSync)((0, import_node_path36.join)(candidate, "skills"))) {
26363
26546
  return candidate;
26364
26547
  }
26365
26548
  }
@@ -26375,7 +26558,7 @@ async function skillIsCurrent(src, dest) {
26375
26558
  const list2 = (dir) => {
26376
26559
  const out = [];
26377
26560
  const walk2 = (d, prefix) => {
26378
- for (const e of (0, import_node_fs52.readdirSync)(d, { withFileTypes: true })) {
26561
+ for (const e of (0, import_node_fs53.readdirSync)(d, { withFileTypes: true })) {
26379
26562
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
26380
26563
  if (e.isDirectory()) walk2((0, import_node_path36.join)(d, e.name), rel);
26381
26564
  else if (e.isFile()) out.push(rel);
@@ -26570,7 +26753,7 @@ async function synthesizeLocally(opts) {
26570
26753
  async function healStaleAnalysisConfig(globals) {
26571
26754
  const configPath = projectPath(CODACY_CONFIG_FILE);
26572
26755
  const standardPath = projectPath(STANDARD_FILE);
26573
- if (!(0, import_node_fs52.existsSync)(configPath) || !(0, import_node_fs52.existsSync)(standardPath)) return;
26756
+ if (!(0, import_node_fs53.existsSync)(configPath) || !(0, import_node_fs53.existsSync)(standardPath)) return;
26574
26757
  const validation = validatePatternIds();
26575
26758
  if (validation.status !== "invalid") return;
26576
26759
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -26673,11 +26856,11 @@ async function installSkills(force, step) {
26673
26856
  for (const skill of SKILLS) {
26674
26857
  const src = (0, import_node_path36.join)(skillsSource, skill);
26675
26858
  const dest = (0, import_node_path36.join)(skillsDest, skill);
26676
- if (!(0, import_node_fs52.existsSync)(src)) {
26859
+ if (!(0, import_node_fs53.existsSync)(src)) {
26677
26860
  printWarn(` Skill data not found: ${skill}`);
26678
26861
  continue;
26679
26862
  }
26680
- if ((0, import_node_fs52.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
26863
+ if ((0, import_node_fs53.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
26681
26864
  skillsInstalled++;
26682
26865
  continue;
26683
26866
  }
@@ -26751,12 +26934,31 @@ async function scaffoldProject(step, defaultsOnly) {
26751
26934
  printWarn(" .gitignore: the Verity block is in place but git still ignores .verity/standard.yaml");
26752
26935
  printWarn(" Something outside this file covers it \u2014 a global (~/.gitignore) or nested");
26753
26936
  printWarn(" .gitignore, or a pattern we do not recognise. Check: git check-ignore -v .verity/standard.yaml");
26754
- printWarn(" Until it is fixed, the Standard and the knowledge graph cannot be committed.");
26937
+ printWarn(" Until it is fixed, the Standard cannot be committed.");
26755
26938
  } else if (ignoreResult === "repaired") {
26756
26939
  printInfo(" .gitignore: rewrote `.verity/` to `.verity/*` so the standard stays committable \u2713");
26940
+ } else if (ignoreResult === "memory-fenced") {
26941
+ printInfo(" .gitignore: the knowledge graph is machine-local now \u2014 it stays out of your diffs \u2713");
26942
+ } else if (ignoreResult === "memory-tracked") {
26943
+ printWarn(" .gitignore: this project commits its knowledge graph.");
26757
26944
  } else {
26758
26945
  printInfo(` .gitignore: Verity block ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
26759
26946
  }
26947
+ const trackedMemory = memoryOptOut() ? [] : committedMemoryFiles();
26948
+ if (trackedMemory.length > 0) {
26949
+ printWarn(` ${trackedMemory.length} knowledge-graph file(s) are tracked, so they show up in every diff.`);
26950
+ const fence = defaultsOnly ? false : await promptYes(" Stop tracking them (files stay on disk)? [Y/n] ", { nonInteractive: false });
26951
+ if (fence) {
26952
+ const result = fenceMemory();
26953
+ if (!result.ok) printWarn(' Could not untrack \u2014 run "verity memory untrack" when you can');
26954
+ else printInfo(` Untracked ${result.untracked} file(s) (staged) and ignored \u2014 commit to finish \u2713`);
26955
+ } else if (defaultsOnly) {
26956
+ printWarn(" Left tracked (--yes did not ask). Convert later with: verity memory untrack");
26957
+ } else {
26958
+ printWarn(' Left tracked. Stop later with "verity memory untrack",');
26959
+ printWarn(' or record it as deliberate with "verity memory track".');
26960
+ }
26961
+ }
26760
26962
  const tracked = committedVerityState();
26761
26963
  if (tracked.length > 0) {
26762
26964
  printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
@@ -26766,7 +26968,7 @@ async function scaffoldProject(step, defaultsOnly) {
26766
26968
  if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
26767
26969
  else if (result === "failed") printWarn(' Could not untrack \u2014 run "git rm -r --cached .verity" manually');
26768
26970
  } else {
26769
- printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml .verity/memory");
26971
+ printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml");
26770
26972
  }
26771
26973
  }
26772
26974
  try {
@@ -26797,7 +26999,7 @@ function registerInitCommand(program2) {
26797
26999
  const staleMarker = clearStalePluginMarker();
26798
27000
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
26799
27001
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
26800
- const isProject = projectMarkers.some((m) => (0, import_node_fs52.existsSync)(m));
27002
+ const isProject = projectMarkers.some((m) => (0, import_node_fs53.existsSync)(m));
26801
27003
  if (!isProject) {
26802
27004
  printError("No project detected in the current directory.");
26803
27005
  printInfo('Run "verity init" from your project root.');
@@ -26956,7 +27158,7 @@ function registerInitCommand(program2) {
26956
27158
  }
26957
27159
  step("Your project's Standard");
26958
27160
  let haveStandard = false;
26959
- if ((0, import_node_fs52.existsSync)(projectPath(STANDARD_FILE))) {
27161
+ if ((0, import_node_fs53.existsSync)(projectPath(STANDARD_FILE))) {
26960
27162
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
26961
27163
  haveStandard = true;
26962
27164
  } else {
@@ -26986,7 +27188,7 @@ function registerInitCommand(program2) {
26986
27188
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
26987
27189
  init: {
26988
27190
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
26989
- cli_version: true ? "0.32.5-experimental.4d91ca0" : "dev"
27191
+ cli_version: true ? "0.32.6" : "dev"
26990
27192
  }
26991
27193
  });
26992
27194
  } catch (err) {
@@ -27002,7 +27204,7 @@ function registerInitCommand(program2) {
27002
27204
  console.log(" learn, memory, insights, reflect)");
27003
27205
  console.log(" .claude/settings.json hooks, reconciled to your chosen moments");
27004
27206
  }
27005
- console.log(" .verity/memory/ knowledge base (commit to git)");
27207
+ console.log(" .verity/memory/ knowledge base (machine-local, not committed)");
27006
27208
  console.log(" .verity/standard.yaml the Standard the gate enforces");
27007
27209
  console.log(" .codacy/codacy.config.json static-analysis patterns (validated)");
27008
27210
  console.log(" VERITY.md project quality overview");
@@ -27036,7 +27238,7 @@ function registerInitCommand(program2) {
27036
27238
  }
27037
27239
 
27038
27240
  // src/commands/uninstall.ts
27039
- var import_node_fs53 = require("node:fs");
27241
+ var import_node_fs54 = require("node:fs");
27040
27242
  var import_node_path37 = require("node:path");
27041
27243
  function registerUninstallCommand(program2) {
27042
27244
  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) => {
@@ -27047,10 +27249,10 @@ function registerUninstallCommand(program2) {
27047
27249
  const skillsRoot = projectPath(".claude/skills");
27048
27250
  for (const name of PROJECT_SKILL_NAMES) {
27049
27251
  const dir = (0, import_node_path37.join)(skillsRoot, name);
27050
- if ((0, import_node_fs53.existsSync)(dir)) {
27252
+ if ((0, import_node_fs54.existsSync)(dir)) {
27051
27253
  actions.push({
27052
27254
  label: `Remove .claude/skills/${name}/`,
27053
- apply: () => (0, import_node_fs53.rmSync)(dir, { recursive: true, force: true })
27255
+ apply: () => (0, import_node_fs54.rmSync)(dir, { recursive: true, force: true })
27054
27256
  });
27055
27257
  }
27056
27258
  }
@@ -27064,24 +27266,24 @@ function registerUninstallCommand(program2) {
27064
27266
  });
27065
27267
  }
27066
27268
  const verityDir = projectPath(VERITY_DIR);
27067
- if ((0, import_node_fs53.existsSync)(verityDir)) {
27269
+ if ((0, import_node_fs54.existsSync)(verityDir)) {
27068
27270
  actions.push({
27069
27271
  label: `Remove ${VERITY_DIR}/`,
27070
- apply: () => (0, import_node_fs53.rmSync)(verityDir, { recursive: true, force: true })
27272
+ apply: () => (0, import_node_fs54.rmSync)(verityDir, { recursive: true, force: true })
27071
27273
  });
27072
27274
  }
27073
27275
  if (!keepVerityMd) {
27074
27276
  const verityMd = projectPath(VERITY_MD_FILE);
27075
- if ((0, import_node_fs53.existsSync)(verityMd)) {
27277
+ if ((0, import_node_fs54.existsSync)(verityMd)) {
27076
27278
  actions.push({
27077
27279
  label: `Remove ${VERITY_MD_FILE}`,
27078
- apply: () => (0, import_node_fs53.rmSync)(verityMd, { force: true })
27280
+ apply: () => (0, import_node_fs54.rmSync)(verityMd, { force: true })
27079
27281
  });
27080
27282
  }
27081
27283
  }
27082
27284
  const cleanupEmptyDir = (path) => {
27083
- if ((0, import_node_fs53.existsSync)(path) && (0, import_node_fs53.statSync)(path).isDirectory() && (0, import_node_fs53.readdirSync)(path).length === 0) {
27084
- (0, import_node_fs53.rmdirSync)(path);
27285
+ if ((0, import_node_fs54.existsSync)(path) && (0, import_node_fs54.statSync)(path).isDirectory() && (0, import_node_fs54.readdirSync)(path).length === 0) {
27286
+ (0, import_node_fs54.rmdirSync)(path);
27085
27287
  }
27086
27288
  };
27087
27289
  actions.push({
@@ -27093,10 +27295,10 @@ function registerUninstallCommand(program2) {
27093
27295
  });
27094
27296
  const home = process.env.HOME ?? "";
27095
27297
  const globalVerityDir = (0, import_node_path37.join)(home, ".verity");
27096
- if (purgeGlobal && (0, import_node_fs53.existsSync)(globalVerityDir)) {
27298
+ if (purgeGlobal && (0, import_node_fs54.existsSync)(globalVerityDir)) {
27097
27299
  actions.push({
27098
27300
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
27099
- apply: () => (0, import_node_fs53.rmSync)(globalVerityDir, { recursive: true, force: true })
27301
+ apply: () => (0, import_node_fs54.rmSync)(globalVerityDir, { recursive: true, force: true })
27100
27302
  });
27101
27303
  }
27102
27304
  if (actions.length === 0) {
@@ -27290,7 +27492,7 @@ function registerTaskCommands(program2) {
27290
27492
  }
27291
27493
 
27292
27494
  // src/commands/reset.ts
27293
- var import_node_fs54 = require("node:fs");
27495
+ var import_node_fs55 = require("node:fs");
27294
27496
  var import_node_path38 = require("node:path");
27295
27497
  function registerResetCommand(program2) {
27296
27498
  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) => {
@@ -27328,11 +27530,11 @@ function registerResetCommand(program2) {
27328
27530
  }
27329
27531
  const cacheDir = projectPath(CACHE_DIR);
27330
27532
  let purged = 0;
27331
- if ((0, import_node_fs54.existsSync)(cacheDir)) {
27332
- for (const entry of (0, import_node_fs54.readdirSync)(cacheDir)) {
27533
+ if ((0, import_node_fs55.existsSync)(cacheDir)) {
27534
+ for (const entry of (0, import_node_fs55.readdirSync)(cacheDir)) {
27333
27535
  if (entry.startsWith("pending-")) {
27334
27536
  try {
27335
- (0, import_node_fs54.unlinkSync)((0, import_node_path38.join)(cacheDir, entry));
27537
+ (0, import_node_fs55.unlinkSync)((0, import_node_path38.join)(cacheDir, entry));
27336
27538
  purged++;
27337
27539
  } catch {
27338
27540
  }
@@ -27347,19 +27549,19 @@ function registerResetCommand(program2) {
27347
27549
  projectPath(`${VERITY_DIR}/.last-analysis`)
27348
27550
  ];
27349
27551
  for (const file of filesToClear) {
27350
- if ((0, import_node_fs54.existsSync)(file)) {
27552
+ if ((0, import_node_fs55.existsSync)(file)) {
27351
27553
  try {
27352
- (0, import_node_fs54.writeFileSync)(file, "");
27554
+ (0, import_node_fs55.writeFileSync)(file, "");
27353
27555
  } catch {
27354
27556
  }
27355
27557
  }
27356
27558
  }
27357
27559
  if (opts.all) {
27358
27560
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
27359
- if ((0, import_node_fs54.existsSync)(logsDir)) {
27360
- for (const entry of (0, import_node_fs54.readdirSync)(logsDir)) {
27561
+ if ((0, import_node_fs55.existsSync)(logsDir)) {
27562
+ for (const entry of (0, import_node_fs55.readdirSync)(logsDir)) {
27361
27563
  try {
27362
- (0, import_node_fs54.unlinkSync)((0, import_node_path38.join)(logsDir, entry));
27564
+ (0, import_node_fs55.unlinkSync)((0, import_node_path38.join)(logsDir, entry));
27363
27565
  } catch {
27364
27566
  }
27365
27567
  }
@@ -27550,12 +27752,64 @@ function registerMemoryCommand(program2) {
27550
27752
  }
27551
27753
  console.log("");
27552
27754
  if (result.failed === 0) {
27553
- printInfo(`Seeded ${result.created} knowledge node(s) from the Standard. Commit .verity/memory/ to share with your team.`);
27755
+ printInfo(`Seeded ${result.created} knowledge node(s) from the Standard into .verity/memory/.`);
27554
27756
  } else {
27555
27757
  printWarn(`Seeded ${result.created} node(s); ${result.failed} failed. See messages above.`);
27556
27758
  }
27557
27759
  process.exit(result.failed === 0 ? 0 : 1);
27558
27760
  });
27761
+ memory.command("untrack").description("Stop committing .verity/memory/ \u2014 the graph stays on disk and leaves your diffs").action(() => {
27762
+ try {
27763
+ process.chdir(repoRoot());
27764
+ } catch {
27765
+ }
27766
+ const tracked = committedMemoryFiles();
27767
+ if (tracked.length === 0 && memoryPosture() === "ignored") {
27768
+ printInfo("The knowledge graph is already machine-local \u2014 nothing to do.");
27769
+ process.exit(0);
27770
+ }
27771
+ const result = fenceMemory();
27772
+ if (!result.ok) {
27773
+ printError(
27774
+ "Could not fence .verity/memory/. Either .gitignore is not writable, or a rule we do not own still re-includes it. Check: git check-ignore -v .verity/memory/index.md"
27775
+ );
27776
+ process.exit(1);
27777
+ }
27778
+ if (result.untracked > 0) {
27779
+ printInfo(`Removed ${result.untracked} file(s) from the index. They are still on disk \u2014 nothing was deleted.`);
27780
+ printWarn("The deletions are STAGED: commit them so the rest of your team picks this up.");
27781
+ printWarn(" Your teammates will see .verity/memory/ disappear when they pull this commit.");
27782
+ printWarn(" That is expected: the graph is rebuilt from the service on their next analysis.");
27783
+ }
27784
+ printInfo(".verity/memory/ is ignored now. It will not appear in a diff or pull request again.");
27785
+ printInfo('Changed your mind? "verity memory track" puts it back and records that it is deliberate.');
27786
+ process.exit(0);
27787
+ });
27788
+ memory.command("track").description("Commit .verity/memory/ on purpose, and record that choice so nothing offers to change it").action(() => {
27789
+ try {
27790
+ process.chdir(repoRoot());
27791
+ } catch {
27792
+ }
27793
+ const result = keepMemoryTracked();
27794
+ if (result === "failed") {
27795
+ printError("Could not write .gitignore.");
27796
+ process.exit(1);
27797
+ }
27798
+ if (result === "already") {
27799
+ printInfo("Already recorded \u2014 this project commits its knowledge graph on purpose.");
27800
+ process.exit(0);
27801
+ }
27802
+ if (result === "refused") {
27803
+ printError("Recorded the opt-out, but git STILL ignores .verity/memory/.");
27804
+ printWarn(' A bare ".verity/" entry makes every "!" line beneath it unreachable.');
27805
+ printWarn(" Check: git check-ignore -v .verity/memory/index.md");
27806
+ printWarn(' "verity init" rewrites that entry to ".verity/*", which makes the opt-out live.');
27807
+ process.exit(1);
27808
+ }
27809
+ printInfo("Recorded in .gitignore: this project commits its knowledge graph on purpose.");
27810
+ printInfo("Commit that .gitignore change so your team inherits it, then: git add .verity/memory");
27811
+ process.exit(0);
27812
+ });
27559
27813
  }
27560
27814
 
27561
27815
  // src/commands/run.ts
@@ -27667,8 +27921,8 @@ function registerTelemetryCommands(program2) {
27667
27921
  }
27668
27922
 
27669
27923
  // src/cli.ts
27670
- program.name("verity").description("CLI for Verity quality gate service").version("0.32.5-experimental.4d91ca0").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) => {
27671
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.5-experimental.4d91ca0");
27924
+ program.name("verity").description("CLI for Verity quality gate service").version("0.32.6").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
27925
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.6");
27672
27926
  setUserNamedServiceUrl(program.opts().serviceUrl);
27673
27927
  try {
27674
27928
  await foldLegacyLocalCredential();