@codacy/verity-cli 0.32.0-experimental.68ae2ee → 0.32.0-experimental.f0746f7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/verity.js CHANGED
@@ -10405,8 +10405,6 @@ var MAX_INTENT_CHARS = 2e3;
10405
10405
  var SNAPSHOT_DIR = `${VERITY_DIR}/.snapshot`;
10406
10406
  var BASELINE_DIR = `${VERITY_DIR}/.baseline`;
10407
10407
  var CONVERSATION_BUFFER_FILE = `${VERITY_DIR}/.conversation-buffer`;
10408
- var PLUGIN_MARKER_FILE = `${VERITY_DIR}/.plugin-active`;
10409
- var PROJECT_CONFIG_FILE = `${VERITY_DIR}/config.json`;
10410
10408
  var CONVERSATION_MAX_ENTRIES = 10;
10411
10409
  var CONVERSATION_WINDOW_MINUTES = 15;
10412
10410
  var MAX_FINDINGS = 25;
@@ -10833,18 +10831,6 @@ function splitLines(s) {
10833
10831
  }
10834
10832
  var SHA_RE = /^[0-9a-f]{40}$/;
10835
10833
  function readBaselineSha() {
10836
- const sha = readRawBaselineSha();
10837
- if (sha === null) return null;
10838
- if (!commitResolves(sha)) {
10839
- try {
10840
- (0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
10841
- } catch {
10842
- }
10843
- return null;
10844
- }
10845
- return sha;
10846
- }
10847
- function readRawBaselineSha() {
10848
10834
  if (!(0, import_node_fs3.existsSync)(BASELINE_SHA_FILE)) return null;
10849
10835
  let sha;
10850
10836
  try {
@@ -10852,7 +10838,16 @@ function readRawBaselineSha() {
10852
10838
  } catch {
10853
10839
  return null;
10854
10840
  }
10855
- return SHA_RE.test(sha) ? sha : null;
10841
+ if (!SHA_RE.test(sha)) return null;
10842
+ const reachable = execGit(`git cat-file -e ${sha}^{commit} 2>/dev/null && echo ok`) === "ok";
10843
+ if (!reachable) {
10844
+ try {
10845
+ (0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
10846
+ } catch {
10847
+ }
10848
+ return null;
10849
+ }
10850
+ return sha;
10856
10851
  }
10857
10852
  function writeBaselineSha(sha) {
10858
10853
  if (!SHA_RE.test(sha)) return;
@@ -10862,25 +10857,6 @@ function writeBaselineSha(sha) {
10862
10857
  } catch {
10863
10858
  }
10864
10859
  }
10865
- function commitObjectExists(sha) {
10866
- if (!SHA_RE.test(sha)) return false;
10867
- return execGit(`git cat-file -e ${sha}^{commit} 2>/dev/null && echo ok`) === "ok";
10868
- }
10869
- function committedSinceRewrite(oldSha) {
10870
- if (!SHA_RE.test(oldSha)) return [];
10871
- const newLocal = new Set(splitLines(execGit(`git rev-list HEAD --not ${oldSha} --remotes`)));
10872
- if (newLocal.size === 0) return [];
10873
- const files = /* @__PURE__ */ new Set();
10874
- for (const line of splitLines(execGit(`git cherry ${oldSha} HEAD`))) {
10875
- const sp = line.indexOf(" ");
10876
- if (sp < 0) continue;
10877
- const mark = line.slice(0, sp);
10878
- const sha = line.slice(sp + 1).trim();
10879
- if (mark !== "+" || !newLocal.has(sha)) continue;
10880
- for (const f of splitLines(execGit(`git diff-tree --no-commit-id --name-only -r ${sha}`))) files.add(f);
10881
- }
10882
- return [...files].filter((f) => !isVerityOwnedPath(f));
10883
- }
10884
10860
  var VERITY_OWNED_PREFIXES = [".verity/", ".gate/", ".codacy/"];
10885
10861
  var VERITY_OWNED_FILES = ["VERITY.md"];
10886
10862
  function isVerityOwnedPath(file) {
@@ -10893,7 +10869,6 @@ function getChangedFiles() {
10893
10869
  for (const f of splitLines(execGit("git diff --name-only HEAD"))) sets.add(f);
10894
10870
  for (const f of splitLines(execGit("git diff --name-only --cached"))) sets.add(f);
10895
10871
  for (const f of splitLines(execGit("git ls-files --others --exclude-standard"))) sets.add(f);
10896
- const rawBaseline = readRawBaselineSha();
10897
10872
  const baseline = readBaselineSha();
10898
10873
  if (baseline) {
10899
10874
  const committed = splitLines(execGit(`git diff --name-only ${baseline}..HEAD`));
@@ -10901,13 +10876,6 @@ function getChangedFiles() {
10901
10876
  hasRecentCommitFiles = true;
10902
10877
  for (const f of committed) sets.add(f);
10903
10878
  }
10904
- } else if (rawBaseline && commitObjectExists(rawBaseline)) {
10905
- const committed = committedSinceRewrite(rawBaseline);
10906
- logEvent("baseline_rewritten", { recovered: committed.length });
10907
- if (committed.length > 0) {
10908
- hasRecentCommitFiles = true;
10909
- for (const f of committed) sets.add(f);
10910
- }
10911
10879
  } else {
10912
10880
  const headTimestamp = parseInt(execGit("git log -1 --format=%ct HEAD"), 10) || 0;
10913
10881
  const commitAge = Math.floor(Date.now() / 1e3) - headTimestamp;
@@ -12733,155 +12701,9 @@ async function applyMomentSelection(moments) {
12733
12701
  return settings;
12734
12702
  }
12735
12703
 
12736
- // src/lib/project-config.ts
12737
- var import_node_fs4 = require("node:fs");
12738
- var DEFAULTS = { git_moments: [] };
12739
- function isMoment(value) {
12740
- return value === "commit" || value === "push";
12741
- }
12742
- function parseMoments(raw) {
12743
- return [...new Set(raw.split(",").map((s) => s.trim()).filter(isMoment))];
12744
- }
12745
- function readProjectConfig() {
12746
- try {
12747
- if (!(0, import_node_fs4.existsSync)(PROJECT_CONFIG_FILE)) return DEFAULTS;
12748
- const raw = JSON.parse((0, import_node_fs4.readFileSync)(PROJECT_CONFIG_FILE, "utf-8"));
12749
- const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
12750
- return { git_moments: [...new Set(moments)] };
12751
- } catch {
12752
- return DEFAULTS;
12753
- }
12754
- }
12755
- function writeProjectConfig(patch) {
12756
- const next = { ...readProjectConfig(), ...patch };
12757
- (0, import_node_fs4.mkdirSync)(VERITY_DIR, { recursive: true });
12758
- (0, import_node_fs4.writeFileSync)(PROJECT_CONFIG_FILE, JSON.stringify(next, null, 2) + "\n");
12759
- return next;
12760
- }
12761
- function resolveGuardMoments(explicit) {
12762
- if (explicit !== void 0) return parseMoments(explicit);
12763
- return readProjectConfig().git_moments;
12764
- }
12765
-
12766
- // src/lib/plugin-ownership.ts
12767
- var import_node_fs6 = require("node:fs");
12768
-
12769
- // src/lib/stderr-log.ts
12770
- var import_node_fs5 = require("node:fs");
12771
- var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
12772
- var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
12773
- function scrub(s) {
12774
- return s.replace(TOKEN_RE2, "verity_***REDACTED***").replace(ANSI_RE, "");
12775
- }
12776
- var installed = false;
12777
- var wroteBanner = false;
12778
- var banner = "";
12779
- function append(text) {
12780
- try {
12781
- const dir = projectPath(DEBUG_LOG_DIR);
12782
- const file = projectPath(STDERR_LOG_FILE);
12783
- (0, import_node_fs5.mkdirSync)(dir, { recursive: true });
12784
- rotateIfNeeded(file);
12785
- (0, import_node_fs5.appendFileSync)(file, text);
12786
- } catch {
12787
- }
12788
- }
12789
- function ensureBanner() {
12790
- if (wroteBanner) return;
12791
- wroteBanner = true;
12792
- append(banner);
12793
- }
12794
- function installStderrLog(cmd, argv, version) {
12795
- if (installed || !isDebugEnabled()) return;
12796
- installed = true;
12797
- banner = `
12798
- \u2501\u2501 verity ${cmd} \xB7 ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 pid ${process.pid}
12799
- v${version} \xB7 ${process.cwd()}
12800
- argv: ${scrub(argv.join(" "))}
12801
- `;
12802
- const original = process.stderr.write.bind(process.stderr);
12803
- const tee = (...args) => {
12804
- const result = original(...args);
12805
- try {
12806
- const chunk = args[0];
12807
- const text = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
12808
- ensureBanner();
12809
- append(scrub(text));
12810
- } catch {
12811
- }
12812
- return result;
12813
- };
12814
- process.stderr.write = tee;
12815
- }
12816
- function logToFileOnly(text) {
12817
- if (!installed) return;
12818
- ensureBanner();
12819
- append(text.endsWith("\n") ? text : `${text}
12820
- `);
12821
- }
12822
-
12823
- // src/lib/plugin-ownership.ts
12824
- var MARKER_TTL_SECONDS = 24 * 60 * 60;
12825
- function isPluginInvocation() {
12826
- return !!process.env.VERITY_PLUGIN_ROOT;
12827
- }
12828
- function readMarker() {
12829
- try {
12830
- if (!(0, import_node_fs6.existsSync)(PLUGIN_MARKER_FILE)) return null;
12831
- const raw = JSON.parse((0, import_node_fs6.readFileSync)(PLUGIN_MARKER_FILE, "utf-8"));
12832
- const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
12833
- if (!pluginRoot) return null;
12834
- return {
12835
- session_id: typeof raw.session_id === "string" ? raw.session_id : null,
12836
- plugin_root: pluginRoot,
12837
- version: typeof raw.version === "string" ? raw.version : null,
12838
- ts: typeof raw.ts === "number" ? raw.ts : 0
12839
- };
12840
- } catch {
12841
- return null;
12842
- }
12843
- }
12844
- function recordPluginOwnership(sessionId) {
12845
- const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
12846
- if (!pluginRoot) return;
12847
- try {
12848
- (0, import_node_fs6.mkdirSync)(VERITY_DIR, { recursive: true });
12849
- const marker = {
12850
- session_id: sessionId,
12851
- plugin_root: pluginRoot,
12852
- version: process.env.VERITY_PLUGIN_VERSION || null,
12853
- ts: Math.floor(Date.now() / 1e3)
12854
- };
12855
- (0, import_node_fs6.writeFileSync)(PLUGIN_MARKER_FILE, JSON.stringify(marker));
12856
- } catch {
12857
- }
12858
- }
12859
- function shouldDeferToPlugin(sessionId) {
12860
- if (isPluginInvocation()) {
12861
- recordPluginOwnership(sessionId);
12862
- return false;
12863
- }
12864
- const marker = readMarker();
12865
- if (!marker) return false;
12866
- if (!(0, import_node_fs6.existsSync)(marker.plugin_root)) return false;
12867
- if (sessionId && marker.session_id) return sessionId === marker.session_id;
12868
- return Math.floor(Date.now() / 1e3) - marker.ts < MARKER_TTL_SECONDS;
12869
- }
12870
- function pluginActiveHere() {
12871
- const marker = readMarker();
12872
- return !!marker && (0, import_node_fs6.existsSync)(marker.plugin_root);
12873
- }
12874
- function deferredToPlugin(command, sessionId) {
12875
- if (!shouldDeferToPlugin(sessionId)) return false;
12876
- logToFileOnly(
12877
- `${command}: the Verity Claude Code plugin owns this session's hooks \u2014 standing down so the turn is not gated twice. Remove the duplicate settings.json hooks with \`verity init --plugin-mode\`.`
12878
- );
12879
- return true;
12880
- }
12881
-
12882
12704
  // src/commands/hooks.ts
12883
12705
  var ALL_MOMENTS = ["stop", "pre-commit", "pre-push"];
12884
- function parseMoments2(raw) {
12706
+ function parseMoments(raw) {
12885
12707
  const seen = /* @__PURE__ */ new Set();
12886
12708
  for (const part of raw.split(",").map((s) => s.trim()).filter(Boolean)) {
12887
12709
  if (ALL_MOMENTS.includes(part)) seen.add(part);
@@ -12893,22 +12715,7 @@ function registerHooksCommands(program2) {
12893
12715
  hooks.command("install").description("Install Verity hooks into Claude Code settings").option("--force", "Overwrite existing Verity hooks").option("--moments <list>", "Reconcile to exactly these moments: stop,pre-commit,pre-push").action(async (opts) => {
12894
12716
  const force = opts.force ?? false;
12895
12717
  if (opts.moments != null) {
12896
- const moments = parseMoments2(opts.moments);
12897
- const gitMoments = [
12898
- ...moments.includes("pre-commit") ? ["commit"] : [],
12899
- ...moments.includes("pre-push") ? ["push"] : []
12900
- ];
12901
- writeProjectConfig({ git_moments: gitMoments });
12902
- if (pluginActiveHere()) {
12903
- printInfo("The Verity plugin wires the hooks; recorded your selection in .verity/config.json:");
12904
- printInfo(` Stop (analysis on every turn): ${moments.includes("stop") ? "on" : "off \u2014 the plugin still wires it; see below"}`);
12905
- printInfo(` Pre-commit gate: ${gitMoments.includes("commit") ? "on" : "off"}`);
12906
- printInfo(` Pre-push/PR gate: ${gitMoments.includes("push") ? "on" : "off"}`);
12907
- if (!moments.includes("stop")) {
12908
- printWarn(" Turning the Stop review off is not yet supported under the plugin \u2014 it stays on.");
12909
- }
12910
- return;
12911
- }
12718
+ const moments = parseMoments(opts.moments);
12912
12719
  await applyMomentSelection(moments);
12913
12720
  const status = await checkAllVerityHooks();
12914
12721
  printInfo("Verity hooks reconciled in .claude/settings.json:");
@@ -12955,24 +12762,6 @@ function registerHooksCommands(program2) {
12955
12762
  });
12956
12763
  hooks.command("check").description("Check if Verity hooks are installed").action(async () => {
12957
12764
  const status = await checkAllVerityHooks();
12958
- if (pluginActiveHere()) {
12959
- const moments = readProjectConfig().git_moments;
12960
- printInfo("Wired by the Verity Claude Code plugin (not .claude/settings.json):");
12961
- printInfo(" Stop hook (verity analyze): installed");
12962
- printInfo(" Intent hook (verity intent capture): installed");
12963
- printInfo(" Baseline hook (verity baseline capture): installed");
12964
- printInfo(
12965
- ` Git-moment gate (verity guard): ${moments.length ? `installed [${moments.join(", ")}]` : "wired but gating nothing"}`
12966
- );
12967
- if (!moments.length) {
12968
- printInfo(' Enable it with "verity config git-moments commit,push".');
12969
- }
12970
- if (status.stop || status.intent || status.baseline || status.guard) {
12971
- printWarn(" Duplicate hooks also exist in .claude/settings.json. They stand down at run time,");
12972
- printWarn(' but remove them with "verity init --plugin-mode" so the wiring says what it does.');
12973
- }
12974
- return;
12975
- }
12976
12765
  printInfo(`Stop hook (verity analyze): ${status.stop ? "installed" : "not installed"}`);
12977
12766
  printInfo(`Intent hook (verity intent capture): ${status.intent ? "installed" : "not installed"}`);
12978
12767
  printInfo(`Baseline hook (verity baseline capture): ${status.baseline ? "installed" : "not installed"}`);
@@ -12998,7 +12787,7 @@ var import_node_crypto8 = require("node:crypto");
12998
12787
 
12999
12788
  // src/lib/conversation-buffer.ts
13000
12789
  var import_promises5 = require("node:fs/promises");
13001
- var import_node_fs7 = require("node:fs");
12790
+ var import_node_fs4 = require("node:fs");
13002
12791
  var import_node_child_process5 = require("node:child_process");
13003
12792
  var import_node_crypto = require("node:crypto");
13004
12793
  function stripImageReferences(text) {
@@ -13034,7 +12823,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
13034
12823
  }
13035
12824
  async function readAndClearConversationBuffer(currentSessionId) {
13036
12825
  try {
13037
- if ((0, import_node_fs7.existsSync)(CONVERSATION_BUFFER_FILE)) {
12826
+ if ((0, import_node_fs4.existsSync)(CONVERSATION_BUFFER_FILE)) {
13038
12827
  const entries = await readBufferEntries();
13039
12828
  let mine = entries;
13040
12829
  let others = [];
@@ -13058,7 +12847,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
13058
12847
  };
13059
12848
  }
13060
12849
  }
13061
- if ((0, import_node_fs7.existsSync)(INTENT_FILE)) {
12850
+ if ((0, import_node_fs4.existsSync)(INTENT_FILE)) {
13062
12851
  try {
13063
12852
  const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
13064
12853
  await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
@@ -13113,301 +12902,65 @@ function getRecentCommitMessages() {
13113
12902
  }
13114
12903
  }
13115
12904
 
13116
- // src/lib/analysis-mode.ts
13117
- var DEBUG_PHRASES = [
13118
- "not working",
13119
- "doesn't work",
13120
- "doesn't work",
13121
- "does not work",
13122
- "isn't working",
13123
- "is not working",
13124
- "can't figure out",
13125
- "stack trace"
13126
- ];
13127
- var DEBUG_WORDS = [
13128
- "fix",
13129
- "bug",
13130
- "broken",
13131
- "crash",
13132
- "crashing",
13133
- "failing",
13134
- "debug",
13135
- "debugging",
13136
- "investigate",
13137
- "troubleshoot",
13138
- "regression",
13139
- "wrong"
13140
- ];
13141
- var DEBUG_PATTERN = new RegExp(
13142
- [
13143
- ...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
13144
- ...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
13145
- ].join("|"),
13146
- "i"
13147
- );
13148
- var FALSE_POSITIVE_PATTERNS = [
13149
- /\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
13150
- /\berror\s+handling\b/i,
13151
- /\berror\s+boundar(?:y|ies)\b/i,
13152
- /\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
13153
- /\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
13154
- ];
13155
- function hasDebugIntent(prompt) {
13156
- if (!DEBUG_PATTERN.test(prompt)) return false;
13157
- for (const fp of FALSE_POSITIVE_PATTERNS) {
13158
- if (fp.test(prompt)) return false;
12905
+ // src/lib/context-identity.ts
12906
+ var import_node_crypto2 = require("node:crypto");
12907
+ var import_node_fs5 = require("node:fs");
12908
+ var import_node_os2 = require("node:os");
12909
+ var import_node_path6 = require("node:path");
12910
+ var SHARED_SENTINELS = /* @__PURE__ */ new Set([
12911
+ "",
12912
+ "-",
12913
+ "n/a",
12914
+ "na",
12915
+ "none",
12916
+ "null",
12917
+ "undefined",
12918
+ "unknown",
12919
+ "anon",
12920
+ "anonymous",
12921
+ "default",
12922
+ "_default"
12923
+ ]);
12924
+ function isSharedSentinel(value) {
12925
+ if (value == null) return true;
12926
+ return SHARED_SENTINELS.has(value.trim().toLowerCase());
12927
+ }
12928
+ var ephemeral = /* @__PURE__ */ new Map();
12929
+ function ephemeralId(slot, width) {
12930
+ let id = ephemeral.get(slot);
12931
+ if (!id) {
12932
+ id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
12933
+ ephemeral.set(slot, id);
13159
12934
  }
13160
- return true;
12935
+ return id;
13161
12936
  }
13162
- var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
13163
- var CODE_AUTHORING_PATTERN = /\b(add|create|implement|build|write|fix|update|change|refactor|modify|remove|delete|move|rename)\b.*\b(function|component|feature|endpoint|test|file|module|class|type|interface|hook|page|route|style|migration|code|bug|error|issue)\b/i;
13164
- function isGitOnlyPrompt(prompt) {
13165
- if (!GIT_ONLY_PATTERN.test(prompt)) return false;
13166
- if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
13167
- return true;
12937
+ function contextIdentity(input) {
12938
+ const tokenUsable = !isSharedSentinel(input.token ?? null);
12939
+ const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
12940
+ const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
12941
+ const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
12942
+ let treeKey = "no-tree";
12943
+ const rawTree = input.treeRoot;
12944
+ if (rawTree && !isSharedSentinel(rawTree)) {
12945
+ let resolved = rawTree;
12946
+ try {
12947
+ resolved = import_node_fs5.realpathSync.native(rawTree);
12948
+ } catch {
12949
+ }
12950
+ treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
12951
+ }
12952
+ return {
12953
+ userKey,
12954
+ treeKey,
12955
+ sessionKey: sessionKey2,
12956
+ userKeySource: tokenUsable ? "token" : "ephemeral",
12957
+ sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
12958
+ ephemeral: !tokenUsable || !sessionUsable
12959
+ };
13168
12960
  }
13169
- function reconcileAnalysisMode(predictedMode, signals) {
13170
- const mode2 = resolveAnalysisMode(predictedMode, signals);
13171
- if (mode2 !== "skip") return mode2;
13172
- const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
13173
- if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
13174
- return mode2;
13175
- }
13176
- function resolveAnalysisMode(predictedMode, signals) {
13177
- if (!predictedMode || !isValidMode(predictedMode)) {
13178
- return detectAnalysisMode(
13179
- signals.noFilesChanged,
13180
- signals.assistantResponse,
13181
- signals.conversationPrompts,
13182
- signals.actionSummary,
13183
- signals.sessionAuthoredCode
13184
- );
13185
- }
13186
- const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
13187
- const agentInvestigated = didAgentInvestigate(signals.actionSummary);
13188
- switch (predictedMode) {
13189
- case "skip":
13190
- if (agentAuthoredCode) return "standard";
13191
- return "skip";
13192
- case "plan":
13193
- if (agentAuthoredCode) return "standard";
13194
- return "plan";
13195
- case "debug":
13196
- return "debug";
13197
- case "standard":
13198
- if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
13199
- return agentInvestigated ? "plan" : "skip";
13200
- }
13201
- return "standard";
13202
- }
13203
- }
13204
- function didAgentInvestigate(summary) {
13205
- if (!summary) return false;
13206
- return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
13207
- }
13208
- function isValidMode(mode2) {
13209
- return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
13210
- }
13211
- function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
13212
- const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
13213
- if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
13214
- if (!agentAuthoredCode) return "skip";
13215
- }
13216
- if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
13217
- return "plan";
13218
- }
13219
- if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
13220
- return didAgentInvestigate(actionSummary) ? "plan" : "skip";
13221
- }
13222
- for (const prompt of conversationPrompts) {
13223
- if (hasDebugIntent(prompt)) {
13224
- return "debug";
13225
- }
13226
- }
13227
- return "standard";
13228
- }
13229
- var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
13230
- var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
13231
- var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
13232
- var CHAIN_RE = /&&|\||;|\$\(|\x60/;
13233
- function isNonAuthoringCommand(cmd) {
13234
- if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
13235
- if (FILE_MUTATE_RE.test(cmd)) return false;
13236
- if (CHAIN_RE.test(cmd)) return false;
13237
- return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
13238
- }
13239
- function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
13240
- if (!actionSummary) return sessionAuthoredCode;
13241
- if ((actionSummary.subagents ?? 0) > 0) return true;
13242
- if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
13243
- const commands = actionSummary.commands ?? [];
13244
- if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
13245
- if (sessionAuthoredCode) {
13246
- const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
13247
- if (!allSafe) return true;
13248
- }
13249
- return false;
13250
- }
13251
- function scopeToAuthored(files, actionSummary) {
13252
- if (!actionSummary) return { files, signal: "no-transcript" };
13253
- const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
13254
- if (touched.length === 0) return { files: [], signal: "none-authored" };
13255
- return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
13256
- }
13257
- function chooseReviewScope(input) {
13258
- if (input.narrowingIsTrustworthy) return input.scopedFiles;
13259
- if (input.recoveredScope.length > 0) return input.recoveredScope;
13260
- return input.authorshipWasObservable ? [] : input.allForReview;
13261
- }
13262
- function narrowToAgentAuthored(files, actionSummary) {
13263
- if (!actionSummary) return files;
13264
- const touched = [
13265
- ...actionSummary.files_edited,
13266
- ...actionSummary.files_created
13267
- ];
13268
- if (touched.length === 0) return files;
13269
- return files.filter((f) => {
13270
- const suffix = "/" + f;
13271
- return touched.some((t) => t === f || t.endsWith(suffix));
13272
- });
13273
- }
13274
-
13275
- // src/lib/skip-detection.ts
13276
- function isBareAckPrompt(prompt) {
13277
- if (typeof prompt !== "string") return false;
13278
- const trimmed = prompt.trim();
13279
- if (trimmed.length === 0) return false;
13280
- if (trimmed.length > 20) return false;
13281
- const bareAckPattern = /^(\d{1,2}|y|n|yes|no|yep|nope|ok(ay)?|sure|skip|cancel|stop|done|noted|got\s+it|sounds\s+good|thanks|thank\s+you|thx)[.!?]*$/i;
13282
- return bareAckPattern.test(trimmed);
13283
- }
13284
- function isContinuationPrompt(prompt) {
13285
- if (typeof prompt !== "string") return false;
13286
- const trimmed = prompt.trim();
13287
- if (trimmed.length === 0) return false;
13288
- if (trimmed.length > 24) return false;
13289
- const continuation = /^(let['’]?s\s+(go|do\s+it|start|continue)|go|go\s+ahead|go\s+on|proceed|continue|carry\s+on|keep\s+going|do\s+it|make\s+it\s+so|next|start|begin|ship\s+it|yes\s+please|please\s+continue|perfect|great|nice|excellent|agreed)[.!]*$/i;
13290
- return continuation.test(trimmed) || isBareAckPrompt(trimmed);
13291
- }
13292
- function isSlashCommand(prompt) {
13293
- if (typeof prompt !== "string") return false;
13294
- return /^\s*\/[A-Za-z][\w-]*(\s|$)/.test(prompt);
13295
- }
13296
- function resolveGoalPrompt(prompts) {
13297
- if (prompts.length === 0) return null;
13298
- const latest = prompts[prompts.length - 1];
13299
- if (!isContinuationPrompt(latest.prompt)) return { entry: latest, turnsBack: 0 };
13300
- for (let i = prompts.length - 2; i >= 0; i--) {
13301
- if (!isContinuationPrompt(prompts[i].prompt)) {
13302
- return { entry: prompts[i], turnsBack: prompts.length - 1 - i };
13303
- }
13304
- }
13305
- return { entry: latest, turnsBack: 0 };
13306
- }
13307
- function isReflectionQuestion(response) {
13308
- if (!response || typeof response !== "string") return false;
13309
- const markers = [
13310
- /reflection\s+for\s+future\s+agents/i,
13311
- /what(?:'s|\s+is)\s+one\s+thing\s+you\s+learned/i,
13312
- /say\s+['"]?skip['"]?\s+to\s+skip/i,
13313
- /quick\s+reflection\s+question/i,
13314
- // Post-flip (VRT-21): the agent drafts the reflection itself and, when
13315
- // interactive, asks the user to confirm/correct before recording. That
13316
- // turn authors no code either, so it's still a reflection turn.
13317
- /reflection\s+draft/i,
13318
- /confirm,?\s+correct,?\s+or\s+add/i
13319
- ];
13320
- return markers.some((m) => m.test(response));
13321
- }
13322
- function isMetaTaskLabel(label2) {
13323
- if (label2 === null || label2 === void 0) return false;
13324
- if (typeof label2 !== "string") return false;
13325
- const trimmed = label2.trim();
13326
- if (trimmed.length === 0) return true;
13327
- const metaPatterns = [
13328
- /^verity\s+[\w-]+\s+response$/i,
13329
- // "Verity reflect response"
13330
- /^simple user response$/i,
13331
- /^verity\s+command$/i,
13332
- // "Verity command"
13333
- /^user\s+(question|reply|response|ack)$/i
13334
- ];
13335
- return metaPatterns.some((p) => p.test(trimmed));
13336
- }
13337
- function shouldSkipForBareAck(input) {
13338
- if (!isBareAckPrompt(input.prompt)) return false;
13339
- if (input.turnAuthoredCode) return false;
13340
- return input.canSeeTurnAuthorship;
13341
- }
13342
- function isCommandOnlyTurn(input) {
13343
- if (!input.authorshipIsObservable) return false;
13344
- if (input.userCommandsTruncated) return false;
13345
- const commands = input.userCommands ?? [];
13346
- if (commands.length === 0) return false;
13347
- if (input.agentAuthoredFiles > 0) return false;
13348
- if (input.agentToolCalls > 0) return false;
13349
- return commands.every(isNonAuthoringCommand);
13350
- }
13351
-
13352
- // src/lib/context-identity.ts
13353
- var import_node_crypto2 = require("node:crypto");
13354
- var import_node_fs8 = require("node:fs");
13355
- var import_node_os2 = require("node:os");
13356
- var import_node_path6 = require("node:path");
13357
- var SHARED_SENTINELS = /* @__PURE__ */ new Set([
13358
- "",
13359
- "-",
13360
- "n/a",
13361
- "na",
13362
- "none",
13363
- "null",
13364
- "undefined",
13365
- "unknown",
13366
- "anon",
13367
- "anonymous",
13368
- "default",
13369
- "_default"
13370
- ]);
13371
- function isSharedSentinel(value) {
13372
- if (value == null) return true;
13373
- return SHARED_SENTINELS.has(value.trim().toLowerCase());
13374
- }
13375
- var ephemeral = /* @__PURE__ */ new Map();
13376
- function ephemeralId(slot, width) {
13377
- let id = ephemeral.get(slot);
13378
- if (!id) {
13379
- id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
13380
- ephemeral.set(slot, id);
13381
- }
13382
- return id;
13383
- }
13384
- function contextIdentity(input) {
13385
- const tokenUsable = !isSharedSentinel(input.token ?? null);
13386
- const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
13387
- const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
13388
- const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
13389
- let treeKey = "no-tree";
13390
- const rawTree = input.treeRoot;
13391
- if (rawTree && !isSharedSentinel(rawTree)) {
13392
- let resolved = rawTree;
13393
- try {
13394
- resolved = import_node_fs8.realpathSync.native(rawTree);
13395
- } catch {
13396
- }
13397
- treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
13398
- }
13399
- return {
13400
- userKey,
13401
- treeKey,
13402
- sessionKey: sessionKey2,
13403
- userKeySource: tokenUsable ? "token" : "ephemeral",
13404
- sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
13405
- ephemeral: !tokenUsable || !sessionUsable
13406
- };
13407
- }
13408
- function verityHome() {
13409
- const override = process.env.VERITY_HOME;
13410
- return override && override.trim() ? (0, import_node_path6.resolve)(override) : (0, import_node_path6.join)((0, import_node_os2.homedir)(), ".verity");
12961
+ function verityHome() {
12962
+ const override = process.env.VERITY_HOME;
12963
+ return override && override.trim() ? (0, import_node_path6.resolve)(override) : (0, import_node_path6.join)((0, import_node_os2.homedir)(), ".verity");
13411
12964
  }
13412
12965
  function dossierDir(identity) {
13413
12966
  return (0, import_node_path6.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
@@ -13428,7 +12981,7 @@ function sessionScopeKey(token, sessionId) {
13428
12981
 
13429
12982
  // src/lib/task-context-buffer.ts
13430
12983
  var import_promises6 = require("node:fs/promises");
13431
- var import_node_fs9 = require("node:fs");
12984
+ var import_node_fs6 = require("node:fs");
13432
12985
  var import_node_path7 = require("node:path");
13433
12986
  var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
13434
12987
  var MAX_BUFFER_BYTES = 500 * 1024;
@@ -13468,7 +13021,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
13468
13021
  }
13469
13022
  async function readTaskContextBuffer(taskId) {
13470
13023
  const filePath = bufferPath(taskId);
13471
- if (!(0, import_node_fs9.existsSync)(filePath)) return null;
13024
+ if (!(0, import_node_fs6.existsSync)(filePath)) return null;
13472
13025
  try {
13473
13026
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
13474
13027
  if (!content.trim()) return null;
@@ -13502,7 +13055,7 @@ async function readTaskContextBuffer(taskId) {
13502
13055
  }
13503
13056
  async function cleanupTaskContextBuffers() {
13504
13057
  try {
13505
- if (!(0, import_node_fs9.existsSync)(TASK_CONTEXT_DIR)) return;
13058
+ if (!(0, import_node_fs6.existsSync)(TASK_CONTEXT_DIR)) return;
13506
13059
  const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
13507
13060
  const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
13508
13061
  for (const file of files) {
@@ -13527,7 +13080,7 @@ async function appendEntry(taskId, entry) {
13527
13080
  try {
13528
13081
  await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
13529
13082
  const filePath = bufferPath(taskId);
13530
- if ((0, import_node_fs9.existsSync)(filePath)) {
13083
+ if ((0, import_node_fs6.existsSync)(filePath)) {
13531
13084
  const stats = await (0, import_promises6.stat)(filePath);
13532
13085
  if (stats.size >= MAX_BUFFER_BYTES) {
13533
13086
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
@@ -13538,7 +13091,7 @@ async function appendEntry(taskId, entry) {
13538
13091
  }
13539
13092
  }
13540
13093
  const line = JSON.stringify(entry) + "\n";
13541
- const existing = (0, import_node_fs9.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
13094
+ const existing = (0, import_node_fs6.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
13542
13095
  await (0, import_promises6.writeFile)(filePath, existing + line);
13543
13096
  } catch {
13544
13097
  }
@@ -13546,7 +13099,7 @@ async function appendEntry(taskId, entry) {
13546
13099
 
13547
13100
  // src/lib/memory-retrieval.ts
13548
13101
  var import_promises7 = require("node:fs/promises");
13549
- var import_node_fs10 = require("node:fs");
13102
+ var import_node_fs7 = require("node:fs");
13550
13103
  var import_node_path8 = require("node:path");
13551
13104
  var memoryDir = () => projectPath(`${VERITY_DIR}/memory`);
13552
13105
  var DOMAINS = ["decisions", "quality", "security", "intent", "gotchas", "patterns", "domain", "integrations"];
@@ -13640,13 +13193,13 @@ function parseFrontmatter(content) {
13640
13193
  return { fm, body: match[2].trim() };
13641
13194
  }
13642
13195
  async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
13643
- if (!(0, import_node_fs10.existsSync)(memoryDir())) return null;
13196
+ if (!(0, import_node_fs7.existsSync)(memoryDir())) return null;
13644
13197
  const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
13645
13198
  const promptTokens = tokenize(promptText);
13646
13199
  const nodes = [];
13647
13200
  for (const domain of DOMAINS) {
13648
13201
  const domainDir = (0, import_node_path8.join)(memoryDir(), domain);
13649
- if (!(0, import_node_fs10.existsSync)(domainDir)) continue;
13202
+ if (!(0, import_node_fs7.existsSync)(domainDir)) continue;
13650
13203
  try {
13651
13204
  const files = await (0, import_promises7.readdir)(domainDir);
13652
13205
  for (const file of files) {
@@ -13711,12 +13264,12 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
13711
13264
 
13712
13265
  // src/lib/memory-sync.ts
13713
13266
  var import_promises8 = require("node:fs/promises");
13714
- var import_node_fs12 = require("node:fs");
13267
+ var import_node_fs9 = require("node:fs");
13715
13268
  var import_node_path10 = require("node:path");
13716
13269
  var import_node_crypto3 = require("node:crypto");
13717
13270
 
13718
13271
  // src/lib/safe-path.ts
13719
- var import_node_fs11 = require("node:fs");
13272
+ var import_node_fs8 = require("node:fs");
13720
13273
  var import_node_path9 = require("node:path");
13721
13274
  function resolveInside(baseDir, candidate) {
13722
13275
  if (typeof candidate !== "string" || candidate.length === 0) return null;
@@ -13726,16 +13279,16 @@ function resolveInside(baseDir, candidate) {
13726
13279
  const baseSep = baseAbs.endsWith(import_node_path9.sep) ? baseAbs : baseAbs + import_node_path9.sep;
13727
13280
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
13728
13281
  try {
13729
- if ((0, import_node_fs11.existsSync)(baseAbs)) {
13730
- const realBase = (0, import_node_fs11.realpathSync)(baseAbs);
13282
+ if ((0, import_node_fs8.existsSync)(baseAbs)) {
13283
+ const realBase = (0, import_node_fs8.realpathSync)(baseAbs);
13731
13284
  const realBaseSep = realBase.endsWith(import_node_path9.sep) ? realBase : realBase + import_node_path9.sep;
13732
13285
  let probe = full;
13733
- while (!(0, import_node_fs11.existsSync)(probe)) {
13286
+ while (!(0, import_node_fs8.existsSync)(probe)) {
13734
13287
  const parent = (0, import_node_path9.dirname)(probe);
13735
13288
  if (parent === probe) break;
13736
13289
  probe = parent;
13737
13290
  }
13738
- const realProbe = (0, import_node_fs11.realpathSync)(probe);
13291
+ const realProbe = (0, import_node_fs8.realpathSync)(probe);
13739
13292
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
13740
13293
  }
13741
13294
  } catch {
@@ -13814,24 +13367,24 @@ async function ensureMemoryDir() {
13814
13367
  for (const domain of DOMAINS2) {
13815
13368
  await (0, import_promises8.mkdir)((0, import_node_path10.join)(memoryDir2(), domain), { recursive: true });
13816
13369
  }
13817
- if (!(0, import_node_fs12.existsSync)((0, import_node_path10.join)(memoryDir2(), "SCHEMA.md"))) {
13370
+ if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "SCHEMA.md"))) {
13818
13371
  await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
13819
13372
  }
13820
- if (!(0, import_node_fs12.existsSync)((0, import_node_path10.join)(memoryDir2(), "index.md"))) {
13373
+ if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "index.md"))) {
13821
13374
  await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
13822
13375
  }
13823
- if (!(0, import_node_fs12.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md"))) {
13376
+ if (!(0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md"))) {
13824
13377
  await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
13825
13378
  }
13826
13379
  }
13827
13380
  async function buildManifest() {
13828
- if (!(0, import_node_fs12.existsSync)(memoryDir2())) {
13381
+ if (!(0, import_node_fs9.existsSync)(memoryDir2())) {
13829
13382
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
13830
13383
  }
13831
13384
  const nodes = [];
13832
13385
  for (const domain of DOMAINS2) {
13833
13386
  const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
13834
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
13387
+ if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
13835
13388
  try {
13836
13389
  const files = await (0, import_promises8.readdir)(domainDir);
13837
13390
  for (const file of files) {
@@ -13867,10 +13420,10 @@ function hashContent(content) {
13867
13420
  }
13868
13421
  async function readOnDiskNodes() {
13869
13422
  const out = /* @__PURE__ */ new Map();
13870
- if (!(0, import_node_fs12.existsSync)(memoryDir2())) return out;
13423
+ if (!(0, import_node_fs9.existsSync)(memoryDir2())) return out;
13871
13424
  for (const domain of DOMAINS2) {
13872
13425
  const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
13873
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
13426
+ if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
13874
13427
  try {
13875
13428
  for (const file of await (0, import_promises8.readdir)(domainDir)) {
13876
13429
  if (!file.endsWith(".md")) continue;
@@ -13922,7 +13475,7 @@ async function computeEditedNodeUploads() {
13922
13475
  for (const [path, prevHash] of prev) {
13923
13476
  if (prevHash == null) continue;
13924
13477
  const full = (0, import_node_path10.join)(memoryDir2(), path);
13925
- if (!(0, import_node_fs12.existsSync)(full)) continue;
13478
+ if (!(0, import_node_fs9.existsSync)(full)) continue;
13926
13479
  let content;
13927
13480
  try {
13928
13481
  content = await (0, import_promises8.readFile)(full, "utf-8");
@@ -13958,7 +13511,7 @@ async function applyMemoryWrites(writes, opts = {}) {
13958
13511
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
13959
13512
  for (const n of notes) logLines.push(` - ${n}`);
13960
13513
  try {
13961
- const existing = (0, import_node_fs12.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
13514
+ const existing = (0, import_node_fs9.existsSync)((0, import_node_path10.join)(memoryDir2(), "log.md")) ? await (0, import_promises8.readFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
13962
13515
  await (0, import_promises8.writeFile)((0, import_node_path10.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
13963
13516
  } catch {
13964
13517
  }
@@ -13979,7 +13532,7 @@ async function applyOneWrite(write, treePaths) {
13979
13532
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
13980
13533
  }
13981
13534
  }
13982
- if ((0, import_node_fs12.existsSync)(fullPath)) {
13535
+ if ((0, import_node_fs9.existsSync)(fullPath)) {
13983
13536
  let existing = "";
13984
13537
  try {
13985
13538
  existing = await (0, import_promises8.readFile)(fullPath, "utf-8");
@@ -14033,7 +13586,7 @@ async function regenerateIndex() {
14033
13586
  let totalNodes = 0;
14034
13587
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
14035
13588
  const domainDir = (0, import_node_path10.join)(memoryDir2(), domain);
14036
- if (!(0, import_node_fs12.existsSync)(domainDir)) continue;
13589
+ if (!(0, import_node_fs9.existsSync)(domainDir)) continue;
14037
13590
  try {
14038
13591
  const files = await (0, import_promises8.readdir)(domainDir);
14039
13592
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -14303,7 +13856,7 @@ function hasLegacyMemoryBlock(text) {
14303
13856
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
14304
13857
  const claudeMdPath = (0, import_node_path10.join)(cwd, "CLAUDE.md");
14305
13858
  let existing = "";
14306
- if ((0, import_node_fs12.existsSync)(claudeMdPath)) {
13859
+ if ((0, import_node_fs9.existsSync)(claudeMdPath)) {
14307
13860
  existing = await (0, import_promises8.readFile)(claudeMdPath, "utf-8");
14308
13861
  }
14309
13862
  let startTag = CLAUDE_MD_START;
@@ -14439,10 +13992,237 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
14439
13992
  `;
14440
13993
 
14441
13994
  // src/lib/dossier-session.ts
14442
- var import_node_fs17 = require("node:fs");
13995
+ var import_node_fs14 = require("node:fs");
14443
13996
  var import_node_crypto7 = require("node:crypto");
14444
13997
  var import_node_path13 = require("node:path");
14445
13998
 
13999
+ // src/lib/analysis-mode.ts
14000
+ var DEBUG_PHRASES = [
14001
+ "not working",
14002
+ "doesn't work",
14003
+ "doesn't work",
14004
+ "does not work",
14005
+ "isn't working",
14006
+ "is not working",
14007
+ "can't figure out",
14008
+ "stack trace"
14009
+ ];
14010
+ var DEBUG_WORDS = [
14011
+ "fix",
14012
+ "bug",
14013
+ "broken",
14014
+ "crash",
14015
+ "crashing",
14016
+ "failing",
14017
+ "debug",
14018
+ "debugging",
14019
+ "investigate",
14020
+ "troubleshoot",
14021
+ "regression",
14022
+ "wrong"
14023
+ ];
14024
+ var DEBUG_PATTERN = new RegExp(
14025
+ [
14026
+ ...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
14027
+ ...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
14028
+ ].join("|"),
14029
+ "i"
14030
+ );
14031
+ var FALSE_POSITIVE_PATTERNS = [
14032
+ /\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
14033
+ /\berror\s+handling\b/i,
14034
+ /\berror\s+boundar(?:y|ies)\b/i,
14035
+ /\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
14036
+ /\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
14037
+ ];
14038
+ function hasDebugIntent(prompt) {
14039
+ if (!DEBUG_PATTERN.test(prompt)) return false;
14040
+ for (const fp of FALSE_POSITIVE_PATTERNS) {
14041
+ if (fp.test(prompt)) return false;
14042
+ }
14043
+ return true;
14044
+ }
14045
+ var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
14046
+ var CODE_AUTHORING_PATTERN = /\b(add|create|implement|build|write|fix|update|change|refactor|modify|remove|delete|move|rename)\b.*\b(function|component|feature|endpoint|test|file|module|class|type|interface|hook|page|route|style|migration|code|bug|error|issue)\b/i;
14047
+ function isGitOnlyPrompt(prompt) {
14048
+ if (!GIT_ONLY_PATTERN.test(prompt)) return false;
14049
+ if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
14050
+ return true;
14051
+ }
14052
+ function reconcileAnalysisMode(predictedMode, signals) {
14053
+ const mode2 = resolveAnalysisMode(predictedMode, signals);
14054
+ if (mode2 !== "skip") return mode2;
14055
+ const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
14056
+ if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
14057
+ return mode2;
14058
+ }
14059
+ function resolveAnalysisMode(predictedMode, signals) {
14060
+ if (!predictedMode || !isValidMode(predictedMode)) {
14061
+ return detectAnalysisMode(
14062
+ signals.noFilesChanged,
14063
+ signals.assistantResponse,
14064
+ signals.conversationPrompts,
14065
+ signals.actionSummary,
14066
+ signals.sessionAuthoredCode
14067
+ );
14068
+ }
14069
+ const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
14070
+ const agentInvestigated = didAgentInvestigate(signals.actionSummary);
14071
+ switch (predictedMode) {
14072
+ case "skip":
14073
+ if (agentAuthoredCode) return "standard";
14074
+ return "skip";
14075
+ case "plan":
14076
+ if (agentAuthoredCode) return "standard";
14077
+ return "plan";
14078
+ case "debug":
14079
+ return "debug";
14080
+ case "standard":
14081
+ if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
14082
+ return agentInvestigated ? "plan" : "skip";
14083
+ }
14084
+ return "standard";
14085
+ }
14086
+ }
14087
+ function didAgentInvestigate(summary) {
14088
+ if (!summary) return false;
14089
+ return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
14090
+ }
14091
+ function isValidMode(mode2) {
14092
+ return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
14093
+ }
14094
+ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
14095
+ const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
14096
+ if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
14097
+ if (!agentAuthoredCode) return "skip";
14098
+ }
14099
+ if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
14100
+ return "plan";
14101
+ }
14102
+ if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
14103
+ return didAgentInvestigate(actionSummary) ? "plan" : "skip";
14104
+ }
14105
+ for (const prompt of conversationPrompts) {
14106
+ if (hasDebugIntent(prompt)) {
14107
+ return "debug";
14108
+ }
14109
+ }
14110
+ return "standard";
14111
+ }
14112
+ var FILE_MUTATE_RE = /(?:^|[\s|&;(`])(?:sed\s+-i|perl\s+-i|awk\b|tee\b|dd\b|cp\b|mv\b|ln\b|install\b|touch\b|patch\b|git\s+(?:apply|am)\b|cargo\s+build|go\s+generate|make\b|--write\b|--fix\b|--in-place\b)|>>?(?![&>])/i;
14113
+ var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
14114
+ var READ_ONLY_RE = /^\s*(?:git\s+(?:status|diff|log|show|branch|remote|config|rev-parse|ls-files|blame|describe)|ls|cat|head|tail|less|grep|rg|find|pwd|echo|printf|wc|which|type|tree|stat|file|env|printenv|date|whoami)\b/i;
14115
+ var CHAIN_RE = /&&|\||;|\$\(|\x60/;
14116
+ function isNonAuthoringCommand(cmd) {
14117
+ if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
14118
+ if (FILE_MUTATE_RE.test(cmd)) return false;
14119
+ if (CHAIN_RE.test(cmd)) return false;
14120
+ return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
14121
+ }
14122
+ function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
14123
+ if (!actionSummary) return sessionAuthoredCode;
14124
+ if ((actionSummary.subagents ?? 0) > 0) return true;
14125
+ if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
14126
+ const commands = actionSummary.commands ?? [];
14127
+ if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
14128
+ if (sessionAuthoredCode) {
14129
+ const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
14130
+ if (!allSafe) return true;
14131
+ }
14132
+ return false;
14133
+ }
14134
+ function scopeToAuthored(files, actionSummary) {
14135
+ if (!actionSummary) return { files, signal: "no-transcript" };
14136
+ const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
14137
+ if (touched.length === 0) return { files: [], signal: "none-authored" };
14138
+ return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
14139
+ }
14140
+ function narrowToAgentAuthored(files, actionSummary) {
14141
+ if (!actionSummary) return files;
14142
+ const touched = [
14143
+ ...actionSummary.files_edited,
14144
+ ...actionSummary.files_created
14145
+ ];
14146
+ if (touched.length === 0) return files;
14147
+ return files.filter((f) => {
14148
+ const suffix = "/" + f;
14149
+ return touched.some((t) => t === f || t.endsWith(suffix));
14150
+ });
14151
+ }
14152
+
14153
+ // src/lib/skip-detection.ts
14154
+ function isBareAckPrompt(prompt) {
14155
+ if (typeof prompt !== "string") return false;
14156
+ const trimmed = prompt.trim();
14157
+ if (trimmed.length === 0) return false;
14158
+ if (trimmed.length > 20) return false;
14159
+ const bareAckPattern = /^(\d{1,2}|y|n|yes|no|yep|nope|ok(ay)?|sure|skip|cancel|stop|done|noted|got\s+it|sounds\s+good|thanks|thank\s+you|thx)[.!?]*$/i;
14160
+ return bareAckPattern.test(trimmed);
14161
+ }
14162
+ function isContinuationPrompt(prompt) {
14163
+ if (typeof prompt !== "string") return false;
14164
+ const trimmed = prompt.trim();
14165
+ if (trimmed.length === 0) return false;
14166
+ if (trimmed.length > 24) return false;
14167
+ const continuation = /^(let['’]?s\s+(go|do\s+it|start|continue)|go|go\s+ahead|go\s+on|proceed|continue|carry\s+on|keep\s+going|do\s+it|make\s+it\s+so|next|start|begin|ship\s+it|yes\s+please|please\s+continue|perfect|great|nice|excellent|agreed)[.!]*$/i;
14168
+ return continuation.test(trimmed) || isBareAckPrompt(trimmed);
14169
+ }
14170
+ function resolveGoalPrompt(prompts) {
14171
+ if (prompts.length === 0) return null;
14172
+ const latest = prompts[prompts.length - 1];
14173
+ if (!isContinuationPrompt(latest.prompt)) return { entry: latest, turnsBack: 0 };
14174
+ for (let i = prompts.length - 2; i >= 0; i--) {
14175
+ if (!isContinuationPrompt(prompts[i].prompt)) {
14176
+ return { entry: prompts[i], turnsBack: prompts.length - 1 - i };
14177
+ }
14178
+ }
14179
+ return { entry: latest, turnsBack: 0 };
14180
+ }
14181
+ function isReflectionQuestion(response) {
14182
+ if (!response || typeof response !== "string") return false;
14183
+ const markers = [
14184
+ /reflection\s+for\s+future\s+agents/i,
14185
+ /what(?:'s|\s+is)\s+one\s+thing\s+you\s+learned/i,
14186
+ /say\s+['"]?skip['"]?\s+to\s+skip/i,
14187
+ /quick\s+reflection\s+question/i,
14188
+ // Post-flip (VRT-21): the agent drafts the reflection itself and, when
14189
+ // interactive, asks the user to confirm/correct before recording. That
14190
+ // turn authors no code either, so it's still a reflection turn.
14191
+ /reflection\s+draft/i,
14192
+ /confirm,?\s+correct,?\s+or\s+add/i
14193
+ ];
14194
+ return markers.some((m) => m.test(response));
14195
+ }
14196
+ function isMetaTaskLabel(label2) {
14197
+ if (label2 === null || label2 === void 0) return false;
14198
+ if (typeof label2 !== "string") return false;
14199
+ const trimmed = label2.trim();
14200
+ if (trimmed.length === 0) return true;
14201
+ const metaPatterns = [
14202
+ /^verity\s+[\w-]+\s+response$/i,
14203
+ // "Verity reflect response"
14204
+ /^simple user response$/i,
14205
+ /^verity\s+command$/i,
14206
+ // "Verity command"
14207
+ /^user\s+(question|reply|response|ack)$/i
14208
+ ];
14209
+ return metaPatterns.some((p) => p.test(trimmed));
14210
+ }
14211
+ function shouldSkipForBareAck(input) {
14212
+ if (!isBareAckPrompt(input.prompt)) return false;
14213
+ if (input.turnAuthoredCode) return false;
14214
+ return input.canSeeTurnAuthorship;
14215
+ }
14216
+ function isCommandOnlyTurn(input) {
14217
+ if (!input.authorshipIsObservable) return false;
14218
+ if (input.userCommandsTruncated) return false;
14219
+ const commands = input.userCommands ?? [];
14220
+ if (commands.length === 0) return false;
14221
+ if (input.agentAuthoredFiles > 0) return false;
14222
+ if (input.agentToolCalls > 0) return false;
14223
+ return commands.every(isNonAuthoringCommand);
14224
+ }
14225
+
14446
14226
  // src/lib/pending-repeat.ts
14447
14227
  var STOP = /* @__PURE__ */ new Set([
14448
14228
  "the",
@@ -14546,7 +14326,7 @@ function statementAnchorKey(file, patternId) {
14546
14326
 
14547
14327
  // src/lib/dossier/log.ts
14548
14328
  var import_node_crypto4 = require("node:crypto");
14549
- var import_node_fs13 = require("node:fs");
14329
+ var import_node_fs10 = require("node:fs");
14550
14330
  var import_node_path11 = require("node:path");
14551
14331
  var CRC_TABLE = (() => {
14552
14332
  const t = new Int32Array(256);
@@ -14566,7 +14346,7 @@ function crc32(s) {
14566
14346
  function openDossier(identity) {
14567
14347
  try {
14568
14348
  const dir = dossierDir(identity);
14569
- (0, import_node_fs13.mkdirSync)(dir, { recursive: true, mode: 448 });
14349
+ (0, import_node_fs10.mkdirSync)(dir, { recursive: true, mode: 448 });
14570
14350
  return {
14571
14351
  dir,
14572
14352
  identity,
@@ -14634,7 +14414,7 @@ function appendEvent(d, ev) {
14634
14414
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
14635
14415
  ...ev
14636
14416
  });
14637
- (0, import_node_fs13.appendFileSync)(d.eventsPath, line, { mode: 384 });
14417
+ (0, import_node_fs10.appendFileSync)(d.eventsPath, line, { mode: 384 });
14638
14418
  return true;
14639
14419
  } catch {
14640
14420
  return false;
@@ -14642,14 +14422,14 @@ function appendEvent(d, ev) {
14642
14422
  }
14643
14423
  function rotateIfNeeded2(d) {
14644
14424
  try {
14645
- if (!(0, import_node_fs13.existsSync)(d.eventsPath)) return;
14646
- if ((0, import_node_fs13.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
14647
- (0, import_node_fs13.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
14648
- (0, import_node_fs13.renameSync)(d.eventsPath, (0, import_node_path11.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
14649
- const kept = (0, import_node_fs13.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
14425
+ if (!(0, import_node_fs10.existsSync)(d.eventsPath)) return;
14426
+ if ((0, import_node_fs10.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
14427
+ (0, import_node_fs10.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
14428
+ (0, import_node_fs10.renameSync)(d.eventsPath, (0, import_node_path11.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
14429
+ const kept = (0, import_node_fs10.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
14650
14430
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
14651
14431
  try {
14652
- (0, import_node_fs13.renameSync)((0, import_node_path11.join)(d.rotatedDir, stale), (0, import_node_path11.join)(d.rotatedDir, `${stale}.pruned`));
14432
+ (0, import_node_fs10.renameSync)((0, import_node_path11.join)(d.rotatedDir, stale), (0, import_node_path11.join)(d.rotatedDir, `${stale}.pruned`));
14653
14433
  } catch {
14654
14434
  }
14655
14435
  }
@@ -14659,7 +14439,7 @@ function rotateIfNeeded2(d) {
14659
14439
 
14660
14440
  // src/lib/dossier/fold-dossier.ts
14661
14441
  var import_node_crypto5 = require("node:crypto");
14662
- var import_node_fs14 = require("node:fs");
14442
+ var import_node_fs11 = require("node:fs");
14663
14443
  var import_node_path12 = require("node:path");
14664
14444
  var EMPTY_CAPABILITIES = () => ({
14665
14445
  human_reachable: { value: "unknown", tier: "unknown" },
@@ -14711,12 +14491,12 @@ function foldDossier(d, opts = {}) {
14711
14491
  }
14712
14492
  };
14713
14493
  try {
14714
- if ((0, import_node_fs14.existsSync)(d.rotatedDir)) {
14715
- const files = (0, import_node_fs14.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
14494
+ if ((0, import_node_fs11.existsSync)(d.rotatedDir)) {
14495
+ const files = (0, import_node_fs11.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
14716
14496
  state.meta.rotations = files.length;
14717
14497
  for (const f of files) {
14718
14498
  try {
14719
- ingest((0, import_node_fs14.readFileSync)((0, import_node_path12.join)(d.rotatedDir, f), "utf8"));
14499
+ ingest((0, import_node_fs11.readFileSync)((0, import_node_path12.join)(d.rotatedDir, f), "utf8"));
14720
14500
  } catch {
14721
14501
  state.meta.dropped_lines++;
14722
14502
  }
@@ -14725,9 +14505,9 @@ function foldDossier(d, opts = {}) {
14725
14505
  } catch {
14726
14506
  }
14727
14507
  try {
14728
- if ((0, import_node_fs14.existsSync)(d.eventsPath)) {
14729
- state.meta.upto_offset = (0, import_node_fs14.statSync)(d.eventsPath).size;
14730
- ingest((0, import_node_fs14.readFileSync)(d.eventsPath, "utf8"));
14508
+ if ((0, import_node_fs11.existsSync)(d.eventsPath)) {
14509
+ state.meta.upto_offset = (0, import_node_fs11.statSync)(d.eventsPath).size;
14510
+ ingest((0, import_node_fs11.readFileSync)(d.eventsPath, "utf8"));
14731
14511
  }
14732
14512
  } catch {
14733
14513
  }
@@ -14998,7 +14778,7 @@ function applyBounds(state, input) {
14998
14778
  }
14999
14779
 
15000
14780
  // src/lib/dossier/cache.ts
15001
- var import_node_fs15 = require("node:fs");
14781
+ var import_node_fs12 = require("node:fs");
15002
14782
  function compactState(s) {
15003
14783
  const ms = (iso) => Date.parse(iso) || 0;
15004
14784
  return {
@@ -15127,20 +14907,20 @@ function encodeState(s) {
15127
14907
  function writeFoldCache(d, state) {
15128
14908
  try {
15129
14909
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
15130
- (0, import_node_fs15.writeFileSync)(tmp, encodeState(state), { mode: 384 });
15131
- (0, import_node_fs15.renameSync)(tmp, d.foldPath);
14910
+ (0, import_node_fs12.writeFileSync)(tmp, encodeState(state), { mode: 384 });
14911
+ (0, import_node_fs12.renameSync)(tmp, d.foldPath);
15132
14912
  } catch {
15133
14913
  }
15134
14914
  }
15135
14915
  function readFoldCache(d) {
15136
14916
  try {
15137
- if (!(0, import_node_fs15.existsSync)(d.foldPath)) return null;
15138
- const raw = JSON.parse((0, import_node_fs15.readFileSync)(d.foldPath, "utf8"));
14917
+ if (!(0, import_node_fs12.existsSync)(d.foldPath)) return null;
14918
+ const raw = JSON.parse((0, import_node_fs12.readFileSync)(d.foldPath, "utf8"));
15139
14919
  if (raw?.v !== 1) return null;
15140
14920
  const cached2 = expandState(raw);
15141
14921
  if (!cached2?.meta) return null;
15142
- const size = (0, import_node_fs15.existsSync)(d.eventsPath) ? (0, import_node_fs15.statSync)(d.eventsPath).size : 0;
15143
- const rotations = (0, import_node_fs15.existsSync)(d.rotatedDir) ? (0, import_node_fs15.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
14922
+ const size = (0, import_node_fs12.existsSync)(d.eventsPath) ? (0, import_node_fs12.statSync)(d.eventsPath).size : 0;
14923
+ const rotations = (0, import_node_fs12.existsSync)(d.rotatedDir) ? (0, import_node_fs12.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
15144
14924
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
15145
14925
  return cached2;
15146
14926
  } catch {
@@ -15191,13 +14971,13 @@ function assessContinuity(i) {
15191
14971
 
15192
14972
  // src/lib/dossier/reanchor.ts
15193
14973
  var import_node_crypto6 = require("node:crypto");
15194
- var import_node_fs16 = require("node:fs");
14974
+ var import_node_fs13 = require("node:fs");
15195
14975
  function lineSha(text) {
15196
14976
  return (0, import_node_crypto6.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
15197
14977
  }
15198
14978
  function fileHash(path) {
15199
14979
  try {
15200
- return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs16.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
14980
+ return (0, import_node_crypto6.createHash)("sha256").update((0, import_node_fs13.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
15201
14981
  } catch {
15202
14982
  return null;
15203
14983
  }
@@ -15569,14 +15349,14 @@ function foreignAuthoredPaths(identity, opts = {}) {
15569
15349
  let sessions = 0;
15570
15350
  try {
15571
15351
  const dir = treeDir(identity);
15572
- if (!(0, import_node_fs17.existsSync)(dir)) return { paths: [], sessions: 0 };
15573
- for (const entry of (0, import_node_fs17.readdirSync)(dir, { withFileTypes: true })) {
15352
+ if (!(0, import_node_fs14.existsSync)(dir)) return { paths: [], sessions: 0 };
15353
+ for (const entry of (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true })) {
15574
15354
  if (!entry.isDirectory()) continue;
15575
15355
  if (entry.name === identity.sessionKey) continue;
15576
15356
  const log = (0, import_node_path13.join)(dir, entry.name, "events.jsonl");
15577
15357
  try {
15578
- if (!(0, import_node_fs17.existsSync)(log)) continue;
15579
- if (now - (0, import_node_fs17.statSync)(log).mtimeMs > windowMs) continue;
15358
+ if (!(0, import_node_fs14.existsSync)(log)) continue;
15359
+ if (now - (0, import_node_fs14.statSync)(log).mtimeMs > windowMs) continue;
15580
15360
  const sib = {
15581
15361
  dir: (0, import_node_path13.join)(dir, entry.name),
15582
15362
  identity,
@@ -15611,13 +15391,13 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15611
15391
  try {
15612
15392
  const mine = dossierDir(identity);
15613
15393
  const userDir = (0, import_node_path13.dirname)((0, import_node_path13.dirname)(mine));
15614
- if (!(0, import_node_fs17.existsSync)(userDir)) return 0;
15394
+ if (!(0, import_node_fs14.existsSync)(userDir)) return 0;
15615
15395
  const cutoff = Date.now() - maxAgeMs;
15616
- for (const tree of (0, import_node_fs17.readdirSync)(userDir, { withFileTypes: true })) {
15396
+ for (const tree of (0, import_node_fs14.readdirSync)(userDir, { withFileTypes: true })) {
15617
15397
  if (!tree.isDirectory()) continue;
15618
15398
  const treePath = (0, import_node_path13.join)(userDir, tree.name);
15619
15399
  let live = 0;
15620
- for (const entry of (0, import_node_fs17.readdirSync)(treePath, { withFileTypes: true })) {
15400
+ for (const entry of (0, import_node_fs14.readdirSync)(treePath, { withFileTypes: true })) {
15621
15401
  if (!entry.isDirectory()) continue;
15622
15402
  const dir = (0, import_node_path13.join)(treePath, entry.name);
15623
15403
  if (dir === mine) {
@@ -15626,9 +15406,9 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15626
15406
  }
15627
15407
  try {
15628
15408
  const log = (0, import_node_path13.join)(dir, "events.jsonl");
15629
- const at = (0, import_node_fs17.existsSync)(log) ? (0, import_node_fs17.statSync)(log).mtimeMs : (0, import_node_fs17.statSync)(dir).mtimeMs;
15409
+ const at = (0, import_node_fs14.existsSync)(log) ? (0, import_node_fs14.statSync)(log).mtimeMs : (0, import_node_fs14.statSync)(dir).mtimeMs;
15630
15410
  if (at < cutoff) {
15631
- (0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
15411
+ (0, import_node_fs14.rmSync)(dir, { recursive: true, force: true });
15632
15412
  removed++;
15633
15413
  } else {
15634
15414
  live++;
@@ -15638,7 +15418,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
15638
15418
  }
15639
15419
  if (live === 0) {
15640
15420
  try {
15641
- (0, import_node_fs17.rmSync)(treePath, { recursive: false, force: false });
15421
+ (0, import_node_fs14.rmSync)(treePath, { recursive: false, force: false });
15642
15422
  } catch {
15643
15423
  }
15644
15424
  }
@@ -15655,8 +15435,8 @@ function sessionDossier(token, sessionId) {
15655
15435
  }
15656
15436
  function hasActiveGoal(d) {
15657
15437
  try {
15658
- if (!(0, import_node_fs17.existsSync)(d.eventsPath)) return false;
15659
- return (0, import_node_fs17.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
15438
+ if (!(0, import_node_fs14.existsSync)(d.eventsPath)) return false;
15439
+ return (0, import_node_fs14.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
15660
15440
  } catch {
15661
15441
  return false;
15662
15442
  }
@@ -15749,7 +15529,7 @@ function recordVerdict(d, v) {
15749
15529
  if (!lines.has(f.file)) {
15750
15530
  try {
15751
15531
  const abs = (0, import_node_path13.join)(root, f.file);
15752
- lines.set(f.file, (0, import_node_fs17.existsSync)(abs) ? (0, import_node_fs17.readFileSync)(abs, "utf8").split("\n") : null);
15532
+ lines.set(f.file, (0, import_node_fs14.existsSync)(abs) ? (0, import_node_fs14.readFileSync)(abs, "utf8").split("\n") : null);
15753
15533
  } catch {
15754
15534
  lines.set(f.file, null);
15755
15535
  }
@@ -15850,7 +15630,7 @@ function recallMemory(d, identity, opts) {
15850
15630
  readFileLines: (file) => {
15851
15631
  try {
15852
15632
  const abs = (0, import_node_path13.join)(root, file);
15853
- return (0, import_node_fs17.existsSync)(abs) ? (0, import_node_fs17.readFileSync)(abs, "utf8").split("\n") : null;
15633
+ return (0, import_node_fs14.existsSync)(abs) ? (0, import_node_fs14.readFileSync)(abs, "utf8").split("\n") : null;
15854
15634
  } catch {
15855
15635
  return null;
15856
15636
  }
@@ -15899,21 +15679,15 @@ function registerIntentCommands(program2) {
15899
15679
  if (!prompt) {
15900
15680
  process.exit(0);
15901
15681
  }
15902
- if (deferredToPlugin("intent capture", event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null)) {
15903
- process.exit(0);
15904
- }
15905
- const isPrimitive = isSlashCommand(prompt);
15906
15682
  const authForScope = await resolveToken(program2.opts().token);
15907
15683
  const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
15908
15684
  const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
15909
- if (!isPrimitive) await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
15910
- if (!isPrimitive) {
15911
- try {
15912
- const tok = await resolveToken(globals.token);
15913
- const session = sessionDossier(tok.ok ? tok.data.token : null, event.session_id ?? null);
15914
- if (session) recordGoal(session.d, prompt);
15915
- } catch {
15916
- }
15685
+ await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
15686
+ try {
15687
+ const tok = await resolveToken(globals.token);
15688
+ const session = sessionDossier(tok.ok ? tok.data.token : null, event.session_id ?? null);
15689
+ if (session) recordGoal(session.d, prompt);
15690
+ } catch {
15917
15691
  }
15918
15692
  try {
15919
15693
  await ensureMemoryDir();
@@ -15994,21 +15768,21 @@ async function fireClassify(prompt, sessionId, globals) {
15994
15768
  }
15995
15769
 
15996
15770
  // src/commands/lifecycle.ts
15997
- var import_node_fs21 = require("node:fs");
15771
+ var import_node_fs18 = require("node:fs");
15998
15772
  var import_node_path17 = require("node:path");
15999
15773
 
16000
15774
  // src/lib/baseline.ts
16001
- var import_node_fs20 = require("node:fs");
15775
+ var import_node_fs17 = require("node:fs");
16002
15776
  var import_node_path16 = require("node:path");
16003
15777
  var import_node_crypto9 = require("node:crypto");
16004
15778
 
16005
15779
  // src/lib/snapshot.ts
16006
- var import_node_fs19 = require("node:fs");
15780
+ var import_node_fs16 = require("node:fs");
16007
15781
  var import_node_path15 = require("node:path");
16008
15782
  var import_node_child_process6 = require("node:child_process");
16009
15783
 
16010
15784
  // src/lib/files.ts
16011
- var import_node_fs18 = require("node:fs");
15785
+ var import_node_fs15 = require("node:fs");
16012
15786
  var import_node_path14 = require("node:path");
16013
15787
  var LANG_MAP = {
16014
15788
  // Analyzable (static analysis + Gemini)
@@ -16085,7 +15859,7 @@ function sortByMtime(files) {
16085
15859
  const resolved = resolveFile(f);
16086
15860
  if (!resolved) return null;
16087
15861
  try {
16088
- const stat3 = (0, import_node_fs18.statSync)(resolved);
15862
+ const stat3 = (0, import_node_fs15.statSync)(resolved);
16089
15863
  return { path: f, resolved, mtime: stat3.mtimeMs };
16090
15864
  } catch {
16091
15865
  return null;
@@ -16118,7 +15892,7 @@ function collectCodeDelta(files, opts) {
16118
15892
  }
16119
15893
  let size;
16120
15894
  try {
16121
- size = (0, import_node_fs18.statSync)(resolved).size;
15895
+ size = (0, import_node_fs15.statSync)(resolved).size;
16122
15896
  } catch {
16123
15897
  exclude(filepath, "not-stattable");
16124
15898
  continue;
@@ -16135,7 +15909,7 @@ function collectCodeDelta(files, opts) {
16135
15909
  }
16136
15910
  let content;
16137
15911
  try {
16138
- content = (0, import_node_fs18.readFileSync)(resolved, "utf-8");
15912
+ content = (0, import_node_fs15.readFileSync)(resolved, "utf-8");
16139
15913
  } catch {
16140
15914
  exclude(filepath, "not-readable");
16141
15915
  continue;
@@ -16174,7 +15948,7 @@ function collectCodeDelta(files, opts) {
16174
15948
 
16175
15949
  // src/lib/snapshot.ts
16176
15950
  function generateSnapshotDiffs(files) {
16177
- if (!(0, import_node_fs19.existsSync)(SNAPSHOT_DIR)) {
15951
+ if (!(0, import_node_fs16.existsSync)(SNAPSHOT_DIR)) {
16178
15952
  return { diffs: [], has_snapshots: false };
16179
15953
  }
16180
15954
  const diffs = [];
@@ -16182,8 +15956,8 @@ function generateSnapshotDiffs(files) {
16182
15956
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16183
15957
  const snapshotPath = (0, import_node_path15.join)(SNAPSHOT_DIR, file.path);
16184
15958
  const language = file.language ?? detectLanguage(file.path);
16185
- if ((0, import_node_fs19.existsSync)(snapshotPath)) {
16186
- const oldContent = (0, import_node_fs19.readFileSync)(snapshotPath, "utf-8");
15959
+ if ((0, import_node_fs16.existsSync)(snapshotPath)) {
15960
+ const oldContent = (0, import_node_fs16.readFileSync)(snapshotPath, "utf-8");
16187
15961
  if (oldContent === file.content) continue;
16188
15962
  const diff = computeDiff(oldContent, file.content, file.path);
16189
15963
  if (diff) {
@@ -16210,8 +15984,8 @@ function saveSnapshots(files) {
16210
15984
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
16211
15985
  const snapshotPath = (0, import_node_path15.join)(SNAPSHOT_DIR, file.path);
16212
15986
  snapshotPaths.add(snapshotPath);
16213
- (0, import_node_fs19.mkdirSync)((0, import_node_path15.dirname)(snapshotPath), { recursive: true });
16214
- (0, import_node_fs19.writeFileSync)(snapshotPath, file.content);
15987
+ (0, import_node_fs16.mkdirSync)((0, import_node_path15.dirname)(snapshotPath), { recursive: true });
15988
+ (0, import_node_fs16.writeFileSync)(snapshotPath, file.content);
16215
15989
  }
16216
15990
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
16217
15991
  }
@@ -16219,9 +15993,9 @@ function computeDiff(oldContent, newContent, filePath) {
16219
15993
  const tmpOld = (0, import_node_path15.join)(SNAPSHOT_DIR, ".diff-old.tmp");
16220
15994
  const tmpNew = (0, import_node_path15.join)(SNAPSHOT_DIR, ".diff-new.tmp");
16221
15995
  try {
16222
- (0, import_node_fs19.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
16223
- (0, import_node_fs19.writeFileSync)(tmpOld, oldContent);
16224
- (0, import_node_fs19.writeFileSync)(tmpNew, newContent);
15996
+ (0, import_node_fs16.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
15997
+ (0, import_node_fs16.writeFileSync)(tmpOld, oldContent);
15998
+ (0, import_node_fs16.writeFileSync)(tmpNew, newContent);
16225
15999
  const result = (0, import_node_child_process6.execSync)(
16226
16000
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
16227
16001
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -16235,32 +16009,32 @@ function computeDiff(oldContent, newContent, filePath) {
16235
16009
  return null;
16236
16010
  } finally {
16237
16011
  try {
16238
- (0, import_node_fs19.unlinkSync)(tmpOld);
16012
+ (0, import_node_fs16.unlinkSync)(tmpOld);
16239
16013
  } catch {
16240
16014
  }
16241
16015
  try {
16242
- (0, import_node_fs19.unlinkSync)(tmpNew);
16016
+ (0, import_node_fs16.unlinkSync)(tmpNew);
16243
16017
  } catch {
16244
16018
  }
16245
16019
  }
16246
16020
  }
16247
16021
  function cleanStaleSnapshots(dir, keepSet) {
16248
- if (!(0, import_node_fs19.existsSync)(dir)) return;
16022
+ if (!(0, import_node_fs16.existsSync)(dir)) return;
16249
16023
  try {
16250
- const entries = (0, import_node_fs19.readdirSync)(dir, { withFileTypes: true });
16024
+ const entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
16251
16025
  for (const entry of entries) {
16252
16026
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
16253
16027
  const fullPath = (0, import_node_path15.join)(dir, entry.name);
16254
16028
  if (entry.isDirectory()) {
16255
16029
  cleanStaleSnapshots(fullPath, keepSet);
16256
16030
  try {
16257
- const remaining = (0, import_node_fs19.readdirSync)(fullPath);
16258
- if (remaining.length === 0) (0, import_node_fs19.rmdirSync)(fullPath);
16031
+ const remaining = (0, import_node_fs16.readdirSync)(fullPath);
16032
+ if (remaining.length === 0) (0, import_node_fs16.rmdirSync)(fullPath);
16259
16033
  } catch {
16260
16034
  }
16261
16035
  } else if (!keepSet.has(fullPath)) {
16262
16036
  try {
16263
- (0, import_node_fs19.unlinkSync)(fullPath);
16037
+ (0, import_node_fs16.unlinkSync)(fullPath);
16264
16038
  } catch {
16265
16039
  }
16266
16040
  }
@@ -16291,8 +16065,8 @@ var CARRY_FILE = `${BASELINE_DIR}/.carry`;
16291
16065
  var CARRY_WINDOW_MS = 12e4;
16292
16066
  function writeCarry(sessionId, headSha) {
16293
16067
  try {
16294
- (0, import_node_fs20.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16295
- (0, import_node_fs20.writeFileSync)(
16068
+ (0, import_node_fs17.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
16069
+ (0, import_node_fs17.writeFileSync)(
16296
16070
  projectPath(CARRY_FILE),
16297
16071
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
16298
16072
  );
@@ -16302,10 +16076,10 @@ function writeCarry(sessionId, headSha) {
16302
16076
  function claimCarry(newKey) {
16303
16077
  const carryPath = projectPath(CARRY_FILE);
16304
16078
  try {
16305
- if (!(0, import_node_fs20.existsSync)(carryPath)) return null;
16306
- const carry = JSON.parse((0, import_node_fs20.readFileSync)(carryPath, "utf-8"));
16079
+ if (!(0, import_node_fs17.existsSync)(carryPath)) return null;
16080
+ const carry = JSON.parse((0, import_node_fs17.readFileSync)(carryPath, "utf-8"));
16307
16081
  try {
16308
- (0, import_node_fs20.rmSync)(carryPath, { force: true });
16082
+ (0, import_node_fs17.rmSync)(carryPath, { force: true });
16309
16083
  } catch {
16310
16084
  }
16311
16085
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -16316,11 +16090,11 @@ function claimCarry(newKey) {
16316
16090
  if (!prior) return null;
16317
16091
  const toDir = sessionDir(newKey);
16318
16092
  try {
16319
- (0, import_node_fs20.rmSync)(toDir, { recursive: true, force: true });
16093
+ (0, import_node_fs17.rmSync)(toDir, { recursive: true, force: true });
16320
16094
  } catch {
16321
16095
  }
16322
- (0, import_node_fs20.renameSync)(fromDir, toDir);
16323
- (0, import_node_fs20.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16096
+ (0, import_node_fs17.renameSync)(fromDir, toDir);
16097
+ (0, import_node_fs17.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
16324
16098
  return readManifest(toDir);
16325
16099
  } catch {
16326
16100
  return null;
@@ -16344,21 +16118,21 @@ function captureBaseline(opts = {}) {
16344
16118
  const head_sha = getCurrentCommit();
16345
16119
  const dirty = getDirtyFiles();
16346
16120
  try {
16347
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
16121
+ (0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
16348
16122
  } catch {
16349
16123
  }
16350
16124
  const filesDir = (0, import_node_path16.join)(dir, "files");
16351
16125
  const mirrored = [];
16352
16126
  try {
16353
- (0, import_node_fs20.mkdirSync)(filesDir, { recursive: true });
16127
+ (0, import_node_fs17.mkdirSync)(filesDir, { recursive: true });
16354
16128
  for (const p of dirty) {
16355
16129
  if (p.includes("..")) continue;
16356
16130
  const content = safeReadForMirror(projectPath(p));
16357
16131
  if (content === null) continue;
16358
16132
  const dest = mirrorPath(dir, p);
16359
16133
  try {
16360
- (0, import_node_fs20.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
16361
- (0, import_node_fs20.writeFileSync)(dest, content);
16134
+ (0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
16135
+ (0, import_node_fs17.writeFileSync)(dest, content);
16362
16136
  mirrored.push(p);
16363
16137
  } catch {
16364
16138
  }
@@ -16373,8 +16147,8 @@ function captureBaseline(opts = {}) {
16373
16147
  version: BASELINE_VERSION
16374
16148
  };
16375
16149
  try {
16376
- (0, import_node_fs20.mkdirSync)(dir, { recursive: true });
16377
- (0, import_node_fs20.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16150
+ (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
16151
+ (0, import_node_fs17.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
16378
16152
  } catch {
16379
16153
  }
16380
16154
  pruneOldBaselines();
@@ -16385,9 +16159,9 @@ function readBaseline(sessionId) {
16385
16159
  }
16386
16160
  function readManifest(dir) {
16387
16161
  const mp = manifestPath(dir);
16388
- if (!(0, import_node_fs20.existsSync)(mp)) return null;
16162
+ if (!(0, import_node_fs17.existsSync)(mp)) return null;
16389
16163
  try {
16390
- const parsed = JSON.parse((0, import_node_fs20.readFileSync)(mp, "utf-8"));
16164
+ const parsed = JSON.parse((0, import_node_fs17.readFileSync)(mp, "utf-8"));
16391
16165
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
16392
16166
  return null;
16393
16167
  }
@@ -16418,9 +16192,9 @@ function preImage(repoRelPath, baseline) {
16418
16192
  function resolvePreImage(repoRelPath, baseline) {
16419
16193
  if (baseline.dirty_paths.includes(repoRelPath)) {
16420
16194
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
16421
- if ((0, import_node_fs20.existsSync)(mp)) {
16195
+ if ((0, import_node_fs17.existsSync)(mp)) {
16422
16196
  try {
16423
- return { content: (0, import_node_fs20.readFileSync)(mp, "utf-8"), existed: true };
16197
+ return { content: (0, import_node_fs17.readFileSync)(mp, "utf-8"), existed: true };
16424
16198
  } catch {
16425
16199
  }
16426
16200
  }
@@ -16465,8 +16239,8 @@ function absorbIntoBaseline(paths, sessionId) {
16465
16239
  const content = safeReadForMirror(projectPath(p));
16466
16240
  if (content === null) continue;
16467
16241
  const dest = mirrorPath(dir, p);
16468
- (0, import_node_fs20.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
16469
- (0, import_node_fs20.writeFileSync)(dest, content);
16242
+ (0, import_node_fs17.mkdirSync)((0, import_node_path16.dirname)(dest), { recursive: true });
16243
+ (0, import_node_fs17.writeFileSync)(dest, content);
16470
16244
  dirty.add(p);
16471
16245
  adopted++;
16472
16246
  } catch {
@@ -16475,7 +16249,7 @@ function absorbIntoBaseline(paths, sessionId) {
16475
16249
  if (adopted === 0) return 0;
16476
16250
  try {
16477
16251
  const updated = { ...baseline, dirty_paths: [...dirty] };
16478
- (0, import_node_fs20.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
16252
+ (0, import_node_fs17.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
16479
16253
  preImageCache.delete(baseline);
16480
16254
  } catch {
16481
16255
  return 0;
@@ -16486,7 +16260,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
16486
16260
  const pre = preImage(repoRelPath, baseline);
16487
16261
  let current;
16488
16262
  try {
16489
- current = (0, import_node_fs20.readFileSync)(projectPath(repoRelPath), "utf-8");
16263
+ current = (0, import_node_fs17.readFileSync)(projectPath(repoRelPath), "utf-8");
16490
16264
  } catch {
16491
16265
  return pre.existed;
16492
16266
  }
@@ -16495,8 +16269,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
16495
16269
  }
16496
16270
  function safeReadForMirror(absPath) {
16497
16271
  try {
16498
- if ((0, import_node_fs20.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
16499
- const buf = (0, import_node_fs20.readFileSync)(absPath);
16272
+ if ((0, import_node_fs17.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
16273
+ const buf = (0, import_node_fs17.readFileSync)(absPath);
16500
16274
  if (buf.includes(0)) return null;
16501
16275
  return buf.toString("utf-8");
16502
16276
  } catch {
@@ -16507,7 +16281,7 @@ function pruneOldBaselines() {
16507
16281
  const root = projectPath(BASELINE_DIR);
16508
16282
  let entries;
16509
16283
  try {
16510
- entries = (0, import_node_fs20.readdirSync)(root);
16284
+ entries = (0, import_node_fs17.readdirSync)(root);
16511
16285
  } catch {
16512
16286
  return;
16513
16287
  }
@@ -16517,8 +16291,8 @@ function pruneOldBaselines() {
16517
16291
  const manifest = readManifest(dir);
16518
16292
  if (!manifest) {
16519
16293
  try {
16520
- if (now - (0, import_node_fs20.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
16521
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
16294
+ if (now - (0, import_node_fs17.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
16295
+ (0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
16522
16296
  }
16523
16297
  } catch {
16524
16298
  }
@@ -16526,7 +16300,7 @@ function pruneOldBaselines() {
16526
16300
  }
16527
16301
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
16528
16302
  try {
16529
- (0, import_node_fs20.rmSync)(dir, { recursive: true, force: true });
16303
+ (0, import_node_fs17.rmSync)(dir, { recursive: true, force: true });
16530
16304
  } catch {
16531
16305
  }
16532
16306
  }
@@ -16620,7 +16394,6 @@ function registerLifecycleCommands(program2) {
16620
16394
  if (!verityConfigured()) process.exit(0);
16621
16395
  const event = await readHookStdin();
16622
16396
  const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
16623
- if (deferredToPlugin("compact", sessionId)) process.exit(0);
16624
16397
  const globals = program2.opts();
16625
16398
  const tok = await resolveToken(globals.token);
16626
16399
  const session2 = sessionDossier(tok.ok ? tok.data.token : null, sessionId);
@@ -16649,7 +16422,6 @@ function registerLifecycleCommands(program2) {
16649
16422
  if (!verityConfigured()) process.exit(0);
16650
16423
  const event = await readHookStdin();
16651
16424
  const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
16652
- if (deferredToPlugin("session end", sessionId)) process.exit(0);
16653
16425
  const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
16654
16426
  if (reason === "clear") {
16655
16427
  writeCarry(sessionId ?? void 0, getCurrentCommit());
@@ -16702,7 +16474,7 @@ function buildCompactionContext(session) {
16702
16474
  readFileLines: (file) => {
16703
16475
  try {
16704
16476
  const abs = (0, import_node_path17.join)(root, file);
16705
- return (0, import_node_fs21.existsSync)(abs) ? (0, import_node_fs21.readFileSync)(abs, "utf8").split("\n") : null;
16477
+ return (0, import_node_fs18.existsSync)(abs) ? (0, import_node_fs18.readFileSync)(abs, "utf8").split("\n") : null;
16706
16478
  } catch {
16707
16479
  return null;
16708
16480
  }
@@ -16759,18 +16531,18 @@ async function readHookStdin() {
16759
16531
 
16760
16532
  // src/commands/standard.ts
16761
16533
  var import_promises12 = require("node:fs/promises");
16762
- var import_node_fs28 = require("node:fs");
16534
+ var import_node_fs25 = require("node:fs");
16763
16535
  var import_yaml3 = __toESM(require_dist());
16764
16536
 
16765
16537
  // src/lib/synthesize.ts
16766
16538
  var import_node_child_process8 = require("node:child_process");
16767
- var import_node_fs24 = require("node:fs");
16539
+ var import_node_fs21 = require("node:fs");
16768
16540
  var import_promises9 = require("node:fs/promises");
16769
16541
  var import_node_path20 = require("node:path");
16770
16542
  var import_yaml = __toESM(require_dist());
16771
16543
 
16772
16544
  // src/lib/data-dir.ts
16773
- var import_node_fs22 = require("node:fs");
16545
+ var import_node_fs19 = require("node:fs");
16774
16546
  var import_node_path18 = require("node:path");
16775
16547
  function resolveDataDir() {
16776
16548
  const candidates = [
@@ -16778,21 +16550,10 @@ function resolveDataDir() {
16778
16550
  // installed: node_modules/@codacy/verity-cli/data
16779
16551
  (0, import_node_path18.join)(__dirname, "..", "..", "data"),
16780
16552
  // edge case: nested resolution
16781
- // THE COMMITTED SOURCE, for a source checkout that has not been built.
16782
- // cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
16783
- // into it) and is gitignored, because skills have one committed source — so
16784
- // in a fresh clone the packaged candidates above do not exist at all, and
16785
- // without this the synthesizer throws "Could not find Verity skill data"
16786
- // for every test and every `verity` run from source. Resolved from this
16787
- // module's own location, never the cwd: see the warning below.
16788
- (0, import_node_path18.join)(__dirname, "..", "..", "client"),
16789
- // bundled: cli/bin/ → ../../client
16790
- (0, import_node_path18.join)(__dirname, "..", "..", "..", "client"),
16791
- // tsx: cli/src/lib/ → ../../../client
16792
16553
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
16793
16554
  ];
16794
16555
  for (const candidate of candidates) {
16795
- if ((0, import_node_fs22.existsSync)((0, import_node_path18.join)(candidate, "skills"))) {
16556
+ if ((0, import_node_fs19.existsSync)((0, import_node_path18.join)(candidate, "skills"))) {
16796
16557
  return candidate;
16797
16558
  }
16798
16559
  }
@@ -16806,7 +16567,7 @@ function setupDataPath(file) {
16806
16567
 
16807
16568
  // src/lib/detect.ts
16808
16569
  var import_node_child_process7 = require("node:child_process");
16809
- var import_node_fs23 = require("node:fs");
16570
+ var import_node_fs20 = require("node:fs");
16810
16571
  var import_node_path19 = require("node:path");
16811
16572
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
16812
16573
  "typescript",
@@ -16863,7 +16624,7 @@ function walk(root) {
16863
16624
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
16864
16625
  let entries;
16865
16626
  try {
16866
- entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
16627
+ entries = (0, import_node_fs20.readdirSync)(dir, { withFileTypes: true });
16867
16628
  } catch {
16868
16629
  return;
16869
16630
  }
@@ -16938,7 +16699,7 @@ var TOOL_CONFIG_MARKERS = [
16938
16699
  ];
16939
16700
  function readJson(path) {
16940
16701
  try {
16941
- return JSON.parse((0, import_node_fs23.readFileSync)(path, "utf-8"));
16702
+ return JSON.parse((0, import_node_fs20.readFileSync)(path, "utf-8"));
16942
16703
  } catch {
16943
16704
  return null;
16944
16705
  }
@@ -16971,9 +16732,9 @@ function declaredDependencies(root, files) {
16971
16732
  ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path19.join)(root, f))
16972
16733
  ];
16973
16734
  for (const path of pythonManifests) {
16974
- if (!(0, import_node_fs23.existsSync)(path)) continue;
16735
+ if (!(0, import_node_fs20.existsSync)(path)) continue;
16975
16736
  try {
16976
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
16737
+ const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
16977
16738
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
16978
16739
  for (const line of text.split("\n")) {
16979
16740
  if (!/dependencies\s*=/.test(line)) continue;
@@ -16987,9 +16748,9 @@ function declaredDependencies(root, files) {
16987
16748
  ...files.filter((f) => f.includes("/") && (0, import_node_path19.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path19.join)(root, f))
16988
16749
  ];
16989
16750
  for (const path of goMods) {
16990
- if (!(0, import_node_fs23.existsSync)(path)) continue;
16751
+ if (!(0, import_node_fs20.existsSync)(path)) continue;
16991
16752
  try {
16992
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
16753
+ const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
16993
16754
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
16994
16755
  names2.push(m[1].replace(/^github\.com\//, ""));
16995
16756
  }
@@ -16998,9 +16759,9 @@ function declaredDependencies(root, files) {
16998
16759
  }
16999
16760
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
17000
16761
  const path = (0, import_node_path19.join)(root, file);
17001
- if (!(0, import_node_fs23.existsSync)(path)) continue;
16762
+ if (!(0, import_node_fs20.existsSync)(path)) continue;
17002
16763
  try {
17003
- const text = (0, import_node_fs23.readFileSync)(path, "utf-8");
16764
+ const text = (0, import_node_fs20.readFileSync)(path, "utf-8");
17004
16765
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
17005
16766
  } catch {
17006
16767
  }
@@ -17008,7 +16769,7 @@ function declaredDependencies(root, files) {
17008
16769
  return names2;
17009
16770
  }
17010
16771
  function detectBuildSystem(root, files) {
17011
- const has = (f) => (0, import_node_fs23.existsSync)((0, import_node_path19.join)(root, f)) || files.some((p) => (0, import_node_path19.basename)(p) === f);
16772
+ const has = (f) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, f)) || files.some((p) => (0, import_node_path19.basename)(p) === f);
17012
16773
  if (has("pnpm-lock.yaml")) return "pnpm";
17013
16774
  if (has("yarn.lock")) return "yarn";
17014
16775
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -17025,7 +16786,7 @@ function detectBuildSystem(root, files) {
17025
16786
  }
17026
16787
  function detectArchitecture(root, files) {
17027
16788
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
17028
- if (workspaceMarkers.some((m) => (0, import_node_fs23.existsSync)((0, import_node_path19.join)(root, m)))) return "monorepo";
16789
+ if (workspaceMarkers.some((m) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, m)))) return "monorepo";
17029
16790
  const pkg = readJson((0, import_node_path19.join)(root, "package.json"));
17030
16791
  if (pkg && "workspaces" in pkg) return "monorepo";
17031
16792
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
@@ -17050,8 +16811,8 @@ function measureAvgFileLength(root, files, languages) {
17050
16811
  for (let i = 0; i < candidates.length; i += stride) {
17051
16812
  const path = (0, import_node_path19.join)(root, candidates[i]);
17052
16813
  try {
17053
- if ((0, import_node_fs23.statSync)(path).size > 2 * 1024 * 1024) continue;
17054
- total += (0, import_node_fs23.readFileSync)(path, "utf-8").split("\n").length;
16814
+ if ((0, import_node_fs20.statSync)(path).size > 2 * 1024 * 1024) continue;
16815
+ total += (0, import_node_fs20.readFileSync)(path, "utf-8").split("\n").length;
17055
16816
  counted++;
17056
16817
  } catch {
17057
16818
  }
@@ -17076,7 +16837,7 @@ function detectProject(root = repoRoot()) {
17076
16837
  const existingToolConfigs = [];
17077
16838
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
17078
16839
  for (const marker of markers) {
17079
- if ((0, import_node_fs23.existsSync)((0, import_node_path19.join)(root, marker))) {
16840
+ if ((0, import_node_fs20.existsSync)((0, import_node_path19.join)(root, marker))) {
17080
16841
  existingToolConfigs.push({ tool, path: `./${marker}` });
17081
16842
  break;
17082
16843
  }
@@ -17181,8 +16942,8 @@ ${closingNote(input.origin)}
17181
16942
 
17182
16943
  // src/lib/synthesize.ts
17183
16944
  function loadCatalog() {
17184
- const catalog = (0, import_yaml.parse)((0, import_node_fs24.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
17185
- const template = (0, import_yaml.parse)((0, import_node_fs24.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
16945
+ const catalog = (0, import_yaml.parse)((0, import_node_fs21.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
16946
+ const template = (0, import_yaml.parse)((0, import_node_fs21.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
17186
16947
  return { catalog, template };
17187
16948
  }
17188
16949
  function selectTools(languages, intensity, catalog) {
@@ -17460,7 +17221,7 @@ function validatePatternIds() {
17460
17221
  }
17461
17222
  async function runSynthesis(opts) {
17462
17223
  const standardPath = projectPath(STANDARD_FILE);
17463
- if ((0, import_node_fs24.existsSync)(standardPath) && !opts.force) {
17224
+ if ((0, import_node_fs21.existsSync)(standardPath) && !opts.force) {
17464
17225
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
17465
17226
  }
17466
17227
  const detected = opts.detected ?? detectProject();
@@ -17588,11 +17349,11 @@ ${validation.detail}`);
17588
17349
 
17589
17350
  // src/lib/setup-state.ts
17590
17351
  var import_promises10 = require("node:fs/promises");
17591
- var import_node_fs25 = require("node:fs");
17352
+ var import_node_fs22 = require("node:fs");
17592
17353
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
17593
17354
  async function readSetupState() {
17594
17355
  const path = projectPath(SETUP_STATE_FILE);
17595
- if (!(0, import_node_fs25.existsSync)(path)) return null;
17356
+ if (!(0, import_node_fs22.existsSync)(path)) return null;
17596
17357
  try {
17597
17358
  const parsed = JSON.parse(await (0, import_promises10.readFile)(path, "utf-8"));
17598
17359
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -17608,12 +17369,12 @@ async function writeSetupState(patch) {
17608
17369
  }
17609
17370
 
17610
17371
  // src/lib/push-setup.ts
17611
- var import_node_fs27 = require("node:fs");
17372
+ var import_node_fs24 = require("node:fs");
17612
17373
  var import_promises11 = require("node:fs/promises");
17613
17374
  var import_yaml2 = __toESM(require_dist());
17614
17375
 
17615
17376
  // src/lib/verityignore.ts
17616
- var import_node_fs26 = require("node:fs");
17377
+ var import_node_fs23 = require("node:fs");
17617
17378
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
17618
17379
  var SECURITY_PROBES = [
17619
17380
  ".env",
@@ -17706,9 +17467,9 @@ function isIgnored2(ig, path) {
17706
17467
  }
17707
17468
  function loadVerityIgnore() {
17708
17469
  const file = projectPath(VERITYIGNORE_FILE);
17709
- if (!(0, import_node_fs26.existsSync)(file)) return EMPTY;
17470
+ if (!(0, import_node_fs23.existsSync)(file)) return EMPTY;
17710
17471
  try {
17711
- return parseVerityIgnore((0, import_node_fs26.readFileSync)(file, "utf-8"));
17472
+ return parseVerityIgnore((0, import_node_fs23.readFileSync)(file, "utf-8"));
17712
17473
  } catch {
17713
17474
  return EMPTY;
17714
17475
  }
@@ -17746,9 +17507,9 @@ function buildStandardUpload(standard, ignoreRaw) {
17746
17507
  }
17747
17508
  function readVerityIgnoreRaw() {
17748
17509
  const file = projectPath(VERITYIGNORE_FILE);
17749
- if (!(0, import_node_fs26.existsSync)(file)) return null;
17510
+ if (!(0, import_node_fs23.existsSync)(file)) return null;
17750
17511
  try {
17751
- return (0, import_node_fs26.readFileSync)(file, "utf-8");
17512
+ return (0, import_node_fs23.readFileSync)(file, "utf-8");
17752
17513
  } catch {
17753
17514
  return null;
17754
17515
  }
@@ -17776,7 +17537,7 @@ async function pushStandardAndConfig(globals, what = {}) {
17776
17537
  }
17777
17538
  let standardVersion = null;
17778
17539
  const standardPath = projectPath(STANDARD_FILE);
17779
- if (pushStandard && (0, import_node_fs27.existsSync)(standardPath)) {
17540
+ if (pushStandard && (0, import_node_fs24.existsSync)(standardPath)) {
17780
17541
  try {
17781
17542
  const content = (0, import_yaml2.parse)(await (0, import_promises11.readFile)(standardPath, "utf-8"));
17782
17543
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -17801,7 +17562,7 @@ async function pushStandardAndConfig(globals, what = {}) {
17801
17562
  }
17802
17563
  let configPushed = false;
17803
17564
  const configPath = projectPath(CODACY_CONFIG_FILE);
17804
- if (pushConfig && (0, import_node_fs27.existsSync)(configPath)) {
17565
+ if (pushConfig && (0, import_node_fs24.existsSync)(configPath)) {
17805
17566
  try {
17806
17567
  const content = JSON.parse(await (0, import_promises11.readFile)(configPath, "utf-8"));
17807
17568
  const result = await apiRequest({
@@ -17833,7 +17594,7 @@ function registerStandardCommands(program2) {
17833
17594
  const state = await readSetupState();
17834
17595
  if (opts.configOnly) {
17835
17596
  const standardPath = projectPath(STANDARD_FILE);
17836
- if (!(0, import_node_fs28.existsSync)(standardPath)) {
17597
+ if (!(0, import_node_fs25.existsSync)(standardPath)) {
17837
17598
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
17838
17599
  process.exit(1);
17839
17600
  }
@@ -18002,22 +17763,6 @@ function registerConfigCommands(program2) {
18002
17763
  }
18003
17764
  process.stdout.write(urlResult.data + "\n");
18004
17765
  });
18005
- config.command("git-moments [moments]").description('Get or set the git moments the guard reviews: commit,push \u2014 or "none"').action((moments) => {
18006
- if (moments === void 0) {
18007
- const current = readProjectConfig().git_moments;
18008
- process.stdout.write((current.length ? current.join(",") : "none") + "\n");
18009
- return;
18010
- }
18011
- const next = moments === "none" ? [] : parseMoments(moments);
18012
- if (moments !== "none" && next.length === 0) {
18013
- printError(`Unrecognised moments: ${moments}. Use "commit", "push", "commit,push", or "none".`);
18014
- process.exit(1);
18015
- }
18016
- writeProjectConfig({ git_moments: next });
18017
- printInfo(
18018
- next.length ? `Git-moment review enabled for: ${next.join(", ")}` : "Git-moment review disabled \u2014 commits and pushes are no longer gated."
18019
- );
18020
- });
18021
17766
  config.command("push").description("Upload the analysis config to the service").option("--file <path>", "Path to config file", CODACY_CONFIG_FILE).action(async (opts) => {
18022
17767
  const globals = program2.opts();
18023
17768
  const tokenResult = await resolveToken(globals.token);
@@ -18160,10 +17905,10 @@ function formatRunDetail(run2) {
18160
17905
  }
18161
17906
 
18162
17907
  // src/lib/ignore-declaration.ts
18163
- var import_node_fs30 = require("node:fs");
17908
+ var import_node_fs27 = require("node:fs");
18164
17909
 
18165
17910
  // src/lib/debounce.ts
18166
- var import_node_fs29 = require("node:fs");
17911
+ var import_node_fs26 = require("node:fs");
18167
17912
  var import_node_crypto10 = require("node:crypto");
18168
17913
  function scopedFile(base, sessionId) {
18169
17914
  if (!sessionId) return base;
@@ -18171,9 +17916,9 @@ function scopedFile(base, sessionId) {
18171
17916
  }
18172
17917
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18173
17918
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18174
- if (!(0, import_node_fs29.existsSync)(file)) return null;
17919
+ if (!(0, import_node_fs26.existsSync)(file)) return null;
18175
17920
  try {
18176
- const lastTs = parseInt((0, import_node_fs29.readFileSync)(file, "utf-8").trim(), 10);
17921
+ const lastTs = parseInt((0, import_node_fs26.readFileSync)(file, "utf-8").trim(), 10);
18177
17922
  const nowTs = Math.floor(Date.now() / 1e3);
18178
17923
  const elapsed = nowTs - lastTs;
18179
17924
  if (elapsed < debounceSeconds) {
@@ -18186,10 +17931,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18186
17931
  function checkMtime(files, bypassForRecentCommits, sessionId) {
18187
17932
  if (bypassForRecentCommits) return null;
18188
17933
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18189
- if (!(0, import_node_fs29.existsSync)(file)) return null;
17934
+ if (!(0, import_node_fs26.existsSync)(file)) return null;
18190
17935
  let debounceTime;
18191
17936
  try {
18192
- debounceTime = (0, import_node_fs29.statSync)(file).mtimeMs;
17937
+ debounceTime = (0, import_node_fs26.statSync)(file).mtimeMs;
18193
17938
  } catch {
18194
17939
  return null;
18195
17940
  }
@@ -18197,7 +17942,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
18197
17942
  const resolved = resolveFile(f);
18198
17943
  if (!resolved) continue;
18199
17944
  try {
18200
- const stat3 = (0, import_node_fs29.statSync)(resolved);
17945
+ const stat3 = (0, import_node_fs26.statSync)(resolved);
18201
17946
  if (stat3.mtimeMs > debounceTime) {
18202
17947
  return null;
18203
17948
  }
@@ -18213,8 +17958,8 @@ function computeContentHash(files) {
18213
17958
  for (const f of sorted) {
18214
17959
  const resolved = resolveFile(f) ?? f;
18215
17960
  try {
18216
- if ((0, import_node_fs29.existsSync)(resolved)) {
18217
- hash.update((0, import_node_fs29.readFileSync)(resolved));
17961
+ if ((0, import_node_fs26.existsSync)(resolved)) {
17962
+ hash.update((0, import_node_fs26.readFileSync)(resolved));
18218
17963
  }
18219
17964
  } catch {
18220
17965
  }
@@ -18224,9 +17969,9 @@ function computeContentHash(files) {
18224
17969
  function checkContentHash(files, sessionId) {
18225
17970
  const hash = computeContentHash(files);
18226
17971
  const file = scopedFile(HASH_FILE, sessionId);
18227
- if ((0, import_node_fs29.existsSync)(file)) {
17972
+ if ((0, import_node_fs26.existsSync)(file)) {
18228
17973
  try {
18229
- const storedHash = (0, import_node_fs29.readFileSync)(file, "utf-8").trim();
17974
+ const storedHash = (0, import_node_fs26.readFileSync)(file, "utf-8").trim();
18230
17975
  if (hash === storedHash) {
18231
17976
  return { skip: "No source changes since last analysis", hash };
18232
17977
  }
@@ -18236,24 +17981,24 @@ function checkContentHash(files, sessionId) {
18236
17981
  return { skip: null, hash };
18237
17982
  }
18238
17983
  function recordAnalysisStart(sessionId) {
18239
- (0, import_node_fs29.mkdirSync)(VERITY_DIR, { recursive: true });
18240
- (0, import_node_fs29.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
17984
+ (0, import_node_fs26.mkdirSync)(VERITY_DIR, { recursive: true });
17985
+ (0, import_node_fs26.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18241
17986
  }
18242
17987
  function recordPassHash(hash, sessionId) {
18243
- (0, import_node_fs29.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
17988
+ (0, import_node_fs26.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18244
17989
  }
18245
17990
  function narrowToRecent(files, sessionId) {
18246
17991
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18247
- if (!(0, import_node_fs29.existsSync)(file)) return files;
17992
+ if (!(0, import_node_fs26.existsSync)(file)) return files;
18248
17993
  let debounceTime;
18249
17994
  try {
18250
- debounceTime = (0, import_node_fs29.statSync)(file).mtimeMs;
17995
+ debounceTime = (0, import_node_fs26.statSync)(file).mtimeMs;
18251
17996
  } catch {
18252
17997
  return files;
18253
17998
  }
18254
17999
  const recent = files.filter((f) => {
18255
18000
  try {
18256
- return (0, import_node_fs29.existsSync)(f) && (0, import_node_fs29.statSync)(f).mtimeMs > debounceTime;
18001
+ return (0, import_node_fs26.existsSync)(f) && (0, import_node_fs26.statSync)(f).mtimeMs > debounceTime;
18257
18002
  } catch {
18258
18003
  return false;
18259
18004
  }
@@ -18266,9 +18011,9 @@ function readIteration(currentCommit, _contentHash) {
18266
18011
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
18267
18012
  function readBlockState(currentCommit, opts) {
18268
18013
  if (opts?.newUserPrompt) return NO_BLOCKS;
18269
- if (!(0, import_node_fs29.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18014
+ if (!(0, import_node_fs26.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18270
18015
  try {
18271
- const stored = (0, import_node_fs29.readFileSync)(ITERATION_FILE, "utf-8").trim();
18016
+ const stored = (0, import_node_fs26.readFileSync)(ITERATION_FILE, "utf-8").trim();
18272
18017
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
18273
18018
  if (!parsed) return NO_BLOCKS;
18274
18019
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -18314,8 +18059,8 @@ function isSameProblem(previous, current) {
18314
18059
  return current.split(",").some((k) => prev.has(k));
18315
18060
  }
18316
18061
  function writeBlockState(commit, state) {
18317
- (0, import_node_fs29.mkdirSync)(VERITY_DIR, { recursive: true });
18318
- (0, import_node_fs29.writeFileSync)(
18062
+ (0, import_node_fs26.mkdirSync)(VERITY_DIR, { recursive: true });
18063
+ (0, import_node_fs26.writeFileSync)(
18319
18064
  ITERATION_FILE,
18320
18065
  JSON.stringify({
18321
18066
  v: 2,
@@ -18420,9 +18165,9 @@ function resolveIgnoreState(keys) {
18420
18165
  }
18421
18166
  function readIgnoreState(sessionId) {
18422
18167
  const file = stateFile(sessionId);
18423
- if (!(0, import_node_fs30.existsSync)(file)) return null;
18168
+ if (!(0, import_node_fs27.existsSync)(file)) return null;
18424
18169
  try {
18425
- const o = JSON.parse((0, import_node_fs30.readFileSync)(file, "utf-8")) ?? {};
18170
+ const o = JSON.parse((0, import_node_fs27.readFileSync)(file, "utf-8")) ?? {};
18426
18171
  const spent = typeof o.spent === "number" ? o.spent : 0;
18427
18172
  const raw = o.active;
18428
18173
  let active = null;
@@ -18446,8 +18191,8 @@ function readIgnoreState(sessionId) {
18446
18191
  }
18447
18192
  function writeIgnoreState(state, sessionId) {
18448
18193
  try {
18449
- (0, import_node_fs30.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
18450
- (0, import_node_fs30.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
18194
+ (0, import_node_fs27.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
18195
+ (0, import_node_fs27.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
18451
18196
  } catch {
18452
18197
  }
18453
18198
  }
@@ -18821,8 +18566,59 @@ function createRun(opts, globals) {
18821
18566
  };
18822
18567
  }
18823
18568
 
18824
- // src/commands/analyze/index.ts
18825
- var import_node_fs43 = require("node:fs");
18569
+ // src/lib/stderr-log.ts
18570
+ var import_node_fs28 = require("node:fs");
18571
+ var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
18572
+ var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
18573
+ function scrub(s) {
18574
+ return s.replace(TOKEN_RE2, "verity_***REDACTED***").replace(ANSI_RE, "");
18575
+ }
18576
+ var installed = false;
18577
+ var wroteBanner = false;
18578
+ var banner = "";
18579
+ function append(text) {
18580
+ try {
18581
+ const dir = projectPath(DEBUG_LOG_DIR);
18582
+ const file = projectPath(STDERR_LOG_FILE);
18583
+ (0, import_node_fs28.mkdirSync)(dir, { recursive: true });
18584
+ rotateIfNeeded(file);
18585
+ (0, import_node_fs28.appendFileSync)(file, text);
18586
+ } catch {
18587
+ }
18588
+ }
18589
+ function ensureBanner() {
18590
+ if (wroteBanner) return;
18591
+ wroteBanner = true;
18592
+ append(banner);
18593
+ }
18594
+ function installStderrLog(cmd, argv, version) {
18595
+ if (installed || !isDebugEnabled()) return;
18596
+ installed = true;
18597
+ banner = `
18598
+ \u2501\u2501 verity ${cmd} \xB7 ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 pid ${process.pid}
18599
+ v${version} \xB7 ${process.cwd()}
18600
+ argv: ${scrub(argv.join(" "))}
18601
+ `;
18602
+ const original = process.stderr.write.bind(process.stderr);
18603
+ const tee = (...args) => {
18604
+ const result = original(...args);
18605
+ try {
18606
+ const chunk = args[0];
18607
+ const text = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
18608
+ ensureBanner();
18609
+ append(scrub(text));
18610
+ } catch {
18611
+ }
18612
+ return result;
18613
+ };
18614
+ process.stderr.write = tee;
18615
+ }
18616
+ function logToFileOnly(text) {
18617
+ if (!installed) return;
18618
+ ensureBanner();
18619
+ append(text.endsWith("\n") ? text : `${text}
18620
+ `);
18621
+ }
18826
18622
 
18827
18623
  // src/lib/repo-context.ts
18828
18624
  var import_node_child_process9 = require("node:child_process");
@@ -19643,7 +19439,7 @@ function installRunEvidence(run2) {
19643
19439
 
19644
19440
  // src/lib/git-frame.ts
19645
19441
  var import_node_child_process10 = require("node:child_process");
19646
- var import_node_fs31 = require("node:fs");
19442
+ var import_node_fs29 = require("node:fs");
19647
19443
  var import_node_os4 = require("node:os");
19648
19444
  var import_node_path21 = require("node:path");
19649
19445
  var import_node_path22 = require("node:path");
@@ -19782,14 +19578,14 @@ function gitAt(dir, args) {
19782
19578
  }
19783
19579
  function realpathOr(p) {
19784
19580
  try {
19785
- return import_node_fs31.realpathSync.native(p);
19581
+ return import_node_fs29.realpathSync.native(p);
19786
19582
  } catch {
19787
19583
  return (0, import_node_path21.resolve)(p);
19788
19584
  }
19789
19585
  }
19790
19586
  function resolveFrame(input) {
19791
19587
  const found = findMomentSegment(input.command, input.on);
19792
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs31.existsSync)(input.hookCwd);
19588
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs29.existsSync)(input.hookCwd);
19793
19589
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
19794
19590
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
19795
19591
  const refuse = (refusal) => ({
@@ -19812,7 +19608,7 @@ function resolveFrame(input) {
19812
19608
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
19813
19609
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
19814
19610
  if (targetDir !== baseDir) {
19815
- if (!(0, import_node_fs31.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
19611
+ if (!(0, import_node_fs29.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
19816
19612
  dir = targetDir;
19817
19613
  }
19818
19614
  }
@@ -19848,19 +19644,21 @@ function refResolves(frame, ref) {
19848
19644
  return frameGit(frame, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]) !== "";
19849
19645
  }
19850
19646
  var SHA_RE2 = /^[0-9a-f]{40}$/;
19851
- function stagedRange(frame) {
19852
- if (!frame.worktreeRoot) return { kind: "nothing", base: null, head: "INDEX", via: "refused" };
19853
- const mergeHead = frame.gitDir ? (0, import_node_path22.join)(frame.gitDir, "MERGE_HEAD") : null;
19854
- if (mergeHead && (0, import_node_fs31.existsSync)(mergeHead)) {
19855
- const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
19856
- const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
19857
- const resolutions = [...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f));
19858
- return { kind: "merge", base: "HEAD", head: "INDEX", via: "merge-resolutions", files: resolutions };
19647
+ function baselineShaAt(frame) {
19648
+ if (!frame.worktreeRoot) return null;
19649
+ try {
19650
+ const sha = (0, import_node_fs29.readFileSync)((0, import_node_path22.join)(frame.worktreeRoot, BASELINE_SHA_FILE), "utf-8").trim();
19651
+ if (!SHA_RE2.test(sha)) return null;
19652
+ return refResolves(frame, sha) ? sha : null;
19653
+ } catch {
19654
+ return null;
19859
19655
  }
19656
+ }
19657
+ function stagedRange() {
19860
19658
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "index" };
19861
19659
  }
19862
19660
  function resolvePushRange(frame, command, on) {
19863
- const nothing = (via2) => ({ kind: "nothing", base: null, head: "HEAD", via: via2 });
19661
+ const nothing = (via) => ({ kind: "nothing", base: null, head: "HEAD", via });
19864
19662
  if (!frame.worktreeRoot) return nothing("refused");
19865
19663
  const found = findMomentSegment(command, on);
19866
19664
  const segment = found ? splitSegments(command)[found.segmentIndex] : "";
@@ -19868,32 +19666,54 @@ function resolvePushRange(frame, command, on) {
19868
19666
  if (target.isDelete) return nothing("deletion");
19869
19667
  const head = target.srcRef ?? "HEAD";
19870
19668
  if (!refResolves(frame, head)) return nothing(`src-unresolvable:${head}`);
19871
- const remotePattern = target.remote ? `--remotes=${target.remote}` : "--remotes";
19872
- const via = target.remote ? `publication:${target.remote}` : "publication";
19873
- const commits = frameGit(frame, ["rev-list", head, "--not", remotePattern]).split("\n").filter(Boolean);
19874
- if (commits.length === 0) return { kind: "nothing", base: null, head, via: "already-published" };
19875
- const boundary = frameGit(frame, ["rev-list", head, "--not", remotePattern, "--boundary"]).split("\n").filter((l) => l.startsWith("-")).map((l) => l.slice(1));
19876
- const base = boundary.find((s) => SHA_RE2.test(s)) ?? null;
19877
- const files = /* @__PURE__ */ new Set();
19878
- for (const sha of commits) {
19879
- for (const f of frameGit(frame, ["diff-tree", "--no-commit-id", "--name-only", "-r", sha]).split("\n")) {
19880
- if (f && !isVerityOwnedPath(f)) files.add(f);
19881
- }
19669
+ const srcName = target.srcRef;
19670
+ const branchForRemote = srcName ?? frame.branch;
19671
+ const candidates = [];
19672
+ if (target.remote && (target.dstRef ?? srcName)) {
19673
+ const dstName = (target.dstRef ?? srcName).replace(/^refs\/heads\//, "");
19674
+ candidates.push({ ref: `refs/remotes/${target.remote}/${dstName}`, via: `refspec:${target.remote}/${dstName}` });
19675
+ }
19676
+ if (target.remote && !srcName && !target.dstRef && frame.branch) {
19677
+ candidates.push({ ref: `refs/remotes/${target.remote}/${frame.branch}`, via: `remote:${target.remote}/${frame.branch}` });
19678
+ }
19679
+ candidates.push({ ref: srcName ? `${srcName}@{push}` : "@{push}", via: "@{push}" });
19680
+ candidates.push({ ref: srcName ? `${srcName}@{upstream}` : "@{upstream}", via: "@{upstream}" });
19681
+ if (branchForRemote) {
19682
+ candidates.push({
19683
+ ref: `refs/remotes/origin/${branchForRemote.replace(/^refs\/heads\//, "")}`,
19684
+ via: `origin/${branchForRemote.replace(/^refs\/heads\//, "")}`
19685
+ });
19686
+ }
19687
+ for (const c of candidates) {
19688
+ if (!refResolves(frame, c.ref)) continue;
19689
+ const mergeBase = frameGit(frame, ["merge-base", c.ref, head]);
19690
+ if (SHA_RE2.test(mergeBase)) return { kind: "push", base: mergeBase, head, via: c.via };
19882
19691
  }
19883
- return { kind: "push", base, head, via, files: [...files], commits };
19692
+ const baseline = baselineShaAt(frame);
19693
+ if (baseline) return { kind: "baseline", base: baseline, head, via: "review-baseline" };
19694
+ if (refResolves(frame, `${head}~1`)) return { kind: "last-commit", base: `${head}~1`, head, via: `${head}~1` };
19695
+ return nothing("no-parent");
19884
19696
  }
19885
19697
  function rangeFiles(frame, range) {
19886
- if (range.files) return range.files.filter((f) => !isVerityOwnedPath(f));
19887
- if (range.kind === "staged") {
19888
- return frameGit(frame, ["diff", "--cached", "--name-only"]).split("\n").filter((l) => l.length > 0).filter((f) => !isVerityOwnedPath(f));
19698
+ let out;
19699
+ switch (range.kind) {
19700
+ case "staged":
19701
+ out = frameGit(frame, ["diff", "--cached", "--name-only"]);
19702
+ break;
19703
+ case "push":
19704
+ case "baseline":
19705
+ case "last-commit":
19706
+ out = frameGit(frame, ["diff", "--name-only", range.base, range.head === "INDEX" ? "HEAD" : range.head]);
19707
+ break;
19708
+ case "nothing":
19709
+ return [];
19889
19710
  }
19890
- return [];
19711
+ return out.split("\n").filter((l) => l.length > 0).filter((f) => !isVerityOwnedPath(f));
19891
19712
  }
19892
19713
  function rangeChangeSignals(frame, range, paths) {
19893
19714
  const out = /* @__PURE__ */ new Map();
19894
19715
  if (range.kind === "nothing" || paths.length === 0) return out;
19895
- if (range.kind === "push" && !range.base) return out;
19896
- const args = range.kind === "staged" || range.kind === "merge" ? ["diff", "--cached", "--unified=0"] : ["diff", "--unified=0", range.base, range.head === "INDEX" ? "HEAD" : range.head];
19716
+ const args = range.kind === "staged" ? ["diff", "--cached", "--unified=0"] : ["diff", "--unified=0", range.base, range.head === "INDEX" ? "HEAD" : range.head];
19897
19717
  const diff = frameGit(frame, [...args, "--", ...paths]);
19898
19718
  let current = null;
19899
19719
  let oldSide = null;
@@ -19925,9 +19745,8 @@ function rangeChangeSignals(frame, range, paths) {
19925
19745
  return out;
19926
19746
  }
19927
19747
  function rangeMessages(frame, range) {
19928
- if (range.kind !== "push" || !range.commits || range.commits.length === 0) return "";
19929
- const commits = range.commits.slice(0, 100);
19930
- return frameGit(frame, ["show", "-s", "--format=%B%x00", ...commits]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
19748
+ if (range.kind === "staged" || range.kind === "nothing" || !range.base) return "";
19749
+ return frameGit(frame, ["log", `${range.base}..${range.head === "INDEX" ? "HEAD" : range.head}`, "--format=%B%x00"]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
19931
19750
  }
19932
19751
  function frameTelemetry(frame, range, divergence) {
19933
19752
  const t = {
@@ -19975,7 +19794,7 @@ function truthy(v) {
19975
19794
  }
19976
19795
 
19977
19796
  // src/lib/transcript.ts
19978
- var import_node_fs32 = require("node:fs");
19797
+ var import_node_fs30 = require("node:fs");
19979
19798
  var MAX_READ_BYTES = 256 * 1024;
19980
19799
  var SMALL_FILE_BYTES = 64 * 1024;
19981
19800
  var MAX_FILES_LIST = 20;
@@ -20002,7 +19821,7 @@ async function extractActionSummary(transcriptPath) {
20002
19821
  function readTurnLines(transcriptPath) {
20003
19822
  let size;
20004
19823
  try {
20005
- size = (0, import_node_fs32.statSync)(transcriptPath).size;
19824
+ size = (0, import_node_fs30.statSync)(transcriptPath).size;
20006
19825
  } catch {
20007
19826
  return null;
20008
19827
  }
@@ -20010,7 +19829,7 @@ function readTurnLines(transcriptPath) {
20010
19829
  let raw;
20011
19830
  let windowed = false;
20012
19831
  if (size <= SMALL_FILE_BYTES) {
20013
- raw = (0, import_node_fs32.readFileSync)(transcriptPath, "utf-8");
19832
+ raw = (0, import_node_fs30.readFileSync)(transcriptPath, "utf-8");
20014
19833
  } else {
20015
19834
  windowed = true;
20016
19835
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -20327,9 +20146,6 @@ async function bootstrap(run2) {
20327
20146
  isTTY: process.stdout.isTTY === true
20328
20147
  });
20329
20148
  const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
20330
- if (deferredToPlugin("analyze", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
20331
- process.exit(0);
20332
- }
20333
20149
  const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
20334
20150
  const tokenResult = await resolveToken(globals.token);
20335
20151
  const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
@@ -20509,7 +20325,7 @@ function channelSilence(input) {
20509
20325
  // src/lib/cli-version.ts
20510
20326
  function cliVersion() {
20511
20327
  try {
20512
- return true ? "0.32.0-experimental.68ae2ee" : "dev";
20328
+ return true ? "0.32.0-experimental.f0746f7" : "dev";
20513
20329
  } catch {
20514
20330
  return "dev";
20515
20331
  }
@@ -20550,7 +20366,7 @@ async function sendSkipBeacon(ctx, reason) {
20550
20366
 
20551
20367
  // src/lib/static-analysis.ts
20552
20368
  var import_node_child_process11 = require("node:child_process");
20553
- var import_node_fs33 = require("node:fs");
20369
+ var import_node_fs31 = require("node:fs");
20554
20370
  var SEVERITY_ORDER = {
20555
20371
  Error: 0,
20556
20372
  Critical: 0,
@@ -20598,7 +20414,7 @@ function runCodacyAnalysis(files) {
20598
20414
  if (files.length === 0) return empty;
20599
20415
  const existingFiles = files.filter((f) => {
20600
20416
  try {
20601
- return (0, import_node_fs33.existsSync)(f);
20417
+ return (0, import_node_fs31.existsSync)(f);
20602
20418
  } catch {
20603
20419
  return false;
20604
20420
  }
@@ -20867,7 +20683,7 @@ async function scope(run2) {
20867
20683
  }
20868
20684
 
20869
20685
  // src/lib/specs.ts
20870
- var import_node_fs34 = require("node:fs");
20686
+ var import_node_fs32 = require("node:fs");
20871
20687
  var import_node_path23 = require("node:path");
20872
20688
  var SPEC_CANDIDATES = [
20873
20689
  "CLAUDE.md",
@@ -20899,16 +20715,16 @@ function discoverSpecs(consulted = []) {
20899
20715
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
20900
20716
  if (totalBytes >= totalCap) return false;
20901
20717
  if (seen.has(specPath)) return true;
20902
- if (!(0, import_node_fs34.existsSync)(specPath)) return true;
20718
+ if (!(0, import_node_fs32.existsSync)(specPath)) return true;
20903
20719
  seen.add(specPath);
20904
20720
  const remaining = totalCap - totalBytes;
20905
20721
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
20906
20722
  const readBytes = Math.min(fileCap, remaining);
20907
20723
  try {
20908
20724
  const buf = Buffer.alloc(readBytes);
20909
- const fd = (0, import_node_fs34.openSync)(specPath, "r");
20910
- const bytesRead = (0, import_node_fs34.readSync)(fd, buf, 0, readBytes, 0);
20911
- (0, import_node_fs34.closeSync)(fd);
20725
+ const fd = (0, import_node_fs32.openSync)(specPath, "r");
20726
+ const bytesRead = (0, import_node_fs32.readSync)(fd, buf, 0, readBytes, 0);
20727
+ (0, import_node_fs32.closeSync)(fd);
20912
20728
  const content = buf.slice(0, bytesRead).toString("utf-8");
20913
20729
  if (!content) return true;
20914
20730
  result.push({ path: specPath, content });
@@ -20924,7 +20740,7 @@ function discoverSpecs(consulted = []) {
20924
20740
  if (!addSpec(candidate)) break;
20925
20741
  }
20926
20742
  for (const dir of ["spec", "docs"]) {
20927
- if (!(0, import_node_fs34.existsSync)(dir)) continue;
20743
+ if (!(0, import_node_fs32.existsSync)(dir)) continue;
20928
20744
  try {
20929
20745
  const mdFiles = findMdFiles(dir, 2).sort();
20930
20746
  for (const mdFile of mdFiles) {
@@ -20939,7 +20755,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
20939
20755
  if (depth >= maxDepth) return [];
20940
20756
  const result = [];
20941
20757
  try {
20942
- const entries = (0, import_node_fs34.readdirSync)(dir, { withFileTypes: true });
20758
+ const entries = (0, import_node_fs32.readdirSync)(dir, { withFileTypes: true });
20943
20759
  for (const entry of entries) {
20944
20760
  const fullPath = (0, import_node_path23.join)(dir, entry.name);
20945
20761
  if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -20958,14 +20774,14 @@ function discoverPlans() {
20958
20774
  const candidates = [];
20959
20775
  const seen = /* @__PURE__ */ new Set();
20960
20776
  for (const plansDir of [localPlansDir, homePlansDir]) {
20961
- if (!(0, import_node_fs34.existsSync)(plansDir)) continue;
20777
+ if (!(0, import_node_fs32.existsSync)(plansDir)) continue;
20962
20778
  try {
20963
- for (const f of (0, import_node_fs34.readdirSync)(plansDir)) {
20779
+ for (const f of (0, import_node_fs32.readdirSync)(plansDir)) {
20964
20780
  if (!f.endsWith(".md") || seen.has(f)) continue;
20965
20781
  seen.add(f);
20966
20782
  const fullPath = (0, import_node_path23.join)(plansDir, f);
20967
20783
  try {
20968
- const stat3 = (0, import_node_fs34.statSync)(fullPath);
20784
+ const stat3 = (0, import_node_fs32.statSync)(fullPath);
20969
20785
  candidates.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
20970
20786
  } catch {
20971
20787
  }
@@ -20978,7 +20794,7 @@ function discoverPlans() {
20978
20794
  for (const entry of candidates.slice(0, MAX_PLAN_FILES)) {
20979
20795
  if (entry.size > MAX_PLAN_FILE_BYTES) continue;
20980
20796
  try {
20981
- const content = (0, import_node_fs34.readFileSync)(entry.path, "utf-8");
20797
+ const content = (0, import_node_fs32.readFileSync)(entry.path, "utf-8");
20982
20798
  result.push({ name: entry.name, content });
20983
20799
  } catch {
20984
20800
  }
@@ -20993,12 +20809,12 @@ function discoverGuardDocs(rangeFiles2) {
20993
20809
  if (result.length >= MAX_SPEC_FILES) break;
20994
20810
  if (!GUARD_DOC_EXT.test(path)) continue;
20995
20811
  if (path.startsWith("/") || path.includes("..")) continue;
20996
- if (!(0, import_node_fs34.existsSync)(path)) continue;
20812
+ if (!(0, import_node_fs32.existsSync)(path)) continue;
20997
20813
  try {
20998
- const stat3 = (0, import_node_fs34.statSync)(path);
20814
+ const stat3 = (0, import_node_fs32.statSync)(path);
20999
20815
  if (stat3.size > MAX_PLAN_FILE_BYTES) continue;
21000
20816
  if (totalBytes + stat3.size > MAX_TOTAL_SPEC_BYTES) continue;
21001
- const content = (0, import_node_fs34.readFileSync)(path, "utf-8");
20817
+ const content = (0, import_node_fs32.readFileSync)(path, "utf-8");
21002
20818
  if (!content) continue;
21003
20819
  result.push({ name: path, content });
21004
20820
  totalBytes += content.length;
@@ -21174,7 +20990,7 @@ async function mode(run2) {
21174
20990
  }
21175
20991
 
21176
20992
  // src/lib/fold.ts
21177
- var import_node_fs35 = require("node:fs");
20993
+ var import_node_fs33 = require("node:fs");
21178
20994
  var import_node_path24 = require("node:path");
21179
20995
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
21180
20996
  "user",
@@ -21312,7 +21128,7 @@ function candidateRoots(repoRoot2) {
21312
21128
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
21313
21129
  const out = [norm];
21314
21130
  try {
21315
- const real = import_node_fs35.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
21131
+ const real = import_node_fs33.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
21316
21132
  if (real !== norm) out.push(real);
21317
21133
  } catch {
21318
21134
  }
@@ -21400,8 +21216,8 @@ function fold(transcriptPath, opts = {}) {
21400
21216
  }
21401
21217
  };
21402
21218
  try {
21403
- if (!(0, import_node_fs35.existsSync)(transcriptPath)) return result;
21404
- ingest((0, import_node_fs35.readFileSync)(transcriptPath, "utf8"), "agent");
21219
+ if (!(0, import_node_fs33.existsSync)(transcriptPath)) return result;
21220
+ ingest((0, import_node_fs33.readFileSync)(transcriptPath, "utf8"), "agent");
21405
21221
  result.coverage.complete = true;
21406
21222
  } catch {
21407
21223
  return result;
@@ -21412,19 +21228,19 @@ function fold(transcriptPath, opts = {}) {
21412
21228
  (0, import_node_path24.basename)(transcriptPath).replace(/\.jsonl$/, ""),
21413
21229
  "subagents"
21414
21230
  );
21415
- if ((0, import_node_fs35.existsSync)(sidecarDir)) {
21231
+ if ((0, import_node_fs33.existsSync)(sidecarDir)) {
21416
21232
  const maxFiles = opts.maxSidecars ?? 200;
21417
21233
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
21418
21234
  const found = [];
21419
21235
  const walk2 = (d, depth) => {
21420
21236
  if (depth > 4) return;
21421
- for (const e of (0, import_node_fs35.readdirSync)(d, { withFileTypes: true })) {
21237
+ for (const e of (0, import_node_fs33.readdirSync)(d, { withFileTypes: true })) {
21422
21238
  const p = (0, import_node_path24.join)(d, e.name);
21423
21239
  if (e.isDirectory()) {
21424
21240
  walk2(p, depth + 1);
21425
21241
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
21426
21242
  try {
21427
- const st = (0, import_node_fs35.statSync)(p);
21243
+ const st = (0, import_node_fs33.statSync)(p);
21428
21244
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
21429
21245
  } catch {
21430
21246
  result.coverage.malformed++;
@@ -21441,7 +21257,7 @@ function fold(transcriptPath, opts = {}) {
21441
21257
  continue;
21442
21258
  }
21443
21259
  try {
21444
- ingest((0, import_node_fs35.readFileSync)(f.path, "utf8"), "subagent");
21260
+ ingest((0, import_node_fs33.readFileSync)(f.path, "utf8"), "subagent");
21445
21261
  bytes += f.size;
21446
21262
  result.coverage.subagentFiles++;
21447
21263
  } catch {
@@ -21476,7 +21292,7 @@ function fold(transcriptPath, opts = {}) {
21476
21292
  }
21477
21293
  function classifyUnobserved(path) {
21478
21294
  try {
21479
- const st = (0, import_node_fs35.statSync)(path);
21295
+ const st = (0, import_node_fs33.statSync)(path);
21480
21296
  if (!st.isFile()) return "unreadable";
21481
21297
  } catch {
21482
21298
  return "unreadable";
@@ -21728,20 +21544,7 @@ async function evidence(run2) {
21728
21544
  widened_to: allForReview.length
21729
21545
  });
21730
21546
  }
21731
- const authorshipWasObservable = scoped.signal === "authored" && actionSummary?.transcript_windowed !== "orphaned";
21732
- if (!narrowingIsTrustworthy && recoveredScope.length === 0 && authorshipWasObservable) {
21733
- logEvent("authored_nothing_reviewable", {
21734
- touched: (actionSummary?.files_edited?.length ?? 0) + (actionSummary?.files_created?.length ?? 0),
21735
- candidates: allForReview.length
21736
- });
21737
- }
21738
- const baseForReview = chooseReviewScope({
21739
- narrowingIsTrustworthy,
21740
- scopedFiles: scoped.files,
21741
- recoveredScope,
21742
- allForReview,
21743
- authorshipWasObservable
21744
- });
21547
+ const baseForReview = narrowingIsTrustworthy ? scoped.files : recoveredScope.length > 0 ? recoveredScope : allForReview;
21745
21548
  const recentForReview = narrowToRecent(baseForReview, baselineSessionId);
21746
21549
  if (!opts.skipStatic && isCodacyAvailable()) {
21747
21550
  let allScannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles]));
@@ -21793,20 +21596,20 @@ async function evidence(run2) {
21793
21596
  }
21794
21597
 
21795
21598
  // src/lib/cache-cleanup.ts
21796
- var import_node_fs36 = require("node:fs");
21599
+ var import_node_fs34 = require("node:fs");
21797
21600
  var import_node_path25 = require("node:path");
21798
21601
  var CACHE_TTL_DAYS = 7;
21799
21602
  function pruneStaleCache() {
21800
21603
  try {
21801
21604
  const dir = projectPath(CACHE_DIR);
21802
21605
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
21803
- for (const entry of (0, import_node_fs36.readdirSync)(dir)) {
21606
+ for (const entry of (0, import_node_fs34.readdirSync)(dir)) {
21804
21607
  if (!entry.startsWith("pending-")) continue;
21805
21608
  const path = (0, import_node_path25.join)(dir, entry);
21806
21609
  try {
21807
- const stat3 = (0, import_node_fs36.statSync)(path);
21610
+ const stat3 = (0, import_node_fs34.statSync)(path);
21808
21611
  if (stat3.mtimeMs < cutoff) {
21809
- (0, import_node_fs36.unlinkSync)(path);
21612
+ (0, import_node_fs34.unlinkSync)(path);
21810
21613
  logEvent("cache_entry_pruned", {
21811
21614
  path: entry,
21812
21615
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -21820,7 +21623,7 @@ function pruneStaleCache() {
21820
21623
  }
21821
21624
 
21822
21625
  // src/lib/context-files.ts
21823
- var import_node_fs37 = require("node:fs");
21626
+ var import_node_fs35 = require("node:fs");
21824
21627
  var import_node_os5 = require("node:os");
21825
21628
  var MAX_CONTEXT_FILES = 10;
21826
21629
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -21878,7 +21681,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
21878
21681
  continue;
21879
21682
  }
21880
21683
  try {
21881
- const content = (0, import_node_fs37.readFileSync)(safePath, "utf8");
21684
+ const content = (0, import_node_fs35.readFileSync)(safePath, "utf8");
21882
21685
  const bytes = Buffer.byteLength(content);
21883
21686
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
21884
21687
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -21969,7 +21772,7 @@ async function repoContext(run2) {
21969
21772
 
21970
21773
  // src/lib/seed-runner.ts
21971
21774
  var import_promises14 = require("node:fs/promises");
21972
- var import_node_fs38 = require("node:fs");
21775
+ var import_node_fs36 = require("node:fs");
21973
21776
  var import_node_path26 = require("node:path");
21974
21777
  var import_yaml4 = __toESM(require_dist());
21975
21778
 
@@ -22209,7 +22012,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
22209
22012
  return fm;
22210
22013
  }
22211
22014
  async function runSeed(opts) {
22212
- if (!(0, import_node_fs38.existsSync)(STANDARD_FILE)) {
22015
+ if (!(0, import_node_fs36.existsSync)(STANDARD_FILE)) {
22213
22016
  return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
22214
22017
  }
22215
22018
  let standardDoc;
@@ -22221,7 +22024,7 @@ async function runSeed(opts) {
22221
22024
  }
22222
22025
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
22223
22026
  let readmeContent;
22224
- if ((0, import_node_fs38.existsSync)("README.md")) {
22027
+ if ((0, import_node_fs36.existsSync)("README.md")) {
22225
22028
  try {
22226
22029
  readmeContent = await (0, import_promises14.readFile)("README.md", "utf-8");
22227
22030
  } catch {
@@ -22229,7 +22032,7 @@ async function runSeed(opts) {
22229
22032
  }
22230
22033
  let claudeMdContent;
22231
22034
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
22232
- if ((0, import_node_fs38.existsSync)(p)) {
22035
+ if ((0, import_node_fs36.existsSync)(p)) {
22233
22036
  try {
22234
22037
  claudeMdContent = await (0, import_promises14.readFile)(p, "utf-8");
22235
22038
  break;
@@ -22253,7 +22056,7 @@ async function runSeed(opts) {
22253
22056
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
22254
22057
  }
22255
22058
  const overviewPath = (0, import_node_path26.join)(MEMORY_DIR, "domain", "project-overview.md");
22256
- if ((0, import_node_fs38.existsSync)(overviewPath) && !opts.force) {
22059
+ if ((0, import_node_fs36.existsSync)(overviewPath) && !opts.force) {
22257
22060
  return { created: 0, failed: 0, skipped: "already_seeded", candidates };
22258
22061
  }
22259
22062
  if (opts.dryRun) {
@@ -22308,7 +22111,7 @@ async function runSeed(opts) {
22308
22111
  }
22309
22112
 
22310
22113
  // src/commands/analyze/phases/08-memory-manifest.ts
22311
- var import_node_fs39 = require("node:fs");
22114
+ var import_node_fs37 = require("node:fs");
22312
22115
  var import_node_path27 = require("node:path");
22313
22116
  async function memoryManifest(run2) {
22314
22117
  const { globals } = run2;
@@ -22320,8 +22123,8 @@ async function memoryManifest(run2) {
22320
22123
  try {
22321
22124
  await ensureMemoryDir();
22322
22125
  const seedMarker = (0, import_node_path27.join)(VERITY_DIR, ".seeded");
22323
- const hasStandard = (0, import_node_fs39.existsSync)(STANDARD_FILE);
22324
- const alreadyTried = (0, import_node_fs39.existsSync)(seedMarker);
22126
+ const hasStandard = (0, import_node_fs37.existsSync)(STANDARD_FILE);
22127
+ const alreadyTried = (0, import_node_fs37.existsSync)(seedMarker);
22325
22128
  if (hasStandard && !alreadyTried) {
22326
22129
  const preManifest = await buildManifest();
22327
22130
  if (preManifest.nodes.length === 0) {
@@ -22334,7 +22137,7 @@ async function memoryManifest(run2) {
22334
22137
  dryRun: false
22335
22138
  });
22336
22139
  if (seedResult.created > 0) {
22337
- (0, import_node_fs39.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
22140
+ (0, import_node_fs37.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
22338
22141
  `);
22339
22142
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
22340
22143
  logEvent("auto_seed_ran", {
@@ -22342,7 +22145,7 @@ async function memoryManifest(run2) {
22342
22145
  failed: seedResult.failed
22343
22146
  });
22344
22147
  } else if (seedResult.skipped === "already_seeded") {
22345
- (0, import_node_fs39.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
22148
+ (0, import_node_fs37.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
22346
22149
  `);
22347
22150
  } else {
22348
22151
  logEvent("auto_seed_noop", {
@@ -22531,7 +22334,7 @@ async function workingMemory(run2) {
22531
22334
  }
22532
22335
 
22533
22336
  // src/lib/note-budget.ts
22534
- var import_node_fs40 = require("node:fs");
22337
+ var import_node_fs38 = require("node:fs");
22535
22338
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
22536
22339
  var EPISODE_STALE_SECONDS = 30 * 60;
22537
22340
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -22553,9 +22356,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
22553
22356
  }
22554
22357
  function readAdvisoryEpisode(sessionId) {
22555
22358
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
22556
- if (!(0, import_node_fs40.existsSync)(file)) return null;
22359
+ if (!(0, import_node_fs38.existsSync)(file)) return null;
22557
22360
  try {
22558
- const o = JSON.parse((0, import_node_fs40.readFileSync)(file, "utf-8")) ?? {};
22361
+ const o = JSON.parse((0, import_node_fs38.readFileSync)(file, "utf-8")) ?? {};
22559
22362
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
22560
22363
  if (isNaN(delivered)) return null;
22561
22364
  return {
@@ -22569,8 +22372,8 @@ function readAdvisoryEpisode(sessionId) {
22569
22372
  }
22570
22373
  function writeAdvisoryEpisode(episode, sessionId) {
22571
22374
  try {
22572
- (0, import_node_fs40.mkdirSync)(VERITY_DIR, { recursive: true });
22573
- (0, import_node_fs40.writeFileSync)(
22375
+ (0, import_node_fs38.mkdirSync)(VERITY_DIR, { recursive: true });
22376
+ (0, import_node_fs38.writeFileSync)(
22574
22377
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
22575
22378
  JSON.stringify({ v: 1, ...episode })
22576
22379
  );
@@ -22887,14 +22690,14 @@ async function buildRequest(run2) {
22887
22690
  }
22888
22691
 
22889
22692
  // src/lib/offline.ts
22890
- var import_node_fs41 = require("node:fs");
22693
+ var import_node_fs39 = require("node:fs");
22891
22694
  var import_node_crypto11 = require("node:crypto");
22892
22695
  function cacheRequest(body) {
22893
22696
  try {
22894
- (0, import_node_fs41.mkdirSync)(CACHE_DIR, { recursive: true });
22697
+ (0, import_node_fs39.mkdirSync)(CACHE_DIR, { recursive: true });
22895
22698
  const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
22896
22699
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
22897
- (0, import_node_fs41.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
22700
+ (0, import_node_fs39.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
22898
22701
  } catch {
22899
22702
  }
22900
22703
  }
@@ -23013,7 +22816,7 @@ async function transmit(run2) {
23013
22816
  }
23014
22817
 
23015
22818
  // src/commands/analyze/phases/13-reconcile.ts
23016
- var import_node_fs42 = require("node:fs");
22819
+ var import_node_fs40 = require("node:fs");
23017
22820
  var import_node_path29 = require("node:path");
23018
22821
  async function reconcile(run2) {
23019
22822
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run2;
@@ -23043,7 +22846,7 @@ async function reconcile(run2) {
23043
22846
  const st = foldDossier(memorySession.d);
23044
22847
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
23045
22848
  try {
23046
- const src = (0, import_node_fs42.readFileSync)((0, import_node_path29.join)(repoRoot(), file), "utf8").split("\n");
22849
+ const src = (0, import_node_fs40.readFileSync)((0, import_node_path29.join)(repoRoot(), file), "utf8").split("\n");
23047
22850
  const at = src[line - 1];
23048
22851
  return at === void 0 ? null : lineSha(at);
23049
22852
  } catch {
@@ -23707,10 +23510,6 @@ function registerAnalyzeCommand(program2) {
23707
23510
  }
23708
23511
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
23709
23512
  async function runAnalyze(opts, globals) {
23710
- if (!verityConfigured()) {
23711
- (0, import_node_fs43.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
23712
- process.exit(0);
23713
- }
23714
23513
  const run2 = createRun(opts, globals);
23715
23514
  installRunEvidence(run2);
23716
23515
  for (const [name, phase] of PIPELINE) {
@@ -23729,6 +23528,7 @@ async function runAnalyze(opts, globals) {
23729
23528
  }
23730
23529
 
23731
23530
  // src/commands/baseline.ts
23531
+ var import_node_fs41 = require("node:fs");
23732
23532
  function registerBaselineCommands(program2) {
23733
23533
  const baseline = program2.command("baseline").description("Manage the task-start working-tree baseline");
23734
23534
  baseline.command("capture").description("Snapshot the working tree at task start (used by SessionStart hook)").option("--session-id <id>", "Session id (overrides any value from stdin)").option("--source <source>", "Lifecycle hint: startup|resume|clear|compact").action(async (opts) => {
@@ -23737,16 +23537,7 @@ function registerBaselineCommands(program2) {
23737
23537
  process.chdir(repoRoot());
23738
23538
  } catch {
23739
23539
  }
23740
- if (!verityConfigured()) {
23741
- const how = isPluginInvocation() ? "Offer to run /verity:setup for the user." : "Offer to run `verity init` (or /verity-setup) for the user.";
23742
- process.stdout.write(
23743
- JSON.stringify({
23744
- hookSpecificOutput: {
23745
- hookEventName: "SessionStart",
23746
- additionalContext: `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
23747
- }
23748
- }) + "\n"
23749
- );
23540
+ if (!(0, import_node_fs41.existsSync)(VERITY_DIR)) {
23750
23541
  process.exit(0);
23751
23542
  }
23752
23543
  let sessionId = opts.sessionId;
@@ -23762,9 +23553,6 @@ function registerBaselineCommands(program2) {
23762
23553
  }
23763
23554
  }
23764
23555
  }
23765
- if (deferredToPlugin("baseline capture", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
23766
- process.exit(0);
23767
- }
23768
23556
  const authForScope = await resolveToken(program2.opts().token);
23769
23557
  const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
23770
23558
  const scopeSession = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
@@ -23789,7 +23577,7 @@ async function readStdin() {
23789
23577
  }
23790
23578
 
23791
23579
  // src/commands/review.ts
23792
- var import_node_fs44 = require("node:fs");
23580
+ var import_node_fs42 = require("node:fs");
23793
23581
  function registerReviewCommand(program2) {
23794
23582
  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) => {
23795
23583
  const globals = program2.opts();
@@ -23808,7 +23596,7 @@ async function runReview(opts, globals) {
23808
23596
  const securityFiles = filterSecurity(allFiles);
23809
23597
  let staticResults;
23810
23598
  if (isCodacyAvailable()) {
23811
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs44.existsSync)(f) || resolveFile(f) !== null);
23599
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs42.existsSync)(f) || resolveFile(f) !== null);
23812
23600
  staticResults = runCodacyAnalysis(scannable);
23813
23601
  } else {
23814
23602
  staticResults = {
@@ -23834,10 +23622,10 @@ async function runReview(opts, globals) {
23834
23622
  const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
23835
23623
  specs = [];
23836
23624
  for (const p of specPaths) {
23837
- if (!(0, import_node_fs44.existsSync)(p)) continue;
23625
+ if (!(0, import_node_fs42.existsSync)(p)) continue;
23838
23626
  try {
23839
- const { readFileSync: readFileSync27 } = await import("node:fs");
23840
- const content = readFileSync27(p, "utf-8");
23627
+ const { readFileSync: readFileSync26 } = await import("node:fs");
23628
+ const content = readFileSync26(p, "utf-8");
23841
23629
  specs.push({ path: p, content: content.slice(0, 10240) });
23842
23630
  } catch {
23843
23631
  }
@@ -23894,7 +23682,7 @@ async function runReview(opts, globals) {
23894
23682
  }
23895
23683
 
23896
23684
  // src/commands/guard.ts
23897
- var import_node_fs45 = require("node:fs");
23685
+ var import_node_fs43 = require("node:fs");
23898
23686
  var import_node_path30 = require("node:path");
23899
23687
  var GUARD_BLOCK_CAP = 2;
23900
23688
  var GUARD_ITER_FILE = (0, import_node_path30.join)(VERITY_DIR, ".guard-iteration");
@@ -23942,7 +23730,7 @@ function readPreToolUseStdin() {
23942
23730
  }
23943
23731
  function readIterMap() {
23944
23732
  try {
23945
- const raw = JSON.parse((0, import_node_fs45.readFileSync)(GUARD_ITER_FILE, "utf-8"));
23733
+ const raw = JSON.parse((0, import_node_fs43.readFileSync)(GUARD_ITER_FILE, "utf-8"));
23946
23734
  if (raw && typeof raw === "object") {
23947
23735
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
23948
23736
  return { [raw.moment]: raw.count };
@@ -23962,10 +23750,10 @@ function readIter(moment) {
23962
23750
  }
23963
23751
  function writeIter(moment, count) {
23964
23752
  try {
23965
- (0, import_node_fs45.mkdirSync)(VERITY_DIR, { recursive: true });
23753
+ (0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
23966
23754
  const map = readIterMap();
23967
23755
  map[moment] = count;
23968
- (0, import_node_fs45.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
23756
+ (0, import_node_fs43.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
23969
23757
  } catch {
23970
23758
  }
23971
23759
  }
@@ -23975,16 +23763,16 @@ function resetIter(moment) {
23975
23763
  if (!(moment in map)) return;
23976
23764
  delete map[moment];
23977
23765
  if (Object.keys(map).length === 0) {
23978
- if ((0, import_node_fs45.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs45.unlinkSync)(GUARD_ITER_FILE);
23766
+ if ((0, import_node_fs43.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs43.unlinkSync)(GUARD_ITER_FILE);
23979
23767
  } else {
23980
- (0, import_node_fs45.mkdirSync)(VERITY_DIR, { recursive: true });
23981
- (0, import_node_fs45.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
23768
+ (0, import_node_fs43.mkdirSync)(VERITY_DIR, { recursive: true });
23769
+ (0, import_node_fs43.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
23982
23770
  }
23983
23771
  } catch {
23984
23772
  }
23985
23773
  }
23986
23774
  function registerGuardCommand(program2) {
23987
- program2.command("guard").description("Git-moment gate: review staged/to-push changes before a commit/push (PreToolUse hook)").option("--on <moments>", "Which git moments to gate: commit,push (default: the project config)").option("--json", "Output raw JSON response (debug)").action(async (opts) => {
23775
+ program2.command("guard").description("Git-moment gate: review staged/to-push changes before a commit/push (PreToolUse hook)").option("--on <moments>", "Which git moments to gate: commit,push", "commit,push").option("--json", "Output raw JSON response (debug)").action(async (opts) => {
23988
23776
  const globals = program2.opts();
23989
23777
  try {
23990
23778
  await runGuard(opts, globals);
@@ -23994,14 +23782,13 @@ function registerGuardCommand(program2) {
23994
23782
  });
23995
23783
  }
23996
23784
  function resolveMomentRange(moment, frame, command, on) {
23997
- return moment === "pre-commit" ? stagedRange(frame) : resolvePushRange(frame, command, on);
23785
+ return moment === "pre-commit" ? stagedRange() : resolvePushRange(frame, command, on);
23998
23786
  }
23999
23787
  function describeRange(range) {
24000
23788
  if (range.kind === "staged") return "staged";
24001
- if (range.kind === "merge") return `merge (${range.via})`;
24002
- if (range.kind === "nothing") return range.via === "already-published" ? "already published" : null;
24003
- const base = range.base && /^[0-9a-f]{40}$/.test(range.base) ? range.base.slice(0, 7) : range.base;
24004
- return base ? `${base}..${range.head} via ${range.via}` : `via ${range.via}`;
23789
+ if (range.kind === "nothing" || !range.base) return null;
23790
+ const base = /^[0-9a-f]{40}$/.test(range.base) ? range.base.slice(0, 7) : range.base;
23791
+ return `${base}..${range.head} via ${range.via}`;
24005
23792
  }
24006
23793
  function matchFlagValue(command, flags) {
24007
23794
  const re = new RegExp(`(?<![\\w-])(?:${flags})(?:=|\\s+)('((?:[^'\\\\]|\\\\.)*)'|"((?:[^"\\\\]|\\\\.)*)"|([^\\s'"-][^\\s]*))`);
@@ -24050,7 +23837,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
24050
23837
  const securityFiles = filterSecurity(files);
24051
23838
  let staticResults;
24052
23839
  if (isCodacyAvailable()) {
24053
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs45.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
23840
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs43.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
24054
23841
  staticResults = runCodacyAnalysis(scannable);
24055
23842
  } else {
24056
23843
  staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
@@ -24123,10 +23910,8 @@ function emitAllowNotice(userMsg, agentMsg) {
24123
23910
  process.exit(0);
24124
23911
  }
24125
23912
  async function runGuard(opts, globals) {
24126
- const on = resolveGuardMoments(opts.on);
24127
- if (on.length === 0) process.exit(0);
23913
+ const on = opts.on.split(",").map((s) => s.trim()).filter((s) => s === "commit" || s === "push");
24128
23914
  const { command, cwd, sessionId } = await readPreToolUseStdin();
24129
- if (deferredToPlugin("guard", sessionId)) process.exit(0);
24130
23915
  const moment = classifyCommand(command, on);
24131
23916
  if (!moment) process.exit(0);
24132
23917
  const verb = moment === "pre-commit" ? "commit" : "push";
@@ -24189,7 +23974,7 @@ async function runGuard(opts, globals) {
24189
23974
  upgradeToExcerpts(repoContext2, {
24190
23975
  readFile: (rel) => {
24191
23976
  try {
24192
- return (0, import_node_fs45.readFileSync)((0, import_node_path30.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
23977
+ return (0, import_node_fs43.readFileSync)((0, import_node_path30.join)(frame.worktreeRoot ?? process.cwd(), rel), "utf8");
24193
23978
  } catch {
24194
23979
  return null;
24195
23980
  }
@@ -24410,7 +24195,7 @@ function registerIgnoreCommand(program2) {
24410
24195
 
24411
24196
  // src/commands/waive.ts
24412
24197
  var import_node_crypto12 = require("node:crypto");
24413
- var import_node_fs46 = require("node:fs");
24198
+ var import_node_fs44 = require("node:fs");
24414
24199
  function registerWaiveCommand(program2) {
24415
24200
  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) => {
24416
24201
  const globals = program2.opts();
@@ -24439,7 +24224,7 @@ function registerWaiveCommand(program2) {
24439
24224
  if (opts.file) {
24440
24225
  body.file = opts.file;
24441
24226
  try {
24442
- body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs46.readFileSync)(opts.file)).digest("hex");
24227
+ body.file_sha256 = (0, import_node_crypto12.createHash)("sha256").update((0, import_node_fs44.readFileSync)(opts.file)).digest("hex");
24443
24228
  } catch {
24444
24229
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
24445
24230
  process.exit(1);
@@ -24464,7 +24249,7 @@ function registerWaiveCommand(program2) {
24464
24249
  }
24465
24250
 
24466
24251
  // src/commands/init.ts
24467
- var import_node_fs51 = require("node:fs");
24252
+ var import_node_fs49 = require("node:fs");
24468
24253
  var import_promises17 = require("node:fs/promises");
24469
24254
  var import_yaml6 = __toESM(require_dist());
24470
24255
  var import_node_path33 = require("node:path");
@@ -24546,7 +24331,7 @@ function printPhase(n, of, title, subtitle) {
24546
24331
  }
24547
24332
 
24548
24333
  // src/commands/doctor.ts
24549
- var import_node_fs48 = require("node:fs");
24334
+ var import_node_fs46 = require("node:fs");
24550
24335
 
24551
24336
  // src/lib/prereqs.ts
24552
24337
  var import_node_child_process13 = require("node:child_process");
@@ -24666,7 +24451,7 @@ var import_promises15 = require("node:fs/promises");
24666
24451
 
24667
24452
  // src/lib/gitignore.ts
24668
24453
  var import_node_child_process14 = require("node:child_process");
24669
- var import_node_fs47 = require("node:fs");
24454
+ var import_node_fs45 = require("node:fs");
24670
24455
  var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
24671
24456
  var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
24672
24457
  var VERITY_GITIGNORE_BLOCK = [
@@ -24699,7 +24484,7 @@ function semanticsHold() {
24699
24484
  function ensureVerityGitignore() {
24700
24485
  let content = "";
24701
24486
  try {
24702
- content = (0, import_node_fs47.readFileSync)(".gitignore", "utf-8");
24487
+ content = (0, import_node_fs45.readFileSync)(".gitignore", "utf-8");
24703
24488
  } catch {
24704
24489
  }
24705
24490
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -24720,7 +24505,7 @@ function ensureVerityGitignore() {
24720
24505
  const sep2 = next === "" ? "" : next.endsWith("\n") ? "\n" : "\n\n";
24721
24506
  next = next + sep2 + VERITY_GITIGNORE_BLOCK;
24722
24507
  }
24723
- (0, import_node_fs47.writeFileSync)(".gitignore", next);
24508
+ (0, import_node_fs45.writeFileSync)(".gitignore", next);
24724
24509
  return verified(needsRepair ? "repaired" : "added");
24725
24510
  } catch {
24726
24511
  return "failed";
@@ -24847,11 +24632,11 @@ async function buildReport() {
24847
24632
  const state = await readSetupState();
24848
24633
  const hooks = await checkAllVerityHooks();
24849
24634
  const telemetry = await checkTelemetry();
24850
- const hasConfig = (0, import_node_fs48.existsSync)(projectPath(CODACY_CONFIG_FILE));
24635
+ const hasConfig = (0, import_node_fs46.existsSync)(projectPath(CODACY_CONFIG_FILE));
24851
24636
  const artifacts = {
24852
- standard: (0, import_node_fs48.existsSync)(projectPath(STANDARD_FILE)),
24637
+ standard: (0, import_node_fs46.existsSync)(projectPath(STANDARD_FILE)),
24853
24638
  analysisConfig: hasConfig,
24854
- verityMd: (0, import_node_fs48.existsSync)(projectPath(VERITY_MD_FILE)),
24639
+ verityMd: (0, import_node_fs46.existsSync)(projectPath(VERITY_MD_FILE)),
24855
24640
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
24856
24641
  };
24857
24642
  const next = [];
@@ -24945,7 +24730,7 @@ function registerDoctorCommand(program2) {
24945
24730
  }
24946
24731
 
24947
24732
  // src/commands/migrate.ts
24948
- var import_node_fs49 = require("node:fs");
24733
+ var import_node_fs47 = require("node:fs");
24949
24734
  var import_node_path31 = require("node:path");
24950
24735
  var import_node_child_process15 = require("node:child_process");
24951
24736
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
@@ -24985,10 +24770,10 @@ async function runMigration(opts = {}) {
24985
24770
  function migrateProjectDir(root, actions) {
24986
24771
  const gateDir = (0, import_node_path31.join)(root, ".gate");
24987
24772
  const verityDir = (0, import_node_path31.join)(root, ".verity");
24988
- if ((0, import_node_fs49.existsSync)(gateDir) && !(0, import_node_fs49.existsSync)(verityDir)) {
24773
+ if ((0, import_node_fs47.existsSync)(gateDir) && !(0, import_node_fs47.existsSync)(verityDir)) {
24989
24774
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
24990
24775
  }
24991
- if ((0, import_node_fs49.existsSync)(gateDir) && (0, import_node_fs49.existsSync)(verityDir)) {
24776
+ if ((0, import_node_fs47.existsSync)(gateDir) && (0, import_node_fs47.existsSync)(verityDir)) {
24992
24777
  return migrateProjectDirCarry(gateDir, verityDir, actions);
24993
24778
  }
24994
24779
  return false;
@@ -25009,13 +24794,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
25009
24794
  }
25010
24795
  }
25011
24796
  if (moved) {
25012
- if ((0, import_node_fs49.existsSync)(gateDir)) {
24797
+ if ((0, import_node_fs47.existsSync)(gateDir)) {
25013
24798
  const carried = carryLegacyContents(gateDir, verityDir);
25014
24799
  if (carried > 0) {
25015
24800
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
25016
24801
  }
25017
24802
  try {
25018
- (0, import_node_fs49.rmSync)(gateDir, { recursive: true, force: true });
24803
+ (0, import_node_fs47.rmSync)(gateDir, { recursive: true, force: true });
25019
24804
  } catch {
25020
24805
  }
25021
24806
  }
@@ -25031,7 +24816,7 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
25031
24816
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
25032
24817
  }
25033
24818
  try {
25034
- (0, import_node_fs49.rmSync)(gateDir, { recursive: true, force: true });
24819
+ (0, import_node_fs47.rmSync)(gateDir, { recursive: true, force: true });
25035
24820
  } catch {
25036
24821
  }
25037
24822
  return carried > 0;
@@ -25040,9 +24825,9 @@ function migrateGlobalCredentials(home, actions) {
25040
24825
  if (!home) return;
25041
24826
  const gateCreds = (0, import_node_path31.join)(home, ".gate", "credentials");
25042
24827
  const verityCreds = (0, import_node_path31.join)(home, ".verity", "credentials");
25043
- if (!(0, import_node_fs49.existsSync)(gateCreds)) return;
25044
- if (!(0, import_node_fs49.existsSync)(verityCreds)) {
25045
- (0, import_node_fs49.mkdirSync)((0, import_node_path31.join)(home, ".verity"), { recursive: true });
24828
+ if (!(0, import_node_fs47.existsSync)(gateCreds)) return;
24829
+ if (!(0, import_node_fs47.existsSync)(verityCreds)) {
24830
+ (0, import_node_fs47.mkdirSync)((0, import_node_path31.join)(home, ".verity"), { recursive: true });
25046
24831
  moveFile(gateCreds, verityCreds);
25047
24832
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
25048
24833
  return;
@@ -25065,7 +24850,7 @@ async function migrateLegacyHooks(root, actions) {
25065
24850
  }
25066
24851
  async function migrateClaudeMd(root, actions) {
25067
24852
  const claudeMd = (0, import_node_path31.join)(root, "CLAUDE.md");
25068
- const hadLegacyBlock = (0, import_node_fs49.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
24853
+ const hadLegacyBlock = (0, import_node_fs47.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
25069
24854
  if (!hadLegacyBlock) return;
25070
24855
  try {
25071
24856
  await ensureClaudeMdPointer(root);
@@ -25077,7 +24862,7 @@ async function migrateClaudeMd(root, actions) {
25077
24862
  function migrateStandardFile(root, actions) {
25078
24863
  const gateMd = (0, import_node_path31.join)(root, "GATE.md");
25079
24864
  const verityMd = (0, import_node_path31.join)(root, "VERITY.md");
25080
- if (!(0, import_node_fs49.existsSync)(gateMd) || (0, import_node_fs49.existsSync)(verityMd)) return;
24865
+ if (!(0, import_node_fs47.existsSync)(gateMd) || (0, import_node_fs47.existsSync)(verityMd)) return;
25081
24866
  let moved = false;
25082
24867
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
25083
24868
  try {
@@ -25089,12 +24874,12 @@ function migrateStandardFile(root, actions) {
25089
24874
  if (!moved) moveFile(gateMd, verityMd);
25090
24875
  const content = readFileSyncSafe(verityMd);
25091
24876
  const refreshed = content.split("GATE.md").join("VERITY.md");
25092
- if (refreshed !== content) (0, import_node_fs49.writeFileSync)(verityMd, refreshed);
24877
+ if (refreshed !== content) (0, import_node_fs47.writeFileSync)(verityMd, refreshed);
25093
24878
  actions.push("Renamed GATE.md \u2192 VERITY.md");
25094
24879
  }
25095
24880
  async function migrateTelemetryHeaders(root, actions) {
25096
24881
  const file = (0, import_node_path31.join)(root, ".claude", "settings.local.json");
25097
- if (!(0, import_node_fs49.existsSync)(file)) return;
24882
+ if (!(0, import_node_fs47.existsSync)(file)) return;
25098
24883
  let settings;
25099
24884
  try {
25100
24885
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -25142,14 +24927,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
25142
24927
  }
25143
24928
  if (toAppend.length > 0) {
25144
24929
  const sep2 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
25145
- (0, import_node_fs49.writeFileSync)(verityCreds, verityContent + sep2 + toAppend.join("\n") + "\n");
24930
+ (0, import_node_fs47.writeFileSync)(verityCreds, verityContent + sep2 + toAppend.join("\n") + "\n");
25146
24931
  }
25147
- (0, import_node_fs49.rmSync)(gateCreds, { force: true });
24932
+ (0, import_node_fs47.rmSync)(gateCreds, { force: true });
25148
24933
  return toAppend.length;
25149
24934
  }
25150
24935
  function readFileSyncSafe(path) {
25151
24936
  try {
25152
- return (0, import_node_fs49.readFileSync)(path, "utf-8");
24937
+ return (0, import_node_fs47.readFileSync)(path, "utf-8");
25153
24938
  } catch {
25154
24939
  return "";
25155
24940
  }
@@ -25164,35 +24949,35 @@ function hasStagedChanges(root) {
25164
24949
  }
25165
24950
  function moveDir(from, to) {
25166
24951
  try {
25167
- (0, import_node_fs49.renameSync)(from, to);
24952
+ (0, import_node_fs47.renameSync)(from, to);
25168
24953
  } catch (err) {
25169
24954
  if (err.code !== "EXDEV") throw err;
25170
- (0, import_node_fs49.cpSync)(from, to, { recursive: true });
25171
- (0, import_node_fs49.rmSync)(from, { recursive: true, force: true });
24955
+ (0, import_node_fs47.cpSync)(from, to, { recursive: true });
24956
+ (0, import_node_fs47.rmSync)(from, { recursive: true, force: true });
25172
24957
  }
25173
24958
  }
25174
24959
  function moveFile(from, to) {
25175
24960
  try {
25176
- (0, import_node_fs49.renameSync)(from, to);
24961
+ (0, import_node_fs47.renameSync)(from, to);
25177
24962
  } catch (err) {
25178
24963
  if (err.code !== "EXDEV") throw err;
25179
- (0, import_node_fs49.cpSync)(from, to);
25180
- (0, import_node_fs49.rmSync)(from, { force: true });
24964
+ (0, import_node_fs47.cpSync)(from, to);
24965
+ (0, import_node_fs47.rmSync)(from, { force: true });
25181
24966
  }
25182
24967
  }
25183
24968
  function carryLegacyContents(gateDir, verityDir) {
25184
24969
  let copied = 0;
25185
24970
  const walk2 = (relDir) => {
25186
24971
  const srcDir = (0, import_node_path31.join)(gateDir, relDir);
25187
- for (const entry of (0, import_node_fs49.readdirSync)(srcDir)) {
24972
+ for (const entry of (0, import_node_fs47.readdirSync)(srcDir)) {
25188
24973
  const rel = relDir ? (0, import_node_path31.join)(relDir, entry) : entry;
25189
24974
  const src = (0, import_node_path31.join)(gateDir, rel);
25190
24975
  const dest = (0, import_node_path31.join)(verityDir, rel);
25191
- if ((0, import_node_fs49.statSync)(src).isDirectory()) {
24976
+ if ((0, import_node_fs47.statSync)(src).isDirectory()) {
25192
24977
  walk2(rel);
25193
- } else if (!(0, import_node_fs49.existsSync)(dest)) {
25194
- (0, import_node_fs49.mkdirSync)((0, import_node_path31.dirname)(dest), { recursive: true });
25195
- (0, import_node_fs49.cpSync)(src, dest);
24978
+ } else if (!(0, import_node_fs47.existsSync)(dest)) {
24979
+ (0, import_node_fs47.mkdirSync)((0, import_node_path31.dirname)(dest), { recursive: true });
24980
+ (0, import_node_fs47.cpSync)(src, dest);
25196
24981
  copied++;
25197
24982
  }
25198
24983
  }
@@ -25203,20 +24988,20 @@ function carryLegacyContents(gateDir, verityDir) {
25203
24988
  async function needsMigration(root = repoRoot()) {
25204
24989
  const gateDir = (0, import_node_path31.join)(root, ".gate");
25205
24990
  const verityDir = (0, import_node_path31.join)(root, ".verity");
25206
- if ((0, import_node_fs49.existsSync)(gateDir) && !(0, import_node_fs49.existsSync)(verityDir)) return true;
25207
- if ((0, import_node_fs49.existsSync)(gateDir) && (0, import_node_fs49.existsSync)(verityDir)) {
25208
- if ((0, import_node_fs49.existsSync)((0, import_node_path31.join)(gateDir, "credentials")) && !(0, import_node_fs49.existsSync)((0, import_node_path31.join)(verityDir, "credentials"))) {
24991
+ if ((0, import_node_fs47.existsSync)(gateDir) && !(0, import_node_fs47.existsSync)(verityDir)) return true;
24992
+ if ((0, import_node_fs47.existsSync)(gateDir) && (0, import_node_fs47.existsSync)(verityDir)) {
24993
+ if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(gateDir, "credentials")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(verityDir, "credentials"))) {
25209
24994
  return true;
25210
24995
  }
25211
- if ((0, import_node_fs49.existsSync)((0, import_node_path31.join)(gateDir, "memory")) && !(0, import_node_fs49.existsSync)((0, import_node_path31.join)(verityDir, "memory"))) {
24996
+ if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(gateDir, "memory")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(verityDir, "memory"))) {
25212
24997
  return true;
25213
24998
  }
25214
24999
  }
25215
25000
  const claudeMd = (0, import_node_path31.join)(root, "CLAUDE.md");
25216
- if ((0, import_node_fs49.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
25001
+ if ((0, import_node_fs47.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
25217
25002
  return true;
25218
25003
  }
25219
- if ((0, import_node_fs49.existsSync)((0, import_node_path31.join)(root, "GATE.md")) && !(0, import_node_fs49.existsSync)((0, import_node_path31.join)(root, "VERITY.md"))) {
25004
+ if ((0, import_node_fs47.existsSync)((0, import_node_path31.join)(root, "GATE.md")) && !(0, import_node_fs47.existsSync)((0, import_node_path31.join)(root, "VERITY.md"))) {
25220
25005
  return true;
25221
25006
  }
25222
25007
  if (await hasLegacyHooksAt(root)) return true;
@@ -25491,7 +25276,7 @@ async function promptMultiSelect(question, choices, fallback) {
25491
25276
  }
25492
25277
 
25493
25278
  // src/lib/remote-config.ts
25494
- var import_node_fs50 = require("node:fs");
25279
+ var import_node_fs48 = require("node:fs");
25495
25280
  var import_promises16 = require("node:fs/promises");
25496
25281
  var import_node_path32 = require("node:path");
25497
25282
  var import_yaml5 = __toESM(require_dist());
@@ -25538,7 +25323,7 @@ async function adoptRemoteSetup(found, opts) {
25538
25323
  written.push(STANDARD_FILE);
25539
25324
  if (rider !== null) {
25540
25325
  const localIgnore = projectPath(VERITYIGNORE_FILE);
25541
- if (!(0, import_node_fs50.existsSync)(localIgnore)) {
25326
+ if (!(0, import_node_fs48.existsSync)(localIgnore)) {
25542
25327
  await writeOut(VERITYIGNORE_FILE, rider);
25543
25328
  written.push(VERITYIGNORE_FILE);
25544
25329
  } else {
@@ -25696,7 +25481,7 @@ function resolveDataDir2() {
25696
25481
  // local dev: running from repo root
25697
25482
  ];
25698
25483
  for (const candidate of candidates) {
25699
- if ((0, import_node_fs51.existsSync)((0, import_node_path33.join)(candidate, "skills"))) {
25484
+ if ((0, import_node_fs49.existsSync)((0, import_node_path33.join)(candidate, "skills"))) {
25700
25485
  return candidate;
25701
25486
  }
25702
25487
  }
@@ -25712,7 +25497,7 @@ async function skillIsCurrent(src, dest) {
25712
25497
  const list2 = (dir) => {
25713
25498
  const out = [];
25714
25499
  const walk2 = (d, prefix) => {
25715
- for (const e of (0, import_node_fs51.readdirSync)(d, { withFileTypes: true })) {
25500
+ for (const e of (0, import_node_fs49.readdirSync)(d, { withFileTypes: true })) {
25716
25501
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
25717
25502
  if (e.isDirectory()) walk2((0, import_node_path33.join)(d, e.name), rel);
25718
25503
  else if (e.isFile()) out.push(rel);
@@ -25904,7 +25689,7 @@ async function synthesizeLocally(opts) {
25904
25689
  async function healStaleAnalysisConfig(globals) {
25905
25690
  const configPath = projectPath(CODACY_CONFIG_FILE);
25906
25691
  const standardPath = projectPath(STANDARD_FILE);
25907
- if (!(0, import_node_fs51.existsSync)(configPath) || !(0, import_node_fs51.existsSync)(standardPath)) return;
25692
+ if (!(0, import_node_fs49.existsSync)(configPath) || !(0, import_node_fs49.existsSync)(standardPath)) return;
25908
25693
  const validation = validatePatternIds();
25909
25694
  if (validation.status !== "invalid") return;
25910
25695
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -25998,125 +25783,14 @@ async function handoffToSetup(enabled, claudeInstalled) {
25998
25783
  }
25999
25784
  await reportPhaseTwo(startedAt);
26000
25785
  }
26001
- async function installSkills(force, step) {
26002
- step("Installing skills");
26003
- const dataDir = resolveDataDir2();
26004
- const skillsSource = (0, import_node_path33.join)(dataDir, "skills");
26005
- const skillsDest = ".claude/skills";
26006
- let skillsInstalled = 0;
26007
- for (const skill of SKILLS) {
26008
- const src = (0, import_node_path33.join)(skillsSource, skill);
26009
- const dest = (0, import_node_path33.join)(skillsDest, skill);
26010
- if (!(0, import_node_fs51.existsSync)(src)) {
26011
- printWarn(` Skill data not found: ${skill}`);
26012
- continue;
26013
- }
26014
- if ((0, import_node_fs51.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
26015
- skillsInstalled++;
26016
- continue;
26017
- }
26018
- await copyDir(src, dest);
26019
- skillsInstalled++;
26020
- }
26021
- printInfo(` ${skillsInstalled}/${SKILLS.length} skills installed to .claude/skills/ \u2713`);
26022
- }
26023
- async function adoptPluginWiring(gitMoments, moments) {
26024
- const settings = await readSettings();
26025
- const stripped = removeVerityHooks(settings);
26026
- const hadAny = JSON.stringify(settings.hooks ?? {}) !== JSON.stringify(stripped.hooks ?? {});
26027
- if (hadAny) {
26028
- await writeSettings(stripped);
26029
- printInfo(" Removed this project's Verity hooks from .claude/settings.json \u2713");
26030
- printInfo(" The plugin wires them now, so each turn is reviewed once.");
26031
- } else {
26032
- printInfo(" Wired by the Verity plugin \u2014 nothing to reconcile here \u2713");
26033
- }
26034
- printInfo(` Pre-commit gate: ${gitMoments.includes("commit") ? "on" : "off"}`);
26035
- printInfo(` Pre-push/PR gate: ${gitMoments.includes("push") ? "on" : "off"}`);
26036
- printInfo(" Stop + intent + baseline + compact + session-end: always on \u2713");
26037
- if (!moments.includes("stop")) {
26038
- printWarn(" Turning the Stop review off is not yet supported under the plugin \u2014 it stays on.");
26039
- }
26040
- }
26041
- async function reconcileOwnWiring(moments) {
26042
- await applyMomentSelection(moments);
26043
- const hookStatus = await checkAllVerityHooks();
26044
- printInfo(` Stop (verity analyze): ${hookStatus.stop ? "on" : "off"}`);
26045
- printInfo(` Pre-commit gate: ${hookStatus.guardOn.includes("commit") ? "on" : "off"}`);
26046
- printInfo(` Pre-push/PR gate: ${hookStatus.guardOn.includes("push") ? "on" : "off"}`);
26047
- printInfo(" Intent + baseline + compact + session-end: always on \u2713");
26048
- if (!hookStatus.stop && hookStatus.guardOn.length === 0) {
26049
- printWarn(" No analysis moment is active \u2014 code changes will NOT be reviewed.");
26050
- printWarn(" Enable one: verity hooks install --moments stop");
26051
- }
26052
- }
26053
- async function checkPrerequisites(step) {
26054
- step("Checking prerequisites");
26055
- const prereqs = await checkPrereqs({ install: true });
26056
- for (const c of prereqs.checks) {
26057
- if (c.status === "ok") {
26058
- if (c.justInstalled) continue;
26059
- printInfo(` ${c.label} ${c.detail} \u2713`);
26060
- } else {
26061
- printWarn(` ${c.label}: ${c.detail}`);
26062
- if (c.remedy) printWarn(` ${c.remedy}`);
26063
- }
26064
- }
26065
- if (prereqs.blocked) {
26066
- printError("A required prerequisite is missing \u2014 cannot continue.");
26067
- process.exit(1);
26068
- }
26069
- return prereqs.checks.some((c) => c.id === "claude" && c.status === "ok");
26070
- }
26071
- async function scaffoldProject(step, defaultsOnly) {
26072
- step("Knowledge base, .gitignore and CLAUDE.md");
26073
- await (0, import_promises17.mkdir)(VERITY_DIR, { recursive: true });
26074
- await ensureMemoryDir();
26075
- const ignoreResult = ensureVerityGitignore();
26076
- if (ignoreResult === "failed") {
26077
- printWarn(" .gitignore: could not write the Verity block \u2014 add it manually");
26078
- printWarn(" (.verity/ holds copies of analyzed files, including any secret the gate flagged)");
26079
- } else if (ignoreResult === "conflict") {
26080
- printWarn(" .gitignore: the Verity block is in place but git still ignores .verity/standard.yaml");
26081
- printWarn(" Something outside this file covers it \u2014 a global (~/.gitignore) or nested");
26082
- printWarn(" .gitignore, or a pattern we do not recognise. Check: git check-ignore -v .verity/standard.yaml");
26083
- printWarn(" Until it is fixed, the Standard and the knowledge graph cannot be committed.");
26084
- } else if (ignoreResult === "repaired") {
26085
- printInfo(" .gitignore: rewrote `.verity/` to `.verity/*` so the standard stays committable \u2713");
26086
- } else {
26087
- printInfo(` .gitignore: Verity block ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
26088
- }
26089
- const tracked = committedVerityState();
26090
- if (tracked.length > 0) {
26091
- printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
26092
- const untrack = defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
26093
- if (untrack) {
26094
- const result = untrackVerityState();
26095
- if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
26096
- else if (result === "failed") printWarn(' Could not untrack \u2014 run "git rm -r --cached .verity" manually');
26097
- } else {
26098
- printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml .verity/memory");
26099
- }
26100
- }
26101
- try {
26102
- await ensureClaudeMdPointer();
26103
- printInfo(" CLAUDE.md instructions \u2713");
26104
- } catch (err) {
26105
- printWarn(` Could not update CLAUDE.md: ${err.message}`);
26106
- }
26107
- }
26108
25786
  function registerInitCommand(program2) {
26109
- program2.command("init").alias("setup").description("Set up Verity in the current project (asks the setup questions, then hands off to /verity-setup)").option("--force", "Reinstall the skills even when they are already up to date (hooks are always reconciled)").option("-y, --yes", "Take the recommended answer for every question (no prompts)").option("--no-setup", "Skip the /verity-setup handoff at the end").option(
26110
- "--plugin-mode",
26111
- "The Claude Code plugin owns the skills and hooks: install neither, and remove any this project already has"
26112
- ).option("--no-adopt", "Don't offer this repository's existing Standard from the service; synthesize a new one").action(async (opts) => {
25787
+ program2.command("init").alias("setup").description("Set up Verity in the current project (asks the setup questions, then hands off to /verity-setup)").option("--force", "Reinstall the skills even when they are already up to date (hooks are always reconciled)").option("-y, --yes", "Take the recommended answer for every question (no prompts)").option("--no-setup", "Skip the /verity-setup handoff at the end").option("--no-adopt", "Don't offer this repository's existing Standard from the service; synthesize a new one").action(async (opts) => {
26113
25788
  const force = opts.force ?? false;
26114
25789
  const wantsHandoff = opts.setup !== false;
26115
25790
  const wantsAdopt = opts.adopt !== false;
26116
25791
  const defaultsOnly = (opts.yes ?? false) || !interactive();
26117
- const pluginMode = opts.pluginMode ?? pluginActiveHere();
26118
25792
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
26119
- const isProject = projectMarkers.some((m) => (0, import_node_fs51.existsSync)(m));
25793
+ const isProject = projectMarkers.some((m) => (0, import_node_fs49.existsSync)(m));
26120
25794
  if (!isProject) {
26121
25795
  printError("No project detected in the current directory.");
26122
25796
  printInfo('Run "verity init" from your project root.');
@@ -26147,13 +25821,43 @@ function registerInitCommand(program2) {
26147
25821
  }
26148
25822
  console.log("");
26149
25823
  }
26150
- const claudeInstalled = await checkPrerequisites(step);
25824
+ step("Checking prerequisites");
25825
+ const prereqs = await checkPrereqs({ install: true });
25826
+ for (const c of prereqs.checks) {
25827
+ if (c.status === "ok") {
25828
+ if (c.justInstalled) continue;
25829
+ printInfo(` ${c.label} ${c.detail} \u2713`);
25830
+ } else {
25831
+ printWarn(` ${c.label}: ${c.detail}`);
25832
+ if (c.remedy) printWarn(` ${c.remedy}`);
25833
+ }
25834
+ }
25835
+ if (prereqs.blocked) {
25836
+ printError("A required prerequisite is missing \u2014 cannot continue.");
25837
+ process.exit(1);
25838
+ }
25839
+ const claudeInstalled = prereqs.checks.some((c) => c.id === "claude" && c.status === "ok");
26151
25840
  console.log("");
26152
- if (pluginMode) {
26153
- printInfo("Skipping skills \u2014 the Verity plugin provides them, namespaced as /verity:<name>.");
26154
- } else {
26155
- await installSkills(force, step);
25841
+ step("Installing skills");
25842
+ const dataDir = resolveDataDir2();
25843
+ const skillsSource = (0, import_node_path33.join)(dataDir, "skills");
25844
+ const skillsDest = ".claude/skills";
25845
+ let skillsInstalled = 0;
25846
+ for (const skill of SKILLS) {
25847
+ const src = (0, import_node_path33.join)(skillsSource, skill);
25848
+ const dest = (0, import_node_path33.join)(skillsDest, skill);
25849
+ if (!(0, import_node_fs49.existsSync)(src)) {
25850
+ printWarn(` Skill data not found: ${skill}`);
25851
+ continue;
25852
+ }
25853
+ if ((0, import_node_fs49.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
25854
+ skillsInstalled++;
25855
+ continue;
25856
+ }
25857
+ await copyDir(src, dest);
25858
+ skillsInstalled++;
26156
25859
  }
25860
+ printInfo(` ${skillsInstalled}/${SKILLS.length} skills installed to .claude/skills/ \u2713`);
26157
25861
  step(defaultsOnly ? "Setup answers (defaults)" : "Your setup answers");
26158
25862
  const previous = await readSetupState();
26159
25863
  const answers = await askSetupQuestions(defaultsOnly, previous);
@@ -26161,20 +25865,54 @@ function registerInitCommand(program2) {
26161
25865
  if (defaultsOnly) {
26162
25866
  printInfo(` intensity: ${intensity} \xB7 moments: ${moments.join(", ") || "none"} (no questions asked)`);
26163
25867
  }
26164
- await scaffoldProject(step, defaultsOnly);
25868
+ step("Knowledge base, .gitignore and CLAUDE.md");
25869
+ await (0, import_promises17.mkdir)(VERITY_DIR, { recursive: true });
25870
+ await ensureMemoryDir();
25871
+ const ignoreResult = ensureVerityGitignore();
25872
+ if (ignoreResult === "failed") {
25873
+ printWarn(" .gitignore: could not write the Verity block \u2014 add it manually");
25874
+ printWarn(" (.verity/ holds copies of analyzed files, including any secret the gate flagged)");
25875
+ } else if (ignoreResult === "conflict") {
25876
+ printWarn(" .gitignore: the Verity block is in place but git still ignores .verity/standard.yaml");
25877
+ printWarn(" Something outside this file covers it \u2014 a global (~/.gitignore) or nested");
25878
+ printWarn(" .gitignore, or a pattern we do not recognise. Check: git check-ignore -v .verity/standard.yaml");
25879
+ printWarn(" Until it is fixed, the Standard and the knowledge graph cannot be committed.");
25880
+ } else if (ignoreResult === "repaired") {
25881
+ printInfo(" .gitignore: rewrote `.verity/` to `.verity/*` so the standard stays committable \u2713");
25882
+ } else {
25883
+ printInfo(` .gitignore: Verity block ${ignoreResult === "added" ? "added" : "already covered"} \u2713`);
25884
+ }
25885
+ const tracked = committedVerityState();
25886
+ if (tracked.length > 0) {
25887
+ printWarn(` ${tracked.length} Verity state file(s) are tracked in git (e.g. ${tracked[0]}).`);
25888
+ const untrack = defaultsOnly ? false : await promptYes(" Untrack them now (files stay on disk)? [Y/n] ", { nonInteractive: false });
25889
+ if (untrack) {
25890
+ const result = untrackVerityState();
25891
+ if (result === "untracked") printInfo(" Untracked (staged) \u2014 commit to finish \u2713");
25892
+ else if (result === "failed") printWarn(' Could not untrack \u2014 run "git rm -r --cached .verity" manually');
25893
+ } else {
25894
+ printWarn(" Left tracked. Fix with: git rm -r --cached .verity && git add .verity/standard.yaml .verity/memory");
25895
+ }
25896
+ }
25897
+ try {
25898
+ await ensureClaudeMdPointer();
25899
+ printInfo(" CLAUDE.md instructions \u2713");
25900
+ } catch (err) {
25901
+ printWarn(` Could not update CLAUDE.md: ${err.message}`);
25902
+ }
26165
25903
  const globalVerityDir = (0, import_node_path33.join)(process.env.HOME ?? "", ".verity");
26166
25904
  await (0, import_promises17.mkdir)(globalVerityDir, { recursive: true });
26167
25905
  console.log("");
26168
25906
  step("Wiring Claude Code hooks");
26169
- const gitMoments = [
26170
- ...moments.includes("pre-commit") ? ["commit"] : [],
26171
- ...moments.includes("pre-push") ? ["push"] : []
26172
- ];
26173
- writeProjectConfig({ git_moments: gitMoments });
26174
- if (pluginMode) {
26175
- await adoptPluginWiring(gitMoments, moments);
26176
- } else {
26177
- await reconcileOwnWiring(moments);
25907
+ await applyMomentSelection(moments);
25908
+ const hookStatus = await checkAllVerityHooks();
25909
+ printInfo(` Stop (verity analyze): ${hookStatus.stop ? "on" : "off"}`);
25910
+ printInfo(` Pre-commit gate: ${hookStatus.guardOn.includes("commit") ? "on" : "off"}`);
25911
+ printInfo(` Pre-push/PR gate: ${hookStatus.guardOn.includes("push") ? "on" : "off"}`);
25912
+ printInfo(` Intent + baseline + compact + session-end: always on \u2713`);
25913
+ if (!hookStatus.stop && hookStatus.guardOn.length === 0) {
25914
+ printWarn(" No analysis moment is active \u2014 code changes will NOT be reviewed.");
25915
+ printWarn(" Enable one: verity hooks install --moments stop");
26178
25916
  }
26179
25917
  console.log("");
26180
25918
  step("Sign in to Verity (optional)");
@@ -26217,7 +25955,7 @@ function registerInitCommand(program2) {
26217
25955
  }
26218
25956
  step("Your project's Standard");
26219
25957
  let haveStandard = false;
26220
- if ((0, import_node_fs51.existsSync)(projectPath(STANDARD_FILE))) {
25958
+ if ((0, import_node_fs49.existsSync)(projectPath(STANDARD_FILE))) {
26221
25959
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
26222
25960
  haveStandard = true;
26223
25961
  } else {
@@ -26244,7 +25982,7 @@ function registerInitCommand(program2) {
26244
25982
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
26245
25983
  init: {
26246
25984
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
26247
- cli_version: true ? "0.32.0-experimental.68ae2ee" : "dev"
25985
+ cli_version: true ? "0.32.0-experimental.f0746f7" : "dev"
26248
25986
  }
26249
25987
  });
26250
25988
  } catch (err) {
@@ -26253,13 +25991,9 @@ function registerInitCommand(program2) {
26253
25991
  console.log("");
26254
25992
  printInfo("This machine is set up.");
26255
25993
  console.log("");
26256
- if (pluginMode) {
26257
- console.log(" (skills and hooks come from the Verity plugin, not this project)");
26258
- } else {
26259
- console.log(" .claude/skills/verity-*/ 8 skills (setup, analyze, status, feedback,");
26260
- console.log(" learn, memory, insights, reflect)");
26261
- console.log(" .claude/settings.json hooks, reconciled to your chosen moments");
26262
- }
25994
+ console.log(" .claude/skills/verity-*/ 8 skills (setup, analyze, status, feedback,");
25995
+ console.log(" learn, memory, insights, reflect)");
25996
+ console.log(" .claude/settings.json hooks, reconciled to your chosen moments");
26263
25997
  console.log(" .verity/memory/ knowledge base (commit to git)");
26264
25998
  console.log(" .verity/standard.yaml the Standard the gate enforces");
26265
25999
  console.log(" .codacy/codacy.config.json static-analysis patterns (validated)");
@@ -26283,7 +26017,7 @@ function registerInitCommand(program2) {
26283
26017
  }
26284
26018
 
26285
26019
  // src/commands/uninstall.ts
26286
- var import_node_fs52 = require("node:fs");
26020
+ var import_node_fs50 = require("node:fs");
26287
26021
  var import_node_path34 = require("node:path");
26288
26022
  var SKILL_NAMES = [
26289
26023
  "verity-setup",
@@ -26304,10 +26038,10 @@ function registerUninstallCommand(program2) {
26304
26038
  const skillsRoot = projectPath(".claude/skills");
26305
26039
  for (const name of SKILL_NAMES) {
26306
26040
  const dir = (0, import_node_path34.join)(skillsRoot, name);
26307
- if ((0, import_node_fs52.existsSync)(dir)) {
26041
+ if ((0, import_node_fs50.existsSync)(dir)) {
26308
26042
  actions.push({
26309
26043
  label: `Remove .claude/skills/${name}/`,
26310
- apply: () => (0, import_node_fs52.rmSync)(dir, { recursive: true, force: true })
26044
+ apply: () => (0, import_node_fs50.rmSync)(dir, { recursive: true, force: true })
26311
26045
  });
26312
26046
  }
26313
26047
  }
@@ -26321,24 +26055,24 @@ function registerUninstallCommand(program2) {
26321
26055
  });
26322
26056
  }
26323
26057
  const verityDir = projectPath(VERITY_DIR);
26324
- if ((0, import_node_fs52.existsSync)(verityDir)) {
26058
+ if ((0, import_node_fs50.existsSync)(verityDir)) {
26325
26059
  actions.push({
26326
26060
  label: `Remove ${VERITY_DIR}/`,
26327
- apply: () => (0, import_node_fs52.rmSync)(verityDir, { recursive: true, force: true })
26061
+ apply: () => (0, import_node_fs50.rmSync)(verityDir, { recursive: true, force: true })
26328
26062
  });
26329
26063
  }
26330
26064
  if (!keepVerityMd) {
26331
26065
  const verityMd = projectPath(VERITY_MD_FILE);
26332
- if ((0, import_node_fs52.existsSync)(verityMd)) {
26066
+ if ((0, import_node_fs50.existsSync)(verityMd)) {
26333
26067
  actions.push({
26334
26068
  label: `Remove ${VERITY_MD_FILE}`,
26335
- apply: () => (0, import_node_fs52.rmSync)(verityMd, { force: true })
26069
+ apply: () => (0, import_node_fs50.rmSync)(verityMd, { force: true })
26336
26070
  });
26337
26071
  }
26338
26072
  }
26339
26073
  const cleanupEmptyDir = (path) => {
26340
- if ((0, import_node_fs52.existsSync)(path) && (0, import_node_fs52.statSync)(path).isDirectory() && (0, import_node_fs52.readdirSync)(path).length === 0) {
26341
- (0, import_node_fs52.rmdirSync)(path);
26074
+ if ((0, import_node_fs50.existsSync)(path) && (0, import_node_fs50.statSync)(path).isDirectory() && (0, import_node_fs50.readdirSync)(path).length === 0) {
26075
+ (0, import_node_fs50.rmdirSync)(path);
26342
26076
  }
26343
26077
  };
26344
26078
  actions.push({
@@ -26350,10 +26084,10 @@ function registerUninstallCommand(program2) {
26350
26084
  });
26351
26085
  const home = process.env.HOME ?? "";
26352
26086
  const globalVerityDir = (0, import_node_path34.join)(home, ".verity");
26353
- if (purgeGlobal && (0, import_node_fs52.existsSync)(globalVerityDir)) {
26087
+ if (purgeGlobal && (0, import_node_fs50.existsSync)(globalVerityDir)) {
26354
26088
  actions.push({
26355
26089
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
26356
- apply: () => (0, import_node_fs52.rmSync)(globalVerityDir, { recursive: true, force: true })
26090
+ apply: () => (0, import_node_fs50.rmSync)(globalVerityDir, { recursive: true, force: true })
26357
26091
  });
26358
26092
  }
26359
26093
  if (actions.length === 0) {
@@ -26547,7 +26281,7 @@ function registerTaskCommands(program2) {
26547
26281
  }
26548
26282
 
26549
26283
  // src/commands/reset.ts
26550
- var import_node_fs53 = require("node:fs");
26284
+ var import_node_fs51 = require("node:fs");
26551
26285
  var import_node_path35 = require("node:path");
26552
26286
  function registerResetCommand(program2) {
26553
26287
  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) => {
@@ -26585,11 +26319,11 @@ function registerResetCommand(program2) {
26585
26319
  }
26586
26320
  const cacheDir = projectPath(CACHE_DIR);
26587
26321
  let purged = 0;
26588
- if ((0, import_node_fs53.existsSync)(cacheDir)) {
26589
- for (const entry of (0, import_node_fs53.readdirSync)(cacheDir)) {
26322
+ if ((0, import_node_fs51.existsSync)(cacheDir)) {
26323
+ for (const entry of (0, import_node_fs51.readdirSync)(cacheDir)) {
26590
26324
  if (entry.startsWith("pending-")) {
26591
26325
  try {
26592
- (0, import_node_fs53.unlinkSync)((0, import_node_path35.join)(cacheDir, entry));
26326
+ (0, import_node_fs51.unlinkSync)((0, import_node_path35.join)(cacheDir, entry));
26593
26327
  purged++;
26594
26328
  } catch {
26595
26329
  }
@@ -26604,19 +26338,19 @@ function registerResetCommand(program2) {
26604
26338
  projectPath(`${VERITY_DIR}/.last-analysis`)
26605
26339
  ];
26606
26340
  for (const file of filesToClear) {
26607
- if ((0, import_node_fs53.existsSync)(file)) {
26341
+ if ((0, import_node_fs51.existsSync)(file)) {
26608
26342
  try {
26609
- (0, import_node_fs53.writeFileSync)(file, "");
26343
+ (0, import_node_fs51.writeFileSync)(file, "");
26610
26344
  } catch {
26611
26345
  }
26612
26346
  }
26613
26347
  }
26614
26348
  if (opts.all) {
26615
26349
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
26616
- if ((0, import_node_fs53.existsSync)(logsDir)) {
26617
- for (const entry of (0, import_node_fs53.readdirSync)(logsDir)) {
26350
+ if ((0, import_node_fs51.existsSync)(logsDir)) {
26351
+ for (const entry of (0, import_node_fs51.readdirSync)(logsDir)) {
26618
26352
  try {
26619
- (0, import_node_fs53.unlinkSync)((0, import_node_path35.join)(logsDir, entry));
26353
+ (0, import_node_fs51.unlinkSync)((0, import_node_path35.join)(logsDir, entry));
26620
26354
  } catch {
26621
26355
  }
26622
26356
  }
@@ -26924,8 +26658,8 @@ function registerTelemetryCommands(program2) {
26924
26658
  }
26925
26659
 
26926
26660
  // src/cli.ts
26927
- program.name("verity").description("CLI for Verity quality gate service").version("0.32.0-experimental.68ae2ee").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) => {
26928
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.0-experimental.68ae2ee");
26661
+ program.name("verity").description("CLI for Verity quality gate service").version("0.32.0-experimental.f0746f7").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) => {
26662
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.32.0-experimental.f0746f7");
26929
26663
  setUserNamedServiceUrl(program.opts().serviceUrl);
26930
26664
  try {
26931
26665
  await foldLegacyLocalCredential();