@codacy/verity-cli 0.33.2-experimental.0c53bed → 0.33.3-experimental.072d5cb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/bin/verity.js +1314 -731
  3. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -10970,8 +10970,8 @@ function filterReviewable(files) {
10970
10970
  const ext = (0, import_node_path3.extname)(f).slice(1);
10971
10971
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
10972
10972
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
10973
- const basename5 = f.split("/").pop() ?? "";
10974
- if (REVIEWABLE_FILENAMES.has(basename5)) return true;
10973
+ const basename6 = f.split("/").pop() ?? "";
10974
+ if (REVIEWABLE_FILENAMES.has(basename6)) return true;
10975
10975
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
10976
10976
  return false;
10977
10977
  });
@@ -13457,7 +13457,7 @@ function registerHooksCommands(program2) {
13457
13457
  }
13458
13458
 
13459
13459
  // src/commands/intent.ts
13460
- var import_node_crypto8 = require("node:crypto");
13460
+ var import_node_crypto9 = require("node:crypto");
13461
13461
 
13462
13462
  // src/lib/conversation-buffer.ts
13463
13463
  var import_promises5 = require("node:fs/promises");
@@ -14009,8 +14009,8 @@ async function appendEntry(taskId, entry) {
14009
14009
 
14010
14010
  // src/lib/memory-retrieval.ts
14011
14011
  var import_promises8 = require("node:fs/promises");
14012
- var import_node_fs13 = require("node:fs");
14013
- var import_node_path13 = require("node:path");
14012
+ var import_node_fs14 = require("node:fs");
14013
+ var import_node_path14 = require("node:path");
14014
14014
 
14015
14015
  // src/lib/org-mirror.ts
14016
14016
  var import_node_fs12 = require("node:fs");
@@ -14201,16 +14201,216 @@ async function readOrgMirror(remote = requestRemote()) {
14201
14201
  return out;
14202
14202
  }
14203
14203
 
14204
- // src/lib/memory-retrieval.ts
14205
- var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
14206
- var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
14207
- var DEFAULT_BUDGET_TOKENS = 2e3;
14208
- var MAX_BUDGET_TOKENS = 4e3;
14209
- var MIN_SCORE = 0.5;
14210
- var ORG_MIN_SHARED_TERMS = 2;
14204
+ // src/lib/safe-read.ts
14205
+ var import_node_fs13 = require("node:fs");
14206
+ var import_node_path13 = require("node:path");
14207
+ var FLAGS = import_node_fs13.constants;
14208
+ var NOFOLLOW = FLAGS.O_NOFOLLOW;
14209
+ var NONBLOCK = FLAGS.O_NONBLOCK;
14210
+ function closeOpened(fd) {
14211
+ try {
14212
+ (0, import_node_fs13.closeSync)(fd);
14213
+ } catch {
14214
+ }
14215
+ }
14216
+ function isInsideRoot(realRoot, realPath) {
14217
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path13.sep) ? realRoot : realRoot + import_node_path13.sep);
14218
+ }
14219
+ function sameOpenedFile(opened, current, nofollowAvailable) {
14220
+ if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
14221
+ return opened.ino === current.ino && opened.dev === current.dev;
14222
+ }
14223
+ function openRegularInRoot(root, path) {
14224
+ const full = (0, import_node_path13.isAbsolute)(path) ? path : (0, import_node_path13.join)(root, path);
14225
+ let fd;
14226
+ try {
14227
+ fd = (0, import_node_fs13.openSync)(full, import_node_fs13.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
14228
+ } catch (err) {
14229
+ const code = err.code;
14230
+ if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
14231
+ if (code === "ENOENT" || code === "ENOTDIR") return { ok: false, reason: "missing" };
14232
+ return { ok: false, reason: "unreadable" };
14233
+ }
14234
+ try {
14235
+ const opened = (0, import_node_fs13.fstatSync)(fd, { bigint: true });
14236
+ if (!opened.isFile()) {
14237
+ closeOpened(fd);
14238
+ return { ok: false, reason: "not-regular" };
14239
+ }
14240
+ const realRoot = import_node_fs13.realpathSync.native(root);
14241
+ const realPath = import_node_fs13.realpathSync.native(full);
14242
+ if (!isInsideRoot(realRoot, realPath)) {
14243
+ closeOpened(fd);
14244
+ return { ok: false, reason: "outside-root" };
14245
+ }
14246
+ const current = (0, import_node_fs13.statSync)(realPath, { bigint: true });
14247
+ if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
14248
+ closeOpened(fd);
14249
+ return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
14250
+ }
14251
+ return { ok: true, fd, size: Number(opened.size), mtimeMs: Number(opened.mtimeMs) };
14252
+ } catch {
14253
+ closeOpened(fd);
14254
+ return { ok: false, reason: "unreadable" };
14255
+ }
14256
+ }
14257
+ function statRegularInRoot(root, path) {
14258
+ const opened = openRegularInRoot(root, path);
14259
+ if (!opened.ok) return opened;
14260
+ closeOpened(opened.fd);
14261
+ return { ok: true, size: opened.size, mtimeMs: opened.mtimeMs };
14262
+ }
14263
+ function readOpened(fd, size) {
14264
+ try {
14265
+ const buffer = Buffer.alloc(size);
14266
+ let offset = 0;
14267
+ while (offset < size) {
14268
+ const n = (0, import_node_fs13.readSync)(fd, buffer, offset, size - offset, offset);
14269
+ if (n === 0) break;
14270
+ offset += n;
14271
+ }
14272
+ return buffer.subarray(0, offset);
14273
+ } finally {
14274
+ closeOpened(fd);
14275
+ }
14276
+ }
14277
+ function readOpenedUtf8(fd, size) {
14278
+ return readOpened(fd, size).toString("utf-8");
14279
+ }
14280
+ function readRegularFileInRoot(root, path, maxBytes) {
14281
+ const opened = openRegularInRoot(root, path);
14282
+ if (!opened.ok) return opened;
14283
+ if (opened.size > maxBytes) {
14284
+ closeOpened(opened.fd);
14285
+ return { ok: false, reason: "too-large", size: opened.size };
14286
+ }
14287
+ try {
14288
+ return { ok: true, content: readOpenedUtf8(opened.fd, opened.size), size: opened.size };
14289
+ } catch {
14290
+ return { ok: false, reason: "unreadable" };
14291
+ }
14292
+ }
14293
+
14294
+ // src/lib/knowledge-score.ts
14295
+ var KIND_PRIOR_MEAN = {
14296
+ decision: 0.78,
14297
+ pattern: 0.89,
14298
+ security: 0.8,
14299
+ quality: 0.71,
14300
+ integration: 0.71,
14301
+ domain: 0.71,
14302
+ gotcha: 0.53,
14303
+ intent: 0.53
14304
+ };
14305
+ var DEFAULT_PRIOR_MEAN = 0.6;
14306
+ var PRIOR_STRENGTH = 2;
14307
+ var RELEVANCE_FLOOR = 0.15;
14308
+ var TAG_SATURATION = 1.5;
14309
+ var STOPWORDS = /* @__PURE__ */ new Set([
14310
+ "the",
14311
+ "and",
14312
+ "for",
14313
+ "are",
14314
+ "but",
14315
+ "not",
14316
+ "you",
14317
+ "all",
14318
+ "any",
14319
+ "can",
14320
+ "had",
14321
+ "has",
14322
+ "her",
14323
+ "was",
14324
+ "one",
14325
+ "our",
14326
+ "out",
14327
+ "him",
14328
+ "his",
14329
+ "how",
14330
+ "its",
14331
+ "may",
14332
+ "who",
14333
+ "did",
14334
+ "get",
14335
+ "got",
14336
+ "let",
14337
+ "say",
14338
+ "she",
14339
+ "too",
14340
+ "use",
14341
+ "via",
14342
+ "yes",
14343
+ "yet",
14344
+ "now",
14345
+ "new",
14346
+ "also",
14347
+ "been",
14348
+ "both",
14349
+ "does",
14350
+ "each",
14351
+ "from",
14352
+ "have",
14353
+ "here",
14354
+ "into",
14355
+ "just",
14356
+ "like",
14357
+ "make",
14358
+ "more",
14359
+ "most",
14360
+ "much",
14361
+ "must",
14362
+ "need",
14363
+ "only",
14364
+ "over",
14365
+ "same",
14366
+ "some",
14367
+ "such",
14368
+ "than",
14369
+ "that",
14370
+ "them",
14371
+ "then",
14372
+ "there",
14373
+ "these",
14374
+ "they",
14375
+ "this",
14376
+ "those",
14377
+ "very",
14378
+ "want",
14379
+ "were",
14380
+ "what",
14381
+ "when",
14382
+ "where",
14383
+ "which",
14384
+ "while",
14385
+ "will",
14386
+ "with",
14387
+ "would",
14388
+ "your",
14389
+ "about",
14390
+ "after",
14391
+ "again",
14392
+ "being",
14393
+ "could",
14394
+ "other",
14395
+ "should",
14396
+ "their",
14397
+ "because",
14398
+ "before",
14399
+ "doing",
14400
+ "going",
14401
+ "still",
14402
+ "think",
14403
+ "thing",
14404
+ "things",
14405
+ "well",
14406
+ "way",
14407
+ "why",
14408
+ "within",
14409
+ "without"
14410
+ ]);
14211
14411
  function tokenize(text) {
14212
14412
  return new Set(
14213
- text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
14413
+ text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
14214
14414
  );
14215
14415
  }
14216
14416
  function jaccardKeywords(a, b) {
@@ -14220,6 +14420,78 @@ function jaccardKeywords(a, b) {
14220
14420
  const union = a.size + b.size - inter;
14221
14421
  return union === 0 ? 0 : inter / union;
14222
14422
  }
14423
+ function relevance(node, ctx) {
14424
+ const globHit = node.globHit === true;
14425
+ let tagScore = 0;
14426
+ const nodeTags = node.context_tags ?? [];
14427
+ if (nodeTags.length > 0 && ctx.changeTags && ctx.changeTags.length > 0) {
14428
+ const change = new Set(ctx.changeTags);
14429
+ let hit = 0;
14430
+ for (const t of nodeTags) {
14431
+ if (!change.has(t)) continue;
14432
+ hit += t.startsWith("pkg:") || t.startsWith("tbl:") ? 1 : t.startsWith("sym:") ? 0.8 : t.startsWith("dir:") ? 0.4 : 0.15;
14433
+ }
14434
+ tagScore = Math.min(1, hit / TAG_SATURATION);
14435
+ }
14436
+ let textScore = 0;
14437
+ if (ctx.promptTokens && ctx.promptTokens.size > 0) {
14438
+ textScore = jaccardKeywords(tokenize(`${node.title} ${node.body}`), ctx.promptTokens);
14439
+ textScore = Math.min(1, textScore * 4);
14440
+ }
14441
+ const distance = node.distance ?? 0;
14442
+ const hopScore = distance > 0 ? Math.min(1, node.hopWeight ?? 1) * 0.45 * Math.pow(0.6, distance - 1) : 0;
14443
+ const globEvidence = globHit && (node.kind !== "integration" || tagScore > 0 || textScore > 0);
14444
+ const evidence2 = [globEvidence ? 0.85 : 0, tagScore * 0.9, textScore * 0.7, hopScore];
14445
+ let miss = 1;
14446
+ for (const e of evidence2) miss *= 1 - Math.max(0, Math.min(1, e));
14447
+ let score = 1 - miss;
14448
+ if (distance > 0) score *= Math.pow(0.85, distance);
14449
+ return { score, via: { glob: globHit, tag: tagScore, text: textScore } };
14450
+ }
14451
+ var KIND_POOL_STRENGTH = 20;
14452
+ function priorFor(kind, pooled) {
14453
+ const base = KIND_PRIOR_MEAN[kind] ?? DEFAULT_PRIOR_MEAN;
14454
+ const a = pooled ? Math.max(0, pooled.alpha) : 0;
14455
+ const b = pooled ? Math.max(0, pooled.beta) : 0;
14456
+ const mean = pooled && kind !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
14457
+ return { alpha: mean * PRIOR_STRENGTH, beta: (1 - mean) * PRIOR_STRENGTH };
14458
+ }
14459
+ function posteriorFor(kind, own, pooled) {
14460
+ const p = priorFor(kind, pooled);
14461
+ if (!own || kind === "integration") return p;
14462
+ return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
14463
+ }
14464
+ function posteriorMean(p) {
14465
+ const n = p.alpha + p.beta;
14466
+ return n <= 0 ? DEFAULT_PRIOR_MEAN : p.alpha / n;
14467
+ }
14468
+ function scoreCandidates(nodes, ctx, opts = {}) {
14469
+ const floor = opts.relevanceFloor ?? RELEVANCE_FLOOR;
14470
+ const out = [];
14471
+ for (const n of nodes) {
14472
+ const rel = relevance(n, ctx);
14473
+ if (rel.score < floor) continue;
14474
+ const post = posteriorFor(n.kind, opts.posteriors?.get(n.id), opts.kindPosteriors?.get(n.kind));
14475
+ const usefulness = posteriorMean(post);
14476
+ out.push({ id: n.id, score: rel.score * usefulness, relevance: rel.score, usefulness, via: rel.via });
14477
+ }
14478
+ out.sort((a, b) => b.score - a.score || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
14479
+ return out;
14480
+ }
14481
+
14482
+ // src/lib/memory-retrieval.ts
14483
+ var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
14484
+ var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
14485
+ var DEFAULT_BUDGET_TOKENS = 2e3;
14486
+ var MAX_BUDGET_TOKENS = 4e3;
14487
+ var MAX_NODE_FILE_BYTES = 64 * 1024;
14488
+ var MIN_SCORE = RELEVANCE_FLOOR * 0.5;
14489
+ var ORG_MIN_SHARED_TERMS = 2;
14490
+ function orgTerms(text) {
14491
+ return new Set(
14492
+ text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
14493
+ );
14494
+ }
14223
14495
  function sharedTerms(a, b) {
14224
14496
  let n = 0;
14225
14497
  for (const w of a) if (b.has(w)) n++;
@@ -14248,34 +14520,27 @@ function globMatch(glob, filePath) {
14248
14520
  return false;
14249
14521
  }
14250
14522
  function scoreNode(node, promptTokens, taskFiles) {
14251
- let score = 0;
14252
- score += node.confidence * 0.5;
14253
- score += Math.log(1 + node.citedCount) * 0.3;
14254
- const nodeTokens = tokenize(`${node.title} ${node.body}`);
14255
- score += jaccardKeywords(nodeTokens, promptTokens) * 2;
14256
- if (node.fileGlobs.length > 0 && taskFiles.length > 0) {
14257
- for (const glob of node.fileGlobs) {
14258
- for (const file of taskFiles) {
14259
- if (globMatch(glob, file)) {
14260
- score += 1.5;
14261
- break;
14262
- }
14263
- }
14264
- if (score > 3) break;
14265
- }
14266
- }
14267
- const kindPriors = {
14268
- security: 0.4,
14269
- gotcha: 0.4,
14270
- decision: 0.3,
14271
- pattern: 0.2,
14272
- integration: 0.3,
14273
- domain: 0.2,
14274
- quality: 0.1,
14275
- intent: 0.1
14276
- };
14277
- score += kindPriors[node.kind] ?? 0;
14278
- return score;
14523
+ const globHit = node.fileGlobs.length > 0 && taskFiles.length > 0 && node.fileGlobs.some((glob) => taskFiles.some((file) => globMatch(glob, file)));
14524
+ const [scored] = scoreCandidates(
14525
+ [{
14526
+ id: node.nodeId,
14527
+ kind: node.kind,
14528
+ title: node.title,
14529
+ body: node.body,
14530
+ file_globs: node.fileGlobs,
14531
+ // Not yet synced to the client graph; absent means "no tag evidence",
14532
+ // never "excluded" (KL18).
14533
+ context_tags: [],
14534
+ globHit
14535
+ }],
14536
+ { promptTokens }
14537
+ // ⚠ The gate is on RELEVANCE, as on the server. This once passed
14538
+ // `relevanceFloor: 0` and left MIN_SCORE (on the product) as the only
14539
+ // filter, so a sub-floor match rode a strong kind prior past it: 30% of
14540
+ // replayed injections had r < RELEVANCE_FLOOR. MIN_SCORE stays as a second
14541
+ // guard for a very weak kind; it can no longer admit what the gate refused.
14542
+ );
14543
+ return scored?.score ?? 0;
14279
14544
  }
14280
14545
  function parseFrontmatter(content) {
14281
14546
  const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
@@ -14315,20 +14580,22 @@ function parseFrontmatter(content) {
14315
14580
  return { fm, body: match[2].trim() };
14316
14581
  }
14317
14582
  async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
14318
- const hasRepoGraph = (0, import_node_fs13.existsSync)(memoryDir());
14583
+ const hasRepoGraph = (0, import_node_fs14.existsSync)(memoryDir());
14319
14584
  const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
14320
14585
  const promptTokens = tokenize(promptText);
14586
+ const orgPromptTerms = orgTerms(promptText);
14321
14587
  const nodes = [];
14322
14588
  for (const domain of hasRepoGraph ? DOMAINS : []) {
14323
- const domainDir = (0, import_node_path13.join)(memoryDir(), domain);
14324
- if (!(0, import_node_fs13.existsSync)(domainDir)) continue;
14589
+ const domainDir = (0, import_node_path14.join)(memoryDir(), domain);
14590
+ if (!(0, import_node_fs14.existsSync)(domainDir)) continue;
14325
14591
  try {
14326
14592
  const files = await (0, import_promises8.readdir)(domainDir);
14327
14593
  for (const file of files) {
14328
14594
  if (!file.endsWith(".md")) continue;
14329
14595
  try {
14330
- const content = await (0, import_promises8.readFile)((0, import_node_path13.join)(domainDir, file), "utf-8");
14331
- const { fm, body } = parseFrontmatter(content);
14596
+ const read = readRegularFileInRoot(memoryDir(), `${domain}/${file}`, MAX_NODE_FILE_BYTES);
14597
+ if (!read.ok) continue;
14598
+ const { fm, body } = parseFrontmatter(read.content);
14332
14599
  if (fm.status && fm.status !== "active") continue;
14333
14600
  nodes.push({
14334
14601
  path: `${domain}/${file}`,
@@ -14350,7 +14617,7 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
14350
14617
  try {
14351
14618
  for (const claim of await readOrgMirror()) {
14352
14619
  const local = orgNodeToLocal(claim);
14353
- if (sharedTerms(tokenize(`${local.title} ${local.body}`), promptTokens) >= ORG_MIN_SHARED_TERMS) nodes.push(local);
14620
+ if (sharedTerms(orgTerms(`${local.title} ${local.body}`), orgPromptTerms) >= ORG_MIN_SHARED_TERMS) nodes.push(local);
14354
14621
  }
14355
14622
  } catch {
14356
14623
  }
@@ -14388,19 +14655,216 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
14388
14655
  return {
14389
14656
  nodes: selected,
14390
14657
  contextBlock: lines.join("\n"),
14391
- tokensUsed
14658
+ tokensUsed,
14659
+ eligible: filtered.length
14392
14660
  };
14393
14661
  }
14394
14662
 
14395
- // src/lib/memory-sync.ts
14396
- var import_promises9 = require("node:fs/promises");
14663
+ // src/lib/injection-record.ts
14397
14664
  var import_node_fs16 = require("node:fs");
14398
- var import_node_path15 = require("node:path");
14399
14665
  var import_node_crypto3 = require("node:crypto");
14400
14666
 
14667
+ // src/lib/safe-write.ts
14668
+ var import_node_fs15 = require("node:fs");
14669
+ var import_node_path15 = require("node:path");
14670
+ var FLAGS2 = import_node_fs15.constants;
14671
+ var O_NOFOLLOW = FLAGS2.O_NOFOLLOW ?? 0;
14672
+ var NOFOLLOW_AVAILABLE = O_NOFOLLOW !== 0;
14673
+ function validateRoot(root) {
14674
+ try {
14675
+ const parentReal = (0, import_node_fs15.realpathSync)((0, import_node_path15.dirname)(root));
14676
+ const expected = (0, import_node_path15.join)(parentReal, (0, import_node_path15.basename)(root));
14677
+ try {
14678
+ (0, import_node_fs15.mkdirSync)(expected);
14679
+ } catch (e) {
14680
+ if (e.code !== "EEXIST") return null;
14681
+ }
14682
+ const st = (0, import_node_fs15.lstatSync)(expected, { bigint: true });
14683
+ if (st.isSymbolicLink() || !st.isDirectory()) return null;
14684
+ if ((0, import_node_fs15.realpathSync)(expected) !== expected) return null;
14685
+ return { real: expected, dev: st.dev, ino: st.ino };
14686
+ } catch {
14687
+ return null;
14688
+ }
14689
+ }
14690
+ function rootUnchanged(root) {
14691
+ try {
14692
+ const st = (0, import_node_fs15.lstatSync)(root.real, { bigint: true });
14693
+ return !st.isSymbolicLink() && st.isDirectory() && st.dev === root.dev && st.ino === root.ino;
14694
+ } catch {
14695
+ return false;
14696
+ }
14697
+ }
14698
+ function bareName(name) {
14699
+ return !!name && name === (0, import_node_path15.basename)(name) && name !== "." && name !== ".." && !name.includes("\0");
14700
+ }
14701
+ function absentOrRegular(path) {
14702
+ try {
14703
+ const st = (0, import_node_fs15.lstatSync)(path);
14704
+ return st.isFile() && !st.isSymbolicLink();
14705
+ } catch (e) {
14706
+ return e.code === "ENOENT";
14707
+ }
14708
+ }
14709
+ function verifyOpened(fd, path, root) {
14710
+ try {
14711
+ const opened = (0, import_node_fs15.fstatSync)(fd, { bigint: true });
14712
+ if (!opened.isFile() || opened.nlink !== 1n) return false;
14713
+ const real = (0, import_node_fs15.realpathSync)(path);
14714
+ if (!isInsideRoot(root.real, real)) return false;
14715
+ const current = (0, import_node_fs15.statSync)(real, { bigint: true });
14716
+ if (!sameOpenedFile(opened, current, NOFOLLOW_AVAILABLE)) return false;
14717
+ return rootUnchanged(root);
14718
+ } catch {
14719
+ return false;
14720
+ }
14721
+ }
14722
+ function removeIfOurs(fd, path) {
14723
+ try {
14724
+ const opened = (0, import_node_fs15.fstatSync)(fd, { bigint: true });
14725
+ const at = (0, import_node_fs15.lstatSync)(path, { bigint: true });
14726
+ if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0, import_node_fs15.unlinkSync)(path);
14727
+ } catch {
14728
+ }
14729
+ }
14730
+ function openTarget(path, append2) {
14731
+ const base = import_node_fs15.constants.O_WRONLY | (append2 ? import_node_fs15.constants.O_APPEND : 0) | O_NOFOLLOW;
14732
+ try {
14733
+ return { fd: (0, import_node_fs15.openSync)(path, base), created: false };
14734
+ } catch (e) {
14735
+ if (e.code !== "ENOENT") return null;
14736
+ }
14737
+ try {
14738
+ return { fd: (0, import_node_fs15.openSync)(path, base | import_node_fs15.constants.O_CREAT | import_node_fs15.constants.O_EXCL, 384), created: true };
14739
+ } catch {
14740
+ return null;
14741
+ }
14742
+ }
14743
+ function writeVerified(root, name, hooks, append2, write) {
14744
+ const r = validateRoot(root);
14745
+ if (!r || !bareName(name)) return false;
14746
+ const path = (0, import_node_path15.join)(r.real, name);
14747
+ if (!absentOrRegular(path)) return false;
14748
+ if (!runHook(hooks)) return false;
14749
+ const opened = openTarget(path, append2);
14750
+ if (!opened) return false;
14751
+ try {
14752
+ if (!verifyOpened(opened.fd, path, r)) {
14753
+ if (opened.created) removeIfOurs(opened.fd, path);
14754
+ return false;
14755
+ }
14756
+ write(opened.fd);
14757
+ return true;
14758
+ } catch {
14759
+ return false;
14760
+ } finally {
14761
+ try {
14762
+ (0, import_node_fs15.closeSync)(opened.fd);
14763
+ } catch {
14764
+ }
14765
+ }
14766
+ }
14767
+ function runHook(hooks) {
14768
+ try {
14769
+ hooks.afterRootValidated?.();
14770
+ return true;
14771
+ } catch {
14772
+ return false;
14773
+ }
14774
+ }
14775
+ function appendInRoot(root, name, text, hooks = {}) {
14776
+ return writeVerified(root, name, hooks, true, (fd) => {
14777
+ (0, import_node_fs15.writeSync)(fd, text);
14778
+ });
14779
+ }
14780
+ function replaceInRoot(root, name, text, hooks = {}) {
14781
+ return writeVerified(root, name, hooks, false, (fd) => {
14782
+ (0, import_node_fs15.ftruncateSync)(fd, 0);
14783
+ (0, import_node_fs15.writeSync)(fd, text, 0);
14784
+ });
14785
+ }
14786
+
14787
+ // src/lib/injection-record.ts
14788
+ var MAX_PENDING = 200;
14789
+ var MAX_RECORD_BYTES = 1024 * 1024;
14790
+ var COMPACT_AT_BYTES = 256 * 1024;
14791
+ var MAX_NODES = 50;
14792
+ var SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
14793
+ var VIA = /^[A-Za-z0-9_+,:.-]{0,40}$/;
14794
+ var PROMPT_HASH = /^[0-9a-f]{16}$/;
14795
+ var nonNegInt = (v, max) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= max;
14796
+ function parseInjectionEvent(raw) {
14797
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
14798
+ const o = raw;
14799
+ if (typeof o.ts !== "number" || !Number.isFinite(o.ts) || o.ts <= 0 || o.ts > 1e13) return null;
14800
+ if (!(o.session_id === null || typeof o.session_id === "string" && SAFE_ID.test(o.session_id))) return null;
14801
+ if (typeof o.prompt_hash !== "string" || !PROMPT_HASH.test(o.prompt_hash)) return null;
14802
+ if (o.arm !== "injected" && o.arm !== "withheld") return null;
14803
+ if (!nonNegInt(o.eligible, 1e5) || !nonNegInt(o.tokens, 1e6)) return null;
14804
+ if (!Array.isArray(o.nodes) || o.nodes.length > MAX_NODES) return null;
14805
+ const nodes = [];
14806
+ for (const n of o.nodes) {
14807
+ if (!n || typeof n !== "object") return null;
14808
+ const r = n;
14809
+ if (typeof r.id !== "string" || !SAFE_ID.test(r.id)) return null;
14810
+ if (typeof r.score !== "number" || !Number.isFinite(r.score) || r.score < 0 || r.score > 10) return null;
14811
+ if (typeof r.via !== "string" || !VIA.test(r.via)) return null;
14812
+ nodes.push({ id: r.id, score: r.score, via: r.via });
14813
+ }
14814
+ return {
14815
+ ts: o.ts,
14816
+ session_id: o.session_id,
14817
+ prompt_hash: o.prompt_hash,
14818
+ arm: o.arm,
14819
+ nodes,
14820
+ eligible: o.eligible,
14821
+ tokens: o.tokens
14822
+ };
14823
+ }
14824
+ var recordPath = () => projectPath(`${VERITY_DIR}/injections.jsonl`);
14825
+ function hashPrompt(prompt) {
14826
+ return (0, import_node_crypto3.createHash)("sha256").update(prompt).digest("hex").slice(0, 16);
14827
+ }
14828
+ function recordInjection(event) {
14829
+ if (!appendInRoot(projectPath(VERITY_DIR), "injections.jsonl", JSON.stringify(event) + "\n")) return;
14830
+ try {
14831
+ if ((0, import_node_fs16.lstatSync)(recordPath()).size > COMPACT_AT_BYTES) writeEvents(readPendingInjections());
14832
+ } catch {
14833
+ }
14834
+ }
14835
+ function writeEvents(events) {
14836
+ replaceInRoot(projectPath(VERITY_DIR), "injections.jsonl", events.map((e) => JSON.stringify(e)).join("\n") + (events.length ? "\n" : ""));
14837
+ }
14838
+ function readPendingInjections() {
14839
+ try {
14840
+ const p = recordPath();
14841
+ if (!(0, import_node_fs16.existsSync)(p)) return [];
14842
+ const read = readRegularFileInRoot(projectPath(VERITY_DIR), "injections.jsonl", MAX_RECORD_BYTES);
14843
+ if (!read.ok) return [];
14844
+ const out = [];
14845
+ for (const line of read.content.split("\n")) {
14846
+ if (!line.trim()) continue;
14847
+ try {
14848
+ const e = parseInjectionEvent(JSON.parse(line));
14849
+ if (e) out.push(e);
14850
+ } catch {
14851
+ }
14852
+ }
14853
+ return out.slice(-MAX_PENDING);
14854
+ } catch {
14855
+ return [];
14856
+ }
14857
+ }
14858
+
14859
+ // src/lib/memory-sync.ts
14860
+ var import_promises9 = require("node:fs/promises");
14861
+ var import_node_fs19 = require("node:fs");
14862
+ var import_node_path17 = require("node:path");
14863
+ var import_node_crypto4 = require("node:crypto");
14864
+
14401
14865
  // src/lib/gitignore.ts
14402
14866
  var import_node_child_process6 = require("node:child_process");
14403
- var import_node_fs14 = require("node:fs");
14867
+ var import_node_fs17 = require("node:fs");
14404
14868
  var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
14405
14869
  var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
14406
14870
  var VERITY_GITIGNORE_BLOCK = [
@@ -14484,7 +14948,7 @@ function fenceMemoryLines(lines) {
14484
14948
  function ensureVerityGitignore() {
14485
14949
  let content = "";
14486
14950
  try {
14487
- content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
14951
+ content = (0, import_node_fs17.readFileSync)(".gitignore", "utf-8");
14488
14952
  } catch {
14489
14953
  }
14490
14954
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14511,7 +14975,7 @@ function ensureVerityGitignore() {
14511
14975
  const sep4 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
14512
14976
  text = text + sep4 + VERITY_GITIGNORE_BLOCK;
14513
14977
  }
14514
- if (text !== content) (0, import_node_fs14.writeFileSync)(".gitignore", text);
14978
+ if (text !== content) (0, import_node_fs17.writeFileSync)(".gitignore", text);
14515
14979
  return verified(
14516
14980
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
14517
14981
  );
@@ -14531,7 +14995,7 @@ function untrackMemory() {
14531
14995
  function writeFencedBlock() {
14532
14996
  let content = "";
14533
14997
  try {
14534
- content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
14998
+ content = (0, import_node_fs17.readFileSync)(".gitignore", "utf-8");
14535
14999
  } catch {
14536
15000
  }
14537
15001
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -14543,7 +15007,7 @@ function writeFencedBlock() {
14543
15007
  text = text + sep4 + VERITY_GITIGNORE_BLOCK;
14544
15008
  }
14545
15009
  try {
14546
- (0, import_node_fs14.writeFileSync)(".gitignore", text);
15010
+ (0, import_node_fs17.writeFileSync)(".gitignore", text);
14547
15011
  return true;
14548
15012
  } catch {
14549
15013
  return false;
@@ -14552,14 +15016,14 @@ function writeFencedBlock() {
14552
15016
  function fenceMemory() {
14553
15017
  let original = null;
14554
15018
  try {
14555
- original = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
15019
+ original = (0, import_node_fs17.readFileSync)(".gitignore", "utf-8");
14556
15020
  } catch {
14557
15021
  original = null;
14558
15022
  }
14559
15023
  const restore = () => {
14560
15024
  try {
14561
- if (original === null) (0, import_node_fs14.rmSync)(".gitignore", { force: true });
14562
- else (0, import_node_fs14.writeFileSync)(".gitignore", original);
15025
+ if (original === null) (0, import_node_fs17.rmSync)(".gitignore", { force: true });
15026
+ else (0, import_node_fs17.writeFileSync)(".gitignore", original);
14563
15027
  } catch {
14564
15028
  }
14565
15029
  };
@@ -14577,7 +15041,7 @@ function fenceMemory() {
14577
15041
  }
14578
15042
  function memoryOptOut() {
14579
15043
  try {
14580
- return (0, import_node_fs14.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
15044
+ return (0, import_node_fs17.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
14581
15045
  } catch {
14582
15046
  return false;
14583
15047
  }
@@ -14585,13 +15049,13 @@ function memoryOptOut() {
14585
15049
  function keepMemoryTracked() {
14586
15050
  let content = "";
14587
15051
  try {
14588
- content = (0, import_node_fs14.readFileSync)(".gitignore", "utf-8");
15052
+ content = (0, import_node_fs17.readFileSync)(".gitignore", "utf-8");
14589
15053
  } catch {
14590
15054
  }
14591
15055
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
14592
15056
  try {
14593
15057
  const sep4 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
14594
- (0, import_node_fs14.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
15058
+ (0, import_node_fs17.writeFileSync)(".gitignore", content + sep4 + MEMORY_OPT_OUT_STANZA);
14595
15059
  } catch {
14596
15060
  return "failed";
14597
15061
  }
@@ -14626,26 +15090,26 @@ function untrackVerityState() {
14626
15090
  }
14627
15091
 
14628
15092
  // src/lib/safe-path.ts
14629
- var import_node_fs15 = require("node:fs");
14630
- var import_node_path14 = require("node:path");
15093
+ var import_node_fs18 = require("node:fs");
15094
+ var import_node_path16 = require("node:path");
14631
15095
  function resolveInside(baseDir, candidate) {
14632
15096
  if (typeof candidate !== "string" || candidate.length === 0) return null;
14633
- if ((0, import_node_path14.isAbsolute)(candidate)) return null;
14634
- const baseAbs = (0, import_node_path14.resolve)(baseDir);
14635
- const full = (0, import_node_path14.resolve)(baseAbs, candidate);
14636
- const baseSep = baseAbs.endsWith(import_node_path14.sep) ? baseAbs : baseAbs + import_node_path14.sep;
15097
+ if ((0, import_node_path16.isAbsolute)(candidate)) return null;
15098
+ const baseAbs = (0, import_node_path16.resolve)(baseDir);
15099
+ const full = (0, import_node_path16.resolve)(baseAbs, candidate);
15100
+ const baseSep = baseAbs.endsWith(import_node_path16.sep) ? baseAbs : baseAbs + import_node_path16.sep;
14637
15101
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
14638
15102
  try {
14639
- if ((0, import_node_fs15.existsSync)(baseAbs)) {
14640
- const realBase = (0, import_node_fs15.realpathSync)(baseAbs);
14641
- const realBaseSep = realBase.endsWith(import_node_path14.sep) ? realBase : realBase + import_node_path14.sep;
15103
+ if ((0, import_node_fs18.existsSync)(baseAbs)) {
15104
+ const realBase = (0, import_node_fs18.realpathSync)(baseAbs);
15105
+ const realBaseSep = realBase.endsWith(import_node_path16.sep) ? realBase : realBase + import_node_path16.sep;
14642
15106
  let probe = full;
14643
- while (!(0, import_node_fs15.existsSync)(probe)) {
14644
- const parent = (0, import_node_path14.dirname)(probe);
15107
+ while (!(0, import_node_fs18.existsSync)(probe)) {
15108
+ const parent = (0, import_node_path16.dirname)(probe);
14645
15109
  if (parent === probe) break;
14646
15110
  probe = parent;
14647
15111
  }
14648
- const realProbe = (0, import_node_fs15.realpathSync)(probe);
15112
+ const realProbe = (0, import_node_fs18.realpathSync)(probe);
14649
15113
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
14650
15114
  }
14651
15115
  } catch {
@@ -14653,37 +15117,37 @@ function resolveInside(baseDir, candidate) {
14653
15117
  }
14654
15118
  return full;
14655
15119
  }
14656
- var O_NOFOLLOW = typeof import_node_fs15.constants.O_NOFOLLOW === "number" ? import_node_fs15.constants.O_NOFOLLOW : 0;
15120
+ var O_NOFOLLOW2 = typeof import_node_fs18.constants.O_NOFOLLOW === "number" ? import_node_fs18.constants.O_NOFOLLOW : 0;
14657
15121
  function readFileInside(baseDir, candidate, maxBytes) {
14658
15122
  const full = resolveInside(baseDir, candidate);
14659
15123
  if (!full) return null;
14660
15124
  let realParent;
14661
15125
  let realBase;
14662
15126
  try {
14663
- realParent = (0, import_node_fs15.realpathSync)((0, import_node_path14.dirname)(full));
14664
- realBase = (0, import_node_fs15.realpathSync)((0, import_node_path14.resolve)(baseDir));
15127
+ realParent = (0, import_node_fs18.realpathSync)((0, import_node_path16.dirname)(full));
15128
+ realBase = (0, import_node_fs18.realpathSync)((0, import_node_path16.resolve)(baseDir));
14665
15129
  } catch {
14666
15130
  return null;
14667
15131
  }
14668
- const realBaseSep = realBase.endsWith(import_node_path14.sep) ? realBase : realBase + import_node_path14.sep;
15132
+ const realBaseSep = realBase.endsWith(import_node_path16.sep) ? realBase : realBase + import_node_path16.sep;
14669
15133
  if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
14670
- const target = (0, import_node_path14.join)(realParent, (0, import_node_path14.basename)(full));
15134
+ const target = (0, import_node_path16.join)(realParent, (0, import_node_path16.basename)(full));
14671
15135
  let fd = null;
14672
15136
  try {
14673
- fd = (0, import_node_fs15.openSync)(target, import_node_fs15.constants.O_RDONLY | O_NOFOLLOW);
14674
- const st = (0, import_node_fs15.fstatSync)(fd);
15137
+ fd = (0, import_node_fs18.openSync)(target, import_node_fs18.constants.O_RDONLY | O_NOFOLLOW2);
15138
+ const st = (0, import_node_fs18.fstatSync)(fd);
14675
15139
  if (!st.isFile()) return null;
14676
15140
  const cap = Math.min(maxBytes, st.size);
14677
15141
  if (cap <= 0) return "";
14678
15142
  const buf = Buffer.alloc(cap);
14679
- const bytesRead = (0, import_node_fs15.readSync)(fd, buf, 0, cap, 0);
15143
+ const bytesRead = (0, import_node_fs18.readSync)(fd, buf, 0, cap, 0);
14680
15144
  return buf.subarray(0, bytesRead).toString("utf-8");
14681
15145
  } catch {
14682
15146
  return null;
14683
15147
  } finally {
14684
15148
  if (fd !== null) {
14685
15149
  try {
14686
- (0, import_node_fs15.closeSync)(fd);
15150
+ (0, import_node_fs18.closeSync)(fd);
14687
15151
  } catch {
14688
15152
  }
14689
15153
  }
@@ -14766,35 +15230,35 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
14766
15230
  async function ensureMemoryDir() {
14767
15231
  await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
14768
15232
  for (const domain of DOMAINS2) {
14769
- await (0, import_promises9.mkdir)((0, import_node_path15.join)(memoryDir2(), domain), { recursive: true });
15233
+ await (0, import_promises9.mkdir)((0, import_node_path17.join)(memoryDir2(), domain), { recursive: true });
14770
15234
  }
14771
- if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "SCHEMA.md"))) {
14772
- await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
15235
+ if (!(0, import_node_fs19.existsSync)((0, import_node_path17.join)(memoryDir2(), "SCHEMA.md"))) {
15236
+ await (0, import_promises9.writeFile)((0, import_node_path17.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
14773
15237
  }
14774
- if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "index.md"))) {
14775
- await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
15238
+ if (!(0, import_node_fs19.existsSync)((0, import_node_path17.join)(memoryDir2(), "index.md"))) {
15239
+ await (0, import_promises9.writeFile)((0, import_node_path17.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
14776
15240
  }
14777
- if (!(0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "log.md"))) {
14778
- await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
15241
+ if (!(0, import_node_fs19.existsSync)((0, import_node_path17.join)(memoryDir2(), "log.md"))) {
15242
+ await (0, import_promises9.writeFile)((0, import_node_path17.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
14779
15243
  }
14780
15244
  }
14781
15245
  async function buildManifest() {
14782
- if (!(0, import_node_fs16.existsSync)(memoryDir2())) {
15246
+ if (!(0, import_node_fs19.existsSync)(memoryDir2())) {
14783
15247
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
14784
15248
  }
14785
15249
  const nodes = [];
14786
15250
  for (const domain of DOMAINS2) {
14787
- const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
14788
- if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
15251
+ const domainDir = (0, import_node_path17.join)(memoryDir2(), domain);
15252
+ if (!(0, import_node_fs19.existsSync)(domainDir)) continue;
14789
15253
  try {
14790
15254
  const files = await (0, import_promises9.readdir)(domainDir);
14791
15255
  for (const file of files) {
14792
15256
  if (!file.endsWith(".md")) continue;
14793
15257
  const filePath = `${domain}/${file}`;
14794
- const fullPath = (0, import_node_path15.join)(memoryDir2(), filePath);
15258
+ const fullPath = (0, import_node_path17.join)(memoryDir2(), filePath);
14795
15259
  try {
14796
15260
  const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
14797
- const hash = (0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16);
15261
+ const hash = (0, import_node_crypto4.createHash)("sha256").update(content).digest("hex").slice(0, 16);
14798
15262
  nodes.push({ path: filePath, content_hash: `sha256:${hash}` });
14799
15263
  } catch {
14800
15264
  }
@@ -14804,32 +15268,32 @@ async function buildManifest() {
14804
15268
  }
14805
15269
  let indexHash = null;
14806
15270
  try {
14807
- const indexContent = await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "index.md"), "utf-8");
14808
- indexHash = `sha256:${(0, import_node_crypto3.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
15271
+ const indexContent = await (0, import_promises9.readFile)((0, import_node_path17.join)(memoryDir2(), "index.md"), "utf-8");
15272
+ indexHash = `sha256:${(0, import_node_crypto4.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
14809
15273
  } catch {
14810
15274
  }
14811
15275
  let logLength = 0;
14812
15276
  try {
14813
- const logContent = await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "utf-8");
15277
+ const logContent = await (0, import_promises9.readFile)((0, import_node_path17.join)(memoryDir2(), "log.md"), "utf-8");
14814
15278
  logLength = logContent.split("\n").length;
14815
15279
  } catch {
14816
15280
  }
14817
15281
  return { schema_version: 1, nodes, index_hash: indexHash, log_length: logLength };
14818
15282
  }
14819
15283
  function hashContent(content) {
14820
- return `sha256:${(0, import_node_crypto3.createHash)("sha256").update(content).digest("hex").slice(0, 16)}`;
15284
+ return `sha256:${(0, import_node_crypto4.createHash)("sha256").update(content).digest("hex").slice(0, 16)}`;
14821
15285
  }
14822
15286
  async function readOnDiskNodes() {
14823
15287
  const out = /* @__PURE__ */ new Map();
14824
- if (!(0, import_node_fs16.existsSync)(memoryDir2())) return out;
15288
+ if (!(0, import_node_fs19.existsSync)(memoryDir2())) return out;
14825
15289
  for (const domain of DOMAINS2) {
14826
- const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
14827
- if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
15290
+ const domainDir = (0, import_node_path17.join)(memoryDir2(), domain);
15291
+ if (!(0, import_node_fs19.existsSync)(domainDir)) continue;
14828
15292
  try {
14829
15293
  for (const file of await (0, import_promises9.readdir)(domainDir)) {
14830
15294
  if (!file.endsWith(".md")) continue;
14831
15295
  try {
14832
- out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path15.join)(domainDir, file), "utf-8")));
15296
+ out.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path17.join)(domainDir, file), "utf-8")));
14833
15297
  } catch {
14834
15298
  }
14835
15299
  }
@@ -14866,7 +15330,7 @@ async function recordSyncedNodePaths() {
14866
15330
  }
14867
15331
  }
14868
15332
  async function writeFileAtomic(path, content) {
14869
- await (0, import_promises9.mkdir)((0, import_node_path15.dirname)(path), { recursive: true });
15333
+ await (0, import_promises9.mkdir)((0, import_node_path17.dirname)(path), { recursive: true });
14870
15334
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
14871
15335
  await (0, import_promises9.writeFile)(tmp, content);
14872
15336
  await (0, import_promises9.rename)(tmp, path);
@@ -14880,8 +15344,8 @@ async function computeEditedNodeUploads() {
14880
15344
  const uploads = [];
14881
15345
  for (const [path, prevHash] of prev) {
14882
15346
  if (prevHash == null) continue;
14883
- const full = (0, import_node_path15.join)(memoryDir2(), path);
14884
- if (!(0, import_node_fs16.existsSync)(full)) continue;
15347
+ const full = (0, import_node_path17.join)(memoryDir2(), path);
15348
+ if (!(0, import_node_fs19.existsSync)(full)) continue;
14885
15349
  let content;
14886
15350
  try {
14887
15351
  content = await (0, import_promises9.readFile)(full, "utf-8");
@@ -14925,8 +15389,8 @@ async function applyMemoryWrites(writes, opts = {}) {
14925
15389
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
14926
15390
  for (const n of notes) logLines.push(` - ${n}`);
14927
15391
  try {
14928
- const existing = (0, import_node_fs16.existsSync)((0, import_node_path15.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
14929
- await (0, import_promises9.writeFile)((0, import_node_path15.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
15392
+ const existing = (0, import_node_fs19.existsSync)((0, import_node_path17.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path17.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
15393
+ await (0, import_promises9.writeFile)((0, import_node_path17.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
14930
15394
  } catch {
14931
15395
  }
14932
15396
  if (opts.baseline === "written") await mergeSyncBaseline(synced);
@@ -14936,7 +15400,7 @@ async function applyMemoryWrites(writes, opts = {}) {
14936
15400
  async function mergeSyncBaseline(entries) {
14937
15401
  if (entries.size === 0) return;
14938
15402
  try {
14939
- if ((0, import_node_fs16.existsSync)(syncStateFile())) {
15403
+ if ((0, import_node_fs19.existsSync)(syncStateFile())) {
14940
15404
  try {
14941
15405
  JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
14942
15406
  } catch {
@@ -14964,7 +15428,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
14964
15428
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
14965
15429
  }
14966
15430
  }
14967
- if ((0, import_node_fs16.existsSync)(fullPath)) {
15431
+ if ((0, import_node_fs19.existsSync)(fullPath)) {
14968
15432
  let existing = "";
14969
15433
  try {
14970
15434
  existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
@@ -14980,7 +15444,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
14980
15444
  notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
14981
15445
  }
14982
15446
  }
14983
- await (0, import_promises9.mkdir)((0, import_node_path15.dirname)(fullPath), { recursive: true });
15447
+ await (0, import_promises9.mkdir)((0, import_node_path17.dirname)(fullPath), { recursive: true });
14984
15448
  await (0, import_promises9.writeFile)(fullPath, content);
14985
15449
  return { written: true, syncedHash: hashContent(content), notes };
14986
15450
  }
@@ -15021,8 +15485,8 @@ async function regenerateIndex() {
15021
15485
  ];
15022
15486
  let totalNodes = 0;
15023
15487
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
15024
- const domainDir = (0, import_node_path15.join)(memoryDir2(), domain);
15025
- if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
15488
+ const domainDir = (0, import_node_path17.join)(memoryDir2(), domain);
15489
+ if (!(0, import_node_fs19.existsSync)(domainDir)) continue;
15026
15490
  try {
15027
15491
  const files = await (0, import_promises9.readdir)(domainDir);
15028
15492
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -15032,7 +15496,7 @@ async function regenerateIndex() {
15032
15496
  for (const file of mdFiles.sort()) {
15033
15497
  const slug = file.replace(/\.md$/, "");
15034
15498
  try {
15035
- const content = await (0, import_promises9.readFile)((0, import_node_path15.join)(domainDir, file), "utf-8");
15499
+ const content = await (0, import_promises9.readFile)((0, import_node_path17.join)(domainDir, file), "utf-8");
15036
15500
  const title = pickFrontmatter(content, "title") ?? slug;
15037
15501
  const kind = pickFrontmatter(content, "kind") ?? "-";
15038
15502
  const confidence = pickFrontmatter(content, "confidence");
@@ -15056,7 +15520,7 @@ async function regenerateIndex() {
15056
15520
  lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
15057
15521
  }
15058
15522
  const next = lines.join("\n") + "\n";
15059
- const indexPath = (0, import_node_path15.join)(memoryDir2(), "index.md");
15523
+ const indexPath = (0, import_node_path17.join)(memoryDir2(), "index.md");
15060
15524
  let existing = null;
15061
15525
  try {
15062
15526
  existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
@@ -15453,9 +15917,9 @@ function hasLegacyMemoryBlock(text) {
15453
15917
  return findMarker(text, LEGACY_MD_START) !== -1;
15454
15918
  }
15455
15919
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
15456
- const claudeMdPath = (0, import_node_path15.join)(cwd, "CLAUDE.md");
15920
+ const claudeMdPath = (0, import_node_path17.join)(cwd, "CLAUDE.md");
15457
15921
  let existing = "";
15458
- if ((0, import_node_fs16.existsSync)(claudeMdPath)) {
15922
+ if ((0, import_node_fs19.existsSync)(claudeMdPath)) {
15459
15923
  existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
15460
15924
  }
15461
15925
  let startTag = CLAUDE_MD_START;
@@ -15596,9 +16060,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
15596
16060
  `;
15597
16061
 
15598
16062
  // src/lib/dossier-session.ts
15599
- var import_node_fs21 = require("node:fs");
15600
- var import_node_crypto7 = require("node:crypto");
15601
- var import_node_path18 = require("node:path");
16063
+ var import_node_fs24 = require("node:fs");
16064
+ var import_node_crypto8 = require("node:crypto");
16065
+ var import_node_path20 = require("node:path");
15602
16066
 
15603
16067
  // src/lib/pending-repeat.ts
15604
16068
  var STOP = /* @__PURE__ */ new Set([
@@ -15702,9 +16166,9 @@ function statementAnchorKey(file, patternId) {
15702
16166
  }
15703
16167
 
15704
16168
  // src/lib/dossier/log.ts
15705
- var import_node_crypto4 = require("node:crypto");
15706
- var import_node_fs17 = require("node:fs");
15707
- var import_node_path16 = require("node:path");
16169
+ var import_node_crypto5 = require("node:crypto");
16170
+ var import_node_fs20 = require("node:fs");
16171
+ var import_node_path18 = require("node:path");
15708
16172
  var CRC_TABLE = (() => {
15709
16173
  const t = new Int32Array(256);
15710
16174
  for (let i = 0; i < 256; i++) {
@@ -15723,13 +16187,13 @@ function crc32(s) {
15723
16187
  function openDossier(identity) {
15724
16188
  try {
15725
16189
  const dir = dossierDir(identity);
15726
- (0, import_node_fs17.mkdirSync)(dir, { recursive: true, mode: 448 });
16190
+ (0, import_node_fs20.mkdirSync)(dir, { recursive: true, mode: 448 });
15727
16191
  return {
15728
16192
  dir,
15729
16193
  identity,
15730
- eventsPath: (0, import_node_path16.join)(dir, "events.jsonl"),
15731
- foldPath: (0, import_node_path16.join)(dir, "fold.json"),
15732
- rotatedDir: (0, import_node_path16.join)(dir, "rotated")
16194
+ eventsPath: (0, import_node_path18.join)(dir, "events.jsonl"),
16195
+ foldPath: (0, import_node_path18.join)(dir, "fold.json"),
16196
+ rotatedDir: (0, import_node_path18.join)(dir, "rotated")
15733
16197
  };
15734
16198
  } catch {
15735
16199
  return null;
@@ -15744,7 +16208,7 @@ function nextSeq() {
15744
16208
  function encodeEvent(ev) {
15745
16209
  const full = {
15746
16210
  v: 1,
15747
- id: (0, import_node_crypto4.randomBytes)(4).toString("hex"),
16211
+ id: (0, import_node_crypto5.randomBytes)(4).toString("hex"),
15748
16212
  ...ev
15749
16213
  };
15750
16214
  let body = JSON.stringify(full);
@@ -15791,7 +16255,7 @@ function appendEvent(d, ev) {
15791
16255
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
15792
16256
  ...ev
15793
16257
  });
15794
- (0, import_node_fs17.appendFileSync)(d.eventsPath, line, { mode: 384 });
16258
+ (0, import_node_fs20.appendFileSync)(d.eventsPath, line, { mode: 384 });
15795
16259
  return true;
15796
16260
  } catch {
15797
16261
  return false;
@@ -15799,14 +16263,14 @@ function appendEvent(d, ev) {
15799
16263
  }
15800
16264
  function rotateIfNeeded2(d) {
15801
16265
  try {
15802
- if (!(0, import_node_fs17.existsSync)(d.eventsPath)) return;
15803
- if ((0, import_node_fs17.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
15804
- (0, import_node_fs17.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
15805
- (0, import_node_fs17.renameSync)(d.eventsPath, (0, import_node_path16.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
15806
- const kept = (0, import_node_fs17.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
16266
+ if (!(0, import_node_fs20.existsSync)(d.eventsPath)) return;
16267
+ if ((0, import_node_fs20.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
16268
+ (0, import_node_fs20.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
16269
+ (0, import_node_fs20.renameSync)(d.eventsPath, (0, import_node_path18.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
16270
+ const kept = (0, import_node_fs20.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15807
16271
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
15808
16272
  try {
15809
- (0, import_node_fs17.renameSync)((0, import_node_path16.join)(d.rotatedDir, stale), (0, import_node_path16.join)(d.rotatedDir, `${stale}.pruned`));
16273
+ (0, import_node_fs20.renameSync)((0, import_node_path18.join)(d.rotatedDir, stale), (0, import_node_path18.join)(d.rotatedDir, `${stale}.pruned`));
15810
16274
  } catch {
15811
16275
  }
15812
16276
  }
@@ -15815,9 +16279,9 @@ function rotateIfNeeded2(d) {
15815
16279
  }
15816
16280
 
15817
16281
  // src/lib/dossier/fold-dossier.ts
15818
- var import_node_crypto5 = require("node:crypto");
15819
- var import_node_fs18 = require("node:fs");
15820
- var import_node_path17 = require("node:path");
16282
+ var import_node_crypto6 = require("node:crypto");
16283
+ var import_node_fs21 = require("node:fs");
16284
+ var import_node_path19 = require("node:path");
15821
16285
  var EMPTY_CAPABILITIES = () => ({
15822
16286
  human_reachable: { value: "unknown", tier: "unknown" },
15823
16287
  authorship_observability: { value: "unknown", tier: "unknown" },
@@ -15868,12 +16332,12 @@ function foldDossier(d, opts = {}) {
15868
16332
  }
15869
16333
  };
15870
16334
  try {
15871
- if ((0, import_node_fs18.existsSync)(d.rotatedDir)) {
15872
- const files = (0, import_node_fs18.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
16335
+ if ((0, import_node_fs21.existsSync)(d.rotatedDir)) {
16336
+ const files = (0, import_node_fs21.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
15873
16337
  state.meta.rotations = files.length;
15874
16338
  for (const f of files) {
15875
16339
  try {
15876
- ingest((0, import_node_fs18.readFileSync)((0, import_node_path17.join)(d.rotatedDir, f), "utf8"));
16340
+ ingest((0, import_node_fs21.readFileSync)((0, import_node_path19.join)(d.rotatedDir, f), "utf8"));
15877
16341
  } catch {
15878
16342
  state.meta.dropped_lines++;
15879
16343
  }
@@ -15882,9 +16346,9 @@ function foldDossier(d, opts = {}) {
15882
16346
  } catch {
15883
16347
  }
15884
16348
  try {
15885
- if ((0, import_node_fs18.existsSync)(d.eventsPath)) {
15886
- state.meta.upto_offset = (0, import_node_fs18.statSync)(d.eventsPath).size;
15887
- ingest((0, import_node_fs18.readFileSync)(d.eventsPath, "utf8"));
16349
+ if ((0, import_node_fs21.existsSync)(d.eventsPath)) {
16350
+ state.meta.upto_offset = (0, import_node_fs21.statSync)(d.eventsPath).size;
16351
+ ingest((0, import_node_fs21.readFileSync)(d.eventsPath, "utf8"));
15888
16352
  }
15889
16353
  } catch {
15890
16354
  }
@@ -15907,7 +16371,7 @@ function reduce(state, events, now) {
15907
16371
  state.meta.seq = Math.max(state.meta.seq, ev.seq);
15908
16372
  switch (ev.k) {
15909
16373
  case "goal": {
15910
- const hash = (0, import_node_crypto5.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
16374
+ const hash = (0, import_node_crypto6.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
15911
16375
  const prev = state.goal[state.goal.length - 1];
15912
16376
  if (prev && prev.hash === hash) {
15913
16377
  prev.repeats = (prev.repeats ?? 0) + 1;
@@ -16155,7 +16619,7 @@ function applyBounds(state, input) {
16155
16619
  }
16156
16620
 
16157
16621
  // src/lib/dossier/cache.ts
16158
- var import_node_fs19 = require("node:fs");
16622
+ var import_node_fs22 = require("node:fs");
16159
16623
  function compactState(s) {
16160
16624
  const ms = (iso) => Date.parse(iso) || 0;
16161
16625
  return {
@@ -16284,20 +16748,20 @@ function encodeState(s) {
16284
16748
  function writeFoldCache(d, state) {
16285
16749
  try {
16286
16750
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
16287
- (0, import_node_fs19.writeFileSync)(tmp, encodeState(state), { mode: 384 });
16288
- (0, import_node_fs19.renameSync)(tmp, d.foldPath);
16751
+ (0, import_node_fs22.writeFileSync)(tmp, encodeState(state), { mode: 384 });
16752
+ (0, import_node_fs22.renameSync)(tmp, d.foldPath);
16289
16753
  } catch {
16290
16754
  }
16291
16755
  }
16292
16756
  function readFoldCache(d) {
16293
16757
  try {
16294
- if (!(0, import_node_fs19.existsSync)(d.foldPath)) return null;
16295
- const raw = JSON.parse((0, import_node_fs19.readFileSync)(d.foldPath, "utf8"));
16758
+ if (!(0, import_node_fs22.existsSync)(d.foldPath)) return null;
16759
+ const raw = JSON.parse((0, import_node_fs22.readFileSync)(d.foldPath, "utf8"));
16296
16760
  if (raw?.v !== 1) return null;
16297
16761
  const cached2 = expandState(raw);
16298
16762
  if (!cached2?.meta) return null;
16299
- const size = (0, import_node_fs19.existsSync)(d.eventsPath) ? (0, import_node_fs19.statSync)(d.eventsPath).size : 0;
16300
- const rotations = (0, import_node_fs19.existsSync)(d.rotatedDir) ? (0, import_node_fs19.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
16763
+ const size = (0, import_node_fs22.existsSync)(d.eventsPath) ? (0, import_node_fs22.statSync)(d.eventsPath).size : 0;
16764
+ const rotations = (0, import_node_fs22.existsSync)(d.rotatedDir) ? (0, import_node_fs22.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
16301
16765
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
16302
16766
  return cached2;
16303
16767
  } catch {
@@ -16347,14 +16811,14 @@ function assessContinuity(i) {
16347
16811
  }
16348
16812
 
16349
16813
  // src/lib/dossier/reanchor.ts
16350
- var import_node_crypto6 = require("node:crypto");
16351
- var import_node_fs20 = require("node:fs");
16814
+ var import_node_crypto7 = require("node:crypto");
16815
+ var import_node_fs23 = require("node:fs");
16352
16816
  function lineSha(text) {
16353
- return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
16817
+ return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
16354
16818
  }
16355
16819
  function fileHash(path) {
16356
16820
  try {
16357
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs20.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
16821
+ return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs23.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
16358
16822
  } catch {
16359
16823
  return null;
16360
16824
  }
@@ -16726,20 +17190,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
16726
17190
  let sessions = 0;
16727
17191
  try {
16728
17192
  const dir = treeDir(identity);
16729
- if (!(0, import_node_fs21.existsSync)(dir)) return { paths: [], sessions: 0 };
16730
- for (const entry of (0, import_node_fs21.readdirSync)(dir, { withFileTypes: true })) {
17193
+ if (!(0, import_node_fs24.existsSync)(dir)) return { paths: [], sessions: 0 };
17194
+ for (const entry of (0, import_node_fs24.readdirSync)(dir, { withFileTypes: true })) {
16731
17195
  if (!entry.isDirectory()) continue;
16732
17196
  if (entry.name === identity.sessionKey) continue;
16733
- const log = (0, import_node_path18.join)(dir, entry.name, "events.jsonl");
17197
+ const log = (0, import_node_path20.join)(dir, entry.name, "events.jsonl");
16734
17198
  try {
16735
- if (!(0, import_node_fs21.existsSync)(log)) continue;
16736
- if (now - (0, import_node_fs21.statSync)(log).mtimeMs > windowMs) continue;
17199
+ if (!(0, import_node_fs24.existsSync)(log)) continue;
17200
+ if (now - (0, import_node_fs24.statSync)(log).mtimeMs > windowMs) continue;
16737
17201
  const sib = {
16738
- dir: (0, import_node_path18.join)(dir, entry.name),
17202
+ dir: (0, import_node_path20.join)(dir, entry.name),
16739
17203
  identity,
16740
17204
  eventsPath: log,
16741
- foldPath: (0, import_node_path18.join)(dir, entry.name, "fold.json"),
16742
- rotatedDir: (0, import_node_path18.join)(dir, entry.name, "rotated")
17205
+ foldPath: (0, import_node_path20.join)(dir, entry.name, "fold.json"),
17206
+ rotatedDir: (0, import_node_path20.join)(dir, entry.name, "rotated")
16743
17207
  };
16744
17208
  const state = readFoldCache(sib) ?? foldDossier(sib);
16745
17209
  sessions++;
@@ -16767,25 +17231,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16767
17231
  let removed = 0;
16768
17232
  try {
16769
17233
  const mine = dossierDir(identity);
16770
- const userDir = (0, import_node_path18.dirname)((0, import_node_path18.dirname)(mine));
16771
- if (!(0, import_node_fs21.existsSync)(userDir)) return 0;
17234
+ const userDir = (0, import_node_path20.dirname)((0, import_node_path20.dirname)(mine));
17235
+ if (!(0, import_node_fs24.existsSync)(userDir)) return 0;
16772
17236
  const cutoff = Date.now() - maxAgeMs;
16773
- for (const tree of (0, import_node_fs21.readdirSync)(userDir, { withFileTypes: true })) {
17237
+ for (const tree of (0, import_node_fs24.readdirSync)(userDir, { withFileTypes: true })) {
16774
17238
  if (!tree.isDirectory()) continue;
16775
- const treePath = (0, import_node_path18.join)(userDir, tree.name);
17239
+ const treePath = (0, import_node_path20.join)(userDir, tree.name);
16776
17240
  let live = 0;
16777
- for (const entry of (0, import_node_fs21.readdirSync)(treePath, { withFileTypes: true })) {
17241
+ for (const entry of (0, import_node_fs24.readdirSync)(treePath, { withFileTypes: true })) {
16778
17242
  if (!entry.isDirectory()) continue;
16779
- const dir = (0, import_node_path18.join)(treePath, entry.name);
17243
+ const dir = (0, import_node_path20.join)(treePath, entry.name);
16780
17244
  if (dir === mine) {
16781
17245
  live++;
16782
17246
  continue;
16783
17247
  }
16784
17248
  try {
16785
- const log = (0, import_node_path18.join)(dir, "events.jsonl");
16786
- const at = (0, import_node_fs21.existsSync)(log) ? (0, import_node_fs21.statSync)(log).mtimeMs : (0, import_node_fs21.statSync)(dir).mtimeMs;
17249
+ const log = (0, import_node_path20.join)(dir, "events.jsonl");
17250
+ const at = (0, import_node_fs24.existsSync)(log) ? (0, import_node_fs24.statSync)(log).mtimeMs : (0, import_node_fs24.statSync)(dir).mtimeMs;
16787
17251
  if (at < cutoff) {
16788
- (0, import_node_fs21.rmSync)(dir, { recursive: true, force: true });
17252
+ (0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
16789
17253
  removed++;
16790
17254
  } else {
16791
17255
  live++;
@@ -16795,7 +17259,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
16795
17259
  }
16796
17260
  if (live === 0) {
16797
17261
  try {
16798
- (0, import_node_fs21.rmSync)(treePath, { recursive: false, force: false });
17262
+ (0, import_node_fs24.rmSync)(treePath, { recursive: false, force: false });
16799
17263
  } catch {
16800
17264
  }
16801
17265
  }
@@ -16812,8 +17276,8 @@ function sessionDossier(token, sessionId) {
16812
17276
  }
16813
17277
  function hasActiveGoal(d) {
16814
17278
  try {
16815
- if (!(0, import_node_fs21.existsSync)(d.eventsPath)) return false;
16816
- return (0, import_node_fs21.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
17279
+ if (!(0, import_node_fs24.existsSync)(d.eventsPath)) return false;
17280
+ return (0, import_node_fs24.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
16817
17281
  } catch {
16818
17282
  return false;
16819
17283
  }
@@ -16837,7 +17301,7 @@ function recordTurn(d, t) {
16837
17301
  for (const a of t.authored) {
16838
17302
  const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
16839
17303
  const prior = t.known?.authored?.get(a.p);
16840
- const hash = fileHash((0, import_node_path18.join)(root, a.p));
17304
+ const hash = fileHash((0, import_node_path20.join)(root, a.p));
16841
17305
  const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
16842
17306
  const adds = Math.max(0, a.a - (prior?.adds ?? 0));
16843
17307
  const dels = Math.max(0, a.d - (prior?.dels ?? 0));
@@ -16851,7 +17315,7 @@ function recordTurn(d, t) {
16851
17315
  // Identity is the COMMAND, not its category — otherwise `npm test -- a` and
16852
17316
  // `npm test -- b` are one row and the streak counts two different commands
16853
17317
  // as a run of one.
16854
- cmd_hash: (0, import_node_crypto7.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
17318
+ cmd_hash: (0, import_node_crypto8.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
16855
17319
  head: c.head || c.class,
16856
17320
  status: toStatus(c.last_status)
16857
17321
  });
@@ -16870,7 +17334,7 @@ function recordTurn(d, t) {
16870
17334
  }
16871
17335
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
16872
17336
  for (const u of t.unobserved) {
16873
- const hash = fileHash((0, import_node_path18.join)(root, u.p));
17337
+ const hash = fileHash((0, import_node_path20.join)(root, u.p));
16874
17338
  if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
16875
17339
  appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
16876
17340
  }
@@ -16905,8 +17369,8 @@ function recordVerdict(d, v) {
16905
17369
  if (!sent.has(f.file)) continue;
16906
17370
  if (!lines.has(f.file)) {
16907
17371
  try {
16908
- const abs = (0, import_node_path18.join)(root, f.file);
16909
- lines.set(f.file, (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null);
17372
+ const abs = (0, import_node_path20.join)(root, f.file);
17373
+ lines.set(f.file, (0, import_node_fs24.existsSync)(abs) ? (0, import_node_fs24.readFileSync)(abs, "utf8").split("\n") : null);
16910
17374
  } catch {
16911
17375
  lines.set(f.file, null);
16912
17376
  }
@@ -17006,8 +17470,8 @@ function recallMemory(d, identity, opts) {
17006
17470
  budgetBytes: opts.budgetBytes,
17007
17471
  readFileLines: (file) => {
17008
17472
  try {
17009
- const abs = (0, import_node_path18.join)(root, file);
17010
- return (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null;
17473
+ const abs = (0, import_node_path20.join)(root, file);
17474
+ return (0, import_node_fs24.existsSync)(abs) ? (0, import_node_fs24.readFileSync)(abs, "utf8").split("\n") : null;
17011
17475
  } catch {
17012
17476
  return null;
17013
17477
  }
@@ -17026,6 +17490,9 @@ function recallMemory(d, identity, opts) {
17026
17490
  }
17027
17491
 
17028
17492
  // src/commands/intent.ts
17493
+ var MAX_PROMPT_EVENT_BYTES = 2 * 1024 * 1024;
17494
+ var MAX_PROMPT_CHARS2 = 2e5;
17495
+ var SESSION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
17029
17496
  function registerIntentCommands(program2) {
17030
17497
  const intent = program2.command("intent").description("Manage intent capture");
17031
17498
  intent.command("capture").description("Capture user intent from stdin (used by UserPromptSubmit hook)").action(async () => {
@@ -17039,16 +17506,24 @@ function registerIntentCommands(program2) {
17039
17506
  process.exit(0);
17040
17507
  }
17041
17508
  const chunks = [];
17509
+ let size = 0;
17042
17510
  for await (const chunk of process.stdin) {
17043
- chunks.push(chunk);
17511
+ size += chunk.length;
17512
+ if (size <= MAX_PROMPT_EVENT_BYTES) chunks.push(chunk);
17044
17513
  }
17045
- const input = Buffer.concat(chunks).toString("utf-8").trim();
17514
+ const input = size > MAX_PROMPT_EVENT_BYTES ? "" : Buffer.concat(chunks).toString("utf-8").trim();
17046
17515
  if (!input) {
17047
17516
  process.exit(0);
17048
17517
  }
17049
- let event;
17518
+ let event = {};
17050
17519
  try {
17051
- event = JSON.parse(input);
17520
+ const parsed = JSON.parse(input);
17521
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) process.exit(0);
17522
+ const o = parsed;
17523
+ event = {
17524
+ prompt: typeof o.prompt === "string" ? o.prompt.slice(0, MAX_PROMPT_CHARS2) : void 0,
17525
+ session_id: typeof o.session_id === "string" && SESSION_ID_RE.test(o.session_id) ? o.session_id : void 0
17526
+ };
17052
17527
  } catch {
17053
17528
  process.exit(0);
17054
17529
  }
@@ -17077,6 +17552,19 @@ function registerIntentCommands(program2) {
17077
17552
  const injection = await retrieveForInjection(prompt);
17078
17553
  if (injection) {
17079
17554
  process.stdout.write(injection.contextBlock);
17555
+ recordInjection({
17556
+ ts: Date.now(),
17557
+ session_id: scopeSession || null,
17558
+ prompt_hash: hashPrompt(prompt),
17559
+ arm: "injected",
17560
+ eligible: injection.eligible,
17561
+ tokens: injection.tokensUsed,
17562
+ nodes: injection.nodes.map((n) => ({
17563
+ id: n.nodeId,
17564
+ score: Math.round(n.score * 1e3) / 1e3,
17565
+ via: `${n.fileGlobs.length ? "g" : ""}${n.scope === "org" ? "o" : ""}x`
17566
+ }))
17567
+ });
17080
17568
  }
17081
17569
  } catch {
17082
17570
  }
@@ -17085,179 +17573,87 @@ function registerIntentCommands(program2) {
17085
17573
  error: err.message?.slice(0, 200) ?? "unknown"
17086
17574
  });
17087
17575
  });
17088
- } catch {
17089
- }
17090
- process.exit(0);
17091
- });
17092
- intent.command("classify-body").description("Output JSON body for POST /classify-task (internal, used by hooks)").requiredOption("--session-id <id>", "Session ID").requiredOption("--prompt <text>", "User prompt").requiredOption("--prompt-hash <hash>", "SHA-256 hash of the prompt").action((opts) => {
17093
- const body = JSON.stringify({
17094
- session_id: opts.sessionId,
17095
- user_prompt: opts.prompt.slice(0, 4e3),
17096
- user_prompt_hash: opts.promptHash
17097
- });
17098
- process.stdout.write(body);
17099
- });
17100
- }
17101
- async function fireClassify(prompt, sessionId, globals) {
17102
- if (!sessionId) {
17103
- logEvent("classify_skipped", { reason: "no_session_id" });
17104
- return;
17105
- }
17106
- const tokenResult = await resolveToken(globals?.token);
17107
- if (!tokenResult.ok) {
17108
- logEvent("classify_skipped", { reason: "no_token", detail: tokenResult.error });
17109
- return;
17110
- }
17111
- const urlResult = await resolveServiceUrl(globals?.serviceUrl);
17112
- if (!urlResult.ok) {
17113
- logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
17114
- return;
17115
- }
17116
- const promptHash = (0, import_node_crypto8.createHash)("sha256").update(prompt).digest("hex");
17117
- const result = await apiRequest({
17118
- method: "POST",
17119
- path: "/classify-task",
17120
- serviceUrl: urlResult.data,
17121
- token: tokenResult.data.token,
17122
- body: {
17123
- session_id: sessionId,
17124
- user_prompt: prompt.slice(0, 4e3),
17125
- user_prompt_hash: promptHash
17126
- },
17127
- timeout: 4e3,
17128
- cmd: "classify"
17129
- });
17130
- if (!result.ok) {
17131
- logEvent("classify_failed", {
17132
- category: result.category,
17133
- http_status: result.http_status ?? null,
17134
- error: result.error?.slice(0, 200) ?? "unknown",
17135
- prompt_len: prompt.length
17136
- });
17137
- return;
17138
- }
17139
- const classificationId = result.data.classification_id;
17140
- const status = result.data.status;
17141
- logEvent("classify_accepted", {
17142
- classification_id: classificationId ?? null,
17143
- status: status ?? null,
17144
- prompt_len: prompt.length
17145
- });
17146
- const decidedTaskId = result.data.decided_task_id;
17147
- if (decidedTaskId) {
17148
- appendPromptToTaskBuffer(decidedTaskId, prompt, sessionId).catch(() => {
17149
- });
17150
- }
17151
- }
17152
-
17153
- // src/commands/lifecycle.ts
17154
- var import_node_fs25 = require("node:fs");
17155
- var import_node_path23 = require("node:path");
17156
-
17157
- // src/lib/baseline.ts
17158
- var import_node_fs24 = require("node:fs");
17159
- var import_node_path22 = require("node:path");
17160
- var import_node_crypto9 = require("node:crypto");
17161
-
17162
- // src/lib/snapshot.ts
17163
- var import_node_fs23 = require("node:fs");
17164
- var import_node_path21 = require("node:path");
17165
- var import_node_child_process7 = require("node:child_process");
17166
-
17167
- // src/lib/files.ts
17168
- var import_node_path20 = require("node:path");
17169
-
17170
- // src/lib/safe-read.ts
17171
- var import_node_fs22 = require("node:fs");
17172
- var import_node_path19 = require("node:path");
17173
- var FLAGS = import_node_fs22.constants;
17174
- var NOFOLLOW = FLAGS.O_NOFOLLOW;
17175
- var NONBLOCK = FLAGS.O_NONBLOCK;
17176
- function closeOpened(fd) {
17177
- try {
17178
- (0, import_node_fs22.closeSync)(fd);
17179
- } catch {
17180
- }
17181
- }
17182
- function isInsideRoot(realRoot, realPath) {
17183
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path19.sep) ? realRoot : realRoot + import_node_path19.sep);
17184
- }
17185
- function sameOpenedFile(opened, current, nofollowAvailable) {
17186
- if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
17187
- return opened.ino === current.ino && opened.dev === current.dev;
17188
- }
17189
- function openRegularInRoot(root, path) {
17190
- const full = (0, import_node_path19.isAbsolute)(path) ? path : (0, import_node_path19.join)(root, path);
17191
- let fd;
17192
- try {
17193
- fd = (0, import_node_fs22.openSync)(full, import_node_fs22.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
17194
- } catch (err) {
17195
- const code = err.code;
17196
- if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
17197
- if (code === "ENOENT" || code === "ENOTDIR") return { ok: false, reason: "missing" };
17198
- return { ok: false, reason: "unreadable" };
17199
- }
17200
- try {
17201
- const opened = (0, import_node_fs22.fstatSync)(fd, { bigint: true });
17202
- if (!opened.isFile()) {
17203
- closeOpened(fd);
17204
- return { ok: false, reason: "not-regular" };
17205
- }
17206
- const realRoot = import_node_fs22.realpathSync.native(root);
17207
- const realPath = import_node_fs22.realpathSync.native(full);
17208
- if (!isInsideRoot(realRoot, realPath)) {
17209
- closeOpened(fd);
17210
- return { ok: false, reason: "outside-root" };
17211
- }
17212
- const current = (0, import_node_fs22.statSync)(realPath, { bigint: true });
17213
- if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
17214
- closeOpened(fd);
17215
- return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
17216
- }
17217
- return { ok: true, fd, size: Number(opened.size), mtimeMs: Number(opened.mtimeMs) };
17218
- } catch {
17219
- closeOpened(fd);
17220
- return { ok: false, reason: "unreadable" };
17221
- }
17222
- }
17223
- function statRegularInRoot(root, path) {
17224
- const opened = openRegularInRoot(root, path);
17225
- if (!opened.ok) return opened;
17226
- closeOpened(opened.fd);
17227
- return { ok: true, size: opened.size, mtimeMs: opened.mtimeMs };
17228
- }
17229
- function readOpened(fd, size) {
17230
- try {
17231
- const buffer = Buffer.alloc(size);
17232
- let offset = 0;
17233
- while (offset < size) {
17234
- const n = (0, import_node_fs22.readSync)(fd, buffer, offset, size - offset, offset);
17235
- if (n === 0) break;
17236
- offset += n;
17576
+ } catch {
17237
17577
  }
17238
- return buffer.subarray(0, offset);
17239
- } finally {
17240
- closeOpened(fd);
17241
- }
17242
- }
17243
- function readOpenedUtf8(fd, size) {
17244
- return readOpened(fd, size).toString("utf-8");
17578
+ process.exit(0);
17579
+ });
17580
+ intent.command("classify-body").description("Output JSON body for POST /classify-task (internal, used by hooks)").requiredOption("--session-id <id>", "Session ID").requiredOption("--prompt <text>", "User prompt").requiredOption("--prompt-hash <hash>", "SHA-256 hash of the prompt").action((opts) => {
17581
+ const body = JSON.stringify({
17582
+ session_id: opts.sessionId,
17583
+ user_prompt: opts.prompt.slice(0, 4e3),
17584
+ user_prompt_hash: opts.promptHash
17585
+ });
17586
+ process.stdout.write(body);
17587
+ });
17245
17588
  }
17246
- function readRegularFileInRoot(root, path, maxBytes) {
17247
- const opened = openRegularInRoot(root, path);
17248
- if (!opened.ok) return opened;
17249
- if (opened.size > maxBytes) {
17250
- closeOpened(opened.fd);
17251
- return { ok: false, reason: "too-large", size: opened.size };
17589
+ async function fireClassify(prompt, sessionId, globals) {
17590
+ if (!sessionId) {
17591
+ logEvent("classify_skipped", { reason: "no_session_id" });
17592
+ return;
17252
17593
  }
17253
- try {
17254
- return { ok: true, content: readOpenedUtf8(opened.fd, opened.size), size: opened.size };
17255
- } catch {
17256
- return { ok: false, reason: "unreadable" };
17594
+ const tokenResult = await resolveToken(globals?.token);
17595
+ if (!tokenResult.ok) {
17596
+ logEvent("classify_skipped", { reason: "no_token", detail: tokenResult.error });
17597
+ return;
17598
+ }
17599
+ const urlResult = await resolveServiceUrl(globals?.serviceUrl);
17600
+ if (!urlResult.ok) {
17601
+ logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
17602
+ return;
17603
+ }
17604
+ const promptHash = (0, import_node_crypto9.createHash)("sha256").update(prompt).digest("hex");
17605
+ const result = await apiRequest({
17606
+ method: "POST",
17607
+ path: "/classify-task",
17608
+ serviceUrl: urlResult.data,
17609
+ token: tokenResult.data.token,
17610
+ body: {
17611
+ session_id: sessionId,
17612
+ user_prompt: prompt.slice(0, 4e3),
17613
+ user_prompt_hash: promptHash
17614
+ },
17615
+ timeout: 4e3,
17616
+ cmd: "classify"
17617
+ });
17618
+ if (!result.ok) {
17619
+ logEvent("classify_failed", {
17620
+ category: result.category,
17621
+ http_status: result.http_status ?? null,
17622
+ error: result.error?.slice(0, 200) ?? "unknown",
17623
+ prompt_len: prompt.length
17624
+ });
17625
+ return;
17626
+ }
17627
+ const classificationId = result.data.classification_id;
17628
+ const status = result.data.status;
17629
+ logEvent("classify_accepted", {
17630
+ classification_id: classificationId ?? null,
17631
+ status: status ?? null,
17632
+ prompt_len: prompt.length
17633
+ });
17634
+ const decidedTaskId = result.data.decided_task_id;
17635
+ if (decidedTaskId) {
17636
+ appendPromptToTaskBuffer(decidedTaskId, prompt, sessionId).catch(() => {
17637
+ });
17257
17638
  }
17258
17639
  }
17259
17640
 
17641
+ // src/commands/lifecycle.ts
17642
+ var import_node_fs27 = require("node:fs");
17643
+ var import_node_path24 = require("node:path");
17644
+
17645
+ // src/lib/baseline.ts
17646
+ var import_node_fs26 = require("node:fs");
17647
+ var import_node_path23 = require("node:path");
17648
+ var import_node_crypto10 = require("node:crypto");
17649
+
17650
+ // src/lib/snapshot.ts
17651
+ var import_node_fs25 = require("node:fs");
17652
+ var import_node_path22 = require("node:path");
17653
+ var import_node_child_process7 = require("node:child_process");
17654
+
17260
17655
  // src/lib/files.ts
17656
+ var import_node_path21 = require("node:path");
17261
17657
  var LANG_MAP = {
17262
17658
  // Analyzable (static analysis + Gemini)
17263
17659
  ts: "typescript",
@@ -17325,7 +17721,7 @@ var LANG_MAP = {
17325
17721
  mk: "make"
17326
17722
  };
17327
17723
  function detectLanguage(filepath) {
17328
- const ext = (0, import_node_path20.extname)(filepath).slice(1);
17724
+ const ext = (0, import_node_path21.extname)(filepath).slice(1);
17329
17725
  return LANG_MAP[ext] ?? ext;
17330
17726
  }
17331
17727
  function sortByMtime(files) {
@@ -17416,16 +17812,16 @@ function collectCodeDelta(files, opts) {
17416
17812
 
17417
17813
  // src/lib/snapshot.ts
17418
17814
  function generateSnapshotDiffs(files) {
17419
- if (!(0, import_node_fs23.existsSync)(SNAPSHOT_DIR)) {
17815
+ if (!(0, import_node_fs25.existsSync)(SNAPSHOT_DIR)) {
17420
17816
  return { diffs: [], has_snapshots: false };
17421
17817
  }
17422
17818
  const diffs = [];
17423
17819
  for (const file of files) {
17424
17820
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
17425
- const snapshotPath = (0, import_node_path21.join)(SNAPSHOT_DIR, file.path);
17821
+ const snapshotPath = (0, import_node_path22.join)(SNAPSHOT_DIR, file.path);
17426
17822
  const language = file.language ?? detectLanguage(file.path);
17427
- if ((0, import_node_fs23.existsSync)(snapshotPath)) {
17428
- const oldContent = (0, import_node_fs23.readFileSync)(snapshotPath, "utf-8");
17823
+ if ((0, import_node_fs25.existsSync)(snapshotPath)) {
17824
+ const oldContent = (0, import_node_fs25.readFileSync)(snapshotPath, "utf-8");
17429
17825
  if (oldContent === file.content) continue;
17430
17826
  const diff = computeDiff(oldContent, file.content, file.path);
17431
17827
  if (diff) {
@@ -17450,20 +17846,20 @@ function saveSnapshots(files) {
17450
17846
  const snapshotPaths = /* @__PURE__ */ new Set();
17451
17847
  for (const file of files) {
17452
17848
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
17453
- const snapshotPath = (0, import_node_path21.join)(SNAPSHOT_DIR, file.path);
17849
+ const snapshotPath = (0, import_node_path22.join)(SNAPSHOT_DIR, file.path);
17454
17850
  snapshotPaths.add(snapshotPath);
17455
- (0, import_node_fs23.mkdirSync)((0, import_node_path21.dirname)(snapshotPath), { recursive: true });
17456
- (0, import_node_fs23.writeFileSync)(snapshotPath, file.content);
17851
+ (0, import_node_fs25.mkdirSync)((0, import_node_path22.dirname)(snapshotPath), { recursive: true });
17852
+ (0, import_node_fs25.writeFileSync)(snapshotPath, file.content);
17457
17853
  }
17458
17854
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
17459
17855
  }
17460
17856
  function computeDiff(oldContent, newContent, filePath) {
17461
- const tmpOld = (0, import_node_path21.join)(SNAPSHOT_DIR, ".diff-old.tmp");
17462
- const tmpNew = (0, import_node_path21.join)(SNAPSHOT_DIR, ".diff-new.tmp");
17857
+ const tmpOld = (0, import_node_path22.join)(SNAPSHOT_DIR, ".diff-old.tmp");
17858
+ const tmpNew = (0, import_node_path22.join)(SNAPSHOT_DIR, ".diff-new.tmp");
17463
17859
  try {
17464
- (0, import_node_fs23.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
17465
- (0, import_node_fs23.writeFileSync)(tmpOld, oldContent);
17466
- (0, import_node_fs23.writeFileSync)(tmpNew, newContent);
17860
+ (0, import_node_fs25.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
17861
+ (0, import_node_fs25.writeFileSync)(tmpOld, oldContent);
17862
+ (0, import_node_fs25.writeFileSync)(tmpNew, newContent);
17467
17863
  const result = (0, import_node_child_process7.execSync)(
17468
17864
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
17469
17865
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -17477,32 +17873,32 @@ function computeDiff(oldContent, newContent, filePath) {
17477
17873
  return null;
17478
17874
  } finally {
17479
17875
  try {
17480
- (0, import_node_fs23.unlinkSync)(tmpOld);
17876
+ (0, import_node_fs25.unlinkSync)(tmpOld);
17481
17877
  } catch {
17482
17878
  }
17483
17879
  try {
17484
- (0, import_node_fs23.unlinkSync)(tmpNew);
17880
+ (0, import_node_fs25.unlinkSync)(tmpNew);
17485
17881
  } catch {
17486
17882
  }
17487
17883
  }
17488
17884
  }
17489
17885
  function cleanStaleSnapshots(dir, keepSet) {
17490
- if (!(0, import_node_fs23.existsSync)(dir)) return;
17886
+ if (!(0, import_node_fs25.existsSync)(dir)) return;
17491
17887
  try {
17492
- const entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
17888
+ const entries = (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true });
17493
17889
  for (const entry of entries) {
17494
17890
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
17495
- const fullPath = (0, import_node_path21.join)(dir, entry.name);
17891
+ const fullPath = (0, import_node_path22.join)(dir, entry.name);
17496
17892
  if (entry.isDirectory()) {
17497
17893
  cleanStaleSnapshots(fullPath, keepSet);
17498
17894
  try {
17499
- const remaining = (0, import_node_fs23.readdirSync)(fullPath);
17500
- if (remaining.length === 0) (0, import_node_fs23.rmdirSync)(fullPath);
17895
+ const remaining = (0, import_node_fs25.readdirSync)(fullPath);
17896
+ if (remaining.length === 0) (0, import_node_fs25.rmdirSync)(fullPath);
17501
17897
  } catch {
17502
17898
  }
17503
17899
  } else if (!keepSet.has(fullPath)) {
17504
17900
  try {
17505
- (0, import_node_fs23.unlinkSync)(fullPath);
17901
+ (0, import_node_fs25.unlinkSync)(fullPath);
17506
17902
  } catch {
17507
17903
  }
17508
17904
  }
@@ -17518,23 +17914,23 @@ var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
17518
17914
  var DEFAULT_SESSION_KEY = "_default";
17519
17915
  function sessionKey(sessionId) {
17520
17916
  if (!sessionId) return DEFAULT_SESSION_KEY;
17521
- return (0, import_node_crypto9.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
17917
+ return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
17522
17918
  }
17523
17919
  function sessionDir(key) {
17524
- return (0, import_node_path22.join)(projectPath(BASELINE_DIR), key);
17920
+ return (0, import_node_path23.join)(projectPath(BASELINE_DIR), key);
17525
17921
  }
17526
17922
  function manifestPath(dir) {
17527
- return (0, import_node_path22.join)(dir, "manifest.json");
17923
+ return (0, import_node_path23.join)(dir, "manifest.json");
17528
17924
  }
17529
17925
  function mirrorPath(dir, repoRelPath) {
17530
- return (0, import_node_path22.join)(dir, "files", repoRelPath);
17926
+ return (0, import_node_path23.join)(dir, "files", repoRelPath);
17531
17927
  }
17532
17928
  var CARRY_FILE = `${BASELINE_DIR}/.carry`;
17533
17929
  var CARRY_WINDOW_MS = 12e4;
17534
17930
  function writeCarry(sessionId, headSha) {
17535
17931
  try {
17536
- (0, import_node_fs24.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
17537
- (0, import_node_fs24.writeFileSync)(
17932
+ (0, import_node_fs26.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
17933
+ (0, import_node_fs26.writeFileSync)(
17538
17934
  projectPath(CARRY_FILE),
17539
17935
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
17540
17936
  );
@@ -17544,10 +17940,10 @@ function writeCarry(sessionId, headSha) {
17544
17940
  function claimCarry(newKey) {
17545
17941
  const carryPath = projectPath(CARRY_FILE);
17546
17942
  try {
17547
- if (!(0, import_node_fs24.existsSync)(carryPath)) return null;
17548
- const carry = JSON.parse((0, import_node_fs24.readFileSync)(carryPath, "utf-8"));
17943
+ if (!(0, import_node_fs26.existsSync)(carryPath)) return null;
17944
+ const carry = JSON.parse((0, import_node_fs26.readFileSync)(carryPath, "utf-8"));
17549
17945
  try {
17550
- (0, import_node_fs24.rmSync)(carryPath, { force: true });
17946
+ (0, import_node_fs26.rmSync)(carryPath, { force: true });
17551
17947
  } catch {
17552
17948
  }
17553
17949
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -17558,11 +17954,11 @@ function claimCarry(newKey) {
17558
17954
  if (!prior) return null;
17559
17955
  const toDir = sessionDir(newKey);
17560
17956
  try {
17561
- (0, import_node_fs24.rmSync)(toDir, { recursive: true, force: true });
17957
+ (0, import_node_fs26.rmSync)(toDir, { recursive: true, force: true });
17562
17958
  } catch {
17563
17959
  }
17564
- (0, import_node_fs24.renameSync)(fromDir, toDir);
17565
- (0, import_node_fs24.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
17960
+ (0, import_node_fs26.renameSync)(fromDir, toDir);
17961
+ (0, import_node_fs26.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
17566
17962
  return readManifest(toDir);
17567
17963
  } catch {
17568
17964
  return null;
@@ -17586,21 +17982,21 @@ function captureBaseline(opts = {}) {
17586
17982
  const head_sha = getCurrentCommit();
17587
17983
  const dirty = getDirtyFiles();
17588
17984
  try {
17589
- (0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
17985
+ (0, import_node_fs26.rmSync)(dir, { recursive: true, force: true });
17590
17986
  } catch {
17591
17987
  }
17592
- const filesDir = (0, import_node_path22.join)(dir, "files");
17988
+ const filesDir = (0, import_node_path23.join)(dir, "files");
17593
17989
  const mirrored = [];
17594
17990
  try {
17595
- (0, import_node_fs24.mkdirSync)(filesDir, { recursive: true });
17991
+ (0, import_node_fs26.mkdirSync)(filesDir, { recursive: true });
17596
17992
  for (const p of dirty) {
17597
17993
  if (p.includes("..")) continue;
17598
17994
  const content = safeReadForMirror(projectPath(p));
17599
17995
  if (content === null) continue;
17600
17996
  const dest = mirrorPath(dir, p);
17601
17997
  try {
17602
- (0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(dest), { recursive: true });
17603
- (0, import_node_fs24.writeFileSync)(dest, content);
17998
+ (0, import_node_fs26.mkdirSync)((0, import_node_path23.dirname)(dest), { recursive: true });
17999
+ (0, import_node_fs26.writeFileSync)(dest, content);
17604
18000
  mirrored.push(p);
17605
18001
  } catch {
17606
18002
  }
@@ -17615,8 +18011,8 @@ function captureBaseline(opts = {}) {
17615
18011
  version: BASELINE_VERSION
17616
18012
  };
17617
18013
  try {
17618
- (0, import_node_fs24.mkdirSync)(dir, { recursive: true });
17619
- (0, import_node_fs24.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
18014
+ (0, import_node_fs26.mkdirSync)(dir, { recursive: true });
18015
+ (0, import_node_fs26.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
17620
18016
  } catch {
17621
18017
  }
17622
18018
  pruneOldBaselines();
@@ -17627,9 +18023,9 @@ function readBaseline(sessionId) {
17627
18023
  }
17628
18024
  function readManifest(dir) {
17629
18025
  const mp = manifestPath(dir);
17630
- if (!(0, import_node_fs24.existsSync)(mp)) return null;
18026
+ if (!(0, import_node_fs26.existsSync)(mp)) return null;
17631
18027
  try {
17632
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(mp, "utf-8"));
18028
+ const parsed = JSON.parse((0, import_node_fs26.readFileSync)(mp, "utf-8"));
17633
18029
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
17634
18030
  return null;
17635
18031
  }
@@ -17660,9 +18056,9 @@ function preImage(repoRelPath, baseline) {
17660
18056
  function resolvePreImage(repoRelPath, baseline) {
17661
18057
  if (baseline.dirty_paths.includes(repoRelPath)) {
17662
18058
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
17663
- if ((0, import_node_fs24.existsSync)(mp)) {
18059
+ if ((0, import_node_fs26.existsSync)(mp)) {
17664
18060
  try {
17665
- return { content: (0, import_node_fs24.readFileSync)(mp, "utf-8"), existed: true };
18061
+ return { content: (0, import_node_fs26.readFileSync)(mp, "utf-8"), existed: true };
17666
18062
  } catch {
17667
18063
  }
17668
18064
  }
@@ -17707,8 +18103,8 @@ function absorbIntoBaseline(paths, sessionId) {
17707
18103
  const content = safeReadForMirror(projectPath(p));
17708
18104
  if (content === null) continue;
17709
18105
  const dest = mirrorPath(dir, p);
17710
- (0, import_node_fs24.mkdirSync)((0, import_node_path22.dirname)(dest), { recursive: true });
17711
- (0, import_node_fs24.writeFileSync)(dest, content);
18106
+ (0, import_node_fs26.mkdirSync)((0, import_node_path23.dirname)(dest), { recursive: true });
18107
+ (0, import_node_fs26.writeFileSync)(dest, content);
17712
18108
  dirty.add(p);
17713
18109
  adopted++;
17714
18110
  } catch {
@@ -17717,7 +18113,7 @@ function absorbIntoBaseline(paths, sessionId) {
17717
18113
  if (adopted === 0) return 0;
17718
18114
  try {
17719
18115
  const updated = { ...baseline, dirty_paths: [...dirty] };
17720
- (0, import_node_fs24.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
18116
+ (0, import_node_fs26.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
17721
18117
  preImageCache.delete(baseline);
17722
18118
  } catch {
17723
18119
  return 0;
@@ -17728,7 +18124,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
17728
18124
  const pre = preImage(repoRelPath, baseline);
17729
18125
  let current;
17730
18126
  try {
17731
- current = (0, import_node_fs24.readFileSync)(projectPath(repoRelPath), "utf-8");
18127
+ current = (0, import_node_fs26.readFileSync)(projectPath(repoRelPath), "utf-8");
17732
18128
  } catch {
17733
18129
  return pre.existed;
17734
18130
  }
@@ -17737,8 +18133,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
17737
18133
  }
17738
18134
  function safeReadForMirror(absPath) {
17739
18135
  try {
17740
- if ((0, import_node_fs24.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
17741
- const buf = (0, import_node_fs24.readFileSync)(absPath);
18136
+ if ((0, import_node_fs26.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
18137
+ const buf = (0, import_node_fs26.readFileSync)(absPath);
17742
18138
  if (buf.includes(0)) return null;
17743
18139
  return buf.toString("utf-8");
17744
18140
  } catch {
@@ -17749,18 +18145,18 @@ function pruneOldBaselines() {
17749
18145
  const root = projectPath(BASELINE_DIR);
17750
18146
  let entries;
17751
18147
  try {
17752
- entries = (0, import_node_fs24.readdirSync)(root);
18148
+ entries = (0, import_node_fs26.readdirSync)(root);
17753
18149
  } catch {
17754
18150
  return;
17755
18151
  }
17756
18152
  const now = Date.now();
17757
18153
  for (const name of entries) {
17758
- const dir = (0, import_node_path22.join)(root, name);
18154
+ const dir = (0, import_node_path23.join)(root, name);
17759
18155
  const manifest = readManifest(dir);
17760
18156
  if (!manifest) {
17761
18157
  try {
17762
- if (now - (0, import_node_fs24.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
17763
- (0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
18158
+ if (now - (0, import_node_fs26.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
18159
+ (0, import_node_fs26.rmSync)(dir, { recursive: true, force: true });
17764
18160
  }
17765
18161
  } catch {
17766
18162
  }
@@ -17768,7 +18164,7 @@ function pruneOldBaselines() {
17768
18164
  }
17769
18165
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
17770
18166
  try {
17771
- (0, import_node_fs24.rmSync)(dir, { recursive: true, force: true });
18167
+ (0, import_node_fs26.rmSync)(dir, { recursive: true, force: true });
17772
18168
  } catch {
17773
18169
  }
17774
18170
  }
@@ -17943,8 +18339,8 @@ function buildCompactionContext(session) {
17943
18339
  commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
17944
18340
  readFileLines: (file) => {
17945
18341
  try {
17946
- const abs = (0, import_node_path23.join)(root, file);
17947
- return (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null;
18342
+ const abs = (0, import_node_path24.join)(root, file);
18343
+ return (0, import_node_fs27.existsSync)(abs) ? (0, import_node_fs27.readFileSync)(abs, "utf8").split("\n") : null;
17948
18344
  } catch {
17949
18345
  return null;
17950
18346
  }
@@ -18001,24 +18397,24 @@ async function readHookStdin() {
18001
18397
 
18002
18398
  // src/commands/standard.ts
18003
18399
  var import_promises13 = require("node:fs/promises");
18004
- var import_node_fs32 = require("node:fs");
18400
+ var import_node_fs34 = require("node:fs");
18005
18401
  var import_yaml3 = __toESM(require_dist());
18006
18402
 
18007
18403
  // src/lib/synthesize.ts
18008
18404
  var import_node_child_process9 = require("node:child_process");
18009
- var import_node_fs28 = require("node:fs");
18405
+ var import_node_fs30 = require("node:fs");
18010
18406
  var import_promises10 = require("node:fs/promises");
18011
- var import_node_path26 = require("node:path");
18407
+ var import_node_path27 = require("node:path");
18012
18408
  var import_yaml = __toESM(require_dist());
18013
18409
 
18014
18410
  // src/lib/data-dir.ts
18015
- var import_node_fs26 = require("node:fs");
18016
- var import_node_path24 = require("node:path");
18411
+ var import_node_fs28 = require("node:fs");
18412
+ var import_node_path25 = require("node:path");
18017
18413
  function resolveDataDir() {
18018
18414
  const candidates2 = [
18019
- (0, import_node_path24.join)(__dirname, "..", "data"),
18415
+ (0, import_node_path25.join)(__dirname, "..", "data"),
18020
18416
  // installed: node_modules/@codacy/verity-cli/data
18021
- (0, import_node_path24.join)(__dirname, "..", "..", "data"),
18417
+ (0, import_node_path25.join)(__dirname, "..", "..", "data"),
18022
18418
  // edge case: nested resolution
18023
18419
  // THE COMMITTED SOURCE, for a source checkout that has not been built.
18024
18420
  // cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
@@ -18027,14 +18423,14 @@ function resolveDataDir() {
18027
18423
  // without this the synthesizer throws "Could not find Verity skill data"
18028
18424
  // for every test and every `verity` run from source. Resolved from this
18029
18425
  // module's own location, never the cwd: see the warning below.
18030
- (0, import_node_path24.join)(__dirname, "..", "..", "client"),
18426
+ (0, import_node_path25.join)(__dirname, "..", "..", "client"),
18031
18427
  // bundled: cli/bin/ → ../../client
18032
- (0, import_node_path24.join)(__dirname, "..", "..", "..", "client"),
18428
+ (0, import_node_path25.join)(__dirname, "..", "..", "..", "client"),
18033
18429
  // tsx: cli/src/lib/ → ../../../client
18034
18430
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
18035
18431
  ];
18036
18432
  for (const candidate of candidates2) {
18037
- if ((0, import_node_fs26.existsSync)((0, import_node_path24.join)(candidate, "skills"))) {
18433
+ if ((0, import_node_fs28.existsSync)((0, import_node_path25.join)(candidate, "skills"))) {
18038
18434
  return candidate;
18039
18435
  }
18040
18436
  }
@@ -18043,13 +18439,13 @@ function resolveDataDir() {
18043
18439
  );
18044
18440
  }
18045
18441
  function setupDataPath(file) {
18046
- return (0, import_node_path24.join)(resolveDataDir(), "skills", "verity-setup", file);
18442
+ return (0, import_node_path25.join)(resolveDataDir(), "skills", "verity-setup", file);
18047
18443
  }
18048
18444
 
18049
18445
  // src/lib/detect.ts
18050
18446
  var import_node_child_process8 = require("node:child_process");
18051
- var import_node_fs27 = require("node:fs");
18052
- var import_node_path25 = require("node:path");
18447
+ var import_node_fs29 = require("node:fs");
18448
+ var import_node_path26 = require("node:path");
18053
18449
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
18054
18450
  "typescript",
18055
18451
  "javascript",
@@ -18106,25 +18502,25 @@ function walk(root) {
18106
18502
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
18107
18503
  let entries;
18108
18504
  try {
18109
- entries = (0, import_node_fs27.readdirSync)(dir, { withFileTypes: true });
18505
+ entries = (0, import_node_fs29.readdirSync)(dir, { withFileTypes: true });
18110
18506
  } catch {
18111
18507
  return;
18112
18508
  }
18113
18509
  for (const entry of entries) {
18114
18510
  if (found.length >= WALK_MAX_FILES) return;
18115
18511
  if (IGNORED_SEGMENTS.includes(entry.name)) continue;
18116
- const full = (0, import_node_path25.join)(dir, entry.name);
18512
+ const full = (0, import_node_path26.join)(dir, entry.name);
18117
18513
  if (entry.isDirectory()) visit(full, depth + 1);
18118
- else if (entry.isFile()) found.push((0, import_node_path25.relative)(root, full));
18514
+ else if (entry.isFile()) found.push((0, import_node_path26.relative)(root, full));
18119
18515
  }
18120
18516
  };
18121
18517
  visit(root, 0);
18122
18518
  return found;
18123
18519
  }
18124
18520
  function languageOf(path) {
18125
- const name = (0, import_node_path25.basename)(path);
18521
+ const name = (0, import_node_path26.basename)(path);
18126
18522
  if (/^Dockerfile(\..+)?$/i.test(name)) return "dockerfile";
18127
- if (!(0, import_node_path25.extname)(name)) return null;
18523
+ if (!(0, import_node_path26.extname)(name)) return null;
18128
18524
  const lang = detectLanguage(path);
18129
18525
  return lang || null;
18130
18526
  }
@@ -18181,7 +18577,7 @@ var TOOL_CONFIG_MARKERS = [
18181
18577
  ];
18182
18578
  function readJson2(path) {
18183
18579
  try {
18184
- return JSON.parse((0, import_node_fs27.readFileSync)(path, "utf-8"));
18580
+ return JSON.parse((0, import_node_fs29.readFileSync)(path, "utf-8"));
18185
18581
  } catch {
18186
18582
  return null;
18187
18583
  }
@@ -18206,17 +18602,17 @@ function declaredDependencies(root, files) {
18206
18602
  if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
18207
18603
  }
18208
18604
  };
18209
- readPackageJson((0, import_node_path25.join)(root, "package.json"));
18210
- const nested = files.filter((f) => f.includes("/") && (0, import_node_path25.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
18211
- for (const rel of nested) readPackageJson((0, import_node_path25.join)(root, rel));
18605
+ readPackageJson((0, import_node_path26.join)(root, "package.json"));
18606
+ const nested = files.filter((f) => f.includes("/") && (0, import_node_path26.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
18607
+ for (const rel of nested) readPackageJson((0, import_node_path26.join)(root, rel));
18212
18608
  const pythonManifests = [
18213
- ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path25.join)(root, f)),
18214
- ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path25.join)(root, f))
18609
+ ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path26.join)(root, f)),
18610
+ ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path26.join)(root, f))
18215
18611
  ];
18216
18612
  for (const path of pythonManifests) {
18217
- if (!(0, import_node_fs27.existsSync)(path)) continue;
18613
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
18218
18614
  try {
18219
- const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
18615
+ const text = (0, import_node_fs29.readFileSync)(path, "utf-8");
18220
18616
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
18221
18617
  for (const line of text.split("\n")) {
18222
18618
  if (!/dependencies\s*=/.test(line)) continue;
@@ -18226,13 +18622,13 @@ function declaredDependencies(root, files) {
18226
18622
  }
18227
18623
  }
18228
18624
  const goMods = [
18229
- (0, import_node_path25.join)(root, "go.mod"),
18230
- ...files.filter((f) => f.includes("/") && (0, import_node_path25.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path25.join)(root, f))
18625
+ (0, import_node_path26.join)(root, "go.mod"),
18626
+ ...files.filter((f) => f.includes("/") && (0, import_node_path26.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path26.join)(root, f))
18231
18627
  ];
18232
18628
  for (const path of goMods) {
18233
- if (!(0, import_node_fs27.existsSync)(path)) continue;
18629
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
18234
18630
  try {
18235
- const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
18631
+ const text = (0, import_node_fs29.readFileSync)(path, "utf-8");
18236
18632
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
18237
18633
  names2.push(m[1].replace(/^github\.com\//, ""));
18238
18634
  }
@@ -18240,10 +18636,10 @@ function declaredDependencies(root, files) {
18240
18636
  }
18241
18637
  }
18242
18638
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
18243
- const path = (0, import_node_path25.join)(root, file);
18244
- if (!(0, import_node_fs27.existsSync)(path)) continue;
18639
+ const path = (0, import_node_path26.join)(root, file);
18640
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
18245
18641
  try {
18246
- const text = (0, import_node_fs27.readFileSync)(path, "utf-8");
18642
+ const text = (0, import_node_fs29.readFileSync)(path, "utf-8");
18247
18643
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
18248
18644
  } catch {
18249
18645
  }
@@ -18251,7 +18647,7 @@ function declaredDependencies(root, files) {
18251
18647
  return names2;
18252
18648
  }
18253
18649
  function detectBuildSystem(root, files) {
18254
- const has = (f) => (0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, f)) || files.some((p) => (0, import_node_path25.basename)(p) === f);
18650
+ const has = (f) => (0, import_node_fs29.existsSync)((0, import_node_path26.join)(root, f)) || files.some((p) => (0, import_node_path26.basename)(p) === f);
18255
18651
  if (has("pnpm-lock.yaml")) return "pnpm";
18256
18652
  if (has("yarn.lock")) return "yarn";
18257
18653
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -18268,8 +18664,8 @@ function detectBuildSystem(root, files) {
18268
18664
  }
18269
18665
  function detectArchitecture(root, files) {
18270
18666
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
18271
- if (workspaceMarkers.some((m) => (0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, m)))) return "monorepo";
18272
- const pkg = readJson2((0, import_node_path25.join)(root, "package.json"));
18667
+ if (workspaceMarkers.some((m) => (0, import_node_fs29.existsSync)((0, import_node_path26.join)(root, m)))) return "monorepo";
18668
+ const pkg = readJson2((0, import_node_path26.join)(root, "package.json"));
18273
18669
  if (pkg && "workspaces" in pkg) return "monorepo";
18274
18670
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
18275
18671
  const nested = manifests.filter((f) => f.includes("/"));
@@ -18291,10 +18687,10 @@ function measureAvgFileLength(root, files, languages) {
18291
18687
  let total = 0;
18292
18688
  let counted = 0;
18293
18689
  for (let i = 0; i < candidates2.length; i += stride) {
18294
- const path = (0, import_node_path25.join)(root, candidates2[i]);
18690
+ const path = (0, import_node_path26.join)(root, candidates2[i]);
18295
18691
  try {
18296
- if ((0, import_node_fs27.statSync)(path).size > 2 * 1024 * 1024) continue;
18297
- total += (0, import_node_fs27.readFileSync)(path, "utf-8").split("\n").length;
18692
+ if ((0, import_node_fs29.statSync)(path).size > 2 * 1024 * 1024) continue;
18693
+ total += (0, import_node_fs29.readFileSync)(path, "utf-8").split("\n").length;
18298
18694
  counted++;
18299
18695
  } catch {
18300
18696
  }
@@ -18324,14 +18720,14 @@ function detectProject(root = repoRoot()) {
18324
18720
  const existingToolConfigs = [];
18325
18721
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
18326
18722
  for (const marker of markers) {
18327
- if ((0, import_node_fs27.existsSync)((0, import_node_path25.join)(root, marker))) {
18723
+ if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(root, marker))) {
18328
18724
  existingToolConfigs.push({ tool, path: `./${marker}` });
18329
18725
  break;
18330
18726
  }
18331
18727
  }
18332
18728
  }
18333
18729
  return {
18334
- projectName: (0, import_node_path25.basename)(root),
18730
+ projectName: (0, import_node_path26.basename)(root),
18335
18731
  languages,
18336
18732
  languageCounts,
18337
18733
  frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
@@ -18429,8 +18825,8 @@ ${closingNote(input.origin)}
18429
18825
 
18430
18826
  // src/lib/synthesize.ts
18431
18827
  function loadCatalog() {
18432
- const catalog = (0, import_yaml.parse)((0, import_node_fs28.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
18433
- const template = (0, import_yaml.parse)((0, import_node_fs28.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
18828
+ const catalog = (0, import_yaml.parse)((0, import_node_fs30.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
18829
+ const template = (0, import_yaml.parse)((0, import_node_fs30.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
18434
18830
  return { catalog, template };
18435
18831
  }
18436
18832
  function selectTools(languages, intensity, catalog) {
@@ -18708,7 +19104,7 @@ function validatePatternIds() {
18708
19104
  }
18709
19105
  async function runSynthesis(opts) {
18710
19106
  const standardPath = projectPath(STANDARD_FILE);
18711
- if ((0, import_node_fs28.existsSync)(standardPath) && !opts.force) {
19107
+ if ((0, import_node_fs30.existsSync)(standardPath) && !opts.force) {
18712
19108
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
18713
19109
  }
18714
19110
  const detected = opts.detected ?? detectProject();
@@ -18777,7 +19173,7 @@ async function correctVerityMdVersion(opts) {
18777
19173
  }
18778
19174
  async function writeFileTo(relative3, body) {
18779
19175
  const target = projectPath(relative3);
18780
- await (0, import_promises10.mkdir)((0, import_node_path26.dirname)(target), { recursive: true });
19176
+ await (0, import_promises10.mkdir)((0, import_node_path27.dirname)(target), { recursive: true });
18781
19177
  await (0, import_promises10.writeFile)(target, body);
18782
19178
  }
18783
19179
  async function deriveConfigForStandard(standard) {
@@ -18836,11 +19232,11 @@ ${validation.detail}`);
18836
19232
 
18837
19233
  // src/lib/setup-state.ts
18838
19234
  var import_promises11 = require("node:fs/promises");
18839
- var import_node_fs29 = require("node:fs");
19235
+ var import_node_fs31 = require("node:fs");
18840
19236
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
18841
19237
  async function readSetupState() {
18842
19238
  const path = projectPath(SETUP_STATE_FILE);
18843
- if (!(0, import_node_fs29.existsSync)(path)) return null;
19239
+ if (!(0, import_node_fs31.existsSync)(path)) return null;
18844
19240
  try {
18845
19241
  const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
18846
19242
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -18856,12 +19252,12 @@ async function writeSetupState(patch) {
18856
19252
  }
18857
19253
 
18858
19254
  // src/lib/push-setup.ts
18859
- var import_node_fs31 = require("node:fs");
19255
+ var import_node_fs33 = require("node:fs");
18860
19256
  var import_promises12 = require("node:fs/promises");
18861
19257
  var import_yaml2 = __toESM(require_dist());
18862
19258
 
18863
19259
  // src/lib/verityignore.ts
18864
- var import_node_fs30 = require("node:fs");
19260
+ var import_node_fs32 = require("node:fs");
18865
19261
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
18866
19262
  var SECURITY_PROBES = [
18867
19263
  ".env",
@@ -18954,9 +19350,9 @@ function isIgnored3(ig, path) {
18954
19350
  }
18955
19351
  function loadVerityIgnore() {
18956
19352
  const file = projectPath(VERITYIGNORE_FILE);
18957
- if (!(0, import_node_fs30.existsSync)(file)) return EMPTY;
19353
+ if (!(0, import_node_fs32.existsSync)(file)) return EMPTY;
18958
19354
  try {
18959
- return parseVerityIgnore((0, import_node_fs30.readFileSync)(file, "utf-8"));
19355
+ return parseVerityIgnore((0, import_node_fs32.readFileSync)(file, "utf-8"));
18960
19356
  } catch {
18961
19357
  return EMPTY;
18962
19358
  }
@@ -18994,9 +19390,9 @@ function buildStandardUpload(standard, ignoreRaw) {
18994
19390
  }
18995
19391
  function readVerityIgnoreRaw() {
18996
19392
  const file = projectPath(VERITYIGNORE_FILE);
18997
- if (!(0, import_node_fs30.existsSync)(file)) return null;
19393
+ if (!(0, import_node_fs32.existsSync)(file)) return null;
18998
19394
  try {
18999
- return (0, import_node_fs30.readFileSync)(file, "utf-8");
19395
+ return (0, import_node_fs32.readFileSync)(file, "utf-8");
19000
19396
  } catch {
19001
19397
  return null;
19002
19398
  }
@@ -19024,7 +19420,7 @@ async function pushStandardAndConfig(globals, what = {}) {
19024
19420
  }
19025
19421
  let standardVersion = null;
19026
19422
  const standardPath = projectPath(STANDARD_FILE);
19027
- if (pushStandard && (0, import_node_fs31.existsSync)(standardPath)) {
19423
+ if (pushStandard && (0, import_node_fs33.existsSync)(standardPath)) {
19028
19424
  try {
19029
19425
  const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
19030
19426
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -19049,7 +19445,7 @@ async function pushStandardAndConfig(globals, what = {}) {
19049
19445
  }
19050
19446
  let configPushed = false;
19051
19447
  const configPath = projectPath(CODACY_CONFIG_FILE);
19052
- if (pushConfig && (0, import_node_fs31.existsSync)(configPath)) {
19448
+ if (pushConfig && (0, import_node_fs33.existsSync)(configPath)) {
19053
19449
  try {
19054
19450
  const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
19055
19451
  const result = await apiRequest({
@@ -19081,7 +19477,7 @@ function registerStandardCommands(program2) {
19081
19477
  const state = await readSetupState();
19082
19478
  if (opts.configOnly) {
19083
19479
  const standardPath = projectPath(STANDARD_FILE);
19084
- if (!(0, import_node_fs32.existsSync)(standardPath)) {
19480
+ if (!(0, import_node_fs34.existsSync)(standardPath)) {
19085
19481
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
19086
19482
  process.exit(1);
19087
19483
  }
@@ -19414,20 +19810,20 @@ function formatRunDetail(run2) {
19414
19810
  }
19415
19811
 
19416
19812
  // src/lib/ignore-declaration.ts
19417
- var import_node_fs34 = require("node:fs");
19813
+ var import_node_fs36 = require("node:fs");
19418
19814
 
19419
19815
  // src/lib/debounce.ts
19420
- var import_node_fs33 = require("node:fs");
19421
- var import_node_crypto10 = require("node:crypto");
19816
+ var import_node_fs35 = require("node:fs");
19817
+ var import_node_crypto11 = require("node:crypto");
19422
19818
  function scopedFile(base, sessionId) {
19423
19819
  if (!sessionId) return base;
19424
- return `${base}.${(0, import_node_crypto10.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
19820
+ return `${base}.${(0, import_node_crypto11.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
19425
19821
  }
19426
19822
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
19427
19823
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19428
- if (!(0, import_node_fs33.existsSync)(file)) return null;
19824
+ if (!(0, import_node_fs35.existsSync)(file)) return null;
19429
19825
  try {
19430
- const lastTs = parseInt((0, import_node_fs33.readFileSync)(file, "utf-8").trim(), 10);
19826
+ const lastTs = parseInt((0, import_node_fs35.readFileSync)(file, "utf-8").trim(), 10);
19431
19827
  const nowTs = Math.floor(Date.now() / 1e3);
19432
19828
  const elapsed = nowTs - lastTs;
19433
19829
  if (elapsed < debounceSeconds) {
@@ -19440,10 +19836,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
19440
19836
  function checkMtime(files, bypassForRecentCommits, sessionId) {
19441
19837
  if (bypassForRecentCommits) return null;
19442
19838
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19443
- if (!(0, import_node_fs33.existsSync)(file)) return null;
19839
+ if (!(0, import_node_fs35.existsSync)(file)) return null;
19444
19840
  let debounceTime;
19445
19841
  try {
19446
- debounceTime = (0, import_node_fs33.statSync)(file).mtimeMs;
19842
+ debounceTime = (0, import_node_fs35.statSync)(file).mtimeMs;
19447
19843
  } catch {
19448
19844
  return null;
19449
19845
  }
@@ -19451,7 +19847,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
19451
19847
  const resolved = resolveFile(f);
19452
19848
  if (!resolved) continue;
19453
19849
  try {
19454
- const stat3 = (0, import_node_fs33.statSync)(resolved);
19850
+ const stat3 = (0, import_node_fs35.statSync)(resolved);
19455
19851
  if (stat3.mtimeMs > debounceTime) {
19456
19852
  return null;
19457
19853
  }
@@ -19462,13 +19858,13 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
19462
19858
  return "No files modified since last analysis";
19463
19859
  }
19464
19860
  function computeContentHash(files) {
19465
- const hash = (0, import_node_crypto10.createHash)("sha1");
19861
+ const hash = (0, import_node_crypto11.createHash)("sha1");
19466
19862
  const sorted = [...files].sort();
19467
19863
  for (const f of sorted) {
19468
19864
  const resolved = resolveFile(f) ?? f;
19469
19865
  try {
19470
- if ((0, import_node_fs33.existsSync)(resolved)) {
19471
- hash.update((0, import_node_fs33.readFileSync)(resolved));
19866
+ if ((0, import_node_fs35.existsSync)(resolved)) {
19867
+ hash.update((0, import_node_fs35.readFileSync)(resolved));
19472
19868
  }
19473
19869
  } catch {
19474
19870
  }
@@ -19478,9 +19874,9 @@ function computeContentHash(files) {
19478
19874
  function checkContentHash(files, sessionId) {
19479
19875
  const hash = computeContentHash(files);
19480
19876
  const file = scopedFile(HASH_FILE, sessionId);
19481
- if ((0, import_node_fs33.existsSync)(file)) {
19877
+ if ((0, import_node_fs35.existsSync)(file)) {
19482
19878
  try {
19483
- const storedHash = (0, import_node_fs33.readFileSync)(file, "utf-8").trim();
19879
+ const storedHash = (0, import_node_fs35.readFileSync)(file, "utf-8").trim();
19484
19880
  if (hash === storedHash) {
19485
19881
  return { skip: "No source changes since last analysis", hash };
19486
19882
  }
@@ -19490,24 +19886,24 @@ function checkContentHash(files, sessionId) {
19490
19886
  return { skip: null, hash };
19491
19887
  }
19492
19888
  function recordAnalysisStart(sessionId) {
19493
- (0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
19494
- (0, import_node_fs33.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
19889
+ (0, import_node_fs35.mkdirSync)(VERITY_DIR, { recursive: true });
19890
+ (0, import_node_fs35.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
19495
19891
  }
19496
19892
  function recordPassHash(hash, sessionId) {
19497
- (0, import_node_fs33.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
19893
+ (0, import_node_fs35.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
19498
19894
  }
19499
19895
  function narrowToRecent(files, sessionId) {
19500
19896
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
19501
- if (!(0, import_node_fs33.existsSync)(file)) return files;
19897
+ if (!(0, import_node_fs35.existsSync)(file)) return files;
19502
19898
  let debounceTime;
19503
19899
  try {
19504
- debounceTime = (0, import_node_fs33.statSync)(file).mtimeMs;
19900
+ debounceTime = (0, import_node_fs35.statSync)(file).mtimeMs;
19505
19901
  } catch {
19506
19902
  return files;
19507
19903
  }
19508
19904
  const recent = files.filter((f) => {
19509
19905
  try {
19510
- return (0, import_node_fs33.existsSync)(f) && (0, import_node_fs33.statSync)(f).mtimeMs > debounceTime;
19906
+ return (0, import_node_fs35.existsSync)(f) && (0, import_node_fs35.statSync)(f).mtimeMs > debounceTime;
19511
19907
  } catch {
19512
19908
  return false;
19513
19909
  }
@@ -19520,9 +19916,9 @@ function readIteration(currentCommit, _contentHash) {
19520
19916
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
19521
19917
  function readBlockState(currentCommit, opts) {
19522
19918
  if (opts?.newUserPrompt) return NO_BLOCKS;
19523
- if (!(0, import_node_fs33.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
19919
+ if (!(0, import_node_fs35.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
19524
19920
  try {
19525
- const stored = (0, import_node_fs33.readFileSync)(ITERATION_FILE, "utf-8").trim();
19921
+ const stored = (0, import_node_fs35.readFileSync)(ITERATION_FILE, "utf-8").trim();
19526
19922
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
19527
19923
  if (!parsed) return NO_BLOCKS;
19528
19924
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -19568,8 +19964,8 @@ function isSameProblem(previous, current) {
19568
19964
  return current.split(",").some((k) => prev.has(k));
19569
19965
  }
19570
19966
  function writeBlockState(commit, state) {
19571
- (0, import_node_fs33.mkdirSync)(VERITY_DIR, { recursive: true });
19572
- (0, import_node_fs33.writeFileSync)(
19967
+ (0, import_node_fs35.mkdirSync)(VERITY_DIR, { recursive: true });
19968
+ (0, import_node_fs35.writeFileSync)(
19573
19969
  ITERATION_FILE,
19574
19970
  JSON.stringify({
19575
19971
  v: 2,
@@ -19674,9 +20070,9 @@ function resolveIgnoreState(keys) {
19674
20070
  }
19675
20071
  function readIgnoreState(sessionId) {
19676
20072
  const file = stateFile(sessionId);
19677
- if (!(0, import_node_fs34.existsSync)(file)) return null;
20073
+ if (!(0, import_node_fs36.existsSync)(file)) return null;
19678
20074
  try {
19679
- const o = JSON.parse((0, import_node_fs34.readFileSync)(file, "utf-8")) ?? {};
20075
+ const o = JSON.parse((0, import_node_fs36.readFileSync)(file, "utf-8")) ?? {};
19680
20076
  const spent = typeof o.spent === "number" ? o.spent : 0;
19681
20077
  const raw = o.active;
19682
20078
  let active = null;
@@ -19700,8 +20096,8 @@ function readIgnoreState(sessionId) {
19700
20096
  }
19701
20097
  function writeIgnoreState(state, sessionId) {
19702
20098
  try {
19703
- (0, import_node_fs34.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
19704
- (0, import_node_fs34.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
20099
+ (0, import_node_fs36.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
20100
+ (0, import_node_fs36.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
19705
20101
  } catch {
19706
20102
  }
19707
20103
  }
@@ -20084,7 +20480,7 @@ function createRun(opts, globals) {
20084
20480
  }
20085
20481
 
20086
20482
  // src/commands/analyze/index.ts
20087
- var import_node_fs47 = require("node:fs");
20483
+ var import_node_fs49 = require("node:fs");
20088
20484
 
20089
20485
  // src/lib/repo-context.ts
20090
20486
  var import_node_child_process10 = require("node:child_process");
@@ -21020,10 +21416,10 @@ function installRunEvidence(run2) {
21020
21416
  }
21021
21417
 
21022
21418
  // src/lib/git-frame.ts
21023
- var import_node_fs35 = require("node:fs");
21419
+ var import_node_fs37 = require("node:fs");
21024
21420
  var import_node_os6 = require("node:os");
21025
- var import_node_path27 = require("node:path");
21026
21421
  var import_node_path28 = require("node:path");
21422
+ var import_node_path29 = require("node:path");
21027
21423
 
21028
21424
  // src/lib/hardened-git.ts
21029
21425
  var import_node_child_process11 = require("node:child_process");
@@ -21185,8 +21581,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
21185
21581
  if (SHELL_DYNAMIC.test(raw) || raw === "-") {
21186
21582
  return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
21187
21583
  }
21188
- const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path28.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
21189
- dir = (0, import_node_path27.isAbsolute)(expanded) ? expanded : (0, import_node_path27.resolve)(dir, expanded);
21584
+ const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path29.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
21585
+ dir = (0, import_node_path28.isAbsolute)(expanded) ? expanded : (0, import_node_path28.resolve)(dir, expanded);
21190
21586
  }
21191
21587
  const seg = segments[segmentIndex];
21192
21588
  const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
@@ -21204,8 +21600,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
21204
21600
  if (SHELL_DYNAMIC.test(raw)) {
21205
21601
  return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
21206
21602
  }
21207
- const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path28.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
21208
- dir = (0, import_node_path27.isAbsolute)(expanded) ? expanded : (0, import_node_path27.resolve)(dir, expanded);
21603
+ const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path29.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
21604
+ dir = (0, import_node_path28.isAbsolute)(expanded) ? expanded : (0, import_node_path28.resolve)(dir, expanded);
21209
21605
  }
21210
21606
  }
21211
21607
  return { dir, named, unresolvable: null };
@@ -21265,14 +21661,14 @@ function gitAt(dir, args) {
21265
21661
  }
21266
21662
  function realpathOr2(p) {
21267
21663
  try {
21268
- return import_node_fs35.realpathSync.native(p);
21664
+ return import_node_fs37.realpathSync.native(p);
21269
21665
  } catch {
21270
- return (0, import_node_path27.resolve)(p);
21666
+ return (0, import_node_path28.resolve)(p);
21271
21667
  }
21272
21668
  }
21273
21669
  function resolveFrame(input) {
21274
21670
  const found = findMomentSegment(input.command, input.on);
21275
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs35.existsSync)(input.hookCwd);
21671
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs37.existsSync)(input.hookCwd);
21276
21672
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
21277
21673
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
21278
21674
  const refuse = (refusal) => ({
@@ -21295,7 +21691,7 @@ function resolveFrame(input) {
21295
21691
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
21296
21692
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
21297
21693
  if (targetDir !== baseDir) {
21298
- if (!(0, import_node_fs35.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
21694
+ if (!(0, import_node_fs37.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
21299
21695
  dir = targetDir;
21300
21696
  }
21301
21697
  }
@@ -21306,7 +21702,7 @@ function resolveFrame(input) {
21306
21702
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
21307
21703
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
21308
21704
  const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
21309
- const commonDir = commonRaw ? realpathOr2((0, import_node_path27.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path27.resolve)(dir, commonRaw)) : null;
21705
+ const commonDir = commonRaw ? realpathOr2((0, import_node_path28.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path28.resolve)(dir, commonRaw)) : null;
21310
21706
  const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
21311
21707
  return {
21312
21708
  moment: found?.moment ?? null,
@@ -21481,8 +21877,8 @@ function stagedRange(frame, command) {
21481
21877
  if (plan.kind === "unpredictable") {
21482
21878
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
21483
21879
  }
21484
- const mergeHead = frame.gitDir ? (0, import_node_path28.join)(frame.gitDir, "MERGE_HEAD") : null;
21485
- if (mergeHead && (0, import_node_fs35.existsSync)(mergeHead)) {
21880
+ const mergeHead = frame.gitDir ? (0, import_node_path29.join)(frame.gitDir, "MERGE_HEAD") : null;
21881
+ if (mergeHead && (0, import_node_fs37.existsSync)(mergeHead)) {
21486
21882
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
21487
21883
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
21488
21884
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -21616,7 +22012,7 @@ function truthy(v) {
21616
22012
  }
21617
22013
 
21618
22014
  // src/lib/transcript.ts
21619
- var import_node_fs36 = require("node:fs");
22015
+ var import_node_fs38 = require("node:fs");
21620
22016
  var MAX_READ_BYTES = 256 * 1024;
21621
22017
  var SMALL_FILE_BYTES = 64 * 1024;
21622
22018
  var MAX_FILES_LIST = 20;
@@ -21643,7 +22039,7 @@ async function extractActionSummary(transcriptPath) {
21643
22039
  function readTurnLines(transcriptPath) {
21644
22040
  let size;
21645
22041
  try {
21646
- size = (0, import_node_fs36.statSync)(transcriptPath).size;
22042
+ size = (0, import_node_fs38.statSync)(transcriptPath).size;
21647
22043
  } catch {
21648
22044
  return null;
21649
22045
  }
@@ -21651,7 +22047,7 @@ function readTurnLines(transcriptPath) {
21651
22047
  let raw;
21652
22048
  let windowed = false;
21653
22049
  if (size <= SMALL_FILE_BYTES) {
21654
- raw = (0, import_node_fs36.readFileSync)(transcriptPath, "utf-8");
22050
+ raw = (0, import_node_fs38.readFileSync)(transcriptPath, "utf-8");
21655
22051
  } else {
21656
22052
  windowed = true;
21657
22053
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -22042,6 +22438,52 @@ function partitionVerityOwned(paths) {
22042
22438
  return { kept, owned };
22043
22439
  }
22044
22440
 
22441
+ // src/lib/knowledge-note-state.ts
22442
+ var stateDir = () => projectPath(VERITY_DIR);
22443
+ var STATE_FILE2 = "knowledge-note-state.json";
22444
+ function parseKnowledgeNote(raw) {
22445
+ if (!raw || typeof raw !== "object") return null;
22446
+ const o = raw;
22447
+ const node_id = typeof o.node_id === "string" ? o.node_id.trim() : "";
22448
+ const text = typeof o.text === "string" ? o.text.trim() : "";
22449
+ if (!node_id || !text) return null;
22450
+ if (text.length > 1e3) return null;
22451
+ return {
22452
+ node_id,
22453
+ text,
22454
+ file: typeof o.file === "string" && o.file ? o.file : null,
22455
+ line: typeof o.line === "number" && Number.isFinite(o.line) && o.line > 0 ? Math.floor(o.line) : null
22456
+ };
22457
+ }
22458
+ function recordNoteOutcome(runId, delivered) {
22459
+ replaceInRoot(stateDir(), STATE_FILE2, JSON.stringify({ run_id: runId, delivered }));
22460
+ }
22461
+ function peekNoteOutcome() {
22462
+ try {
22463
+ const read = readRegularFileInRoot(stateDir(), STATE_FILE2, 4096);
22464
+ if (!read.ok || !read.content.trim()) return null;
22465
+ const parsed = JSON.parse(read.content);
22466
+ if (!parsed || typeof parsed !== "object") return null;
22467
+ const o = parsed;
22468
+ if (typeof o.run_id !== "string" || !/^run-\d{14}-[0-9a-f]{8}$/.test(o.run_id)) return null;
22469
+ if (typeof o.delivered !== "boolean") return null;
22470
+ return { run_id: o.run_id, delivered: o.delivered };
22471
+ } catch {
22472
+ return null;
22473
+ }
22474
+ }
22475
+ function clearNoteOutcome() {
22476
+ replaceInRoot(stateDir(), STATE_FILE2, "");
22477
+ }
22478
+ function episodeForWire(e, humanSpoke) {
22479
+ return {
22480
+ delivered: e?.delivered ?? 0,
22481
+ tasks_completed: e?.tasksCompleted ?? 0,
22482
+ ts: e?.ts ?? 0,
22483
+ human_spoke: humanSpoke
22484
+ };
22485
+ }
22486
+
22045
22487
  // src/lib/channel.ts
22046
22488
  var MAX_AGENT_CONTEXT_CHARS = 1500;
22047
22489
  var MAX_AGENT_ITEMS = 5;
@@ -22063,7 +22505,14 @@ function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints =
22063
22505
  reviewStatus: metadata.review_status,
22064
22506
  coverage: metadata.coverage,
22065
22507
  intentVerdict: intent.verdict,
22066
- intentGaps: intent.gaps
22508
+ intentGaps: intent.gaps,
22509
+ // Phase 5. Parsed defensively: a malformed or oversized note degrades to
22510
+ // silence rather than to a broken agent message, and an old server simply
22511
+ // sends nothing — which is indistinguishable from a server that chose to
22512
+ // stay quiet, as it should be.
22513
+ knowledgeNote: parseKnowledgeNote(
22514
+ response.knowledge_note ?? metadata.knowledge_note
22515
+ )?.text
22067
22516
  };
22068
22517
  }
22069
22518
  function classifyChannelContent(input) {
@@ -22071,7 +22520,13 @@ function classifyChannelContent(input) {
22071
22520
  const intentFlag = input.intentVerdict === "misaligned" || input.intentVerdict === "partial";
22072
22521
  const advisory = (input.findings ?? []).some((f) => f.scope !== "pre-existing") || (input.pendingItems ?? []).some(
22073
22522
  (p) => p.pattern_id !== "intent-misalignment" && !!(p.description ?? p.title ?? p.reason)
22074
- );
22523
+ ) || // ⚠ A KNOWLEDGE NOTE IS ADVISORY CONTENT, and it must be classified as such
22524
+ // or the invariant above breaks: `buildAgentContext` would return a message
22525
+ // on a run where all three classes are false, which is exactly the drift
22526
+ // this pair is written to prevent. It is advisory rather than refusal or
22527
+ // intent because it costs the agent a turn — the same cost the episode
22528
+ // budget exists to bound.
22529
+ !!input.knowledgeNote;
22075
22530
  return { refusal, intentFlag, advisory };
22076
22531
  }
22077
22532
  function buildAgentContext(input) {
@@ -22098,6 +22553,9 @@ function buildAgentContext(input) {
22098
22553
  );
22099
22554
  }
22100
22555
  }
22556
+ if (input.knowledgeNote && lines.length < MAX_AGENT_ITEMS) {
22557
+ lines.push(`- ${input.knowledgeNote}`);
22558
+ }
22101
22559
  const agentFindings = (input.findings ?? []).filter((f) => f.scope !== "pre-existing");
22102
22560
  for (const f of agentFindings) {
22103
22561
  if (lines.length >= MAX_AGENT_ITEMS) break;
@@ -22159,7 +22617,7 @@ function channelSilence(input) {
22159
22617
  // src/lib/cli-version.ts
22160
22618
  function cliVersion() {
22161
22619
  try {
22162
- return true ? "0.33.2-experimental.0c53bed" : "dev";
22620
+ return true ? "0.33.3-experimental.072d5cb" : "dev";
22163
22621
  } catch {
22164
22622
  return "dev";
22165
22623
  }
@@ -22200,7 +22658,7 @@ async function sendSkipBeacon(ctx, reason) {
22200
22658
 
22201
22659
  // src/lib/static-analysis.ts
22202
22660
  var import_node_child_process12 = require("node:child_process");
22203
- var import_node_fs37 = require("node:fs");
22661
+ var import_node_fs39 = require("node:fs");
22204
22662
  var SEVERITY_ORDER = {
22205
22663
  Error: 0,
22206
22664
  Critical: 0,
@@ -22256,7 +22714,7 @@ function runCodacyAnalysis(files) {
22256
22714
  if (files.length === 0) return empty;
22257
22715
  const existingFiles = files.filter((f) => {
22258
22716
  try {
22259
- return (0, import_node_fs37.existsSync)(f);
22717
+ return (0, import_node_fs39.existsSync)(f);
22260
22718
  } catch {
22261
22719
  return false;
22262
22720
  }
@@ -22525,8 +22983,8 @@ async function scope(run2) {
22525
22983
  }
22526
22984
 
22527
22985
  // src/lib/specs.ts
22528
- var import_node_fs38 = require("node:fs");
22529
- var import_node_path29 = require("node:path");
22986
+ var import_node_fs40 = require("node:fs");
22987
+ var import_node_path30 = require("node:path");
22530
22988
  var SPEC_CANDIDATES = [
22531
22989
  "CLAUDE.md",
22532
22990
  "AGENTS.md",
@@ -22548,7 +23006,7 @@ var UNCONSULTED_TOTAL_BYTES = 30720;
22548
23006
  function readSpecFiles(specsOpt, root) {
22549
23007
  const out = [];
22550
23008
  for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
22551
- const candidate = (0, import_node_path29.isAbsolute)(raw) ? (0, import_node_path29.relative)(root, raw) : raw;
23009
+ const candidate = (0, import_node_path30.isAbsolute)(raw) ? (0, import_node_path30.relative)(root, raw) : raw;
22552
23010
  const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
22553
23011
  if (content === null) continue;
22554
23012
  out.push({ path: raw, content });
@@ -22567,7 +23025,7 @@ function discoverSpecs(consulted = []) {
22567
23025
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
22568
23026
  if (totalBytes >= totalCap) return false;
22569
23027
  if (seen.has(specPath)) return true;
22570
- if (!(0, import_node_fs38.existsSync)(specPath)) return true;
23028
+ if (!(0, import_node_fs40.existsSync)(specPath)) return true;
22571
23029
  seen.add(specPath);
22572
23030
  const remaining = totalCap - totalBytes;
22573
23031
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
@@ -22590,7 +23048,7 @@ function discoverSpecs(consulted = []) {
22590
23048
  if (!addSpec(candidate)) break;
22591
23049
  }
22592
23050
  for (const dir of ["spec", "docs"]) {
22593
- if (!(0, import_node_fs38.existsSync)(dir)) continue;
23051
+ if (!(0, import_node_fs40.existsSync)(dir)) continue;
22594
23052
  try {
22595
23053
  const mdFiles = findMdFiles(dir, 2).sort();
22596
23054
  for (const mdFile of mdFiles) {
@@ -22605,9 +23063,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
22605
23063
  if (depth >= maxDepth) return [];
22606
23064
  const result = [];
22607
23065
  try {
22608
- const entries = (0, import_node_fs38.readdirSync)(dir, { withFileTypes: true });
23066
+ const entries = (0, import_node_fs40.readdirSync)(dir, { withFileTypes: true });
22609
23067
  for (const entry of entries) {
22610
- const fullPath = (0, import_node_path29.join)(dir, entry.name);
23068
+ const fullPath = (0, import_node_path30.join)(dir, entry.name);
22611
23069
  if (entry.isFile() && entry.name.endsWith(".md")) {
22612
23070
  result.push(fullPath);
22613
23071
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -22620,25 +23078,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
22620
23078
  }
22621
23079
  function discoverPlans() {
22622
23080
  const home = process.env.HOME ?? "";
22623
- const homePlansDir = (0, import_node_path29.join)(home, ".claude", "plans");
23081
+ const homePlansDir = (0, import_node_path30.join)(home, ".claude", "plans");
22624
23082
  const sources = [];
22625
23083
  if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
22626
- sources.push({ root: process.cwd(), prefix: (0, import_node_path29.join)(".claude", "plans") });
23084
+ sources.push({ root: process.cwd(), prefix: (0, import_node_path30.join)(".claude", "plans") });
22627
23085
  }
22628
- if (home && (0, import_node_fs38.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
23086
+ if (home && (0, import_node_fs40.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
22629
23087
  const candidates2 = [];
22630
23088
  const seen = /* @__PURE__ */ new Set();
22631
23089
  for (const source of sources) {
22632
23090
  let names2;
22633
23091
  try {
22634
- names2 = (0, import_node_fs38.readdirSync)(source.prefix ? (0, import_node_path29.join)(source.root, source.prefix) : source.root);
23092
+ names2 = (0, import_node_fs40.readdirSync)(source.prefix ? (0, import_node_path30.join)(source.root, source.prefix) : source.root);
22635
23093
  } catch {
22636
23094
  continue;
22637
23095
  }
22638
23096
  for (const f of names2) {
22639
23097
  if (!f.endsWith(".md") || seen.has(f)) continue;
22640
23098
  seen.add(f);
22641
- const relPath = source.prefix ? (0, import_node_path29.join)(source.prefix, f) : f;
23099
+ const relPath = source.prefix ? (0, import_node_path30.join)(source.prefix, f) : f;
22642
23100
  const stat3 = statRegularInRoot(source.root, relPath);
22643
23101
  if (!stat3.ok) continue;
22644
23102
  candidates2.push({ name: f, root: source.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
@@ -22656,9 +23114,9 @@ function discoverPlans() {
22656
23114
  function isRealDirectoryChain(root, parts) {
22657
23115
  let current = root;
22658
23116
  for (const part of parts) {
22659
- current = (0, import_node_path29.join)(current, part);
23117
+ current = (0, import_node_path30.join)(current, part);
22660
23118
  try {
22661
- if (!(0, import_node_fs38.lstatSync)(current).isDirectory()) return false;
23119
+ if (!(0, import_node_fs40.lstatSync)(current).isDirectory()) return false;
22662
23120
  } catch {
22663
23121
  return false;
22664
23122
  }
@@ -22673,7 +23131,7 @@ function discoverGuardDocs(rangeFiles2) {
22673
23131
  if (result.length >= MAX_SPEC_FILES) break;
22674
23132
  if (!GUARD_DOC_EXT.test(path)) continue;
22675
23133
  if (path.startsWith("/") || path.includes("..")) continue;
22676
- if (!(0, import_node_fs38.existsSync)(path)) continue;
23134
+ if (!(0, import_node_fs40.existsSync)(path)) continue;
22677
23135
  const opened = openRegularInRoot(process.cwd(), path);
22678
23136
  if (!opened.ok) continue;
22679
23137
  if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
@@ -22859,8 +23317,8 @@ async function mode(run2) {
22859
23317
  }
22860
23318
 
22861
23319
  // src/lib/fold.ts
22862
- var import_node_fs39 = require("node:fs");
22863
- var import_node_path30 = require("node:path");
23320
+ var import_node_fs41 = require("node:fs");
23321
+ var import_node_path31 = require("node:path");
22864
23322
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
22865
23323
  "user",
22866
23324
  "assistant",
@@ -22997,7 +23455,7 @@ function candidateRoots(repoRoot2) {
22997
23455
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
22998
23456
  const out = [norm];
22999
23457
  try {
23000
- const real = import_node_fs39.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
23458
+ const real = import_node_fs41.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
23001
23459
  if (real !== norm) out.push(real);
23002
23460
  } catch {
23003
23461
  }
@@ -23085,31 +23543,31 @@ function fold(transcriptPath, opts = {}) {
23085
23543
  }
23086
23544
  };
23087
23545
  try {
23088
- if (!(0, import_node_fs39.existsSync)(transcriptPath)) return result;
23089
- ingest((0, import_node_fs39.readFileSync)(transcriptPath, "utf8"), "agent");
23546
+ if (!(0, import_node_fs41.existsSync)(transcriptPath)) return result;
23547
+ ingest((0, import_node_fs41.readFileSync)(transcriptPath, "utf8"), "agent");
23090
23548
  result.coverage.complete = true;
23091
23549
  } catch {
23092
23550
  return result;
23093
23551
  }
23094
23552
  try {
23095
- const sidecarDir = (0, import_node_path30.join)(
23096
- (0, import_node_path30.dirname)(transcriptPath),
23097
- (0, import_node_path30.basename)(transcriptPath).replace(/\.jsonl$/, ""),
23553
+ const sidecarDir = (0, import_node_path31.join)(
23554
+ (0, import_node_path31.dirname)(transcriptPath),
23555
+ (0, import_node_path31.basename)(transcriptPath).replace(/\.jsonl$/, ""),
23098
23556
  "subagents"
23099
23557
  );
23100
- if ((0, import_node_fs39.existsSync)(sidecarDir)) {
23558
+ if ((0, import_node_fs41.existsSync)(sidecarDir)) {
23101
23559
  const maxFiles = opts.maxSidecars ?? 200;
23102
23560
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
23103
23561
  const found = [];
23104
23562
  const walk2 = (d, depth) => {
23105
23563
  if (depth > 4) return;
23106
- for (const e of (0, import_node_fs39.readdirSync)(d, { withFileTypes: true })) {
23107
- const p = (0, import_node_path30.join)(d, e.name);
23564
+ for (const e of (0, import_node_fs41.readdirSync)(d, { withFileTypes: true })) {
23565
+ const p = (0, import_node_path31.join)(d, e.name);
23108
23566
  if (e.isDirectory()) {
23109
23567
  walk2(p, depth + 1);
23110
23568
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
23111
23569
  try {
23112
- const st = (0, import_node_fs39.statSync)(p);
23570
+ const st = (0, import_node_fs41.statSync)(p);
23113
23571
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
23114
23572
  } catch {
23115
23573
  result.coverage.malformed++;
@@ -23126,7 +23584,7 @@ function fold(transcriptPath, opts = {}) {
23126
23584
  continue;
23127
23585
  }
23128
23586
  try {
23129
- ingest((0, import_node_fs39.readFileSync)(f.path, "utf8"), "subagent");
23587
+ ingest((0, import_node_fs41.readFileSync)(f.path, "utf8"), "subagent");
23130
23588
  bytes += f.size;
23131
23589
  result.coverage.subagentFiles++;
23132
23590
  } catch {
@@ -23161,7 +23619,7 @@ function fold(transcriptPath, opts = {}) {
23161
23619
  }
23162
23620
  function classifyUnobserved(path) {
23163
23621
  try {
23164
- const st = (0, import_node_fs39.statSync)(path);
23622
+ const st = (0, import_node_fs41.statSync)(path);
23165
23623
  if (!st.isFile()) return "unreadable";
23166
23624
  } catch {
23167
23625
  return "unreadable";
@@ -23476,20 +23934,20 @@ async function evidence(run2) {
23476
23934
  }
23477
23935
 
23478
23936
  // src/lib/cache-cleanup.ts
23479
- var import_node_fs40 = require("node:fs");
23480
- var import_node_path31 = require("node:path");
23937
+ var import_node_fs42 = require("node:fs");
23938
+ var import_node_path32 = require("node:path");
23481
23939
  var CACHE_TTL_DAYS = 7;
23482
23940
  function pruneStaleCache() {
23483
23941
  try {
23484
23942
  const dir = projectPath(CACHE_DIR);
23485
23943
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
23486
- for (const entry of (0, import_node_fs40.readdirSync)(dir)) {
23944
+ for (const entry of (0, import_node_fs42.readdirSync)(dir)) {
23487
23945
  if (!entry.startsWith("pending-")) continue;
23488
- const path = (0, import_node_path31.join)(dir, entry);
23946
+ const path = (0, import_node_path32.join)(dir, entry);
23489
23947
  try {
23490
- const stat3 = (0, import_node_fs40.statSync)(path);
23948
+ const stat3 = (0, import_node_fs42.statSync)(path);
23491
23949
  if (stat3.mtimeMs < cutoff) {
23492
- (0, import_node_fs40.unlinkSync)(path);
23950
+ (0, import_node_fs42.unlinkSync)(path);
23493
23951
  logEvent("cache_entry_pruned", {
23494
23952
  path: entry,
23495
23953
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -23503,7 +23961,7 @@ function pruneStaleCache() {
23503
23961
  }
23504
23962
 
23505
23963
  // src/lib/context-files.ts
23506
- var import_node_fs41 = require("node:fs");
23964
+ var import_node_fs43 = require("node:fs");
23507
23965
  var import_node_os7 = require("node:os");
23508
23966
  var MAX_CONTEXT_FILES = 10;
23509
23967
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -23561,7 +24019,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
23561
24019
  continue;
23562
24020
  }
23563
24021
  try {
23564
- const content = (0, import_node_fs41.readFileSync)(safePath, "utf8");
24022
+ const content = (0, import_node_fs43.readFileSync)(safePath, "utf8");
23565
24023
  const bytes = Buffer.byteLength(content);
23566
24024
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
23567
24025
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -23653,8 +24111,8 @@ async function repoContext(run2) {
23653
24111
 
23654
24112
  // src/lib/seed-runner.ts
23655
24113
  var import_promises15 = require("node:fs/promises");
23656
- var import_node_fs42 = require("node:fs");
23657
- var import_node_path32 = require("node:path");
24114
+ var import_node_fs44 = require("node:fs");
24115
+ var import_node_path33 = require("node:path");
23658
24116
  var import_yaml4 = __toESM(require_dist());
23659
24117
 
23660
24118
  // src/lib/seed.ts
@@ -23870,6 +24328,73 @@ _Seeded from CLAUDE.md. Edit or archive if outdated._`,
23870
24328
  }
23871
24329
 
23872
24330
  // src/lib/seed-runner.ts
24331
+ var NODE_DIRS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
24332
+ function normalizeTitle(title) {
24333
+ return title.trim().replace(/\s+/g, " ").toLowerCase();
24334
+ }
24335
+ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
24336
+ const titles = /* @__PURE__ */ new Set();
24337
+ for (const dir of NODE_DIRS) {
24338
+ const full = (0, import_node_path33.join)(memoryDir3, dir);
24339
+ if (!(0, import_node_fs44.existsSync)(full)) continue;
24340
+ let files;
24341
+ try {
24342
+ files = await (0, import_promises15.readdir)(full);
24343
+ } catch {
24344
+ continue;
24345
+ }
24346
+ for (const file of files) {
24347
+ if (!file.endsWith(".md")) continue;
24348
+ let content;
24349
+ try {
24350
+ content = await (0, import_promises15.readFile)((0, import_node_path33.join)(full, file), "utf-8");
24351
+ } catch {
24352
+ continue;
24353
+ }
24354
+ if (!isSeedNodeMarkdown(content)) continue;
24355
+ const title = pickFrontmatterTitle(content);
24356
+ if (title) titles.add(normalizeTitle(title));
24357
+ }
24358
+ }
24359
+ return titles;
24360
+ }
24361
+ function frontmatterOf(content) {
24362
+ if (!content.startsWith("---")) return null;
24363
+ const end = content.indexOf("\n---", 3);
24364
+ return end === -1 ? content : content.slice(0, end);
24365
+ }
24366
+ function isSeedNodeMarkdown(content) {
24367
+ const frontmatter = frontmatterOf(content);
24368
+ return frontmatter !== null && /^created_by:\s*["']?seed["']?\s*$/m.test(frontmatter);
24369
+ }
24370
+ function pickFrontmatterTitle(content) {
24371
+ const frontmatter = frontmatterOf(content);
24372
+ const match = frontmatter?.match(/^title:[ \t]*(.*)$/m);
24373
+ if (!match) return null;
24374
+ const raw = match[1].trim();
24375
+ if (raw.startsWith('"')) {
24376
+ try {
24377
+ return String(JSON.parse(raw));
24378
+ } catch {
24379
+ return raw.slice(1, raw.endsWith('"') ? -1 : void 0).replace(/\\"/g, '"');
24380
+ }
24381
+ }
24382
+ return raw;
24383
+ }
24384
+ async function serverSeedTitles(opts) {
24385
+ const res = await apiRequest({
24386
+ method: "GET",
24387
+ path: "/compound/memory/nodes?created_by=seed&status=active&limit=100",
24388
+ serviceUrl: opts.serviceUrl,
24389
+ token: opts.token,
24390
+ verbose: opts.verbose,
24391
+ cmd: "memory_seed"
24392
+ });
24393
+ if (!res.ok || !Array.isArray(res.data.nodes)) return null;
24394
+ const titles = /* @__PURE__ */ new Set();
24395
+ for (const n of res.data.nodes) if (typeof n?.title === "string") titles.add(normalizeTitle(n.title));
24396
+ return titles;
24397
+ }
23873
24398
  function renderNodeMarkdown(candidate, nodeId, createdAt) {
23874
24399
  const fm = [
23875
24400
  "---",
@@ -23893,19 +24418,19 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
23893
24418
  return fm;
23894
24419
  }
23895
24420
  async function runSeed(opts) {
23896
- if (!(0, import_node_fs42.existsSync)(STANDARD_FILE)) {
23897
- return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
24421
+ if (!(0, import_node_fs44.existsSync)(STANDARD_FILE)) {
24422
+ return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
23898
24423
  }
23899
24424
  let standardDoc;
23900
24425
  try {
23901
24426
  const raw = await (0, import_promises15.readFile)(STANDARD_FILE, "utf-8");
23902
24427
  standardDoc = (0, import_yaml4.parse)(raw);
23903
24428
  } catch {
23904
- return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
24429
+ return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
23905
24430
  }
23906
24431
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
23907
24432
  let readmeContent;
23908
- if ((0, import_node_fs42.existsSync)("README.md")) {
24433
+ if ((0, import_node_fs44.existsSync)("README.md")) {
23909
24434
  try {
23910
24435
  readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
23911
24436
  } catch {
@@ -23913,7 +24438,7 @@ async function runSeed(opts) {
23913
24438
  }
23914
24439
  let claudeMdContent;
23915
24440
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
23916
- if ((0, import_node_fs42.existsSync)(p)) {
24441
+ if ((0, import_node_fs44.existsSync)(p)) {
23917
24442
  try {
23918
24443
  claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
23919
24444
  break;
@@ -23934,19 +24459,33 @@ async function runSeed(opts) {
23934
24459
  claudeMdContent
23935
24460
  });
23936
24461
  if (candidates2.length === 0) {
23937
- return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
24462
+ return { created: 0, existing: 0, failed: 0, skipped: "no_candidates", candidates: [] };
23938
24463
  }
23939
- const overviewPath = (0, import_node_path32.join)(MEMORY_DIR, "domain", "project-overview.md");
23940
- if ((0, import_node_fs42.existsSync)(overviewPath) && !opts.force) {
23941
- return { created: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
24464
+ let toPost = candidates2;
24465
+ if (!opts.force) {
24466
+ const local = await localSeedTitles();
24467
+ toPost = toPost.filter((c) => !local.has(normalizeTitle(c.title)));
24468
+ if (toPost.length === 0) {
24469
+ return { created: 0, existing: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
24470
+ }
24471
+ if (!opts.dryRun) {
24472
+ const remote = await serverSeedTitles(opts);
24473
+ if (remote) {
24474
+ toPost = toPost.filter((c) => !remote.has(normalizeTitle(c.title)));
24475
+ if (toPost.length === 0) {
24476
+ return { created: 0, existing: 0, failed: 0, skipped: "already_seeded", candidates: candidates2 };
24477
+ }
24478
+ }
24479
+ }
23942
24480
  }
23943
24481
  if (opts.dryRun) {
23944
- return { created: 0, failed: 0, skipped: null, candidates: candidates2 };
24482
+ return { created: 0, existing: 0, failed: 0, skipped: null, candidates: candidates2 };
23945
24483
  }
23946
24484
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
23947
24485
  let created = 0;
24486
+ let existing = 0;
23948
24487
  let failed = 0;
23949
- for (const c of candidates2) {
24488
+ for (const c of toPost) {
23950
24489
  const res = await apiRequest({
23951
24490
  method: "POST",
23952
24491
  path: "/compound/memory/nodes",
@@ -23978,22 +24517,31 @@ async function runSeed(opts) {
23978
24517
  failed++;
23979
24518
  continue;
23980
24519
  }
24520
+ const deduplicated = res.data.deduplicated === true;
24521
+ if (deduplicated && (0, import_node_fs44.existsSync)(targetPath)) {
24522
+ existing++;
24523
+ continue;
24524
+ }
24525
+ const content = typeof res.data.content === "string" && res.data.content.length > 0 ? res.data.content : renderNodeMarkdown(c, nodeId, createdAt);
23981
24526
  try {
23982
- await (0, import_promises15.mkdir)((0, import_node_path32.dirname)(targetPath), { recursive: true });
23983
- await (0, import_promises15.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
23984
- created++;
23985
- opts.onCreated?.(nodeId, filePathRel, c);
24527
+ await (0, import_promises15.mkdir)((0, import_node_path33.dirname)(targetPath), { recursive: true });
24528
+ await (0, import_promises15.writeFile)(targetPath, content);
24529
+ if (deduplicated) existing++;
24530
+ else {
24531
+ created++;
24532
+ opts.onCreated?.(nodeId, filePathRel, c);
24533
+ }
23986
24534
  } catch (err) {
23987
24535
  opts.onFailed?.(c, `Server accepted "${c.title}" but couldn't write local file: ${err.message}`);
23988
24536
  failed++;
23989
24537
  }
23990
24538
  }
23991
- return { created, failed, skipped: null, candidates: candidates2 };
24539
+ return { created, existing, failed, skipped: null, candidates: candidates2 };
23992
24540
  }
23993
24541
 
23994
24542
  // src/commands/analyze/phases/08-memory-manifest.ts
23995
- var import_node_fs43 = require("node:fs");
23996
- var import_node_path33 = require("node:path");
24543
+ var import_node_fs45 = require("node:fs");
24544
+ var import_node_path34 = require("node:path");
23997
24545
  async function memoryManifest(run2) {
23998
24546
  const { globals } = run2;
23999
24547
  const { serviceUrl, token } = run2;
@@ -24003,9 +24551,9 @@ async function memoryManifest(run2) {
24003
24551
  let autoSeedNotice = null;
24004
24552
  try {
24005
24553
  await ensureMemoryDir();
24006
- const seedMarker = (0, import_node_path33.join)(VERITY_DIR, ".seeded");
24007
- const hasStandard = (0, import_node_fs43.existsSync)(STANDARD_FILE);
24008
- const alreadyTried = (0, import_node_fs43.existsSync)(seedMarker);
24554
+ const seedMarker = (0, import_node_path34.join)(VERITY_DIR, ".seeded");
24555
+ const hasStandard = (0, import_node_fs45.existsSync)(STANDARD_FILE);
24556
+ const alreadyTried = (0, import_node_fs45.existsSync)(seedMarker);
24009
24557
  if (hasStandard && !alreadyTried) {
24010
24558
  const preManifest = await buildManifest();
24011
24559
  if (preManifest.nodes.length === 0) {
@@ -24017,16 +24565,19 @@ async function memoryManifest(run2) {
24017
24565
  force: false,
24018
24566
  dryRun: false
24019
24567
  });
24020
- if (seedResult.created > 0) {
24021
- (0, import_node_fs43.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
24568
+ if (seedResult.created > 0 || seedResult.existing > 0) {
24569
+ (0, import_node_fs45.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
24022
24570
  `);
24023
- autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
24571
+ if (seedResult.created > 0) {
24572
+ autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
24573
+ }
24024
24574
  logEvent("auto_seed_ran", {
24025
24575
  created: seedResult.created,
24576
+ existing: seedResult.existing,
24026
24577
  failed: seedResult.failed
24027
24578
  });
24028
24579
  } else if (seedResult.skipped === "already_seeded") {
24029
- (0, import_node_fs43.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
24580
+ (0, import_node_fs45.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
24030
24581
  `);
24031
24582
  } else {
24032
24583
  logEvent("auto_seed_noop", {
@@ -24121,7 +24672,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
24121
24672
  }
24122
24673
 
24123
24674
  // src/commands/analyze/phases/10-working-memory.ts
24124
- var import_node_path34 = require("node:path");
24675
+ var import_node_path35 = require("node:path");
24125
24676
  async function workingMemory(run2) {
24126
24677
  const { opts } = run2;
24127
24678
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run2;
@@ -24133,7 +24684,7 @@ async function workingMemory(run2) {
24133
24684
  const priorState = foldForMarks(memorySession.d);
24134
24685
  incrementReport = computeIncrement(
24135
24686
  allForReview,
24136
- (p) => fileHash((0, import_node_path34.join)(repoRoot(), p)),
24687
+ (p) => fileHash((0, import_node_path35.join)(repoRoot(), p)),
24137
24688
  priorState.authored_all.map((a) => ({
24138
24689
  path: a.path,
24139
24690
  hash_at_last_verdict: a.hash_at_last_verdict
@@ -24215,7 +24766,7 @@ async function workingMemory(run2) {
24215
24766
  }
24216
24767
 
24217
24768
  // src/lib/note-budget.ts
24218
- var import_node_fs44 = require("node:fs");
24769
+ var import_node_fs46 = require("node:fs");
24219
24770
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
24220
24771
  var EPISODE_STALE_SECONDS = 30 * 60;
24221
24772
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -24237,9 +24788,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
24237
24788
  }
24238
24789
  function readAdvisoryEpisode(sessionId) {
24239
24790
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
24240
- if (!(0, import_node_fs44.existsSync)(file)) return null;
24791
+ if (!(0, import_node_fs46.existsSync)(file)) return null;
24241
24792
  try {
24242
- const o = JSON.parse((0, import_node_fs44.readFileSync)(file, "utf-8")) ?? {};
24793
+ const o = JSON.parse((0, import_node_fs46.readFileSync)(file, "utf-8")) ?? {};
24243
24794
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
24244
24795
  if (isNaN(delivered)) return null;
24245
24796
  return {
@@ -24253,8 +24804,8 @@ function readAdvisoryEpisode(sessionId) {
24253
24804
  }
24254
24805
  function writeAdvisoryEpisode(episode, sessionId) {
24255
24806
  try {
24256
- (0, import_node_fs44.mkdirSync)(VERITY_DIR, { recursive: true });
24257
- (0, import_node_fs44.writeFileSync)(
24807
+ (0, import_node_fs46.mkdirSync)(VERITY_DIR, { recursive: true });
24808
+ (0, import_node_fs46.writeFileSync)(
24258
24809
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
24259
24810
  JSON.stringify({ v: 1, ...episode })
24260
24811
  );
@@ -24323,6 +24874,11 @@ var MAX_ASSISTANT_RESPONSE_CHARS_PLAN = 32768;
24323
24874
  var MAX_ASSISTANT_RESPONSE_CHARS_DEFAULT = 8e3;
24324
24875
  async function buildRequest(run2) {
24325
24876
  const { actionSummary, allChanged, allForReview, analysisMode, analyzable, assistantResponse, codeDelta, conversation, deletedNodePaths, editedUploads, foldConservation, foldResult, incrementReport, iteration, memory, memoryManifest: memoryManifest2, memorySession, plans, reachability, reviewable, securityFiles, sessionId, snapshotResult, specs, staticResults, stopReason, turnId } = run2;
24877
+ const advisoryEpisode = episodeForWire(
24878
+ readAdvisoryEpisode(run2.baselineSessionId),
24879
+ (conversation?.prompts?.length ?? 0) > 0
24880
+ );
24881
+ const noteConfirmation = peekNoteOutcome();
24326
24882
  const excludedByReason = {};
24327
24883
  for (const e of codeDelta.excluded ?? []) {
24328
24884
  excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
@@ -24493,7 +25049,26 @@ async function buildRequest(run2) {
24493
25049
  },
24494
25050
  ...memoryManifest2 && { memory_manifest: memoryManifest2 },
24495
25051
  ...deletedNodePaths.length > 0 && { deleted_node_paths: deletedNodePaths },
24496
- ...editedUploads.length > 0 && { memory_files_upload: editedUploads }
25052
+ ...editedUploads.length > 0 && { memory_files_upload: editedUploads },
25053
+ // --- KNOWLEDGE-LOOP phase 5 -------------------------------------------
25054
+ //
25055
+ // The server decides whether to speak a memory node, and needs the episode
25056
+ // state to apply the SAME budget the client applies to its own advisory
25057
+ // content (`note-budget.ts`, ported and parity-tested). Sending it is not a
25058
+ // request for a note: it is what lets the budget be evaluated before the
25059
+ // ε-coin, which is what keeps the two holdout arms comparable.
25060
+ //
25061
+ // Absent on an old CLI, and the server answers `no_episode_state` rather
25062
+ // than guessing — silence is the safe direction when a forced turn cannot
25063
+ // be accounted for.
25064
+ advisory_episode: advisoryEpisode,
25065
+ // What the PREVIOUS run did with the note it was sent. The server decides,
25066
+ // but only the client knows whether the sentence actually reached the
25067
+ // agent, and an undelivered note must be voided rather than counted.
25068
+ ...noteConfirmation && {
25069
+ knowledge_note_run_id: noteConfirmation.run_id,
25070
+ knowledge_note_delivered: noteConfirmation.delivered
25071
+ }
24497
25072
  };
24498
25073
  if (snapshotResult.has_snapshots && snapshotResult.diffs.length > 0) {
24499
25074
  requestBody.snapshot_diffs = snapshotResult.diffs;
@@ -24562,14 +25137,14 @@ async function buildRequest(run2) {
24562
25137
  }
24563
25138
 
24564
25139
  // src/lib/offline.ts
24565
- var import_node_fs45 = require("node:fs");
24566
- var import_node_crypto11 = require("node:crypto");
25140
+ var import_node_fs47 = require("node:fs");
25141
+ var import_node_crypto12 = require("node:crypto");
24567
25142
  function cacheRequest(body) {
24568
25143
  try {
24569
- (0, import_node_fs45.mkdirSync)(CACHE_DIR, { recursive: true });
24570
- const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
25144
+ (0, import_node_fs47.mkdirSync)(CACHE_DIR, { recursive: true });
25145
+ const suffix = (0, import_node_crypto12.randomBytes)(4).toString("hex");
24571
25146
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
24572
- (0, import_node_fs45.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
25147
+ (0, import_node_fs47.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
24573
25148
  } catch {
24574
25149
  }
24575
25150
  }
@@ -24688,8 +25263,8 @@ async function transmit(run2) {
24688
25263
  }
24689
25264
 
24690
25265
  // src/commands/analyze/phases/13-reconcile.ts
24691
- var import_node_fs46 = require("node:fs");
24692
- var import_node_path35 = require("node:path");
25266
+ var import_node_fs48 = require("node:fs");
25267
+ var import_node_path36 = require("node:path");
24693
25268
  async function reconcile(run2) {
24694
25269
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
24695
25270
  const sentPaths = codeDelta.files.map((f) => f.path);
@@ -24718,7 +25293,7 @@ async function reconcile(run2) {
24718
25293
  const st = foldDossier(memorySession.d);
24719
25294
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
24720
25295
  try {
24721
- const src = (0, import_node_fs46.readFileSync)((0, import_node_path35.join)(repoRoot(), file), "utf8").split("\n");
25296
+ const src = (0, import_node_fs48.readFileSync)((0, import_node_path36.join)(repoRoot(), file), "utf8").split("\n");
24722
25297
  const at = src[line - 1];
24723
25298
  return at === void 0 ? null : lineSha(at);
24724
25299
  } catch {
@@ -25171,7 +25746,14 @@ function screenRemediation(fix, findingFile) {
25171
25746
 
25172
25747
  // src/commands/analyze/phases/14-render.ts
25173
25748
  function agentContextFor(response, intentRepeat = 0, priorPendingFingerprints = []) {
25174
- return buildAgentContext(channelInputFrom(response, intentRepeat, priorPendingFingerprints));
25749
+ const built = buildAgentContext(channelInputFrom(response, intentRepeat, priorPendingFingerprints));
25750
+ clearNoteOutcome();
25751
+ const note = parseKnowledgeNote(response.knowledge_note);
25752
+ if (note) {
25753
+ const runId = typeof response.run_id === "string" ? response.run_id : null;
25754
+ if (runId) recordNoteOutcome(runId, !!built && built.includes(note.text));
25755
+ }
25756
+ return built;
25175
25757
  }
25176
25758
  async function render(run2) {
25177
25759
  const { opts, globals } = run2;
@@ -25533,7 +26115,7 @@ function registerAnalyzeCommand(program2) {
25533
26115
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
25534
26116
  async function runAnalyze(opts, globals) {
25535
26117
  if (!verityConfigured()) {
25536
- (0, import_node_fs47.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
26118
+ (0, import_node_fs49.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
25537
26119
  process.exit(0);
25538
26120
  }
25539
26121
  const run2 = createRun(opts, globals);
@@ -25554,11 +26136,11 @@ async function runAnalyze(opts, globals) {
25554
26136
  }
25555
26137
 
25556
26138
  // src/commands/baseline.ts
25557
- var import_node_fs49 = require("node:fs");
26139
+ var import_node_fs51 = require("node:fs");
25558
26140
 
25559
26141
  // src/lib/project-skills.ts
25560
- var import_node_fs48 = require("node:fs");
25561
- var import_node_path36 = require("node:path");
26142
+ var import_node_fs50 = require("node:fs");
26143
+ var import_node_path37 = require("node:path");
25562
26144
  var PROJECT_SKILL_NAMES = [
25563
26145
  "verity-setup",
25564
26146
  "verity-analyze",
@@ -25583,14 +26165,14 @@ var LEGACY_SKILL_NAMES = [
25583
26165
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
25584
26166
  function staleProjectSkills() {
25585
26167
  const root = projectPath(".claude/skills");
25586
- if (!(0, import_node_fs48.existsSync)(root)) return [];
25587
- return ALL.filter((name) => (0, import_node_fs48.existsSync)((0, import_node_path36.join)(root, name)));
26168
+ if (!(0, import_node_fs50.existsSync)(root)) return [];
26169
+ return ALL.filter((name) => (0, import_node_fs50.existsSync)((0, import_node_path37.join)(root, name)));
25588
26170
  }
25589
26171
  function removeProjectSkills() {
25590
26172
  const root = projectPath(".claude/skills");
25591
26173
  const removed = [];
25592
26174
  for (const name of staleProjectSkills()) {
25593
- (0, import_node_fs48.rmSync)((0, import_node_path36.join)(root, name), { recursive: true, force: true });
26175
+ (0, import_node_fs50.rmSync)((0, import_node_path37.join)(root, name), { recursive: true, force: true });
25594
26176
  removed.push(name);
25595
26177
  }
25596
26178
  return removed;
@@ -25655,13 +26237,13 @@ function registerBaselineCommands(program2) {
25655
26237
  let memoryMsg = null;
25656
26238
  let memoryAgentLine = null;
25657
26239
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
25658
- if (realStart && !(0, import_node_fs49.existsSync)(memoryNotice)) {
26240
+ if (realStart && !(0, import_node_fs51.existsSync)(memoryNotice)) {
25659
26241
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
25660
26242
  if (trackedGraph > 0) {
25661
26243
  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.`;
25662
26244
  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.`;
25663
26245
  try {
25664
- (0, import_node_fs49.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
26246
+ (0, import_node_fs51.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
25665
26247
  } catch {
25666
26248
  }
25667
26249
  }
@@ -25732,7 +26314,7 @@ function registerBaselineCommands(program2) {
25732
26314
  }
25733
26315
  var MAX_HOOK_EVENT_BYTES = 64 * 1024;
25734
26316
  var HOOK_SOURCES = /* @__PURE__ */ new Set(["startup", "resume", "clear", "compact"]);
25735
- var SESSION_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
26317
+ var SESSION_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
25736
26318
  async function readStdin() {
25737
26319
  const chunks = [];
25738
26320
  let size = 0;
@@ -25754,7 +26336,7 @@ function parseHookEvent(input) {
25754
26336
  return { sessionId: validSessionId(id), source: hookSource(source) };
25755
26337
  }
25756
26338
  function validSessionId(value) {
25757
- return typeof value === "string" && SESSION_ID_RE.test(value) ? value : void 0;
26339
+ return typeof value === "string" && SESSION_ID_RE2.test(value) ? value : void 0;
25758
26340
  }
25759
26341
  function hookSource(value) {
25760
26342
  if (typeof value !== "string") return void 0;
@@ -25762,7 +26344,7 @@ function hookSource(value) {
25762
26344
  }
25763
26345
 
25764
26346
  // src/commands/review.ts
25765
- var import_node_fs50 = require("node:fs");
26347
+ var import_node_fs52 = require("node:fs");
25766
26348
  function registerReviewCommand(program2) {
25767
26349
  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) => {
25768
26350
  const globals = program2.opts();
@@ -25779,7 +26361,7 @@ async function runReview(opts, globals) {
25779
26361
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
25780
26362
  const analyzable = filterAnalyzable(allFiles);
25781
26363
  const securityFiles = filterSecurity(allFiles);
25782
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs50.existsSync)(f) || resolveFile(f) !== null);
26364
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs52.existsSync)(f) || resolveFile(f) !== null);
25783
26365
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
25784
26366
  const codeDelta = collectCodeDelta(allFiles);
25785
26367
  const tokenResult = await resolveToken(globals.token);
@@ -25845,8 +26427,8 @@ async function runReview(opts, globals) {
25845
26427
  }
25846
26428
 
25847
26429
  // src/commands/guard.ts
25848
- var import_node_fs51 = require("node:fs");
25849
- var import_node_path37 = require("node:path");
26430
+ var import_node_fs53 = require("node:fs");
26431
+ var import_node_path38 = require("node:path");
25850
26432
 
25851
26433
  // src/lib/terminal-text.ts
25852
26434
  var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
@@ -26221,7 +26803,7 @@ async function buildAgentDiffs(ctx, paths, limits = { perFileChars: 24e3, totalC
26221
26803
  // src/commands/guard.ts
26222
26804
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
26223
26805
  var GUARD_BLOCK_CAP = 2;
26224
- var GUARD_ITER_FILE = (0, import_node_path37.join)(VERITY_DIR, ".guard-iteration");
26806
+ var GUARD_ITER_FILE = (0, import_node_path38.join)(VERITY_DIR, ".guard-iteration");
26225
26807
  function readPreToolUseStdin() {
26226
26808
  const empty = { command: "", cwd: null, sessionId: null };
26227
26809
  return new Promise((resolve6) => {
@@ -26266,7 +26848,7 @@ function readPreToolUseStdin() {
26266
26848
  }
26267
26849
  function readIterMap() {
26268
26850
  try {
26269
- const raw = JSON.parse((0, import_node_fs51.readFileSync)(GUARD_ITER_FILE, "utf-8"));
26851
+ const raw = JSON.parse((0, import_node_fs53.readFileSync)(GUARD_ITER_FILE, "utf-8"));
26270
26852
  if (raw && typeof raw === "object") {
26271
26853
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
26272
26854
  return { [raw.moment]: raw.count };
@@ -26286,10 +26868,10 @@ function readIter(moment) {
26286
26868
  }
26287
26869
  function writeIter(moment, count) {
26288
26870
  try {
26289
- (0, import_node_fs51.mkdirSync)(VERITY_DIR, { recursive: true });
26871
+ (0, import_node_fs53.mkdirSync)(VERITY_DIR, { recursive: true });
26290
26872
  const map = readIterMap();
26291
26873
  map[moment] = count;
26292
- (0, import_node_fs51.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26874
+ (0, import_node_fs53.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26293
26875
  } catch {
26294
26876
  }
26295
26877
  }
@@ -26299,10 +26881,10 @@ function resetIter(moment) {
26299
26881
  if (!(moment in map)) return;
26300
26882
  delete map[moment];
26301
26883
  if (Object.keys(map).length === 0) {
26302
- if ((0, import_node_fs51.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs51.unlinkSync)(GUARD_ITER_FILE);
26884
+ if ((0, import_node_fs53.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs53.unlinkSync)(GUARD_ITER_FILE);
26303
26885
  } else {
26304
- (0, import_node_fs51.mkdirSync)(VERITY_DIR, { recursive: true });
26305
- (0, import_node_fs51.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26886
+ (0, import_node_fs53.mkdirSync)(VERITY_DIR, { recursive: true });
26887
+ (0, import_node_fs53.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
26306
26888
  }
26307
26889
  } catch {
26308
26890
  }
@@ -26372,7 +26954,7 @@ function hasBlockingFinding(response, sentFiles) {
26372
26954
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
26373
26955
  const analyzable = filterAnalyzable(files);
26374
26956
  const securityFiles = filterSecurity(files);
26375
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs51.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
26957
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs53.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
26376
26958
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
26377
26959
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
26378
26960
  const requestBody = {
@@ -26881,8 +27463,8 @@ function registerIgnoreCommand(program2) {
26881
27463
  }
26882
27464
 
26883
27465
  // src/commands/waive.ts
26884
- var import_node_crypto12 = require("node:crypto");
26885
- var import_node_fs52 = require("node:fs");
27466
+ var import_node_crypto13 = require("node:crypto");
27467
+ var import_node_fs54 = require("node:fs");
26886
27468
  function registerWaiveCommand(program2) {
26887
27469
  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) => {
26888
27470
  const globals = program2.opts();
@@ -26911,7 +27493,7 @@ function registerWaiveCommand(program2) {
26911
27493
  if (opts.file) {
26912
27494
  body.file = opts.file;
26913
27495
  try {
26914
- body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs52.readFileSync)(opts.file)).digest("hex");
27496
+ body.file_sha256 = (0, import_node_crypto13.createHash)("sha256").update((0, import_node_fs54.readFileSync)(opts.file)).digest("hex");
26915
27497
  } catch {
26916
27498
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
26917
27499
  process.exit(1);
@@ -26936,10 +27518,10 @@ function registerWaiveCommand(program2) {
26936
27518
  }
26937
27519
 
26938
27520
  // src/commands/init.ts
26939
- var import_node_fs56 = require("node:fs");
27521
+ var import_node_fs58 = require("node:fs");
26940
27522
  var import_promises19 = require("node:fs/promises");
26941
27523
  var import_yaml6 = __toESM(require_dist());
26942
- var import_node_path40 = require("node:path");
27524
+ var import_node_path41 = require("node:path");
26943
27525
  var import_node_child_process17 = require("node:child_process");
26944
27526
 
26945
27527
  // src/lib/banner.ts
@@ -27018,7 +27600,7 @@ function printPhase(n, of, title, subtitle) {
27018
27600
  }
27019
27601
 
27020
27602
  // src/commands/doctor.ts
27021
- var import_node_fs53 = require("node:fs");
27603
+ var import_node_fs55 = require("node:fs");
27022
27604
 
27023
27605
  // src/lib/prereqs.ts
27024
27606
  var import_node_child_process15 = require("node:child_process");
@@ -27226,11 +27808,11 @@ async function buildReport() {
27226
27808
  const hooks = wiring.status;
27227
27809
  const provenance = cliProvenance();
27228
27810
  const telemetry = await checkTelemetry();
27229
- const hasConfig = (0, import_node_fs53.existsSync)(projectPath(CODACY_CONFIG_FILE));
27811
+ const hasConfig = (0, import_node_fs55.existsSync)(projectPath(CODACY_CONFIG_FILE));
27230
27812
  const artifacts = {
27231
- standard: (0, import_node_fs53.existsSync)(projectPath(STANDARD_FILE)),
27813
+ standard: (0, import_node_fs55.existsSync)(projectPath(STANDARD_FILE)),
27232
27814
  analysisConfig: hasConfig,
27233
- verityMd: (0, import_node_fs53.existsSync)(projectPath(VERITY_MD_FILE)),
27815
+ verityMd: (0, import_node_fs55.existsSync)(projectPath(VERITY_MD_FILE)),
27234
27816
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
27235
27817
  };
27236
27818
  const next = [];
@@ -27371,8 +27953,8 @@ function registerDoctorCommand(program2) {
27371
27953
  }
27372
27954
 
27373
27955
  // src/commands/migrate.ts
27374
- var import_node_fs54 = require("node:fs");
27375
- var import_node_path38 = require("node:path");
27956
+ var import_node_fs56 = require("node:fs");
27957
+ var import_node_path39 = require("node:path");
27376
27958
  var import_node_child_process16 = require("node:child_process");
27377
27959
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
27378
27960
  function defaultNpmRemover(pkg) {
@@ -27409,12 +27991,12 @@ async function runMigration(opts = {}) {
27409
27991
  return { actions, migrated: actions.length > 0 };
27410
27992
  }
27411
27993
  function migrateProjectDir(root, actions) {
27412
- const gateDir = (0, import_node_path38.join)(root, ".gate");
27413
- const verityDir = (0, import_node_path38.join)(root, ".verity");
27414
- if ((0, import_node_fs54.existsSync)(gateDir) && !(0, import_node_fs54.existsSync)(verityDir)) {
27994
+ const gateDir = (0, import_node_path39.join)(root, ".gate");
27995
+ const verityDir = (0, import_node_path39.join)(root, ".verity");
27996
+ if ((0, import_node_fs56.existsSync)(gateDir) && !(0, import_node_fs56.existsSync)(verityDir)) {
27415
27997
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
27416
27998
  }
27417
- if ((0, import_node_fs54.existsSync)(gateDir) && (0, import_node_fs54.existsSync)(verityDir)) {
27999
+ if ((0, import_node_fs56.existsSync)(gateDir) && (0, import_node_fs56.existsSync)(verityDir)) {
27418
28000
  return migrateProjectDirCarry(gateDir, verityDir, actions);
27419
28001
  }
27420
28002
  return false;
@@ -27435,13 +28017,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
27435
28017
  }
27436
28018
  }
27437
28019
  if (moved) {
27438
- if ((0, import_node_fs54.existsSync)(gateDir)) {
28020
+ if ((0, import_node_fs56.existsSync)(gateDir)) {
27439
28021
  const carried = carryLegacyContents(gateDir, verityDir);
27440
28022
  if (carried > 0) {
27441
28023
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
27442
28024
  }
27443
28025
  try {
27444
- (0, import_node_fs54.rmSync)(gateDir, { recursive: true, force: true });
28026
+ (0, import_node_fs56.rmSync)(gateDir, { recursive: true, force: true });
27445
28027
  } catch {
27446
28028
  }
27447
28029
  }
@@ -27457,18 +28039,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
27457
28039
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
27458
28040
  }
27459
28041
  try {
27460
- (0, import_node_fs54.rmSync)(gateDir, { recursive: true, force: true });
28042
+ (0, import_node_fs56.rmSync)(gateDir, { recursive: true, force: true });
27461
28043
  } catch {
27462
28044
  }
27463
28045
  return carried > 0;
27464
28046
  }
27465
28047
  function migrateGlobalCredentials(home, actions) {
27466
28048
  if (!home) return;
27467
- const gateCreds = (0, import_node_path38.join)(home, ".gate", "credentials");
27468
- const verityCreds = (0, import_node_path38.join)(home, ".verity", "credentials");
27469
- if (!(0, import_node_fs54.existsSync)(gateCreds)) return;
27470
- if (!(0, import_node_fs54.existsSync)(verityCreds)) {
27471
- (0, import_node_fs54.mkdirSync)((0, import_node_path38.join)(home, ".verity"), { recursive: true });
28049
+ const gateCreds = (0, import_node_path39.join)(home, ".gate", "credentials");
28050
+ const verityCreds = (0, import_node_path39.join)(home, ".verity", "credentials");
28051
+ if (!(0, import_node_fs56.existsSync)(gateCreds)) return;
28052
+ if (!(0, import_node_fs56.existsSync)(verityCreds)) {
28053
+ (0, import_node_fs56.mkdirSync)((0, import_node_path39.join)(home, ".verity"), { recursive: true });
27472
28054
  moveFile(gateCreds, verityCreds);
27473
28055
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
27474
28056
  return;
@@ -27490,8 +28072,8 @@ async function migrateLegacyHooks(root, actions) {
27490
28072
  }
27491
28073
  }
27492
28074
  async function migrateClaudeMd(root, actions) {
27493
- const claudeMd = (0, import_node_path38.join)(root, "CLAUDE.md");
27494
- const hadLegacyBlock = (0, import_node_fs54.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
28075
+ const claudeMd = (0, import_node_path39.join)(root, "CLAUDE.md");
28076
+ const hadLegacyBlock = (0, import_node_fs56.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
27495
28077
  if (!hadLegacyBlock) return;
27496
28078
  try {
27497
28079
  await ensureClaudeMdPointer(root);
@@ -27501,9 +28083,9 @@ async function migrateClaudeMd(root, actions) {
27501
28083
  }
27502
28084
  }
27503
28085
  function migrateStandardFile(root, actions) {
27504
- const gateMd = (0, import_node_path38.join)(root, "GATE.md");
27505
- const verityMd = (0, import_node_path38.join)(root, "VERITY.md");
27506
- if (!(0, import_node_fs54.existsSync)(gateMd) || (0, import_node_fs54.existsSync)(verityMd)) return;
28086
+ const gateMd = (0, import_node_path39.join)(root, "GATE.md");
28087
+ const verityMd = (0, import_node_path39.join)(root, "VERITY.md");
28088
+ if (!(0, import_node_fs56.existsSync)(gateMd) || (0, import_node_fs56.existsSync)(verityMd)) return;
27507
28089
  let moved = false;
27508
28090
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
27509
28091
  try {
@@ -27515,12 +28097,12 @@ function migrateStandardFile(root, actions) {
27515
28097
  if (!moved) moveFile(gateMd, verityMd);
27516
28098
  const content = readFileSyncSafe(verityMd);
27517
28099
  const refreshed = content.split("GATE.md").join("VERITY.md");
27518
- if (refreshed !== content) (0, import_node_fs54.writeFileSync)(verityMd, refreshed);
28100
+ if (refreshed !== content) (0, import_node_fs56.writeFileSync)(verityMd, refreshed);
27519
28101
  actions.push("Renamed GATE.md \u2192 VERITY.md");
27520
28102
  }
27521
28103
  async function migrateTelemetryHeaders(root, actions) {
27522
- const file = (0, import_node_path38.join)(root, ".claude", "settings.local.json");
27523
- if (!(0, import_node_fs54.existsSync)(file)) return;
28104
+ const file = (0, import_node_path39.join)(root, ".claude", "settings.local.json");
28105
+ if (!(0, import_node_fs56.existsSync)(file)) return;
27524
28106
  let settings;
27525
28107
  try {
27526
28108
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -27568,14 +28150,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
27568
28150
  }
27569
28151
  if (toAppend.length > 0) {
27570
28152
  const sep4 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
27571
- (0, import_node_fs54.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
28153
+ (0, import_node_fs56.writeFileSync)(verityCreds, verityContent + sep4 + toAppend.join("\n") + "\n");
27572
28154
  }
27573
- (0, import_node_fs54.rmSync)(gateCreds, { force: true });
28155
+ (0, import_node_fs56.rmSync)(gateCreds, { force: true });
27574
28156
  return toAppend.length;
27575
28157
  }
27576
28158
  function readFileSyncSafe(path) {
27577
28159
  try {
27578
- return (0, import_node_fs54.readFileSync)(path, "utf-8");
28160
+ return (0, import_node_fs56.readFileSync)(path, "utf-8");
27579
28161
  } catch {
27580
28162
  return "";
27581
28163
  }
@@ -27590,35 +28172,35 @@ function hasStagedChanges(root) {
27590
28172
  }
27591
28173
  function moveDir(from, to) {
27592
28174
  try {
27593
- (0, import_node_fs54.renameSync)(from, to);
28175
+ (0, import_node_fs56.renameSync)(from, to);
27594
28176
  } catch (err) {
27595
28177
  if (err.code !== "EXDEV") throw err;
27596
- (0, import_node_fs54.cpSync)(from, to, { recursive: true });
27597
- (0, import_node_fs54.rmSync)(from, { recursive: true, force: true });
28178
+ (0, import_node_fs56.cpSync)(from, to, { recursive: true });
28179
+ (0, import_node_fs56.rmSync)(from, { recursive: true, force: true });
27598
28180
  }
27599
28181
  }
27600
28182
  function moveFile(from, to) {
27601
28183
  try {
27602
- (0, import_node_fs54.renameSync)(from, to);
28184
+ (0, import_node_fs56.renameSync)(from, to);
27603
28185
  } catch (err) {
27604
28186
  if (err.code !== "EXDEV") throw err;
27605
- (0, import_node_fs54.cpSync)(from, to);
27606
- (0, import_node_fs54.rmSync)(from, { force: true });
28187
+ (0, import_node_fs56.cpSync)(from, to);
28188
+ (0, import_node_fs56.rmSync)(from, { force: true });
27607
28189
  }
27608
28190
  }
27609
28191
  function carryLegacyContents(gateDir, verityDir) {
27610
28192
  let copied = 0;
27611
28193
  const walk2 = (relDir) => {
27612
- const srcDir = (0, import_node_path38.join)(gateDir, relDir);
27613
- for (const entry of (0, import_node_fs54.readdirSync)(srcDir)) {
27614
- const rel = relDir ? (0, import_node_path38.join)(relDir, entry) : entry;
27615
- const src = (0, import_node_path38.join)(gateDir, rel);
27616
- const dest = (0, import_node_path38.join)(verityDir, rel);
27617
- if ((0, import_node_fs54.statSync)(src).isDirectory()) {
28194
+ const srcDir = (0, import_node_path39.join)(gateDir, relDir);
28195
+ for (const entry of (0, import_node_fs56.readdirSync)(srcDir)) {
28196
+ const rel = relDir ? (0, import_node_path39.join)(relDir, entry) : entry;
28197
+ const src = (0, import_node_path39.join)(gateDir, rel);
28198
+ const dest = (0, import_node_path39.join)(verityDir, rel);
28199
+ if ((0, import_node_fs56.statSync)(src).isDirectory()) {
27618
28200
  walk2(rel);
27619
- } else if (!(0, import_node_fs54.existsSync)(dest)) {
27620
- (0, import_node_fs54.mkdirSync)((0, import_node_path38.dirname)(dest), { recursive: true });
27621
- (0, import_node_fs54.cpSync)(src, dest);
28201
+ } else if (!(0, import_node_fs56.existsSync)(dest)) {
28202
+ (0, import_node_fs56.mkdirSync)((0, import_node_path39.dirname)(dest), { recursive: true });
28203
+ (0, import_node_fs56.cpSync)(src, dest);
27622
28204
  copied++;
27623
28205
  }
27624
28206
  }
@@ -27627,22 +28209,22 @@ function carryLegacyContents(gateDir, verityDir) {
27627
28209
  return copied;
27628
28210
  }
27629
28211
  async function needsMigration(root = repoRoot()) {
27630
- const gateDir = (0, import_node_path38.join)(root, ".gate");
27631
- const verityDir = (0, import_node_path38.join)(root, ".verity");
27632
- if ((0, import_node_fs54.existsSync)(gateDir) && !(0, import_node_fs54.existsSync)(verityDir)) return true;
27633
- if ((0, import_node_fs54.existsSync)(gateDir) && (0, import_node_fs54.existsSync)(verityDir)) {
27634
- if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(gateDir, "credentials")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(verityDir, "credentials"))) {
28212
+ const gateDir = (0, import_node_path39.join)(root, ".gate");
28213
+ const verityDir = (0, import_node_path39.join)(root, ".verity");
28214
+ if ((0, import_node_fs56.existsSync)(gateDir) && !(0, import_node_fs56.existsSync)(verityDir)) return true;
28215
+ if ((0, import_node_fs56.existsSync)(gateDir) && (0, import_node_fs56.existsSync)(verityDir)) {
28216
+ if ((0, import_node_fs56.existsSync)((0, import_node_path39.join)(gateDir, "credentials")) && !(0, import_node_fs56.existsSync)((0, import_node_path39.join)(verityDir, "credentials"))) {
27635
28217
  return true;
27636
28218
  }
27637
- if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(gateDir, "memory")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(verityDir, "memory"))) {
28219
+ if ((0, import_node_fs56.existsSync)((0, import_node_path39.join)(gateDir, "memory")) && !(0, import_node_fs56.existsSync)((0, import_node_path39.join)(verityDir, "memory"))) {
27638
28220
  return true;
27639
28221
  }
27640
28222
  }
27641
- const claudeMd = (0, import_node_path38.join)(root, "CLAUDE.md");
27642
- if ((0, import_node_fs54.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
28223
+ const claudeMd = (0, import_node_path39.join)(root, "CLAUDE.md");
28224
+ if ((0, import_node_fs56.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
27643
28225
  return true;
27644
28226
  }
27645
- if ((0, import_node_fs54.existsSync)((0, import_node_path38.join)(root, "GATE.md")) && !(0, import_node_fs54.existsSync)((0, import_node_path38.join)(root, "VERITY.md"))) {
28227
+ if ((0, import_node_fs56.existsSync)((0, import_node_path39.join)(root, "GATE.md")) && !(0, import_node_fs56.existsSync)((0, import_node_path39.join)(root, "VERITY.md"))) {
27646
28228
  return true;
27647
28229
  }
27648
28230
  if (await hasLegacyHooksAt(root)) return true;
@@ -27923,9 +28505,9 @@ async function promptMultiSelect(question, choices, fallback) {
27923
28505
  }
27924
28506
 
27925
28507
  // src/lib/remote-config.ts
27926
- var import_node_fs55 = require("node:fs");
28508
+ var import_node_fs57 = require("node:fs");
27927
28509
  var import_promises18 = require("node:fs/promises");
27928
- var import_node_path39 = require("node:path");
28510
+ var import_node_path40 = require("node:path");
27929
28511
  var import_yaml5 = __toESM(require_dist());
27930
28512
  var IGNORE_RIDER = "verityignore";
27931
28513
  async function fetchRemoteSetup(opts) {
@@ -27970,7 +28552,7 @@ async function adoptRemoteSetup(found, opts) {
27970
28552
  written.push(STANDARD_FILE);
27971
28553
  if (rider !== null) {
27972
28554
  const localIgnore = projectPath(VERITYIGNORE_FILE);
27973
- if (!(0, import_node_fs55.existsSync)(localIgnore)) {
28555
+ if (!(0, import_node_fs57.existsSync)(localIgnore)) {
27974
28556
  await writeOut(VERITYIGNORE_FILE, rider);
27975
28557
  written.push(VERITYIGNORE_FILE);
27976
28558
  } else {
@@ -28003,7 +28585,7 @@ async function adoptRemoteSetup(found, opts) {
28003
28585
  }
28004
28586
  async function writeOut(relative3, body) {
28005
28587
  const target = projectPath(relative3);
28006
- await (0, import_promises18.mkdir)((0, import_node_path39.dirname)(target), { recursive: true });
28588
+ await (0, import_promises18.mkdir)((0, import_node_path40.dirname)(target), { recursive: true });
28007
28589
  await (0, import_promises18.writeFile)(target, body);
28008
28590
  }
28009
28591
  function describeRemote(found) {
@@ -28120,15 +28702,15 @@ async function runOptionalAuth(resolution, opts = {}) {
28120
28702
  }
28121
28703
  function resolveDataDir2() {
28122
28704
  const candidates2 = [
28123
- (0, import_node_path40.join)(__dirname, "..", "data"),
28705
+ (0, import_node_path41.join)(__dirname, "..", "data"),
28124
28706
  // installed: node_modules/@codacy/verity-cli/data
28125
- (0, import_node_path40.join)(__dirname, "..", "..", "data"),
28707
+ (0, import_node_path41.join)(__dirname, "..", "..", "data"),
28126
28708
  // edge case: nested resolution
28127
- (0, import_node_path40.join)(process.cwd(), "cli", "data")
28709
+ (0, import_node_path41.join)(process.cwd(), "cli", "data")
28128
28710
  // local dev: running from repo root
28129
28711
  ];
28130
28712
  for (const candidate of candidates2) {
28131
- if ((0, import_node_fs56.existsSync)((0, import_node_path40.join)(candidate, "skills"))) {
28713
+ if ((0, import_node_fs58.existsSync)((0, import_node_path41.join)(candidate, "skills"))) {
28132
28714
  return candidate;
28133
28715
  }
28134
28716
  }
@@ -28144,9 +28726,9 @@ async function skillIsCurrent(src, dest) {
28144
28726
  const list2 = (dir) => {
28145
28727
  const out = [];
28146
28728
  const walk2 = (d, prefix) => {
28147
- for (const e of (0, import_node_fs56.readdirSync)(d, { withFileTypes: true })) {
28729
+ for (const e of (0, import_node_fs58.readdirSync)(d, { withFileTypes: true })) {
28148
28730
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
28149
- if (e.isDirectory()) walk2((0, import_node_path40.join)(d, e.name), rel);
28731
+ if (e.isDirectory()) walk2((0, import_node_path41.join)(d, e.name), rel);
28150
28732
  else if (e.isFile()) out.push(rel);
28151
28733
  }
28152
28734
  };
@@ -28157,8 +28739,8 @@ async function skillIsCurrent(src, dest) {
28157
28739
  const shipped = list2(src);
28158
28740
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
28159
28741
  for (const rel of shipped) {
28160
- const a = await (0, import_promises19.readFile)((0, import_node_path40.join)(src, rel), "utf-8");
28161
- const b = await (0, import_promises19.readFile)((0, import_node_path40.join)(dest, rel), "utf-8");
28742
+ const a = await (0, import_promises19.readFile)((0, import_node_path41.join)(src, rel), "utf-8");
28743
+ const b = await (0, import_promises19.readFile)((0, import_node_path41.join)(dest, rel), "utf-8");
28162
28744
  if (a !== b) return false;
28163
28745
  }
28164
28746
  return true;
@@ -28339,7 +28921,7 @@ async function synthesizeLocally(opts) {
28339
28921
  async function healStaleAnalysisConfig(globals) {
28340
28922
  const configPath = projectPath(CODACY_CONFIG_FILE);
28341
28923
  const standardPath = projectPath(STANDARD_FILE);
28342
- if (!(0, import_node_fs56.existsSync)(configPath) || !(0, import_node_fs56.existsSync)(standardPath)) return;
28924
+ if (!(0, import_node_fs58.existsSync)(configPath) || !(0, import_node_fs58.existsSync)(standardPath)) return;
28343
28925
  const validation = validatePatternIds();
28344
28926
  if (validation.status !== "invalid") return;
28345
28927
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -28436,17 +29018,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
28436
29018
  async function installSkills(force, step) {
28437
29019
  step("Installing skills");
28438
29020
  const dataDir = resolveDataDir2();
28439
- const skillsSource = (0, import_node_path40.join)(dataDir, "skills");
29021
+ const skillsSource = (0, import_node_path41.join)(dataDir, "skills");
28440
29022
  const skillsDest = ".claude/skills";
28441
29023
  let skillsInstalled = 0;
28442
29024
  for (const skill of SKILLS) {
28443
- const src = (0, import_node_path40.join)(skillsSource, skill);
28444
- const dest = (0, import_node_path40.join)(skillsDest, skill);
28445
- if (!(0, import_node_fs56.existsSync)(src)) {
29025
+ const src = (0, import_node_path41.join)(skillsSource, skill);
29026
+ const dest = (0, import_node_path41.join)(skillsDest, skill);
29027
+ if (!(0, import_node_fs58.existsSync)(src)) {
28446
29028
  printWarn(` Skill data not found: ${skill}`);
28447
29029
  continue;
28448
29030
  }
28449
- if ((0, import_node_fs56.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
29031
+ if ((0, import_node_fs58.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
28450
29032
  skillsInstalled++;
28451
29033
  continue;
28452
29034
  }
@@ -28585,7 +29167,7 @@ function registerInitCommand(program2) {
28585
29167
  const staleMarker = clearStalePluginMarker();
28586
29168
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
28587
29169
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
28588
- const isProject = projectMarkers.some((m) => (0, import_node_fs56.existsSync)(m));
29170
+ const isProject = projectMarkers.some((m) => (0, import_node_fs58.existsSync)(m));
28589
29171
  if (!isProject) {
28590
29172
  printError("No project detected in the current directory.");
28591
29173
  printInfo('Run "verity init" from your project root.');
@@ -28675,7 +29257,7 @@ function registerInitCommand(program2) {
28675
29257
  printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
28676
29258
  }
28677
29259
  await scaffoldProject(step, defaultsOnly);
28678
- const globalVerityDir = (0, import_node_path40.join)(process.env.HOME ?? "", ".verity");
29260
+ const globalVerityDir = (0, import_node_path41.join)(process.env.HOME ?? "", ".verity");
28679
29261
  await (0, import_promises19.mkdir)(globalVerityDir, { recursive: true });
28680
29262
  console.log("");
28681
29263
  step("Wiring Claude Code hooks");
@@ -28744,7 +29326,7 @@ function registerInitCommand(program2) {
28744
29326
  }
28745
29327
  step("Your project's Standard");
28746
29328
  let haveStandard = false;
28747
- if ((0, import_node_fs56.existsSync)(projectPath(STANDARD_FILE))) {
29329
+ if ((0, import_node_fs58.existsSync)(projectPath(STANDARD_FILE))) {
28748
29330
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
28749
29331
  haveStandard = true;
28750
29332
  } else {
@@ -28774,7 +29356,7 @@ function registerInitCommand(program2) {
28774
29356
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
28775
29357
  init: {
28776
29358
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
28777
- cli_version: true ? "0.33.2-experimental.0c53bed" : "dev"
29359
+ cli_version: true ? "0.33.3-experimental.072d5cb" : "dev"
28778
29360
  }
28779
29361
  });
28780
29362
  } catch (err) {
@@ -28824,8 +29406,8 @@ function registerInitCommand(program2) {
28824
29406
  }
28825
29407
 
28826
29408
  // src/commands/uninstall.ts
28827
- var import_node_fs57 = require("node:fs");
28828
- var import_node_path41 = require("node:path");
29409
+ var import_node_fs59 = require("node:fs");
29410
+ var import_node_path42 = require("node:path");
28829
29411
  function registerUninstallCommand(program2) {
28830
29412
  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) => {
28831
29413
  const dryRun = opts.dryRun ?? false;
@@ -28834,11 +29416,11 @@ function registerUninstallCommand(program2) {
28834
29416
  const actions = [];
28835
29417
  const skillsRoot = projectPath(".claude/skills");
28836
29418
  for (const name of PROJECT_SKILL_NAMES) {
28837
- const dir = (0, import_node_path41.join)(skillsRoot, name);
28838
- if ((0, import_node_fs57.existsSync)(dir)) {
29419
+ const dir = (0, import_node_path42.join)(skillsRoot, name);
29420
+ if ((0, import_node_fs59.existsSync)(dir)) {
28839
29421
  actions.push({
28840
29422
  label: `Remove .claude/skills/${name}/`,
28841
- apply: () => (0, import_node_fs57.rmSync)(dir, { recursive: true, force: true })
29423
+ apply: () => (0, import_node_fs59.rmSync)(dir, { recursive: true, force: true })
28842
29424
  });
28843
29425
  }
28844
29426
  }
@@ -28852,24 +29434,24 @@ function registerUninstallCommand(program2) {
28852
29434
  });
28853
29435
  }
28854
29436
  const verityDir = projectPath(VERITY_DIR);
28855
- if ((0, import_node_fs57.existsSync)(verityDir)) {
29437
+ if ((0, import_node_fs59.existsSync)(verityDir)) {
28856
29438
  actions.push({
28857
29439
  label: `Remove ${VERITY_DIR}/`,
28858
- apply: () => (0, import_node_fs57.rmSync)(verityDir, { recursive: true, force: true })
29440
+ apply: () => (0, import_node_fs59.rmSync)(verityDir, { recursive: true, force: true })
28859
29441
  });
28860
29442
  }
28861
29443
  if (!keepVerityMd) {
28862
29444
  const verityMd = projectPath(VERITY_MD_FILE);
28863
- if ((0, import_node_fs57.existsSync)(verityMd)) {
29445
+ if ((0, import_node_fs59.existsSync)(verityMd)) {
28864
29446
  actions.push({
28865
29447
  label: `Remove ${VERITY_MD_FILE}`,
28866
- apply: () => (0, import_node_fs57.rmSync)(verityMd, { force: true })
29448
+ apply: () => (0, import_node_fs59.rmSync)(verityMd, { force: true })
28867
29449
  });
28868
29450
  }
28869
29451
  }
28870
29452
  const cleanupEmptyDir = (path) => {
28871
- if ((0, import_node_fs57.existsSync)(path) && (0, import_node_fs57.statSync)(path).isDirectory() && (0, import_node_fs57.readdirSync)(path).length === 0) {
28872
- (0, import_node_fs57.rmdirSync)(path);
29453
+ if ((0, import_node_fs59.existsSync)(path) && (0, import_node_fs59.statSync)(path).isDirectory() && (0, import_node_fs59.readdirSync)(path).length === 0) {
29454
+ (0, import_node_fs59.rmdirSync)(path);
28873
29455
  }
28874
29456
  };
28875
29457
  actions.push({
@@ -28880,11 +29462,11 @@ function registerUninstallCommand(program2) {
28880
29462
  }
28881
29463
  });
28882
29464
  const home = process.env.HOME ?? "";
28883
- const globalVerityDir = (0, import_node_path41.join)(home, ".verity");
28884
- if (purgeGlobal && (0, import_node_fs57.existsSync)(globalVerityDir)) {
29465
+ const globalVerityDir = (0, import_node_path42.join)(home, ".verity");
29466
+ if (purgeGlobal && (0, import_node_fs59.existsSync)(globalVerityDir)) {
28885
29467
  actions.push({
28886
29468
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
28887
- apply: () => (0, import_node_fs57.rmSync)(globalVerityDir, { recursive: true, force: true })
29469
+ apply: () => (0, import_node_fs59.rmSync)(globalVerityDir, { recursive: true, force: true })
28888
29470
  });
28889
29471
  }
28890
29472
  if (actions.length === 0) {
@@ -29078,8 +29660,8 @@ function registerTaskCommands(program2) {
29078
29660
  }
29079
29661
 
29080
29662
  // src/commands/reset.ts
29081
- var import_node_fs58 = require("node:fs");
29082
- var import_node_path42 = require("node:path");
29663
+ var import_node_fs60 = require("node:fs");
29664
+ var import_node_path43 = require("node:path");
29083
29665
  function registerResetCommand(program2) {
29084
29666
  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) => {
29085
29667
  const globals = program2.opts();
@@ -29116,11 +29698,11 @@ function registerResetCommand(program2) {
29116
29698
  }
29117
29699
  const cacheDir = projectPath(CACHE_DIR);
29118
29700
  let purged = 0;
29119
- if ((0, import_node_fs58.existsSync)(cacheDir)) {
29120
- for (const entry of (0, import_node_fs58.readdirSync)(cacheDir)) {
29701
+ if ((0, import_node_fs60.existsSync)(cacheDir)) {
29702
+ for (const entry of (0, import_node_fs60.readdirSync)(cacheDir)) {
29121
29703
  if (entry.startsWith("pending-")) {
29122
29704
  try {
29123
- (0, import_node_fs58.unlinkSync)((0, import_node_path42.join)(cacheDir, entry));
29705
+ (0, import_node_fs60.unlinkSync)((0, import_node_path43.join)(cacheDir, entry));
29124
29706
  purged++;
29125
29707
  } catch {
29126
29708
  }
@@ -29135,19 +29717,19 @@ function registerResetCommand(program2) {
29135
29717
  projectPath(`${VERITY_DIR}/.last-analysis`)
29136
29718
  ];
29137
29719
  for (const file of filesToClear) {
29138
- if ((0, import_node_fs58.existsSync)(file)) {
29720
+ if ((0, import_node_fs60.existsSync)(file)) {
29139
29721
  try {
29140
- (0, import_node_fs58.writeFileSync)(file, "");
29722
+ (0, import_node_fs60.writeFileSync)(file, "");
29141
29723
  } catch {
29142
29724
  }
29143
29725
  }
29144
29726
  }
29145
29727
  if (opts.all) {
29146
29728
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
29147
- if ((0, import_node_fs58.existsSync)(logsDir)) {
29148
- for (const entry of (0, import_node_fs58.readdirSync)(logsDir)) {
29729
+ if ((0, import_node_fs60.existsSync)(logsDir)) {
29730
+ for (const entry of (0, import_node_fs60.readdirSync)(logsDir)) {
29149
29731
  try {
29150
- (0, import_node_fs58.unlinkSync)((0, import_node_path42.join)(logsDir, entry));
29732
+ (0, import_node_fs60.unlinkSync)((0, import_node_path43.join)(logsDir, entry));
29151
29733
  } catch {
29152
29734
  }
29153
29735
  }
@@ -29159,7 +29741,7 @@ function registerResetCommand(program2) {
29159
29741
  }
29160
29742
 
29161
29743
  // src/commands/reflect.ts
29162
- var import_node_fs59 = require("node:fs");
29744
+ var import_node_fs61 = require("node:fs");
29163
29745
 
29164
29746
  // src/lib/reflection-globs.ts
29165
29747
  var MAX_GLOBS = 6;
@@ -29197,7 +29779,7 @@ async function writeNodeToDisk(args) {
29197
29779
  { treePaths: listTrackedFiles(), recordBaseline: false }
29198
29780
  );
29199
29781
  if (written === 0) return false;
29200
- return (0, import_node_fs59.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
29782
+ return (0, import_node_fs61.existsSync)(projectPath(`${VERITY_DIR}/memory/${args.filePath}`));
29201
29783
  } catch {
29202
29784
  return false;
29203
29785
  }
@@ -29400,7 +29982,7 @@ function registerMemoryCommand(program2) {
29400
29982
  process.exit(0);
29401
29983
  }
29402
29984
  if (result.skipped === "already_seeded") {
29403
- printInfo("Memory graph already seeded (.verity/memory/domain/project-overview.md exists). Use --force to re-seed.");
29985
+ printInfo("Memory graph already seeded \u2014 this project has seed nodes (locally or on the server). Use --force to re-materialize them.");
29404
29986
  process.exit(0);
29405
29987
  }
29406
29988
  if (opts.dryRun) {
@@ -29411,10 +29993,11 @@ function registerMemoryCommand(program2) {
29411
29993
  process.exit(0);
29412
29994
  }
29413
29995
  console.log("");
29996
+ const existingNote = result.existing > 0 ? ` ${result.existing} already existed on the server and were not duplicated.` : "";
29414
29997
  if (result.failed === 0) {
29415
- printInfo(`Seeded ${result.created} knowledge node(s) from the Standard into .verity/memory/.`);
29998
+ printInfo(`Seeded ${result.created} knowledge node(s) from the Standard into .verity/memory/.${existingNote}`);
29416
29999
  } else {
29417
- printWarn(`Seeded ${result.created} node(s); ${result.failed} failed. See messages above.`);
30000
+ printWarn(`Seeded ${result.created} node(s); ${result.failed} failed.${existingNote} See messages above.`);
29418
30001
  }
29419
30002
  process.exit(result.failed === 0 ? 0 : 1);
29420
30003
  });
@@ -29696,8 +30279,8 @@ function registerTelemetryCommands(program2) {
29696
30279
  }
29697
30280
 
29698
30281
  // src/cli.ts
29699
- program.name("verity").description("CLI for Verity quality gate service").version("0.33.2-experimental.0c53bed").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) => {
29700
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.2-experimental.0c53bed");
30282
+ program.name("verity").description("CLI for Verity quality gate service").version("0.33.3-experimental.072d5cb").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) => {
30283
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.33.3-experimental.072d5cb");
29701
30284
  setUserNamedServiceUrl(program.opts().serviceUrl);
29702
30285
  try {
29703
30286
  await foldLegacyLocalCredential();