@codacy/verity-cli 0.30.0 → 0.30.1-experimental.e2137b9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/verity.js +868 -473
  2. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -10342,6 +10342,10 @@ function repoRoot() {
10342
10342
  }
10343
10343
  return _repoRoot;
10344
10344
  }
10345
+ function _resetRepoRoot() {
10346
+ _repoRoot = null;
10347
+ _mainRoot = void 0;
10348
+ }
10345
10349
  var _mainRoot;
10346
10350
  function mainWorktreeRoot() {
10347
10351
  if (_mainRoot !== void 0) return _mainRoot;
@@ -10493,7 +10497,7 @@ var SECURITY_PATTERNS = [
10493
10497
  /Dockerfile/
10494
10498
  ];
10495
10499
  var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
10496
- var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
10500
+ var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
10497
10501
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
10498
10502
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
10499
10503
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -10804,13 +10808,6 @@ function execGit(cmd) {
10804
10808
  return "";
10805
10809
  }
10806
10810
  }
10807
- function execGitArgs(args) {
10808
- try {
10809
- return (0, import_node_child_process3.execFileSync)("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
10810
- } catch {
10811
- return "";
10812
- }
10813
- }
10814
10811
  function splitLines(s) {
10815
10812
  return s.split("\n").filter((l) => l.length > 0);
10816
10813
  }
@@ -10877,9 +10874,6 @@ function getChangedFiles() {
10877
10874
  const filtered = Array.from(sets).filter((f) => !isVerityOwnedPath(f));
10878
10875
  return { files: filtered, hasRecentCommitFiles };
10879
10876
  }
10880
- function getStagedFiles() {
10881
- return splitLines(execGit("git diff --cached --name-only")).filter((f) => !isVerityOwnedPath(f));
10882
- }
10883
10877
  function getDirtyFiles() {
10884
10878
  const set = /* @__PURE__ */ new Set();
10885
10879
  for (const f of splitLines(execGit("git diff --name-only HEAD"))) set.add(f);
@@ -10900,33 +10894,6 @@ function showContentAtRef(ref, repoRelPath) {
10900
10894
  return null;
10901
10895
  }
10902
10896
  }
10903
- function getPushRangeFiles() {
10904
- const diff = (range) => splitLines(execGitArgs(["diff", "--name-only", range])).filter((f) => !f.startsWith(".verity/") && !f.startsWith(".verity\\"));
10905
- const resolvers = [
10906
- () => execGitArgs(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{push}"]) ? "@{push}..HEAD" : null,
10907
- () => execGitArgs(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"]) ? "@{upstream}..HEAD" : null,
10908
- () => {
10909
- const branch = execGitArgs(["rev-parse", "--abbrev-ref", "HEAD"]);
10910
- return branch && branch !== "HEAD" && execGitArgs(["rev-parse", "--verify", "-q", `origin/${branch}`]) ? `origin/${branch}..HEAD` : null;
10911
- }
10912
- ];
10913
- for (const resolve3 of resolvers) {
10914
- const range = resolve3();
10915
- if (range) return { files: diff(range), range };
10916
- }
10917
- const baseline = readBaselineSha();
10918
- if (baseline) {
10919
- const files = diff(`${baseline}..HEAD`);
10920
- if (files.length > 0) return { files, range: `${baseline}..HEAD` };
10921
- }
10922
- const last = diff("HEAD~1..HEAD");
10923
- return { files: last, range: last.length > 0 ? "HEAD~1..HEAD" : null };
10924
- }
10925
- function getPushRangeMessages() {
10926
- const { range } = getPushRangeFiles();
10927
- if (!range) return "";
10928
- return execGitArgs(["log", range, "--format=%B%x00"]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
10929
- }
10930
10897
  function filterAnalyzable(files) {
10931
10898
  return files.filter((f) => {
10932
10899
  const ext = (0, import_node_path3.extname)(f).slice(1);
@@ -11417,7 +11384,7 @@ var readline = __toESM(require("node:readline/promises"));
11417
11384
  var import_node_os = require("node:os");
11418
11385
 
11419
11386
  // src/lib/provider-auth.ts
11420
- var sleep = (ms) => new Promise((resolve3) => setTimeout(resolve3, ms));
11387
+ var sleep = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
11421
11388
  var form = (fields) => new URLSearchParams(fields).toString();
11422
11389
  async function githubAccountId(owner) {
11423
11390
  try {
@@ -13747,6 +13714,160 @@ var import_node_fs14 = require("node:fs");
13747
13714
  var import_node_crypto7 = require("node:crypto");
13748
13715
  var import_node_path13 = require("node:path");
13749
13716
 
13717
+ // src/lib/analysis-mode.ts
13718
+ var DEBUG_PHRASES = [
13719
+ "not working",
13720
+ "doesn't work",
13721
+ "doesn't work",
13722
+ "does not work",
13723
+ "isn't working",
13724
+ "is not working",
13725
+ "can't figure out",
13726
+ "stack trace"
13727
+ ];
13728
+ var DEBUG_WORDS = [
13729
+ "fix",
13730
+ "bug",
13731
+ "broken",
13732
+ "crash",
13733
+ "crashing",
13734
+ "failing",
13735
+ "debug",
13736
+ "debugging",
13737
+ "investigate",
13738
+ "troubleshoot",
13739
+ "regression",
13740
+ "wrong"
13741
+ ];
13742
+ var DEBUG_PATTERN = new RegExp(
13743
+ [
13744
+ ...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
13745
+ ...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
13746
+ ].join("|"),
13747
+ "i"
13748
+ );
13749
+ var FALSE_POSITIVE_PATTERNS = [
13750
+ /\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
13751
+ /\berror\s+handling\b/i,
13752
+ /\berror\s+boundar(?:y|ies)\b/i,
13753
+ /\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
13754
+ /\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
13755
+ ];
13756
+ function hasDebugIntent(prompt) {
13757
+ if (!DEBUG_PATTERN.test(prompt)) return false;
13758
+ for (const fp of FALSE_POSITIVE_PATTERNS) {
13759
+ if (fp.test(prompt)) return false;
13760
+ }
13761
+ return true;
13762
+ }
13763
+ var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
13764
+ 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;
13765
+ function isGitOnlyPrompt(prompt) {
13766
+ if (!GIT_ONLY_PATTERN.test(prompt)) return false;
13767
+ if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
13768
+ return true;
13769
+ }
13770
+ function reconcileAnalysisMode(predictedMode, signals) {
13771
+ const mode2 = resolveAnalysisMode(predictedMode, signals);
13772
+ if (mode2 !== "skip") return mode2;
13773
+ const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
13774
+ if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
13775
+ return mode2;
13776
+ }
13777
+ function resolveAnalysisMode(predictedMode, signals) {
13778
+ if (!predictedMode || !isValidMode(predictedMode)) {
13779
+ return detectAnalysisMode(
13780
+ signals.noFilesChanged,
13781
+ signals.assistantResponse,
13782
+ signals.conversationPrompts,
13783
+ signals.actionSummary,
13784
+ signals.sessionAuthoredCode
13785
+ );
13786
+ }
13787
+ const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
13788
+ const agentInvestigated = didAgentInvestigate(signals.actionSummary);
13789
+ switch (predictedMode) {
13790
+ case "skip":
13791
+ if (agentAuthoredCode) return "standard";
13792
+ return "skip";
13793
+ case "plan":
13794
+ if (agentAuthoredCode) return "standard";
13795
+ return "plan";
13796
+ case "debug":
13797
+ return "debug";
13798
+ case "standard":
13799
+ if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
13800
+ return agentInvestigated ? "plan" : "skip";
13801
+ }
13802
+ return "standard";
13803
+ }
13804
+ }
13805
+ function didAgentInvestigate(summary) {
13806
+ if (!summary) return false;
13807
+ return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
13808
+ }
13809
+ function isValidMode(mode2) {
13810
+ return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
13811
+ }
13812
+ function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
13813
+ const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
13814
+ if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
13815
+ if (!agentAuthoredCode) return "skip";
13816
+ }
13817
+ if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
13818
+ return "plan";
13819
+ }
13820
+ if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
13821
+ return didAgentInvestigate(actionSummary) ? "plan" : "skip";
13822
+ }
13823
+ for (const prompt of conversationPrompts) {
13824
+ if (hasDebugIntent(prompt)) {
13825
+ return "debug";
13826
+ }
13827
+ }
13828
+ return "standard";
13829
+ }
13830
+ 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;
13831
+ var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
13832
+ 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;
13833
+ var CHAIN_RE = /&&|\||;|\$\(|\x60/;
13834
+ function isNonAuthoringCommand(cmd) {
13835
+ if (typeof cmd !== "string" || cmd.trim().length === 0) return false;
13836
+ if (FILE_MUTATE_RE.test(cmd)) return false;
13837
+ if (CHAIN_RE.test(cmd)) return false;
13838
+ return GIT_PLUMBING_RE.test(cmd) || READ_ONLY_RE.test(cmd);
13839
+ }
13840
+ function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
13841
+ if (!actionSummary) return sessionAuthoredCode;
13842
+ if ((actionSummary.subagents ?? 0) > 0) return true;
13843
+ if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
13844
+ const commands = actionSummary.commands ?? [];
13845
+ if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
13846
+ if (sessionAuthoredCode) {
13847
+ const allSafe = commands.length > 0 && commands.every(isNonAuthoringCommand);
13848
+ if (!allSafe) return true;
13849
+ }
13850
+ return false;
13851
+ }
13852
+ function scopeToAuthored(files, actionSummary) {
13853
+ if (!actionSummary) return { files, signal: "no-transcript" };
13854
+ const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
13855
+ if (touched.length === 0) return { files: [], signal: "none-authored" };
13856
+ return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
13857
+ }
13858
+ function narrowToAgentAuthored(files, actionSummary) {
13859
+ if (!actionSummary) return files;
13860
+ const touched = [
13861
+ ...actionSummary.files_edited,
13862
+ ...actionSummary.files_created
13863
+ ];
13864
+ if (touched.length === 0) return files;
13865
+ return files.filter((f) => {
13866
+ const suffix = "/" + f;
13867
+ return touched.some((t) => t === f || t.endsWith(suffix));
13868
+ });
13869
+ }
13870
+
13750
13871
  // src/lib/skip-detection.ts
13751
13872
  function isBareAckPrompt(prompt) {
13752
13873
  if (typeof prompt !== "string") return false;
@@ -13810,6 +13931,15 @@ function shouldSkipForBareAck(input) {
13810
13931
  if (input.turnAuthoredCode) return false;
13811
13932
  return input.canSeeTurnAuthorship;
13812
13933
  }
13934
+ function isCommandOnlyTurn(input) {
13935
+ if (!input.authorshipIsObservable) return false;
13936
+ if (input.userCommandsTruncated) return false;
13937
+ const commands = input.userCommands ?? [];
13938
+ if (commands.length === 0) return false;
13939
+ if (input.agentAuthoredFiles > 0) return false;
13940
+ if (input.agentToolCalls > 0) return false;
13941
+ return commands.every(isNonAuthoringCommand);
13942
+ }
13813
13943
 
13814
13944
  // src/lib/pending-repeat.ts
13815
13945
  var STOP = /* @__PURE__ */ new Set([
@@ -16119,17 +16249,17 @@ async function readHookStdin() {
16119
16249
  try {
16120
16250
  if (process.stdin.isTTY) return {};
16121
16251
  const chunks = [];
16122
- const timeout = new Promise((resolve3) => setTimeout(() => resolve3({}), 500));
16123
- const read = new Promise((resolve3) => {
16252
+ const timeout = new Promise((resolve4) => setTimeout(() => resolve4({}), 500));
16253
+ const read = new Promise((resolve4) => {
16124
16254
  process.stdin.on("data", (c) => chunks.push(c));
16125
16255
  process.stdin.on("end", () => {
16126
16256
  try {
16127
- resolve3(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
16257
+ resolve4(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
16128
16258
  } catch {
16129
- resolve3({});
16259
+ resolve4({});
16130
16260
  }
16131
16261
  });
16132
- process.stdin.on("error", () => resolve3({}));
16262
+ process.stdin.on("error", () => resolve4({}));
16133
16263
  process.stdin.resume();
16134
16264
  });
16135
16265
  return await Promise.race([read, timeout]);
@@ -16647,6 +16777,7 @@ function createRun(opts, globals) {
16647
16777
  phaseReached: "",
16648
16778
  phasesCompleted: [],
16649
16779
  skipReason: null,
16780
+ treeFrame: null,
16650
16781
  turnId: "",
16651
16782
  // The value `resolveReachability` itself returns when every rung declines.
16652
16783
  reachability: { human_reachable: "unknown", human_reachable_source: "inferred", rung: "none" },
@@ -16786,6 +16917,10 @@ function formatRunEvidence(run, startedAt) {
16786
16917
  `;
16787
16918
  out += row("turn", `${run.turnId || "(unminted)"}${run.sessionId ? ` \xB7 session ${run.sessionId}` : ""}`);
16788
16919
  out += row("reached", `${run.phaseReached || "(none)"}${run.skipReason ? ` \xB7 SKIPPED: ${run.skipReason}` : ""} \xB7 ${ms}ms`);
16920
+ if (run.treeFrame) {
16921
+ const f = run.treeFrame;
16922
+ out += row("tree", f.worktreeRoot ? `${f.worktreeRoot}${f.isLinkedWorktree ? " \xB7 linked worktree" : ""}${f.branch ? ` \xB7 branch ${f.branch}` : " \xB7 detached"}` : `(unresolved: ${f.refusal ?? "unknown"})`);
16923
+ }
16789
16924
  out += row("changed", `${run.changedUniverse.length} from git \xB7 analyzable ${run.analyzable.length} \xB7 reviewable ${run.reviewable.length} \xB7 security ${run.securityFiles.length} \xB7 forReview ${run.allForReview.length}`);
16790
16925
  const done = (phase) => run.phasesCompleted.includes(phase);
16791
16926
  const ifDone = (phase, value) => done(phase) ? value : "?";
@@ -16882,6 +17017,301 @@ function installRunEvidence(run) {
16882
17017
  });
16883
17018
  }
16884
17019
 
17020
+ // src/lib/git-frame.ts
17021
+ var import_node_child_process7 = require("node:child_process");
17022
+ var import_node_fs20 = require("node:fs");
17023
+ var import_node_os3 = require("node:os");
17024
+ var import_node_path18 = require("node:path");
17025
+ var import_node_path19 = require("node:path");
17026
+ var VALUE_TOKEN = `(?:'[^']*'|"[^"]*"|\\S+)`;
17027
+ var GIT_GLOBAL_OPTS = `(?:\\s+(?:-[Cc]\\s+${VALUE_TOKEN}|--?[\\w-]+(?:=\\S+)?))*`;
17028
+ var COMMIT_HEAD = `git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`;
17029
+ var PUSH_HEAD = `git${GIT_GLOBAL_OPTS}\\s+push\\b`;
17030
+ var GH_PR_HEAD = `gh${GIT_GLOBAL_OPTS}\\s+pr\\s+create\\b`;
17031
+ var COMMIT_RE = new RegExp(`(?:^|[\\s;&|(])${COMMIT_HEAD}|(?:^|[;&|(])\\s*[^\\s;&|()'"]*\\/${COMMIT_HEAD}`);
17032
+ var PUSH_RE = new RegExp(`(?:^|[\\s;&|(])${PUSH_HEAD}|(?:^|[;&|(])\\s*[^\\s;&|()'"]*\\/${PUSH_HEAD}`);
17033
+ var GH_PR_RE = new RegExp(`(?:^|[\\s;&|(])${GH_PR_HEAD}|(?:^|[;&|(])\\s*[^\\s;&|()'"]*\\/${GH_PR_HEAD}`);
17034
+ function splitSegments(command) {
17035
+ return (command ?? "").split(/&&|\|\||;|\n/);
17036
+ }
17037
+ function findMomentSegment(command, on) {
17038
+ const segments = splitSegments(command);
17039
+ let commitIdx = -1;
17040
+ let pushIdx = -1;
17041
+ for (let i = 0; i < segments.length; i++) {
17042
+ const seg = segments[i];
17043
+ if (/--dry-run\b/.test(seg)) continue;
17044
+ if (commitIdx === -1 && COMMIT_RE.test(seg)) commitIdx = i;
17045
+ if (pushIdx === -1 && (PUSH_RE.test(seg) || GH_PR_RE.test(seg))) pushIdx = i;
17046
+ }
17047
+ if (commitIdx !== -1 && on.includes("commit")) return { moment: "pre-commit", segmentIndex: commitIdx };
17048
+ if (pushIdx !== -1 && on.includes("push")) return { moment: "pre-push", segmentIndex: pushIdx };
17049
+ return null;
17050
+ }
17051
+ function classifyCommand(command, on) {
17052
+ return findMomentSegment(command, on)?.moment ?? null;
17053
+ }
17054
+ function unquote(token) {
17055
+ if (token.length >= 2) {
17056
+ const first = token[0];
17057
+ if ((first === "'" || first === '"') && token.endsWith(first)) return token.slice(1, -1);
17058
+ }
17059
+ return token;
17060
+ }
17061
+ var SHELL_DYNAMIC = /[$`\\]/;
17062
+ function extractCommandTarget(command, segmentIndex, baseDir) {
17063
+ const segments = splitSegments(command);
17064
+ let dir = baseDir;
17065
+ let named = false;
17066
+ for (let i = 0; i < segmentIndex; i++) {
17067
+ const m = segments[i].match(new RegExp(`^\\s*cd(?:\\s+(${VALUE_TOKEN}))?\\s*$`));
17068
+ if (!m) continue;
17069
+ named = true;
17070
+ if (m[1] === void 0) {
17071
+ dir = (0, import_node_os3.homedir)();
17072
+ continue;
17073
+ }
17074
+ const raw = unquote(m[1]);
17075
+ if (SHELL_DYNAMIC.test(raw) || raw === "-") {
17076
+ return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
17077
+ }
17078
+ const expanded = raw === "~" ? (0, import_node_os3.homedir)() : raw.startsWith("~/") ? (0, import_node_path19.join)((0, import_node_os3.homedir)(), raw.slice(2)) : raw;
17079
+ dir = (0, import_node_path18.isAbsolute)(expanded) ? expanded : (0, import_node_path18.resolve)(dir, expanded);
17080
+ }
17081
+ const seg = segments[segmentIndex];
17082
+ const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
17083
+ if (overrideMatch) {
17084
+ return { dir: null, named: true, unresolvable: `git-dir/work-tree/index override in command: ${overrideMatch[0].trim()}` };
17085
+ }
17086
+ const gitMatch = seg.match(new RegExp(`(?:^|[\\s;&|(])(?:[^\\s;&|()'"]*\\/)?git(${GIT_GLOBAL_OPTS})\\s`));
17087
+ if (gitMatch) {
17088
+ const optsRegion = gitMatch[1] ?? "";
17089
+ const cRe = new RegExp(`-C\\s+(${VALUE_TOKEN})`, "g");
17090
+ let cm;
17091
+ while ((cm = cRe.exec(optsRegion)) !== null) {
17092
+ named = true;
17093
+ const raw = unquote(cm[1]);
17094
+ if (SHELL_DYNAMIC.test(raw)) {
17095
+ return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
17096
+ }
17097
+ const expanded = raw === "~" ? (0, import_node_os3.homedir)() : raw.startsWith("~/") ? (0, import_node_path19.join)((0, import_node_os3.homedir)(), raw.slice(2)) : raw;
17098
+ dir = (0, import_node_path18.isAbsolute)(expanded) ? expanded : (0, import_node_path18.resolve)(dir, expanded);
17099
+ }
17100
+ }
17101
+ return { dir, named, unresolvable: null };
17102
+ }
17103
+ var PUSH_VALUE_FLAGS = /* @__PURE__ */ new Set(["-o", "--push-option", "--receive-pack", "--exec"]);
17104
+ function parsePushTarget(segment) {
17105
+ const none = { remote: null, srcRef: null, dstRef: null, isDelete: false };
17106
+ const m = PUSH_RE.exec(segment);
17107
+ if (!m) return none;
17108
+ const rest = segment.slice(m.index + m[0].length);
17109
+ const tokens = (rest.match(new RegExp(`'[^']*'|"[^"]*"|\\S+`, "g")) ?? []).map(unquote);
17110
+ let remote = null;
17111
+ let refspec = null;
17112
+ let isDelete = false;
17113
+ for (let i = 0; i < tokens.length; i++) {
17114
+ const t = tokens[i];
17115
+ if (t === "-d" || t === "--delete") {
17116
+ isDelete = true;
17117
+ continue;
17118
+ }
17119
+ if (t.startsWith("--repo=")) {
17120
+ remote = t.slice("--repo=".length);
17121
+ continue;
17122
+ }
17123
+ if (t === "--repo") {
17124
+ remote = tokens[++i] ?? null;
17125
+ continue;
17126
+ }
17127
+ if (PUSH_VALUE_FLAGS.has(t)) {
17128
+ i++;
17129
+ continue;
17130
+ }
17131
+ if (t.startsWith("-")) continue;
17132
+ if (SHELL_DYNAMIC.test(t)) return none;
17133
+ if (remote === null) {
17134
+ remote = t;
17135
+ continue;
17136
+ }
17137
+ if (refspec === null) {
17138
+ refspec = t;
17139
+ continue;
17140
+ }
17141
+ break;
17142
+ }
17143
+ if (refspec === null) return { remote, srcRef: null, dstRef: null, isDelete };
17144
+ const spec = refspec.startsWith("+") ? refspec.slice(1) : refspec;
17145
+ const colon = spec.indexOf(":");
17146
+ if (colon === -1) return { remote, srcRef: spec, dstRef: null, isDelete };
17147
+ const src = spec.slice(0, colon);
17148
+ const dst = spec.slice(colon + 1);
17149
+ if (src === "") return { remote, srcRef: null, dstRef: dst || null, isDelete: true };
17150
+ return { remote, srcRef: src, dstRef: dst || null, isDelete };
17151
+ }
17152
+ function gitAt(dir, args) {
17153
+ try {
17154
+ return (0, import_node_child_process7.execFileSync)("git", args, { cwd: dir, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
17155
+ } catch {
17156
+ return "";
17157
+ }
17158
+ }
17159
+ function realpathOr(p) {
17160
+ try {
17161
+ return import_node_fs20.realpathSync.native(p);
17162
+ } catch {
17163
+ return (0, import_node_path18.resolve)(p);
17164
+ }
17165
+ }
17166
+ function resolveFrame(input) {
17167
+ const found = findMomentSegment(input.command, input.on);
17168
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs20.existsSync)(input.hookCwd);
17169
+ const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
17170
+ let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
17171
+ const refuse = (refusal) => ({
17172
+ moment: found?.moment ?? null,
17173
+ frame: { worktreeRoot: null, gitDir: null, commonDir: null, isLinkedWorktree: false, branch: null, anchor, refusal }
17174
+ });
17175
+ let dir = baseDir;
17176
+ if (found) {
17177
+ const segments = splitSegments(input.command);
17178
+ const kindRes = found.moment === "pre-commit" ? [COMMIT_RE] : [PUSH_RE, GH_PR_RE];
17179
+ const dirs = /* @__PURE__ */ new Set();
17180
+ for (let i = 0; i < segments.length; i++) {
17181
+ if (/--dry-run\b/.test(segments[i])) continue;
17182
+ if (!kindRes.some((re) => re.test(segments[i]))) continue;
17183
+ const target = extractCommandTarget(input.command, i, baseDir);
17184
+ if (target.named) anchor = "command-target";
17185
+ if (target.unresolvable) return refuse(`target:${target.unresolvable}`);
17186
+ dirs.add(target.dir ?? baseDir);
17187
+ }
17188
+ if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
17189
+ const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
17190
+ if (targetDir !== baseDir) {
17191
+ if (!(0, import_node_fs20.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
17192
+ dir = targetDir;
17193
+ }
17194
+ }
17195
+ const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
17196
+ if (!toplevel) {
17197
+ return refuse(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
17198
+ }
17199
+ const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
17200
+ const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
17201
+ const gitDir = gitDirRaw ? realpathOr(gitDirRaw) : null;
17202
+ const commonDir = commonRaw ? realpathOr((0, import_node_path18.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path18.resolve)(dir, commonRaw)) : null;
17203
+ const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
17204
+ return {
17205
+ moment: found?.moment ?? null,
17206
+ frame: {
17207
+ worktreeRoot: realpathOr(toplevel),
17208
+ gitDir,
17209
+ commonDir,
17210
+ // The one honest definition: a linked worktree's own git dir differs from
17211
+ // the shared one. No path convention involved — see the header.
17212
+ isLinkedWorktree: !!gitDir && !!commonDir && gitDir !== commonDir,
17213
+ branch: !branchRaw || branchRaw === "HEAD" ? null : branchRaw,
17214
+ anchor,
17215
+ refusal: null
17216
+ }
17217
+ };
17218
+ }
17219
+ function frameGit(frame, args) {
17220
+ if (!frame.worktreeRoot) return "";
17221
+ return gitAt(frame.worktreeRoot, args);
17222
+ }
17223
+ function refResolves(frame, ref) {
17224
+ return frameGit(frame, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]) !== "";
17225
+ }
17226
+ var SHA_RE2 = /^[0-9a-f]{40}$/;
17227
+ function baselineShaAt(frame) {
17228
+ if (!frame.worktreeRoot) return null;
17229
+ try {
17230
+ const sha = (0, import_node_fs20.readFileSync)((0, import_node_path19.join)(frame.worktreeRoot, BASELINE_SHA_FILE), "utf-8").trim();
17231
+ if (!SHA_RE2.test(sha)) return null;
17232
+ return refResolves(frame, sha) ? sha : null;
17233
+ } catch {
17234
+ return null;
17235
+ }
17236
+ }
17237
+ function stagedRange() {
17238
+ return { kind: "staged", base: "HEAD", head: "INDEX", via: "index" };
17239
+ }
17240
+ function resolvePushRange(frame, command, on) {
17241
+ const nothing = (via) => ({ kind: "nothing", base: null, head: "HEAD", via });
17242
+ if (!frame.worktreeRoot) return nothing("refused");
17243
+ const found = findMomentSegment(command, on);
17244
+ const segment = found ? splitSegments(command)[found.segmentIndex] : "";
17245
+ const target = parsePushTarget(segment);
17246
+ if (target.isDelete) return nothing("deletion");
17247
+ const head = target.srcRef ?? "HEAD";
17248
+ if (!refResolves(frame, head)) return nothing(`src-unresolvable:${head}`);
17249
+ const srcName = target.srcRef;
17250
+ const branchForRemote = srcName ?? frame.branch;
17251
+ const candidates = [];
17252
+ if (target.remote && (target.dstRef ?? srcName)) {
17253
+ const dstName = (target.dstRef ?? srcName).replace(/^refs\/heads\//, "");
17254
+ candidates.push({ ref: `refs/remotes/${target.remote}/${dstName}`, via: `refspec:${target.remote}/${dstName}` });
17255
+ }
17256
+ if (target.remote && !srcName && !target.dstRef && frame.branch) {
17257
+ candidates.push({ ref: `refs/remotes/${target.remote}/${frame.branch}`, via: `remote:${target.remote}/${frame.branch}` });
17258
+ }
17259
+ candidates.push({ ref: srcName ? `${srcName}@{push}` : "@{push}", via: "@{push}" });
17260
+ candidates.push({ ref: srcName ? `${srcName}@{upstream}` : "@{upstream}", via: "@{upstream}" });
17261
+ if (branchForRemote) {
17262
+ candidates.push({
17263
+ ref: `refs/remotes/origin/${branchForRemote.replace(/^refs\/heads\//, "")}`,
17264
+ via: `origin/${branchForRemote.replace(/^refs\/heads\//, "")}`
17265
+ });
17266
+ }
17267
+ for (const c of candidates) {
17268
+ if (!refResolves(frame, c.ref)) continue;
17269
+ const mergeBase = frameGit(frame, ["merge-base", c.ref, head]);
17270
+ if (SHA_RE2.test(mergeBase)) return { kind: "push", base: mergeBase, head, via: c.via };
17271
+ }
17272
+ const baseline = baselineShaAt(frame);
17273
+ if (baseline) return { kind: "baseline", base: baseline, head, via: "review-baseline" };
17274
+ if (refResolves(frame, `${head}~1`)) return { kind: "last-commit", base: `${head}~1`, head, via: `${head}~1` };
17275
+ return nothing("no-parent");
17276
+ }
17277
+ function rangeFiles(frame, range) {
17278
+ let out;
17279
+ switch (range.kind) {
17280
+ case "staged":
17281
+ out = frameGit(frame, ["diff", "--cached", "--name-only"]);
17282
+ break;
17283
+ case "push":
17284
+ case "baseline":
17285
+ case "last-commit":
17286
+ out = frameGit(frame, ["diff", "--name-only", range.base, range.head === "INDEX" ? "HEAD" : range.head]);
17287
+ break;
17288
+ case "nothing":
17289
+ return [];
17290
+ }
17291
+ return out.split("\n").filter((l) => l.length > 0).filter((f) => !isVerityOwnedPath(f));
17292
+ }
17293
+ function rangeMessages(frame, range) {
17294
+ if (range.kind === "staged" || range.kind === "nothing" || !range.base) return "";
17295
+ 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");
17296
+ }
17297
+ function frameTelemetry(frame, range, divergence) {
17298
+ const t = {
17299
+ anchor: frame.anchor,
17300
+ linked_worktree: frame.isLinkedWorktree,
17301
+ range_via: range?.via ?? null,
17302
+ refusal: frame.refusal
17303
+ };
17304
+ if (divergence) {
17305
+ t.root_differs = !!frame.worktreeRoot && !!divergence.actualRoot && realpathOr(frame.worktreeRoot) !== realpathOr(divergence.actualRoot);
17306
+ const a = [...divergence.actualFiles].sort().join("\n");
17307
+ const b = [...divergence.frameFiles].sort().join("\n");
17308
+ t.files_differ = a !== b;
17309
+ t.frame_file_count = divergence.frameFiles.length;
17310
+ t.actual_file_count = divergence.actualFiles.length;
17311
+ }
17312
+ return t;
17313
+ }
17314
+
16885
17315
  // src/lib/reachability.ts
16886
17316
  function resolveReachability(input = {}) {
16887
17317
  const env = input.env ?? {};
@@ -16910,7 +17340,7 @@ function truthy(v) {
16910
17340
  }
16911
17341
 
16912
17342
  // src/lib/transcript.ts
16913
- var import_node_fs20 = require("node:fs");
17343
+ var import_node_fs21 = require("node:fs");
16914
17344
  var MAX_READ_BYTES = 256 * 1024;
16915
17345
  var SMALL_FILE_BYTES = 64 * 1024;
16916
17346
  var MAX_FILES_LIST = 20;
@@ -16920,6 +17350,8 @@ var MAX_COMMAND_CHARS = 80;
16920
17350
  var MAX_TOOL_BLOCKS = 200;
16921
17351
  var MAX_SUMMARY_BYTES = 4096;
16922
17352
  var HOME = process.env.HOME ?? "";
17353
+ var BASH_INPUT_RE = /^\s*<bash-input>([\s\S]*?)<\/bash-input>/;
17354
+ var BASH_ECHO_RE = /^\s*<bash-(?:stdout|stderr)>/;
16923
17355
  async function extractActionSummary(transcriptPath) {
16924
17356
  try {
16925
17357
  const read = readTurnLines(transcriptPath);
@@ -16934,7 +17366,7 @@ async function extractActionSummary(transcriptPath) {
16934
17366
  function readTurnLines(transcriptPath) {
16935
17367
  let size;
16936
17368
  try {
16937
- size = (0, import_node_fs20.statSync)(transcriptPath).size;
17369
+ size = (0, import_node_fs21.statSync)(transcriptPath).size;
16938
17370
  } catch {
16939
17371
  return null;
16940
17372
  }
@@ -16942,7 +17374,7 @@ function readTurnLines(transcriptPath) {
16942
17374
  let raw;
16943
17375
  let windowed = false;
16944
17376
  if (size <= SMALL_FILE_BYTES) {
16945
- raw = (0, import_node_fs20.readFileSync)(transcriptPath, "utf-8");
17377
+ raw = (0, import_node_fs21.readFileSync)(transcriptPath, "utf-8");
16946
17378
  } else {
16947
17379
  windowed = true;
16948
17380
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -16983,7 +17415,7 @@ function isRealUserMessage(parsed) {
16983
17415
  const message = parsed.message;
16984
17416
  if (!message) return false;
16985
17417
  const content = message.content;
16986
- if (typeof content === "string") return true;
17418
+ if (typeof content === "string") return !BASH_ECHO_RE.test(content);
16987
17419
  if (Array.isArray(content)) {
16988
17420
  return content.some((b) => {
16989
17421
  if (typeof b !== "object" || b === null) return false;
@@ -16998,6 +17430,8 @@ function buildSummary(lines) {
16998
17430
  const filesEdited = /* @__PURE__ */ new Set();
16999
17431
  const filesCreated = /* @__PURE__ */ new Set();
17000
17432
  const commands = [];
17433
+ const userCommands = [];
17434
+ let userCommandsTruncated = false;
17001
17435
  let searches = 0;
17002
17436
  let subagents = 0;
17003
17437
  let webFetches = 0;
@@ -17015,6 +17449,17 @@ function buildSummary(lines) {
17015
17449
  if (entry.type === "user" && !firstTimestamp) {
17016
17450
  firstTimestamp = entry.timestamp ?? null;
17017
17451
  }
17452
+ if (entry.type === "user") {
17453
+ const typed = userTypedCommands(entry);
17454
+ if (typed.truncated) userCommandsTruncated = true;
17455
+ for (const cmd of typed.commands) {
17456
+ if (userCommands.length >= MAX_COMMANDS) {
17457
+ userCommandsTruncated = true;
17458
+ break;
17459
+ }
17460
+ userCommands.push(cmd);
17461
+ }
17462
+ }
17018
17463
  if (entry.type !== "assistant") continue;
17019
17464
  turnMessages++;
17020
17465
  lastTimestamp = entry.timestamp ?? lastTimestamp;
@@ -17092,6 +17537,8 @@ function buildSummary(lines) {
17092
17537
  ],
17093
17538
  searches,
17094
17539
  commands,
17540
+ user_commands: userCommands,
17541
+ ...userCommandsTruncated ? { user_commands_truncated: true } : {},
17095
17542
  subagents,
17096
17543
  web_fetches: webFetches,
17097
17544
  total_tool_calls: totalToolCalls,
@@ -17100,6 +17547,8 @@ function buildSummary(lines) {
17100
17547
  };
17101
17548
  if (JSON.stringify(summary).length > MAX_SUMMARY_BYTES) {
17102
17549
  summary.commands = [];
17550
+ summary.user_commands = [];
17551
+ summary.user_commands_truncated = true;
17103
17552
  if (JSON.stringify(summary).length > MAX_SUMMARY_BYTES) {
17104
17553
  summary.files_read = summary.files_read.slice(0, 10);
17105
17554
  summary.files_edited = summary.files_edited.slice(0, 10);
@@ -17117,6 +17566,22 @@ function addPath(set, rawPath) {
17117
17566
  if (p.length > 200) p = p.slice(0, 200);
17118
17567
  set.add(p);
17119
17568
  }
17569
+ function userTypedCommands(entry) {
17570
+ const none = { commands: [], truncated: false };
17571
+ const message = entry.message;
17572
+ const content = message?.content;
17573
+ if (typeof content !== "string") return none;
17574
+ const m = BASH_INPUT_RE.exec(content);
17575
+ if (!m) return none;
17576
+ const commands = [];
17577
+ let truncated = false;
17578
+ for (const line of m[1].split("\n")) {
17579
+ if (line.length > MAX_COMMAND_CHARS) truncated = true;
17580
+ const cmd = sanitizeCommand(line);
17581
+ if (cmd) commands.push(cmd);
17582
+ }
17583
+ return { commands, truncated };
17584
+ }
17120
17585
  function sanitizeCommand(rawCmd) {
17121
17586
  if (typeof rawCmd !== "string" || !rawCmd) return null;
17122
17587
  let cmd = rawCmd.split("\n")[0];
@@ -17150,28 +17615,28 @@ async function readStopHookStdin() {
17150
17615
  try {
17151
17616
  if (process.stdin.isTTY) return empty;
17152
17617
  const chunks = [];
17153
- const timeout = new Promise((resolve3) => setTimeout(() => resolve3(empty), 500));
17154
- const read = new Promise((resolve3) => {
17618
+ const timeout = new Promise((resolve4) => setTimeout(() => resolve4(empty), 500));
17619
+ const read = new Promise((resolve4) => {
17155
17620
  process.stdin.on("data", (chunk) => chunks.push(chunk));
17156
17621
  process.stdin.on("end", () => {
17157
17622
  const raw = Buffer.concat(chunks).toString("utf-8").trim();
17158
17623
  if (!raw) {
17159
- resolve3(empty);
17624
+ resolve4(empty);
17160
17625
  return;
17161
17626
  }
17162
17627
  try {
17163
17628
  const data = JSON.parse(raw);
17164
- resolve3({
17629
+ resolve4({
17165
17630
  assistantMessage: typeof data.last_assistant_message === "string" ? data.last_assistant_message : null,
17166
17631
  stopReason: typeof data.stop_reason === "string" ? data.stop_reason : null,
17167
17632
  transcriptPath: typeof data.transcript_path === "string" ? data.transcript_path : null,
17168
17633
  sessionId: typeof data.session_id === "string" ? data.session_id : null
17169
17634
  });
17170
17635
  } catch {
17171
- resolve3(empty);
17636
+ resolve4(empty);
17172
17637
  }
17173
17638
  });
17174
- process.stdin.on("error", () => resolve3(empty));
17639
+ process.stdin.on("error", () => resolve4(empty));
17175
17640
  process.stdin.resume();
17176
17641
  });
17177
17642
  return await Promise.race([read, timeout]);
@@ -17185,6 +17650,7 @@ async function bootstrap(run) {
17185
17650
  process.chdir(repoRoot());
17186
17651
  } catch {
17187
17652
  }
17653
+ run.treeFrame = resolveFrame({ command: "", on: [], hookCwd: null }).frame;
17188
17654
  const turnId = `t-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
17189
17655
  let reachability = resolveReachability({
17190
17656
  autonomousFlag: process.env.VERITY_AUTONOMOUS === "1" || opts.mode === "autonomous",
@@ -17350,7 +17816,7 @@ function truncateToCap(text) {
17350
17816
  function buildHookOutput(gateDecision, systemMessage, agentContext) {
17351
17817
  return {
17352
17818
  gate_decision: gateDecision,
17353
- systemMessage,
17819
+ ...systemMessage === null ? {} : { systemMessage },
17354
17820
  ...agentContext ? {
17355
17821
  hookSpecificOutput: {
17356
17822
  hookEventName: "Stop",
@@ -17371,7 +17837,7 @@ function channelSilence(input) {
17371
17837
  // src/lib/cli-version.ts
17372
17838
  function cliVersion() {
17373
17839
  try {
17374
- return true ? "0.30.0" : "dev";
17840
+ return true ? "0.30.1-experimental.e2137b9" : "dev";
17375
17841
  } catch {
17376
17842
  return "dev";
17377
17843
  }
@@ -17411,8 +17877,8 @@ async function sendSkipBeacon(ctx, reason) {
17411
17877
  }
17412
17878
 
17413
17879
  // src/lib/static-analysis.ts
17414
- var import_node_child_process7 = require("node:child_process");
17415
- var import_node_fs21 = require("node:fs");
17880
+ var import_node_child_process8 = require("node:child_process");
17881
+ var import_node_fs22 = require("node:fs");
17416
17882
  var SEVERITY_ORDER = {
17417
17883
  Error: 0,
17418
17884
  Critical: 0,
@@ -17424,7 +17890,7 @@ var SEVERITY_ORDER = {
17424
17890
  };
17425
17891
  function isCodacyAvailable() {
17426
17892
  try {
17427
- (0, import_node_child_process7.execSync)("which codacy-analysis", { stdio: "pipe" });
17893
+ (0, import_node_child_process8.execSync)("which codacy-analysis", { stdio: "pipe" });
17428
17894
  return true;
17429
17895
  } catch {
17430
17896
  return false;
@@ -17460,13 +17926,13 @@ function runCodacyAnalysis(files) {
17460
17926
  if (files.length === 0) return empty;
17461
17927
  const existingFiles = files.filter((f) => {
17462
17928
  try {
17463
- return (0, import_node_fs21.existsSync)(f);
17929
+ return (0, import_node_fs22.existsSync)(f);
17464
17930
  } catch {
17465
17931
  return false;
17466
17932
  }
17467
17933
  });
17468
17934
  if (existingFiles.length === 0) return empty;
17469
- const proc = (0, import_node_child_process7.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
17935
+ const proc = (0, import_node_child_process8.spawnSync)("codacy-analysis", buildAnalyzerArgv(existingFiles), {
17470
17936
  encoding: "utf-8",
17471
17937
  maxBuffer: 10 * 1024 * 1024
17472
17938
  });
@@ -17657,6 +18123,7 @@ async function passAndExit(run, reason, skip, kindOverride) {
17657
18123
  "verity-command",
17658
18124
  "bare-acknowledgment",
17659
18125
  "reflection-prompt",
18126
+ "command-only-turn",
17660
18127
  "skip-mode",
17661
18128
  "zero-increment",
17662
18129
  "debounce",
@@ -17675,10 +18142,12 @@ async function passAndExit(run, reason, skip, kindOverride) {
17675
18142
  }
17676
18143
  const AGENT_SILENT_SKIPS = /* @__PURE__ */ new Set([]);
17677
18144
  const agentNote = AGENT_SILENT_SKIPS.has(skip) ? null : note;
18145
+ const HUMAN_SILENT_SKIPS = /* @__PURE__ */ new Set(["command-only-turn"]);
18146
+ const humanNote = HUMAN_SILENT_SKIPS.has(skip) ? null : `Verity: ${reason}`;
17678
18147
  printJsonCompact(
17679
18148
  buildHookOutput(
17680
18149
  verdict,
17681
- `Verity: ${reason}`,
18150
+ humanNote,
17682
18151
  // `additionalContext` is the agent's ONLY input. Writing only
17683
18152
  // `systemMessage` — the human's field — tells the agent nothing at all,
17684
18153
  // which is what sixteen of the nineteen terminating paths used to do.
@@ -17706,8 +18175,8 @@ async function scope(run) {
17706
18175
  }
17707
18176
 
17708
18177
  // src/lib/specs.ts
17709
- var import_node_fs22 = require("node:fs");
17710
- var import_node_path18 = require("node:path");
18178
+ var import_node_fs23 = require("node:fs");
18179
+ var import_node_path20 = require("node:path");
17711
18180
  var SPEC_CANDIDATES = [
17712
18181
  "CLAUDE.md",
17713
18182
  "AGENTS.md",
@@ -17738,16 +18207,16 @@ function discoverSpecs(consulted = []) {
17738
18207
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
17739
18208
  if (totalBytes >= totalCap) return false;
17740
18209
  if (seen.has(specPath)) return true;
17741
- if (!(0, import_node_fs22.existsSync)(specPath)) return true;
18210
+ if (!(0, import_node_fs23.existsSync)(specPath)) return true;
17742
18211
  seen.add(specPath);
17743
18212
  const remaining = totalCap - totalBytes;
17744
18213
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
17745
18214
  const readBytes = Math.min(fileCap, remaining);
17746
18215
  try {
17747
18216
  const buf = Buffer.alloc(readBytes);
17748
- const fd = (0, import_node_fs22.openSync)(specPath, "r");
17749
- const bytesRead = (0, import_node_fs22.readSync)(fd, buf, 0, readBytes, 0);
17750
- (0, import_node_fs22.closeSync)(fd);
18217
+ const fd = (0, import_node_fs23.openSync)(specPath, "r");
18218
+ const bytesRead = (0, import_node_fs23.readSync)(fd, buf, 0, readBytes, 0);
18219
+ (0, import_node_fs23.closeSync)(fd);
17751
18220
  const content = buf.slice(0, bytesRead).toString("utf-8");
17752
18221
  if (!content) return true;
17753
18222
  result.push({ path: specPath, content });
@@ -17763,7 +18232,7 @@ function discoverSpecs(consulted = []) {
17763
18232
  if (!addSpec(candidate)) break;
17764
18233
  }
17765
18234
  for (const dir of ["spec", "docs"]) {
17766
- if (!(0, import_node_fs22.existsSync)(dir)) continue;
18235
+ if (!(0, import_node_fs23.existsSync)(dir)) continue;
17767
18236
  try {
17768
18237
  const mdFiles = findMdFiles(dir, 2).sort();
17769
18238
  for (const mdFile of mdFiles) {
@@ -17778,9 +18247,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
17778
18247
  if (depth >= maxDepth) return [];
17779
18248
  const result = [];
17780
18249
  try {
17781
- const entries = (0, import_node_fs22.readdirSync)(dir, { withFileTypes: true });
18250
+ const entries = (0, import_node_fs23.readdirSync)(dir, { withFileTypes: true });
17782
18251
  for (const entry of entries) {
17783
- const fullPath = (0, import_node_path18.join)(dir, entry.name);
18252
+ const fullPath = (0, import_node_path20.join)(dir, entry.name);
17784
18253
  if (entry.isFile() && entry.name.endsWith(".md")) {
17785
18254
  result.push(fullPath);
17786
18255
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -17792,19 +18261,19 @@ function findMdFiles(dir, maxDepth, depth = 0) {
17792
18261
  return result;
17793
18262
  }
17794
18263
  function discoverPlans() {
17795
- const homePlansDir = (0, import_node_path18.join)(process.env.HOME ?? "", ".claude", "plans");
18264
+ const homePlansDir = (0, import_node_path20.join)(process.env.HOME ?? "", ".claude", "plans");
17796
18265
  const localPlansDir = ".claude/plans";
17797
18266
  const candidates = [];
17798
18267
  const seen = /* @__PURE__ */ new Set();
17799
18268
  for (const plansDir of [localPlansDir, homePlansDir]) {
17800
- if (!(0, import_node_fs22.existsSync)(plansDir)) continue;
18269
+ if (!(0, import_node_fs23.existsSync)(plansDir)) continue;
17801
18270
  try {
17802
- for (const f of (0, import_node_fs22.readdirSync)(plansDir)) {
18271
+ for (const f of (0, import_node_fs23.readdirSync)(plansDir)) {
17803
18272
  if (!f.endsWith(".md") || seen.has(f)) continue;
17804
18273
  seen.add(f);
17805
- const fullPath = (0, import_node_path18.join)(plansDir, f);
18274
+ const fullPath = (0, import_node_path20.join)(plansDir, f);
17806
18275
  try {
17807
- const stat3 = (0, import_node_fs22.statSync)(fullPath);
18276
+ const stat3 = (0, import_node_fs23.statSync)(fullPath);
17808
18277
  candidates.push({ name: f, path: fullPath, mtime: stat3.mtimeMs, size: stat3.size });
17809
18278
  } catch {
17810
18279
  }
@@ -17817,7 +18286,7 @@ function discoverPlans() {
17817
18286
  for (const entry of candidates.slice(0, MAX_PLAN_FILES)) {
17818
18287
  if (entry.size > MAX_PLAN_FILE_BYTES) continue;
17819
18288
  try {
17820
- const content = (0, import_node_fs22.readFileSync)(entry.path, "utf-8");
18289
+ const content = (0, import_node_fs23.readFileSync)(entry.path, "utf-8");
17821
18290
  result.push({ name: entry.name, content });
17822
18291
  } catch {
17823
18292
  }
@@ -17828,6 +18297,15 @@ function discoverPlans() {
17828
18297
  // src/commands/analyze/phases/03-intent-inputs.ts
17829
18298
  async function intentInputs(run) {
17830
18299
  const { actionSummary, allForReview, assistantResponse, baseline, baselineSessionId } = run;
18300
+ if (isCommandOnlyTurn({
18301
+ userCommands: actionSummary?.user_commands,
18302
+ userCommandsTruncated: actionSummary?.user_commands_truncated,
18303
+ agentAuthoredFiles: (actionSummary?.files_edited.length ?? 0) + (actionSummary?.files_created.length ?? 0),
18304
+ agentToolCalls: actionSummary?.total_tool_calls ?? 0,
18305
+ authorshipIsObservable: !!actionSummary && actionSummary.transcript_windowed !== "orphaned"
18306
+ })) {
18307
+ await passAndExit(run, "User command only \u2014 skipping analysis", "command-only-turn");
18308
+ }
17831
18309
  const conversation = await readAndClearConversationBuffer(baselineSessionId);
17832
18310
  const specs = discoverSpecs(actionSummary?.files_read ?? []);
17833
18311
  const plans = discoverPlans();
@@ -17868,156 +18346,6 @@ async function connect(run) {
17868
18346
  Object.assign(run, { urlResult, serviceUrl: urlResult.data, token: tokenResult.data.token });
17869
18347
  }
17870
18348
 
17871
- // src/lib/analysis-mode.ts
17872
- var DEBUG_PHRASES = [
17873
- "not working",
17874
- "doesn't work",
17875
- "doesn't work",
17876
- "does not work",
17877
- "isn't working",
17878
- "is not working",
17879
- "can't figure out",
17880
- "stack trace"
17881
- ];
17882
- var DEBUG_WORDS = [
17883
- "fix",
17884
- "bug",
17885
- "broken",
17886
- "crash",
17887
- "crashing",
17888
- "failing",
17889
- "debug",
17890
- "debugging",
17891
- "investigate",
17892
- "troubleshoot",
17893
- "regression",
17894
- "wrong"
17895
- ];
17896
- var DEBUG_PATTERN = new RegExp(
17897
- [
17898
- ...DEBUG_PHRASES.map((p) => p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")),
17899
- ...DEBUG_WORDS.map((w) => `\\b${w}\\b`)
17900
- ].join("|"),
17901
- "i"
17902
- );
17903
- var FALSE_POSITIVE_PATTERNS = [
17904
- /\b(?:add|create|implement|write|build|design|set\s*up)\b.{0,20}\berror\b/i,
17905
- /\berror\s+handling\b/i,
17906
- /\berror\s+boundar(?:y|ies)\b/i,
17907
- /\berror\s+(?:type|class|page|component|message|code|enum)\b/i,
17908
- /\b(?:add|create|implement|write|build)\b.{0,20}\b(?:fix|debug|issue)\b/i
17909
- ];
17910
- function hasDebugIntent(prompt) {
17911
- if (!DEBUG_PATTERN.test(prompt)) return false;
17912
- for (const fp of FALSE_POSITIVE_PATTERNS) {
17913
- if (fp.test(prompt)) return false;
17914
- }
17915
- return true;
17916
- }
17917
- var GIT_ONLY_PATTERN = /\b(commit|push|deploy|merge|rebase|tag|release|publish|ship)\b/i;
17918
- 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;
17919
- function isGitOnlyPrompt(prompt) {
17920
- if (!GIT_ONLY_PATTERN.test(prompt)) return false;
17921
- if (CODE_AUTHORING_PATTERN.test(prompt)) return false;
17922
- return true;
17923
- }
17924
- function reconcileAnalysisMode(predictedMode, signals) {
17925
- const mode2 = resolveAnalysisMode(predictedMode, signals);
17926
- if (mode2 !== "skip") return mode2;
17927
- const windowIsOrphaned = signals.actionSummary?.transcript_windowed === "orphaned";
17928
- if (windowIsOrphaned && !signals.sessionAuthoredCode) return "standard";
17929
- return mode2;
17930
- }
17931
- function resolveAnalysisMode(predictedMode, signals) {
17932
- if (!predictedMode || !isValidMode(predictedMode)) {
17933
- return detectAnalysisMode(
17934
- signals.noFilesChanged,
17935
- signals.assistantResponse,
17936
- signals.conversationPrompts,
17937
- signals.actionSummary,
17938
- signals.sessionAuthoredCode
17939
- );
17940
- }
17941
- const agentAuthoredCode = !!(signals.actionSummary && (signals.actionSummary.files_edited.length > 0 || signals.actionSummary.files_created.length > 0)) || !!signals.sessionAuthoredCode;
17942
- const agentInvestigated = didAgentInvestigate(signals.actionSummary);
17943
- switch (predictedMode) {
17944
- case "skip":
17945
- if (agentAuthoredCode) return "standard";
17946
- return "skip";
17947
- case "plan":
17948
- if (agentAuthoredCode) return "standard";
17949
- return "plan";
17950
- case "debug":
17951
- return "debug";
17952
- case "standard":
17953
- if (!!signals.actionSummary && !agentAuthoredCode && !!signals.assistantResponse) {
17954
- return agentInvestigated ? "plan" : "skip";
17955
- }
17956
- return "standard";
17957
- }
17958
- }
17959
- function didAgentInvestigate(summary) {
17960
- if (!summary) return false;
17961
- return summary.files_read.length > 0 || summary.searches > 0 || summary.commands.length > 0 || summary.subagents > 0 || summary.web_fetches > 0;
17962
- }
17963
- function isValidMode(mode2) {
17964
- return mode2 === "standard" || mode2 === "plan" || mode2 === "debug" || mode2 === "skip";
17965
- }
17966
- function detectAnalysisMode(noFilesChanged, assistantResponse, conversationPrompts, actionSummary, sessionAuthoredCode) {
17967
- const agentAuthoredCode = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0)) || !!sessionAuthoredCode;
17968
- if (conversationPrompts.length > 0 && conversationPrompts.every(isGitOnlyPrompt)) {
17969
- if (!agentAuthoredCode) return "skip";
17970
- }
17971
- if (noFilesChanged && !!assistantResponse && !agentAuthoredCode) {
17972
- return "plan";
17973
- }
17974
- if (!!actionSummary && !agentAuthoredCode && !!assistantResponse) {
17975
- return didAgentInvestigate(actionSummary) ? "plan" : "skip";
17976
- }
17977
- for (const prompt of conversationPrompts) {
17978
- if (hasDebugIntent(prompt)) {
17979
- return "debug";
17980
- }
17981
- }
17982
- return "standard";
17983
- }
17984
- 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;
17985
- var GIT_PLUMBING_RE = /^\s*git\s+(?:merge|rebase|stash|cherry-pick|revert|pull|fetch|checkout|switch|reset|restore|clean)\b/i;
17986
- 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;
17987
- var CHAIN_RE = /&&|\||;|\$\(|\x60/;
17988
- function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
17989
- if (!actionSummary) return sessionAuthoredCode;
17990
- if ((actionSummary.subagents ?? 0) > 0) return true;
17991
- if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
17992
- const commands = actionSummary.commands ?? [];
17993
- if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
17994
- if (sessionAuthoredCode) {
17995
- const allSafe = commands.length > 0 && commands.every(
17996
- (c) => !CHAIN_RE.test(c) && (GIT_PLUMBING_RE.test(c) || READ_ONLY_RE.test(c))
17997
- );
17998
- if (!allSafe) return true;
17999
- }
18000
- return false;
18001
- }
18002
- function scopeToAuthored(files, actionSummary) {
18003
- if (!actionSummary) return { files, signal: "no-transcript" };
18004
- const touched = [...actionSummary.files_edited ?? [], ...actionSummary.files_created ?? []];
18005
- if (touched.length === 0) return { files: [], signal: "none-authored" };
18006
- return { files: narrowToAgentAuthored(files, actionSummary), signal: "authored" };
18007
- }
18008
- function narrowToAgentAuthored(files, actionSummary) {
18009
- if (!actionSummary) return files;
18010
- const touched = [
18011
- ...actionSummary.files_edited,
18012
- ...actionSummary.files_created
18013
- ];
18014
- if (touched.length === 0) return files;
18015
- return files.filter((f) => {
18016
- const suffix = "/" + f;
18017
- return touched.some((t) => t === f || t.endsWith(suffix));
18018
- });
18019
- }
18020
-
18021
18349
  // src/commands/analyze/phases/05-mode.ts
18022
18350
  async function mode(run) {
18023
18351
  const { opts, globals } = run;
@@ -18092,7 +18420,7 @@ async function mode(run) {
18092
18420
  }
18093
18421
 
18094
18422
  // src/lib/debounce.ts
18095
- var import_node_fs23 = require("node:fs");
18423
+ var import_node_fs24 = require("node:fs");
18096
18424
  var import_node_crypto10 = require("node:crypto");
18097
18425
  function scopedFile(base, sessionId) {
18098
18426
  if (!sessionId) return base;
@@ -18100,9 +18428,9 @@ function scopedFile(base, sessionId) {
18100
18428
  }
18101
18429
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18102
18430
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18103
- if (!(0, import_node_fs23.existsSync)(file)) return null;
18431
+ if (!(0, import_node_fs24.existsSync)(file)) return null;
18104
18432
  try {
18105
- const lastTs = parseInt((0, import_node_fs23.readFileSync)(file, "utf-8").trim(), 10);
18433
+ const lastTs = parseInt((0, import_node_fs24.readFileSync)(file, "utf-8").trim(), 10);
18106
18434
  const nowTs = Math.floor(Date.now() / 1e3);
18107
18435
  const elapsed = nowTs - lastTs;
18108
18436
  if (elapsed < debounceSeconds) {
@@ -18115,10 +18443,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
18115
18443
  function checkMtime(files, bypassForRecentCommits, sessionId) {
18116
18444
  if (bypassForRecentCommits) return null;
18117
18445
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18118
- if (!(0, import_node_fs23.existsSync)(file)) return null;
18446
+ if (!(0, import_node_fs24.existsSync)(file)) return null;
18119
18447
  let debounceTime;
18120
18448
  try {
18121
- debounceTime = (0, import_node_fs23.statSync)(file).mtimeMs;
18449
+ debounceTime = (0, import_node_fs24.statSync)(file).mtimeMs;
18122
18450
  } catch {
18123
18451
  return null;
18124
18452
  }
@@ -18126,7 +18454,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
18126
18454
  const resolved = resolveFile(f);
18127
18455
  if (!resolved) continue;
18128
18456
  try {
18129
- const stat3 = (0, import_node_fs23.statSync)(resolved);
18457
+ const stat3 = (0, import_node_fs24.statSync)(resolved);
18130
18458
  if (stat3.mtimeMs > debounceTime) {
18131
18459
  return null;
18132
18460
  }
@@ -18142,8 +18470,8 @@ function computeContentHash(files) {
18142
18470
  for (const f of sorted) {
18143
18471
  const resolved = resolveFile(f) ?? f;
18144
18472
  try {
18145
- if ((0, import_node_fs23.existsSync)(resolved)) {
18146
- hash.update((0, import_node_fs23.readFileSync)(resolved));
18473
+ if ((0, import_node_fs24.existsSync)(resolved)) {
18474
+ hash.update((0, import_node_fs24.readFileSync)(resolved));
18147
18475
  }
18148
18476
  } catch {
18149
18477
  }
@@ -18153,9 +18481,9 @@ function computeContentHash(files) {
18153
18481
  function checkContentHash(files, sessionId) {
18154
18482
  const hash = computeContentHash(files);
18155
18483
  const file = scopedFile(HASH_FILE, sessionId);
18156
- if ((0, import_node_fs23.existsSync)(file)) {
18484
+ if ((0, import_node_fs24.existsSync)(file)) {
18157
18485
  try {
18158
- const storedHash = (0, import_node_fs23.readFileSync)(file, "utf-8").trim();
18486
+ const storedHash = (0, import_node_fs24.readFileSync)(file, "utf-8").trim();
18159
18487
  if (hash === storedHash) {
18160
18488
  return { skip: "No source changes since last analysis", hash };
18161
18489
  }
@@ -18165,24 +18493,24 @@ function checkContentHash(files, sessionId) {
18165
18493
  return { skip: null, hash };
18166
18494
  }
18167
18495
  function recordAnalysisStart(sessionId) {
18168
- (0, import_node_fs23.mkdirSync)(VERITY_DIR, { recursive: true });
18169
- (0, import_node_fs23.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18496
+ (0, import_node_fs24.mkdirSync)(VERITY_DIR, { recursive: true });
18497
+ (0, import_node_fs24.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
18170
18498
  }
18171
18499
  function recordPassHash(hash, sessionId) {
18172
- (0, import_node_fs23.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18500
+ (0, import_node_fs24.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
18173
18501
  }
18174
18502
  function narrowToRecent(files, sessionId) {
18175
18503
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
18176
- if (!(0, import_node_fs23.existsSync)(file)) return files;
18504
+ if (!(0, import_node_fs24.existsSync)(file)) return files;
18177
18505
  let debounceTime;
18178
18506
  try {
18179
- debounceTime = (0, import_node_fs23.statSync)(file).mtimeMs;
18507
+ debounceTime = (0, import_node_fs24.statSync)(file).mtimeMs;
18180
18508
  } catch {
18181
18509
  return files;
18182
18510
  }
18183
18511
  const recent = files.filter((f) => {
18184
18512
  try {
18185
- return (0, import_node_fs23.existsSync)(f) && (0, import_node_fs23.statSync)(f).mtimeMs > debounceTime;
18513
+ return (0, import_node_fs24.existsSync)(f) && (0, import_node_fs24.statSync)(f).mtimeMs > debounceTime;
18186
18514
  } catch {
18187
18515
  return false;
18188
18516
  }
@@ -18195,9 +18523,9 @@ function readIteration(currentCommit, _contentHash) {
18195
18523
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
18196
18524
  function readBlockState(currentCommit, opts) {
18197
18525
  if (opts?.newUserPrompt) return NO_BLOCKS;
18198
- if (!(0, import_node_fs23.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18526
+ if (!(0, import_node_fs24.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
18199
18527
  try {
18200
- const stored = (0, import_node_fs23.readFileSync)(ITERATION_FILE, "utf-8").trim();
18528
+ const stored = (0, import_node_fs24.readFileSync)(ITERATION_FILE, "utf-8").trim();
18201
18529
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
18202
18530
  if (!parsed) return NO_BLOCKS;
18203
18531
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -18243,8 +18571,8 @@ function isSameProblem(previous, current) {
18243
18571
  return current.split(",").some((k) => prev.has(k));
18244
18572
  }
18245
18573
  function writeBlockState(commit, state) {
18246
- (0, import_node_fs23.mkdirSync)(VERITY_DIR, { recursive: true });
18247
- (0, import_node_fs23.writeFileSync)(
18574
+ (0, import_node_fs24.mkdirSync)(VERITY_DIR, { recursive: true });
18575
+ (0, import_node_fs24.writeFileSync)(
18248
18576
  ITERATION_FILE,
18249
18577
  JSON.stringify({
18250
18578
  v: 2,
@@ -18261,8 +18589,8 @@ function resetBlockState(commit) {
18261
18589
  }
18262
18590
 
18263
18591
  // src/lib/fold.ts
18264
- var import_node_fs24 = require("node:fs");
18265
- var import_node_path19 = require("node:path");
18592
+ var import_node_fs25 = require("node:fs");
18593
+ var import_node_path21 = require("node:path");
18266
18594
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
18267
18595
  "user",
18268
18596
  "assistant",
@@ -18300,7 +18628,7 @@ var COMMAND_CLASSES = [
18300
18628
  [/\btsc\b|\bmypy\b|\btypecheck\b/, "typecheck"],
18301
18629
  [/^git\s/, "git"]
18302
18630
  ];
18303
- function classifyCommand(cmd) {
18631
+ function classifyCommand2(cmd) {
18304
18632
  for (const [re, cls] of COMMAND_CLASSES) if (re.test(cmd)) return cls;
18305
18633
  return "other";
18306
18634
  }
@@ -18399,7 +18727,7 @@ function candidateRoots(repoRoot2) {
18399
18727
  const norm = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
18400
18728
  const out = [norm];
18401
18729
  try {
18402
- const real = import_node_fs24.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
18730
+ const real = import_node_fs25.realpathSync.native(norm).replace(/\\/g, "/").replace(/\/+$/, "");
18403
18731
  if (real !== norm) out.push(real);
18404
18732
  } catch {
18405
18733
  }
@@ -18487,31 +18815,31 @@ function fold(transcriptPath, opts = {}) {
18487
18815
  }
18488
18816
  };
18489
18817
  try {
18490
- if (!(0, import_node_fs24.existsSync)(transcriptPath)) return result;
18491
- ingest((0, import_node_fs24.readFileSync)(transcriptPath, "utf8"), "agent");
18818
+ if (!(0, import_node_fs25.existsSync)(transcriptPath)) return result;
18819
+ ingest((0, import_node_fs25.readFileSync)(transcriptPath, "utf8"), "agent");
18492
18820
  result.coverage.complete = true;
18493
18821
  } catch {
18494
18822
  return result;
18495
18823
  }
18496
18824
  try {
18497
- const sidecarDir = (0, import_node_path19.join)(
18498
- (0, import_node_path19.dirname)(transcriptPath),
18499
- (0, import_node_path19.basename)(transcriptPath).replace(/\.jsonl$/, ""),
18825
+ const sidecarDir = (0, import_node_path21.join)(
18826
+ (0, import_node_path21.dirname)(transcriptPath),
18827
+ (0, import_node_path21.basename)(transcriptPath).replace(/\.jsonl$/, ""),
18500
18828
  "subagents"
18501
18829
  );
18502
- if ((0, import_node_fs24.existsSync)(sidecarDir)) {
18830
+ if ((0, import_node_fs25.existsSync)(sidecarDir)) {
18503
18831
  const maxFiles = opts.maxSidecars ?? 200;
18504
18832
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
18505
18833
  const found = [];
18506
18834
  const walk = (d, depth) => {
18507
18835
  if (depth > 4) return;
18508
- for (const e of (0, import_node_fs24.readdirSync)(d, { withFileTypes: true })) {
18509
- const p = (0, import_node_path19.join)(d, e.name);
18836
+ for (const e of (0, import_node_fs25.readdirSync)(d, { withFileTypes: true })) {
18837
+ const p = (0, import_node_path21.join)(d, e.name);
18510
18838
  if (e.isDirectory()) {
18511
18839
  walk(p, depth + 1);
18512
18840
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
18513
18841
  try {
18514
- const st = (0, import_node_fs24.statSync)(p);
18842
+ const st = (0, import_node_fs25.statSync)(p);
18515
18843
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
18516
18844
  } catch {
18517
18845
  result.coverage.malformed++;
@@ -18528,7 +18856,7 @@ function fold(transcriptPath, opts = {}) {
18528
18856
  continue;
18529
18857
  }
18530
18858
  try {
18531
- ingest((0, import_node_fs24.readFileSync)(f.path, "utf8"), "subagent");
18859
+ ingest((0, import_node_fs25.readFileSync)(f.path, "utf8"), "subagent");
18532
18860
  bytes += f.size;
18533
18861
  result.coverage.subagentFiles++;
18534
18862
  } catch {
@@ -18563,7 +18891,7 @@ function fold(transcriptPath, opts = {}) {
18563
18891
  }
18564
18892
  function classifyUnobserved(path) {
18565
18893
  try {
18566
- const st = (0, import_node_fs24.statSync)(path);
18894
+ const st = (0, import_node_fs25.statSync)(path);
18567
18895
  if (!st.isFile()) return "unreadable";
18568
18896
  } catch {
18569
18897
  return "unreadable";
@@ -18629,7 +18957,7 @@ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse
18629
18957
  if (name === "Bash") {
18630
18958
  const cmd = typeof input.command === "string" ? input.command : "";
18631
18959
  if (cmd) {
18632
- const cls = classifyCommand(cmd);
18960
+ const cls = classifyCommand2(cmd);
18633
18961
  const prev = commandStats.get(cls) ?? { last_status: null, runs: 0, head: "" };
18634
18962
  commandStats.set(cls, {
18635
18963
  // UNKNOWN until this command's OWN result arrives. Inheriting the
@@ -18867,20 +19195,20 @@ async function evidence(run) {
18867
19195
  }
18868
19196
 
18869
19197
  // src/lib/cache-cleanup.ts
18870
- var import_node_fs25 = require("node:fs");
18871
- var import_node_path20 = require("node:path");
19198
+ var import_node_fs26 = require("node:fs");
19199
+ var import_node_path22 = require("node:path");
18872
19200
  var CACHE_TTL_DAYS = 7;
18873
19201
  function pruneStaleCache() {
18874
19202
  try {
18875
19203
  const dir = projectPath(CACHE_DIR);
18876
19204
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
18877
- for (const entry of (0, import_node_fs25.readdirSync)(dir)) {
19205
+ for (const entry of (0, import_node_fs26.readdirSync)(dir)) {
18878
19206
  if (!entry.startsWith("pending-")) continue;
18879
- const path = (0, import_node_path20.join)(dir, entry);
19207
+ const path = (0, import_node_path22.join)(dir, entry);
18880
19208
  try {
18881
- const stat3 = (0, import_node_fs25.statSync)(path);
19209
+ const stat3 = (0, import_node_fs26.statSync)(path);
18882
19210
  if (stat3.mtimeMs < cutoff) {
18883
- (0, import_node_fs25.unlinkSync)(path);
19211
+ (0, import_node_fs26.unlinkSync)(path);
18884
19212
  logEvent("cache_entry_pruned", {
18885
19213
  path: entry,
18886
19214
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -18894,7 +19222,7 @@ function pruneStaleCache() {
18894
19222
  }
18895
19223
 
18896
19224
  // src/lib/context-files.ts
18897
- var import_node_fs26 = require("node:fs");
19225
+ var import_node_fs27 = require("node:fs");
18898
19226
  var MAX_CONTEXT_FILES = 10;
18899
19227
  var MAX_CONTEXT_FILE_BYTES = 10240;
18900
19228
  var MAX_CONTEXT_TOTAL_BYTES = 51200;
@@ -18915,7 +19243,7 @@ function gatherContextFiles(contextPaths, deltaFiles) {
18915
19243
  continue;
18916
19244
  }
18917
19245
  try {
18918
- const content = (0, import_node_fs26.readFileSync)(safePath, "utf8");
19246
+ const content = (0, import_node_fs27.readFileSync)(safePath, "utf8");
18919
19247
  const bytes = Buffer.byteLength(content);
18920
19248
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
18921
19249
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -18977,8 +19305,8 @@ async function contextFiles(run) {
18977
19305
 
18978
19306
  // src/lib/seed-runner.ts
18979
19307
  var import_promises11 = require("node:fs/promises");
18980
- var import_node_fs27 = require("node:fs");
18981
- var import_node_path21 = require("node:path");
19308
+ var import_node_fs28 = require("node:fs");
19309
+ var import_node_path23 = require("node:path");
18982
19310
  var import_yaml2 = __toESM(require_dist());
18983
19311
 
18984
19312
  // src/lib/seed.ts
@@ -19217,7 +19545,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
19217
19545
  return fm;
19218
19546
  }
19219
19547
  async function runSeed(opts) {
19220
- if (!(0, import_node_fs27.existsSync)(STANDARD_FILE)) {
19548
+ if (!(0, import_node_fs28.existsSync)(STANDARD_FILE)) {
19221
19549
  return { created: 0, failed: 0, skipped: "no_standard", candidates: [] };
19222
19550
  }
19223
19551
  let standardDoc;
@@ -19229,7 +19557,7 @@ async function runSeed(opts) {
19229
19557
  }
19230
19558
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
19231
19559
  let readmeContent;
19232
- if ((0, import_node_fs27.existsSync)("README.md")) {
19560
+ if ((0, import_node_fs28.existsSync)("README.md")) {
19233
19561
  try {
19234
19562
  readmeContent = await (0, import_promises11.readFile)("README.md", "utf-8");
19235
19563
  } catch {
@@ -19237,7 +19565,7 @@ async function runSeed(opts) {
19237
19565
  }
19238
19566
  let claudeMdContent;
19239
19567
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
19240
- if ((0, import_node_fs27.existsSync)(p)) {
19568
+ if ((0, import_node_fs28.existsSync)(p)) {
19241
19569
  try {
19242
19570
  claudeMdContent = await (0, import_promises11.readFile)(p, "utf-8");
19243
19571
  break;
@@ -19260,8 +19588,8 @@ async function runSeed(opts) {
19260
19588
  if (candidates.length === 0) {
19261
19589
  return { created: 0, failed: 0, skipped: "no_candidates", candidates: [] };
19262
19590
  }
19263
- const overviewPath = (0, import_node_path21.join)(MEMORY_DIR, "domain", "project-overview.md");
19264
- if ((0, import_node_fs27.existsSync)(overviewPath) && !opts.force) {
19591
+ const overviewPath = (0, import_node_path23.join)(MEMORY_DIR, "domain", "project-overview.md");
19592
+ if ((0, import_node_fs28.existsSync)(overviewPath) && !opts.force) {
19265
19593
  return { created: 0, failed: 0, skipped: "already_seeded", candidates };
19266
19594
  }
19267
19595
  if (opts.dryRun) {
@@ -19303,7 +19631,7 @@ async function runSeed(opts) {
19303
19631
  continue;
19304
19632
  }
19305
19633
  try {
19306
- await (0, import_promises11.mkdir)((0, import_node_path21.dirname)(targetPath), { recursive: true });
19634
+ await (0, import_promises11.mkdir)((0, import_node_path23.dirname)(targetPath), { recursive: true });
19307
19635
  await (0, import_promises11.writeFile)(targetPath, renderNodeMarkdown(c, nodeId, createdAt));
19308
19636
  created++;
19309
19637
  opts.onCreated?.(nodeId, filePathRel, c);
@@ -19316,8 +19644,8 @@ async function runSeed(opts) {
19316
19644
  }
19317
19645
 
19318
19646
  // src/commands/analyze/phases/08-memory-manifest.ts
19319
- var import_node_fs28 = require("node:fs");
19320
- var import_node_path22 = require("node:path");
19647
+ var import_node_fs29 = require("node:fs");
19648
+ var import_node_path24 = require("node:path");
19321
19649
  async function memoryManifest(run) {
19322
19650
  const { globals } = run;
19323
19651
  const { serviceUrl, token } = run;
@@ -19327,9 +19655,9 @@ async function memoryManifest(run) {
19327
19655
  let autoSeedNotice = null;
19328
19656
  try {
19329
19657
  await ensureMemoryDir();
19330
- const seedMarker = (0, import_node_path22.join)(VERITY_DIR, ".seeded");
19331
- const hasStandard = (0, import_node_fs28.existsSync)(STANDARD_FILE);
19332
- const alreadyTried = (0, import_node_fs28.existsSync)(seedMarker);
19658
+ const seedMarker = (0, import_node_path24.join)(VERITY_DIR, ".seeded");
19659
+ const hasStandard = (0, import_node_fs29.existsSync)(STANDARD_FILE);
19660
+ const alreadyTried = (0, import_node_fs29.existsSync)(seedMarker);
19333
19661
  if (hasStandard && !alreadyTried) {
19334
19662
  const preManifest = await buildManifest();
19335
19663
  if (preManifest.nodes.length === 0) {
@@ -19342,7 +19670,7 @@ async function memoryManifest(run) {
19342
19670
  dryRun: false
19343
19671
  });
19344
19672
  if (seedResult.created > 0) {
19345
- (0, import_node_fs28.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
19673
+ (0, import_node_fs29.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created}
19346
19674
  `);
19347
19675
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
19348
19676
  logEvent("auto_seed_ran", {
@@ -19350,7 +19678,7 @@ async function memoryManifest(run) {
19350
19678
  failed: seedResult.failed
19351
19679
  });
19352
19680
  } else if (seedResult.skipped === "already_seeded") {
19353
- (0, import_node_fs28.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
19681
+ (0, import_node_fs29.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
19354
19682
  `);
19355
19683
  } else {
19356
19684
  logEvent("auto_seed_noop", {
@@ -19445,7 +19773,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
19445
19773
  }
19446
19774
 
19447
19775
  // src/commands/analyze/phases/10-working-memory.ts
19448
- var import_node_path23 = require("node:path");
19776
+ var import_node_path25 = require("node:path");
19449
19777
  async function workingMemory(run) {
19450
19778
  const { opts } = run;
19451
19779
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run;
@@ -19457,7 +19785,7 @@ async function workingMemory(run) {
19457
19785
  const priorState = foldForMarks(memorySession.d);
19458
19786
  incrementReport = computeIncrement(
19459
19787
  allForReview,
19460
- (p) => fileHash((0, import_node_path23.join)(repoRoot(), p)),
19788
+ (p) => fileHash((0, import_node_path25.join)(repoRoot(), p)),
19461
19789
  priorState.authored_all.map((a) => ({
19462
19790
  path: a.path,
19463
19791
  hash_at_last_verdict: a.hash_at_last_verdict
@@ -19539,7 +19867,7 @@ async function workingMemory(run) {
19539
19867
  }
19540
19868
 
19541
19869
  // src/lib/note-budget.ts
19542
- var import_node_fs29 = require("node:fs");
19870
+ var import_node_fs30 = require("node:fs");
19543
19871
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
19544
19872
  var EPISODE_STALE_SECONDS = 30 * 60;
19545
19873
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -19561,9 +19889,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
19561
19889
  }
19562
19890
  function readAdvisoryEpisode(sessionId) {
19563
19891
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
19564
- if (!(0, import_node_fs29.existsSync)(file)) return null;
19892
+ if (!(0, import_node_fs30.existsSync)(file)) return null;
19565
19893
  try {
19566
- const o = JSON.parse((0, import_node_fs29.readFileSync)(file, "utf-8")) ?? {};
19894
+ const o = JSON.parse((0, import_node_fs30.readFileSync)(file, "utf-8")) ?? {};
19567
19895
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
19568
19896
  if (isNaN(delivered)) return null;
19569
19897
  return {
@@ -19577,8 +19905,8 @@ function readAdvisoryEpisode(sessionId) {
19577
19905
  }
19578
19906
  function writeAdvisoryEpisode(episode, sessionId) {
19579
19907
  try {
19580
- (0, import_node_fs29.mkdirSync)(VERITY_DIR, { recursive: true });
19581
- (0, import_node_fs29.writeFileSync)(
19908
+ (0, import_node_fs30.mkdirSync)(VERITY_DIR, { recursive: true });
19909
+ (0, import_node_fs30.writeFileSync)(
19582
19910
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
19583
19911
  JSON.stringify({ v: 1, ...episode })
19584
19912
  );
@@ -19608,7 +19936,7 @@ function isExplicitlyAutonomous(env = process.env) {
19608
19936
  }
19609
19937
 
19610
19938
  // src/lib/task-context.ts
19611
- var import_node_child_process8 = require("node:child_process");
19939
+ var import_node_child_process9 = require("node:child_process");
19612
19940
  var CLOSING_RE = /\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\b[\s:]*#(\d+)/i;
19613
19941
  var BRANCH_RE = /(?:^|[/_-])(?:issue|gh|fix)[-_/]?(\d+)\b/i;
19614
19942
  function parseLinkedIssue(sources) {
@@ -19624,7 +19952,7 @@ function parseLinkedIssue(sources) {
19624
19952
  }
19625
19953
  function safeExec(cmd, timeout) {
19626
19954
  try {
19627
- return (0, import_node_child_process8.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
19955
+ return (0, import_node_child_process9.execSync)(cmd, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout }).trim();
19628
19956
  } catch {
19629
19957
  return "";
19630
19958
  }
@@ -19870,7 +20198,10 @@ async function buildRequest(run) {
19870
20198
  }
19871
20199
  if (specs.length > 0) intentContext.specs = specs;
19872
20200
  if (plans.length > 0) intentContext.plans = plans;
19873
- if (actionSummary) intentContext.action_summary = actionSummary;
20201
+ if (actionSummary) {
20202
+ const { user_commands: _uc, user_commands_truncated: _uct, ...onTheWire } = actionSummary;
20203
+ intentContext.action_summary = onTheWire;
20204
+ }
19874
20205
  for (const key of Object.keys(intentContext)) {
19875
20206
  if (intentContext[key] == null) delete intentContext[key];
19876
20207
  }
@@ -19880,14 +20211,14 @@ async function buildRequest(run) {
19880
20211
  }
19881
20212
 
19882
20213
  // src/lib/offline.ts
19883
- var import_node_fs30 = require("node:fs");
20214
+ var import_node_fs31 = require("node:fs");
19884
20215
  var import_node_crypto11 = require("node:crypto");
19885
20216
  function cacheRequest(body) {
19886
20217
  try {
19887
- (0, import_node_fs30.mkdirSync)(CACHE_DIR, { recursive: true });
20218
+ (0, import_node_fs31.mkdirSync)(CACHE_DIR, { recursive: true });
19888
20219
  const suffix = (0, import_node_crypto11.randomBytes)(4).toString("hex");
19889
20220
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
19890
- (0, import_node_fs30.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
20221
+ (0, import_node_fs31.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body)));
19891
20222
  } catch {
19892
20223
  }
19893
20224
  }
@@ -20006,8 +20337,8 @@ async function transmit(run) {
20006
20337
  }
20007
20338
 
20008
20339
  // src/commands/analyze/phases/13-reconcile.ts
20009
- var import_node_fs31 = require("node:fs");
20010
- var import_node_path24 = require("node:path");
20340
+ var import_node_fs32 = require("node:fs");
20341
+ var import_node_path26 = require("node:path");
20011
20342
  async function reconcile(run) {
20012
20343
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory, memorySession, response, reviewable, securityFiles, turnId } = run;
20013
20344
  const sentPaths = codeDelta.files.map((f) => f.path);
@@ -20017,7 +20348,7 @@ async function reconcile(run) {
20017
20348
  const st = foldDossier(memorySession.d);
20018
20349
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line) => {
20019
20350
  try {
20020
- const src = (0, import_node_fs31.readFileSync)((0, import_node_path24.join)(repoRoot(), file), "utf8").split("\n");
20351
+ const src = (0, import_node_fs32.readFileSync)((0, import_node_path26.join)(repoRoot(), file), "utf8").split("\n");
20021
20352
  const at = src[line - 1];
20022
20353
  return at === void 0 ? null : lineSha(at);
20023
20354
  } catch {
@@ -20672,7 +21003,7 @@ async function runAnalyze(opts, globals) {
20672
21003
  }
20673
21004
 
20674
21005
  // src/commands/baseline.ts
20675
- var import_node_fs32 = require("node:fs");
21006
+ var import_node_fs33 = require("node:fs");
20676
21007
  function registerBaselineCommands(program2) {
20677
21008
  const baseline = program2.command("baseline").description("Manage the task-start working-tree baseline");
20678
21009
  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) => {
@@ -20681,7 +21012,7 @@ function registerBaselineCommands(program2) {
20681
21012
  process.chdir(repoRoot());
20682
21013
  } catch {
20683
21014
  }
20684
- if (!(0, import_node_fs32.existsSync)(VERITY_DIR)) {
21015
+ if (!(0, import_node_fs33.existsSync)(VERITY_DIR)) {
20685
21016
  process.exit(0);
20686
21017
  }
20687
21018
  let sessionId = opts.sessionId;
@@ -20721,7 +21052,7 @@ async function readStdin() {
20721
21052
  }
20722
21053
 
20723
21054
  // src/commands/review.ts
20724
- var import_node_fs33 = require("node:fs");
21055
+ var import_node_fs34 = require("node:fs");
20725
21056
  function registerReviewCommand(program2) {
20726
21057
  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) => {
20727
21058
  const globals = program2.opts();
@@ -20740,7 +21071,7 @@ async function runReview(opts, globals) {
20740
21071
  const securityFiles = filterSecurity(allFiles);
20741
21072
  let staticResults;
20742
21073
  if (isCodacyAvailable()) {
20743
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs33.existsSync)(f) || resolveFile(f) !== null);
21074
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs34.existsSync)(f) || resolveFile(f) !== null);
20744
21075
  staticResults = runCodacyAnalysis(scannable);
20745
21076
  } else {
20746
21077
  staticResults = {
@@ -20766,10 +21097,10 @@ async function runReview(opts, globals) {
20766
21097
  const specPaths = opts.specs.split(",").map((f) => f.trim()).filter(Boolean);
20767
21098
  specs = [];
20768
21099
  for (const p of specPaths) {
20769
- if (!(0, import_node_fs33.existsSync)(p)) continue;
21100
+ if (!(0, import_node_fs34.existsSync)(p)) continue;
20770
21101
  try {
20771
- const { readFileSync: readFileSync19 } = await import("node:fs");
20772
- const content = readFileSync19(p, "utf-8");
21102
+ const { readFileSync: readFileSync20 } = await import("node:fs");
21103
+ const content = readFileSync20(p, "utf-8");
20773
21104
  specs.push({ path: p, content: content.slice(0, 10240) });
20774
21105
  } catch {
20775
21106
  }
@@ -20826,15 +21157,15 @@ async function runReview(opts, globals) {
20826
21157
  }
20827
21158
 
20828
21159
  // src/commands/guard.ts
20829
- var import_node_fs34 = require("node:fs");
20830
- var import_node_path25 = require("node:path");
21160
+ var import_node_fs35 = require("node:fs");
21161
+ var import_node_path27 = require("node:path");
20831
21162
  var GUARD_BLOCK_CAP = 2;
20832
- var GUARD_ITER_FILE = (0, import_node_path25.join)(VERITY_DIR, ".guard-iteration");
21163
+ var GUARD_ITER_FILE = (0, import_node_path27.join)(VERITY_DIR, ".guard-iteration");
20833
21164
  function readPreToolUseStdin() {
20834
21165
  const empty = { command: "", cwd: null, sessionId: null };
20835
- return new Promise((resolve3) => {
21166
+ return new Promise((resolve4) => {
20836
21167
  try {
20837
- if (process.stdin.isTTY) return resolve3(empty);
21168
+ if (process.stdin.isTTY) return resolve4(empty);
20838
21169
  const chunks = [];
20839
21170
  let timer;
20840
21171
  let settled = false;
@@ -20847,7 +21178,7 @@ function readPreToolUseStdin() {
20847
21178
  process.stdin.removeListener("end", onEnd);
20848
21179
  process.stdin.removeListener("error", onError);
20849
21180
  process.stdin.pause();
20850
- resolve3(value);
21181
+ resolve4(value);
20851
21182
  };
20852
21183
  const onEnd = () => {
20853
21184
  try {
@@ -20868,32 +21199,13 @@ function readPreToolUseStdin() {
20868
21199
  process.stdin.on("error", onError);
20869
21200
  process.stdin.resume();
20870
21201
  } catch {
20871
- resolve3(empty);
21202
+ resolve4(empty);
20872
21203
  }
20873
21204
  });
20874
21205
  }
20875
- function buildCommandRe(head) {
20876
- return new RegExp(`(?:^|[\\s;&|(])${head}|(?:^|[;&|(])\\s*[^\\s;&|()'"]*\\/${head}`);
20877
- }
20878
- var GIT_GLOBAL_OPTS = "(?:\\s+(?:-[Cc]\\s+\\S+|--?[\\w-]+(?:=\\S+)?))*";
20879
- var COMMIT_RE = buildCommandRe(`git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`);
20880
- var PUSH_RE = buildCommandRe(`git${GIT_GLOBAL_OPTS}\\s+push\\b`);
20881
- var GH_PR_RE = buildCommandRe(`gh${GIT_GLOBAL_OPTS}\\s+pr\\s+create\\b`);
20882
- function classifyCommand2(command, on) {
20883
- let commit = false;
20884
- let push = false;
20885
- for (const seg of (command ?? "").split(/&&|\|\||;|\n/)) {
20886
- if (/--dry-run\b/.test(seg)) continue;
20887
- if (COMMIT_RE.test(seg)) commit = true;
20888
- if (PUSH_RE.test(seg) || GH_PR_RE.test(seg)) push = true;
20889
- }
20890
- if (commit && on.includes("commit")) return "pre-commit";
20891
- if (push && on.includes("push")) return "pre-push";
20892
- return null;
20893
- }
20894
21206
  function readIterMap() {
20895
21207
  try {
20896
- const raw = JSON.parse((0, import_node_fs34.readFileSync)(GUARD_ITER_FILE, "utf-8"));
21208
+ const raw = JSON.parse((0, import_node_fs35.readFileSync)(GUARD_ITER_FILE, "utf-8"));
20897
21209
  if (raw && typeof raw === "object") {
20898
21210
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
20899
21211
  return { [raw.moment]: raw.count };
@@ -20913,10 +21225,10 @@ function readIter(moment) {
20913
21225
  }
20914
21226
  function writeIter(moment, count) {
20915
21227
  try {
20916
- (0, import_node_fs34.mkdirSync)(VERITY_DIR, { recursive: true });
21228
+ (0, import_node_fs35.mkdirSync)(VERITY_DIR, { recursive: true });
20917
21229
  const map = readIterMap();
20918
21230
  map[moment] = count;
20919
- (0, import_node_fs34.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
21231
+ (0, import_node_fs35.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
20920
21232
  } catch {
20921
21233
  }
20922
21234
  }
@@ -20926,10 +21238,10 @@ function resetIter(moment) {
20926
21238
  if (!(moment in map)) return;
20927
21239
  delete map[moment];
20928
21240
  if (Object.keys(map).length === 0) {
20929
- if ((0, import_node_fs34.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs34.unlinkSync)(GUARD_ITER_FILE);
21241
+ if ((0, import_node_fs35.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs35.unlinkSync)(GUARD_ITER_FILE);
20930
21242
  } else {
20931
- (0, import_node_fs34.mkdirSync)(VERITY_DIR, { recursive: true });
20932
- (0, import_node_fs34.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
21243
+ (0, import_node_fs35.mkdirSync)(VERITY_DIR, { recursive: true });
21244
+ (0, import_node_fs35.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
20933
21245
  }
20934
21246
  } catch {
20935
21247
  }
@@ -20944,8 +21256,14 @@ function registerGuardCommand(program2) {
20944
21256
  }
20945
21257
  });
20946
21258
  }
20947
- function getMomentFiles(moment) {
20948
- return moment === "pre-commit" ? getStagedFiles() : getPushRangeFiles().files;
21259
+ function resolveMomentRange(moment, frame, command, on) {
21260
+ return moment === "pre-commit" ? stagedRange() : resolvePushRange(frame, command, on);
21261
+ }
21262
+ function describeRange(range) {
21263
+ if (range.kind === "staged") return "staged";
21264
+ if (range.kind === "nothing" || !range.base) return null;
21265
+ const base = /^[0-9a-f]{40}$/.test(range.base) ? range.base.slice(0, 7) : range.base;
21266
+ return `${base}..${range.head} via ${range.via}`;
20949
21267
  }
20950
21268
  function matchFlagValue(command, flags) {
20951
21269
  const re = new RegExp(`(?<![\\w-])(?:${flags})(?:=|\\s+)('((?:[^'\\\\]|\\\\.)*)'|"((?:[^"\\\\]|\\\\.)*)"|([^\\s'"-][^\\s]*))`);
@@ -20980,26 +21298,24 @@ function isSubstantiveIntent(text) {
20980
21298
  if (SHELL_PLUMBING.test(t)) return false;
20981
21299
  return true;
20982
21300
  }
20983
- function extractStatedIntent(moment, command) {
20984
- const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? (getPushRangeMessages() || null);
21301
+ function extractStatedIntent(moment, command, pushedMessages = null) {
21302
+ const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
20985
21303
  return isSubstantiveIntent(text) ? text : null;
20986
21304
  }
20987
21305
  function hasBlockingFinding(response) {
20988
21306
  const findings = response.findings ?? [];
20989
21307
  return findings.some((f) => f.scope !== "pre-existing" && ["critical", "high"].includes((f.severity ?? "").toLowerCase()));
20990
21308
  }
20991
- function buildGuardRequest(moment, files, iter, sessionId, command) {
21309
+ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
20992
21310
  const analyzable = filterAnalyzable(files);
20993
21311
  const securityFiles = filterSecurity(files);
20994
21312
  let staticResults;
20995
21313
  if (isCodacyAvailable()) {
20996
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs34.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
21314
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs35.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
20997
21315
  staticResults = runCodacyAnalysis(scannable);
20998
21316
  } else {
20999
21317
  staticResults = { tool: "@codacy/analysis-cli", findings: [], summary: { total_findings: 0, by_severity: {}, tools_run: [] } };
21000
21318
  }
21001
- const codeDelta = collectCodeDelta(files);
21002
- if (codeDelta.total_files === 0) return null;
21003
21319
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
21004
21320
  const requestBody = {
21005
21321
  static_results: staticResults,
@@ -21016,9 +21332,9 @@ function buildGuardRequest(moment, files, iter, sessionId, command) {
21016
21332
  iteration: iter + 1
21017
21333
  }
21018
21334
  };
21335
+ if (coverageTelemetry) requestBody.coverage_telemetry = coverageTelemetry;
21019
21336
  const specs = discoverSpecs();
21020
21337
  const plans = discoverPlans();
21021
- const statedIntent = extractStatedIntent(moment, command);
21022
21338
  if (specs.length > 0 || plans.length > 0 || statedIntent) {
21023
21339
  const intentContext = {};
21024
21340
  if (statedIntent) intentContext.user_prompt = statedIntent;
@@ -21028,6 +21344,39 @@ function buildGuardRequest(moment, files, iter, sessionId, command) {
21028
21344
  }
21029
21345
  return requestBody;
21030
21346
  }
21347
+ function buildGuardCoverage(files, codeDelta, frame, frameRange) {
21348
+ const byReason = {};
21349
+ for (const e of codeDelta.excluded) byReason[e.reason] = (byReason[e.reason] ?? 0) + 1;
21350
+ return {
21351
+ changed_all: files.length,
21352
+ analyzable: filterAnalyzable(files).length,
21353
+ reviewable: filterReviewable(files).length,
21354
+ security: filterSecurity(files).length,
21355
+ for_review: files.length,
21356
+ sent: codeDelta.total_files,
21357
+ capped_out: codeDelta.truncated?.dropped ?? 0,
21358
+ excluded: codeDelta.excluded.length,
21359
+ excluded_by_reason: byReason,
21360
+ transcript_windowed: null,
21361
+ guard_frame: frameTelemetry(frame, frameRange)
21362
+ };
21363
+ }
21364
+ function coverageSummary(c) {
21365
+ const range = c.range ? ` @ ${c.range}` : "";
21366
+ return `reviewed ${c.sent.length} file(s)${range}`;
21367
+ }
21368
+ function coverageBlock(c) {
21369
+ const lines = [];
21370
+ const tree = c.root ? `${c.root}${c.linked ? " (linked worktree)" : ""}${c.branch ? ` \xB7 branch ${c.branch}` : ""}` : "(no tree resolved)";
21371
+ lines.push(`Reviewed (${c.moment}): ${c.sent.length} file(s)${c.range ? ` @ ${c.range}` : ""}`);
21372
+ lines.push(` Tree: ${tree}`);
21373
+ for (const f of c.sent) lines.push(` - ${f}`);
21374
+ if (c.excluded.length > 0) {
21375
+ lines.push(` Excluded (${c.excluded.length}):`);
21376
+ for (const e of c.excluded) lines.push(` - ${e.path} (${e.reason})`);
21377
+ }
21378
+ return lines.join("\n");
21379
+ }
21031
21380
  function emitAllowNotice(userMsg, agentMsg) {
21032
21381
  process.stdout.write(JSON.stringify({
21033
21382
  systemMessage: userMsg,
@@ -21038,15 +21387,24 @@ function emitAllowNotice(userMsg, agentMsg) {
21038
21387
  async function runGuard(opts, globals) {
21039
21388
  const on = opts.on.split(",").map((s) => s.trim()).filter((s) => s === "commit" || s === "push");
21040
21389
  const { command, cwd, sessionId } = await readPreToolUseStdin();
21041
- if (cwd && (0, import_node_fs34.existsSync)(cwd)) {
21042
- try {
21043
- process.chdir(cwd);
21044
- } catch {
21045
- }
21046
- }
21047
- const moment = classifyCommand2(command, on);
21390
+ const moment = classifyCommand(command, on);
21048
21391
  if (!moment) process.exit(0);
21049
21392
  const verb = moment === "pre-commit" ? "commit" : "push";
21393
+ const { frame } = resolveFrame({ command, on, hookCwd: cwd });
21394
+ if (frame.refusal || !frame.worktreeRoot) {
21395
+ logEvent("guard_frame", { moment, ...frameTelemetry(frame, null) });
21396
+ if ((frame.refusal ?? "").startsWith("anchor:")) process.exit(0);
21397
+ emitAllowNotice(
21398
+ `\u26A0 Verity ${moment}: could not resolve the tree this ${verb} targets \u2014 ${verb}ed WITHOUT review`,
21399
+ `Verity ${moment}: the target tree could not be resolved (${frame.refusal}); the ${verb} was allowed WITHOUT a Verity review.`
21400
+ );
21401
+ }
21402
+ try {
21403
+ process.chdir(frame.worktreeRoot);
21404
+ } catch {
21405
+ process.exit(0);
21406
+ }
21407
+ _resetRepoRoot();
21050
21408
  const iter = readIter(moment);
21051
21409
  if (iter >= GUARD_BLOCK_CAP) {
21052
21410
  resetIter(moment);
@@ -21055,13 +21413,39 @@ async function runGuard(opts, globals) {
21055
21413
  `Verity ${moment}: review-cycle cap (${GUARD_BLOCK_CAP}) reached; the ${verb} was allowed without a further block.`
21056
21414
  );
21057
21415
  }
21058
- const files = getMomentFiles(moment);
21416
+ const range = resolveMomentRange(moment, frame, command, on);
21417
+ const files = rangeFiles(frame, range);
21059
21418
  if (files.length === 0) process.exit(0);
21060
21419
  const tokenResult = await resolveToken(globals.token);
21061
21420
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
21062
21421
  if (!tokenResult.ok || !urlResult.ok) process.exit(0);
21063
- const requestBody = buildGuardRequest(moment, files, iter, sessionId, command);
21064
- if (!requestBody) process.exit(0);
21422
+ logEvent("guard_frame", { moment, ...frameTelemetry(frame, range) });
21423
+ const codeDelta = collectCodeDelta(files);
21424
+ if (codeDelta.total_files === 0) process.exit(0);
21425
+ const statedIntent = extractStatedIntent(
21426
+ moment,
21427
+ command,
21428
+ moment === "pre-push" ? rangeMessages(frame, range) || null : null
21429
+ );
21430
+ const requestBody = buildGuardRequest(
21431
+ moment,
21432
+ files,
21433
+ codeDelta,
21434
+ iter,
21435
+ sessionId,
21436
+ statedIntent,
21437
+ buildGuardCoverage(files, codeDelta, frame, range)
21438
+ );
21439
+ const coverage = {
21440
+ moment,
21441
+ root: frame.worktreeRoot,
21442
+ branch: frame.branch,
21443
+ linked: frame.isLinkedWorktree,
21444
+ range: describeRange(range),
21445
+ sent: codeDelta.files.map((f) => f.path),
21446
+ excluded: codeDelta.excluded.map((e) => ({ path: e.path, reason: e.reason }))
21447
+ };
21448
+ logToFileOnly(coverageBlock(coverage));
21065
21449
  const result = await analyzeRequest({
21066
21450
  serviceUrl: urlResult.data,
21067
21451
  token: tokenResult.data.token,
@@ -21082,31 +21466,39 @@ async function runGuard(opts, globals) {
21082
21466
  const decision = response.gate_decision ?? "(unrecognised)";
21083
21467
  const viewUrl = response.view_url ?? "";
21084
21468
  const link = viewUrl ? ` \u2014 ${viewUrl}` : "";
21469
+ const covLine = coverageSummary(coverage);
21470
+ const covDetail = coverageBlock(coverage);
21085
21471
  if (decision === "FAIL" && hasBlockingFinding(response)) {
21086
21472
  writeIter(moment, iter + 1);
21087
- writeBlockMessage(moment, response);
21473
+ writeBlockMessage(moment, response, covDetail);
21088
21474
  process.exit(2);
21089
21475
  }
21090
21476
  resetIter(moment);
21091
21477
  if (decision === "FAIL") {
21092
21478
  const narrative = response.assessment?.narrative ?? "";
21093
21479
  emitAllowNotice(
21094
- `\u26A0 Verity ${moment}: the ${verb} may not match its stated purpose \u2014 proceeding${link}`,
21095
- `Verity ${moment}: intent-alignment WARNING (not blocked).${narrative ? " " + narrative : ""}${viewUrl ? ` Report: ${viewUrl}` : ""}`
21480
+ `\u26A0 Verity ${moment}: the ${verb} may not match its stated purpose \u2014 proceeding (${covLine})${link}`,
21481
+ `Verity ${moment}: intent-alignment WARNING (not blocked).${narrative ? " " + narrative : ""}
21482
+ ${covDetail}${viewUrl ? `
21483
+ Report: ${viewUrl}` : ""}`
21096
21484
  );
21097
21485
  }
21098
21486
  if (decision === "WARN") {
21099
21487
  emitAllowNotice(
21100
- `\u26A0 Verity ${moment}: WARN \u2014 proceeding${link}`,
21101
- `Verity ${moment} review: WARN (proceeding).${viewUrl ? ` Report: ${viewUrl}` : ""}`
21488
+ `\u26A0 Verity ${moment}: WARN \u2014 proceeding (${covLine})${link}`,
21489
+ `Verity ${moment} review: WARN (proceeding).
21490
+ ${covDetail}${viewUrl ? `
21491
+ Report: ${viewUrl}` : ""}`
21102
21492
  );
21103
21493
  }
21104
21494
  emitAllowNotice(
21105
- `\u2713 Verity ${moment}: PASS${link}`,
21106
- `Verity ${moment} review: PASS.${viewUrl ? ` Report: ${viewUrl}` : ""}`
21495
+ `\u2713 Verity ${moment}: PASS (${covLine})${link}`,
21496
+ `Verity ${moment} review: PASS.
21497
+ ${covDetail}${viewUrl ? `
21498
+ Report: ${viewUrl}` : ""}`
21107
21499
  );
21108
21500
  }
21109
- function writeBlockMessage(moment, response) {
21501
+ function writeBlockMessage(moment, response, covDetail) {
21110
21502
  const label2 = moment === "pre-commit" ? "pre-commit" : "pre-push";
21111
21503
  const verb = moment === "pre-commit" ? "commit" : "push";
21112
21504
  const assessment = response.assessment;
@@ -21136,6 +21528,9 @@ function writeBlockMessage(moment, response) {
21136
21528
  `);
21137
21529
  }
21138
21530
  }
21531
+ process.stderr.write(`${DIM}${covDetail}${NC}
21532
+
21533
+ `);
21139
21534
  if (viewUrl) process.stderr.write(`${CYAN}Full report: ${viewUrl}${NC}
21140
21535
 
21141
21536
  `);
@@ -21144,16 +21539,16 @@ function writeBlockMessage(moment, response) {
21144
21539
  }
21145
21540
 
21146
21541
  // src/commands/init.ts
21147
- var import_node_fs36 = require("node:fs");
21542
+ var import_node_fs37 = require("node:fs");
21148
21543
  var import_promises13 = require("node:fs/promises");
21149
- var import_node_path27 = require("node:path");
21150
- var import_node_child_process10 = require("node:child_process");
21544
+ var import_node_path29 = require("node:path");
21545
+ var import_node_child_process11 = require("node:child_process");
21151
21546
  var readline2 = __toESM(require("node:readline/promises"));
21152
21547
 
21153
21548
  // src/commands/migrate.ts
21154
- var import_node_fs35 = require("node:fs");
21155
- var import_node_path26 = require("node:path");
21156
- var import_node_child_process9 = require("node:child_process");
21549
+ var import_node_fs36 = require("node:fs");
21550
+ var import_node_path28 = require("node:path");
21551
+ var import_node_child_process10 = require("node:child_process");
21157
21552
 
21158
21553
  // src/lib/telemetry.ts
21159
21554
  var import_promises12 = require("node:fs/promises");
@@ -21248,11 +21643,11 @@ async function uninstallTelemetry() {
21248
21643
  // src/commands/migrate.ts
21249
21644
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
21250
21645
  function defaultNpmRemover(pkg) {
21251
- (0, import_node_child_process9.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
21646
+ (0, import_node_child_process10.execSync)(`npm rm -g ${pkg}`, { stdio: "pipe", timeout: 12e4 });
21252
21647
  }
21253
21648
  function isGitTracked(cwd, relPath) {
21254
21649
  try {
21255
- (0, import_node_child_process9.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
21650
+ (0, import_node_child_process10.execSync)(`git ls-files --error-unmatch ${relPath}`, { cwd, stdio: "pipe" });
21256
21651
  return true;
21257
21652
  } catch {
21258
21653
  return false;
@@ -21260,7 +21655,7 @@ function isGitTracked(cwd, relPath) {
21260
21655
  }
21261
21656
  function isGitRepo(cwd) {
21262
21657
  try {
21263
- (0, import_node_child_process9.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
21658
+ (0, import_node_child_process10.execSync)("git rev-parse --is-inside-work-tree", { cwd, stdio: "pipe" });
21264
21659
  return true;
21265
21660
  } catch {
21266
21661
  return false;
@@ -21281,12 +21676,12 @@ async function runMigration(opts = {}) {
21281
21676
  return { actions, migrated: actions.length > 0 };
21282
21677
  }
21283
21678
  function migrateProjectDir(root, actions) {
21284
- const gateDir = (0, import_node_path26.join)(root, ".gate");
21285
- const verityDir = (0, import_node_path26.join)(root, ".verity");
21286
- if ((0, import_node_fs35.existsSync)(gateDir) && !(0, import_node_fs35.existsSync)(verityDir)) {
21679
+ const gateDir = (0, import_node_path28.join)(root, ".gate");
21680
+ const verityDir = (0, import_node_path28.join)(root, ".verity");
21681
+ if ((0, import_node_fs36.existsSync)(gateDir) && !(0, import_node_fs36.existsSync)(verityDir)) {
21287
21682
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
21288
21683
  }
21289
- if ((0, import_node_fs35.existsSync)(gateDir) && (0, import_node_fs35.existsSync)(verityDir)) {
21684
+ if ((0, import_node_fs36.existsSync)(gateDir) && (0, import_node_fs36.existsSync)(verityDir)) {
21290
21685
  return migrateProjectDirCarry(gateDir, verityDir, actions);
21291
21686
  }
21292
21687
  return false;
@@ -21300,20 +21695,20 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
21300
21695
  );
21301
21696
  }
21302
21697
  try {
21303
- (0, import_node_child_process9.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
21698
+ (0, import_node_child_process10.execSync)("git mv .gate .verity", { cwd: root, stdio: "pipe" });
21304
21699
  actions.push("Moved .gate/ \u2192 .verity/ (git mv, staged)");
21305
21700
  moved = true;
21306
21701
  } catch {
21307
21702
  }
21308
21703
  }
21309
21704
  if (moved) {
21310
- if ((0, import_node_fs35.existsSync)(gateDir)) {
21705
+ if ((0, import_node_fs36.existsSync)(gateDir)) {
21311
21706
  const carried = carryLegacyContents(gateDir, verityDir);
21312
21707
  if (carried > 0) {
21313
21708
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
21314
21709
  }
21315
21710
  try {
21316
- (0, import_node_fs35.rmSync)(gateDir, { recursive: true, force: true });
21711
+ (0, import_node_fs36.rmSync)(gateDir, { recursive: true, force: true });
21317
21712
  } catch {
21318
21713
  }
21319
21714
  }
@@ -21329,18 +21724,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
21329
21724
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
21330
21725
  }
21331
21726
  try {
21332
- (0, import_node_fs35.rmSync)(gateDir, { recursive: true, force: true });
21727
+ (0, import_node_fs36.rmSync)(gateDir, { recursive: true, force: true });
21333
21728
  } catch {
21334
21729
  }
21335
21730
  return carried > 0;
21336
21731
  }
21337
21732
  function migrateGlobalCredentials(home, actions) {
21338
21733
  if (!home) return;
21339
- const gateCreds = (0, import_node_path26.join)(home, ".gate", "credentials");
21340
- const verityCreds = (0, import_node_path26.join)(home, ".verity", "credentials");
21341
- if (!(0, import_node_fs35.existsSync)(gateCreds)) return;
21342
- if (!(0, import_node_fs35.existsSync)(verityCreds)) {
21343
- (0, import_node_fs35.mkdirSync)((0, import_node_path26.join)(home, ".verity"), { recursive: true });
21734
+ const gateCreds = (0, import_node_path28.join)(home, ".gate", "credentials");
21735
+ const verityCreds = (0, import_node_path28.join)(home, ".verity", "credentials");
21736
+ if (!(0, import_node_fs36.existsSync)(gateCreds)) return;
21737
+ if (!(0, import_node_fs36.existsSync)(verityCreds)) {
21738
+ (0, import_node_fs36.mkdirSync)((0, import_node_path28.join)(home, ".verity"), { recursive: true });
21344
21739
  moveFile(gateCreds, verityCreds);
21345
21740
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
21346
21741
  return;
@@ -21362,8 +21757,8 @@ async function migrateLegacyHooks(root, actions) {
21362
21757
  }
21363
21758
  }
21364
21759
  async function migrateClaudeMd(root, actions) {
21365
- const claudeMd = (0, import_node_path26.join)(root, "CLAUDE.md");
21366
- const hadLegacyBlock = (0, import_node_fs35.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
21760
+ const claudeMd = (0, import_node_path28.join)(root, "CLAUDE.md");
21761
+ const hadLegacyBlock = (0, import_node_fs36.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
21367
21762
  if (!hadLegacyBlock) return;
21368
21763
  try {
21369
21764
  await ensureClaudeMdPointer(root);
@@ -21373,13 +21768,13 @@ async function migrateClaudeMd(root, actions) {
21373
21768
  }
21374
21769
  }
21375
21770
  function migrateStandardFile(root, actions) {
21376
- const gateMd = (0, import_node_path26.join)(root, "GATE.md");
21377
- const verityMd = (0, import_node_path26.join)(root, "VERITY.md");
21378
- if (!(0, import_node_fs35.existsSync)(gateMd) || (0, import_node_fs35.existsSync)(verityMd)) return;
21771
+ const gateMd = (0, import_node_path28.join)(root, "GATE.md");
21772
+ const verityMd = (0, import_node_path28.join)(root, "VERITY.md");
21773
+ if (!(0, import_node_fs36.existsSync)(gateMd) || (0, import_node_fs36.existsSync)(verityMd)) return;
21379
21774
  let moved = false;
21380
21775
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
21381
21776
  try {
21382
- (0, import_node_child_process9.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
21777
+ (0, import_node_child_process10.execSync)("git mv GATE.md VERITY.md", { cwd: root, stdio: "pipe" });
21383
21778
  moved = true;
21384
21779
  } catch {
21385
21780
  }
@@ -21387,12 +21782,12 @@ function migrateStandardFile(root, actions) {
21387
21782
  if (!moved) moveFile(gateMd, verityMd);
21388
21783
  const content = readFileSyncSafe(verityMd);
21389
21784
  const refreshed = content.split("GATE.md").join("VERITY.md");
21390
- if (refreshed !== content) (0, import_node_fs35.writeFileSync)(verityMd, refreshed);
21785
+ if (refreshed !== content) (0, import_node_fs36.writeFileSync)(verityMd, refreshed);
21391
21786
  actions.push("Renamed GATE.md \u2192 VERITY.md");
21392
21787
  }
21393
21788
  async function migrateTelemetryHeaders(root, actions) {
21394
- const file = (0, import_node_path26.join)(root, ".claude", "settings.local.json");
21395
- if (!(0, import_node_fs35.existsSync)(file)) return;
21789
+ const file = (0, import_node_path28.join)(root, ".claude", "settings.local.json");
21790
+ if (!(0, import_node_fs36.existsSync)(file)) return;
21396
21791
  let settings;
21397
21792
  try {
21398
21793
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -21440,21 +21835,21 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
21440
21835
  }
21441
21836
  if (toAppend.length > 0) {
21442
21837
  const sep2 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
21443
- (0, import_node_fs35.writeFileSync)(verityCreds, verityContent + sep2 + toAppend.join("\n") + "\n");
21838
+ (0, import_node_fs36.writeFileSync)(verityCreds, verityContent + sep2 + toAppend.join("\n") + "\n");
21444
21839
  }
21445
- (0, import_node_fs35.rmSync)(gateCreds, { force: true });
21840
+ (0, import_node_fs36.rmSync)(gateCreds, { force: true });
21446
21841
  return toAppend.length;
21447
21842
  }
21448
21843
  function readFileSyncSafe(path) {
21449
21844
  try {
21450
- return (0, import_node_fs35.readFileSync)(path, "utf-8");
21845
+ return (0, import_node_fs36.readFileSync)(path, "utf-8");
21451
21846
  } catch {
21452
21847
  return "";
21453
21848
  }
21454
21849
  }
21455
21850
  function hasStagedChanges(root) {
21456
21851
  try {
21457
- (0, import_node_child_process9.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
21852
+ (0, import_node_child_process10.execSync)("git diff --cached --quiet", { cwd: root, stdio: "pipe" });
21458
21853
  return false;
21459
21854
  } catch {
21460
21855
  return true;
@@ -21462,35 +21857,35 @@ function hasStagedChanges(root) {
21462
21857
  }
21463
21858
  function moveDir(from, to) {
21464
21859
  try {
21465
- (0, import_node_fs35.renameSync)(from, to);
21860
+ (0, import_node_fs36.renameSync)(from, to);
21466
21861
  } catch (err) {
21467
21862
  if (err.code !== "EXDEV") throw err;
21468
- (0, import_node_fs35.cpSync)(from, to, { recursive: true });
21469
- (0, import_node_fs35.rmSync)(from, { recursive: true, force: true });
21863
+ (0, import_node_fs36.cpSync)(from, to, { recursive: true });
21864
+ (0, import_node_fs36.rmSync)(from, { recursive: true, force: true });
21470
21865
  }
21471
21866
  }
21472
21867
  function moveFile(from, to) {
21473
21868
  try {
21474
- (0, import_node_fs35.renameSync)(from, to);
21869
+ (0, import_node_fs36.renameSync)(from, to);
21475
21870
  } catch (err) {
21476
21871
  if (err.code !== "EXDEV") throw err;
21477
- (0, import_node_fs35.cpSync)(from, to);
21478
- (0, import_node_fs35.rmSync)(from, { force: true });
21872
+ (0, import_node_fs36.cpSync)(from, to);
21873
+ (0, import_node_fs36.rmSync)(from, { force: true });
21479
21874
  }
21480
21875
  }
21481
21876
  function carryLegacyContents(gateDir, verityDir) {
21482
21877
  let copied = 0;
21483
21878
  const walk = (relDir) => {
21484
- const srcDir = (0, import_node_path26.join)(gateDir, relDir);
21485
- for (const entry of (0, import_node_fs35.readdirSync)(srcDir)) {
21486
- const rel = relDir ? (0, import_node_path26.join)(relDir, entry) : entry;
21487
- const src = (0, import_node_path26.join)(gateDir, rel);
21488
- const dest = (0, import_node_path26.join)(verityDir, rel);
21489
- if ((0, import_node_fs35.statSync)(src).isDirectory()) {
21879
+ const srcDir = (0, import_node_path28.join)(gateDir, relDir);
21880
+ for (const entry of (0, import_node_fs36.readdirSync)(srcDir)) {
21881
+ const rel = relDir ? (0, import_node_path28.join)(relDir, entry) : entry;
21882
+ const src = (0, import_node_path28.join)(gateDir, rel);
21883
+ const dest = (0, import_node_path28.join)(verityDir, rel);
21884
+ if ((0, import_node_fs36.statSync)(src).isDirectory()) {
21490
21885
  walk(rel);
21491
- } else if (!(0, import_node_fs35.existsSync)(dest)) {
21492
- (0, import_node_fs35.mkdirSync)((0, import_node_path26.dirname)(dest), { recursive: true });
21493
- (0, import_node_fs35.cpSync)(src, dest);
21886
+ } else if (!(0, import_node_fs36.existsSync)(dest)) {
21887
+ (0, import_node_fs36.mkdirSync)((0, import_node_path28.dirname)(dest), { recursive: true });
21888
+ (0, import_node_fs36.cpSync)(src, dest);
21494
21889
  copied++;
21495
21890
  }
21496
21891
  }
@@ -21499,22 +21894,22 @@ function carryLegacyContents(gateDir, verityDir) {
21499
21894
  return copied;
21500
21895
  }
21501
21896
  async function needsMigration(root = repoRoot()) {
21502
- const gateDir = (0, import_node_path26.join)(root, ".gate");
21503
- const verityDir = (0, import_node_path26.join)(root, ".verity");
21504
- if ((0, import_node_fs35.existsSync)(gateDir) && !(0, import_node_fs35.existsSync)(verityDir)) return true;
21505
- if ((0, import_node_fs35.existsSync)(gateDir) && (0, import_node_fs35.existsSync)(verityDir)) {
21506
- if ((0, import_node_fs35.existsSync)((0, import_node_path26.join)(gateDir, "credentials")) && !(0, import_node_fs35.existsSync)((0, import_node_path26.join)(verityDir, "credentials"))) {
21897
+ const gateDir = (0, import_node_path28.join)(root, ".gate");
21898
+ const verityDir = (0, import_node_path28.join)(root, ".verity");
21899
+ if ((0, import_node_fs36.existsSync)(gateDir) && !(0, import_node_fs36.existsSync)(verityDir)) return true;
21900
+ if ((0, import_node_fs36.existsSync)(gateDir) && (0, import_node_fs36.existsSync)(verityDir)) {
21901
+ if ((0, import_node_fs36.existsSync)((0, import_node_path28.join)(gateDir, "credentials")) && !(0, import_node_fs36.existsSync)((0, import_node_path28.join)(verityDir, "credentials"))) {
21507
21902
  return true;
21508
21903
  }
21509
- if ((0, import_node_fs35.existsSync)((0, import_node_path26.join)(gateDir, "memory")) && !(0, import_node_fs35.existsSync)((0, import_node_path26.join)(verityDir, "memory"))) {
21904
+ if ((0, import_node_fs36.existsSync)((0, import_node_path28.join)(gateDir, "memory")) && !(0, import_node_fs36.existsSync)((0, import_node_path28.join)(verityDir, "memory"))) {
21510
21905
  return true;
21511
21906
  }
21512
21907
  }
21513
- const claudeMd = (0, import_node_path26.join)(root, "CLAUDE.md");
21514
- if ((0, import_node_fs35.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
21908
+ const claudeMd = (0, import_node_path28.join)(root, "CLAUDE.md");
21909
+ if ((0, import_node_fs36.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
21515
21910
  return true;
21516
21911
  }
21517
- if ((0, import_node_fs35.existsSync)((0, import_node_path26.join)(root, "GATE.md")) && !(0, import_node_fs35.existsSync)((0, import_node_path26.join)(root, "VERITY.md"))) {
21912
+ if ((0, import_node_fs36.existsSync)((0, import_node_path28.join)(root, "GATE.md")) && !(0, import_node_fs36.existsSync)((0, import_node_path28.join)(root, "VERITY.md"))) {
21518
21913
  return true;
21519
21914
  }
21520
21915
  if (await hasLegacyHooksAt(root)) return true;
@@ -21607,7 +22002,7 @@ async function runOptionalAuth(resolution, opts = {}) {
21607
22002
  }
21608
22003
  let remote = "";
21609
22004
  try {
21610
- remote = (0, import_node_child_process10.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
22005
+ remote = (0, import_node_child_process11.execSync)("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
21611
22006
  } catch {
21612
22007
  }
21613
22008
  if (!healed) {
@@ -21650,15 +22045,15 @@ async function runOptionalAuth(resolution, opts = {}) {
21650
22045
  }
21651
22046
  function resolveDataDir() {
21652
22047
  const candidates = [
21653
- (0, import_node_path27.join)(__dirname, "..", "data"),
22048
+ (0, import_node_path29.join)(__dirname, "..", "data"),
21654
22049
  // installed: node_modules/@codacy/verity-cli/data
21655
- (0, import_node_path27.join)(__dirname, "..", "..", "data"),
22050
+ (0, import_node_path29.join)(__dirname, "..", "..", "data"),
21656
22051
  // edge case: nested resolution
21657
- (0, import_node_path27.join)(process.cwd(), "cli", "data")
22052
+ (0, import_node_path29.join)(process.cwd(), "cli", "data")
21658
22053
  // local dev: running from repo root
21659
22054
  ];
21660
22055
  for (const candidate of candidates) {
21661
- if ((0, import_node_fs36.existsSync)((0, import_node_path27.join)(candidate, "skills"))) {
22056
+ if ((0, import_node_fs37.existsSync)((0, import_node_path29.join)(candidate, "skills"))) {
21662
22057
  return candidate;
21663
22058
  }
21664
22059
  }
@@ -21674,7 +22069,7 @@ function registerInitCommand(program2) {
21674
22069
  program2.command("init").description("Initialize Verity in the current project").option("--force", "Overwrite existing skills and hooks").action(async (opts) => {
21675
22070
  const force = opts.force ?? false;
21676
22071
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
21677
- const isProject = projectMarkers.some((m) => (0, import_node_fs36.existsSync)(m));
22072
+ const isProject = projectMarkers.some((m) => (0, import_node_fs37.existsSync)(m));
21678
22073
  if (!isProject) {
21679
22074
  printError("No project detected in the current directory.");
21680
22075
  printInfo('Run "verity init" from your project root.');
@@ -21702,30 +22097,30 @@ function registerInitCommand(program2) {
21702
22097
  }
21703
22098
  printInfo(` Node.js ${nodeVersion} \u2713`);
21704
22099
  try {
21705
- const gitVersion = (0, import_node_child_process10.execSync)("git --version", { encoding: "utf-8" }).trim();
22100
+ const gitVersion = (0, import_node_child_process11.execSync)("git --version", { encoding: "utf-8" }).trim();
21706
22101
  printInfo(` ${gitVersion} \u2713`);
21707
22102
  } catch {
21708
22103
  printError("git is required but not installed. Install from https://git-scm.com");
21709
22104
  process.exit(1);
21710
22105
  }
21711
22106
  try {
21712
- (0, import_node_child_process10.execSync)("which claude", { encoding: "utf-8" });
22107
+ (0, import_node_child_process11.execSync)("which claude", { encoding: "utf-8" });
21713
22108
  printInfo(" Claude Code \u2713");
21714
22109
  } catch {
21715
22110
  printWarn(" Claude Code not found \u2014 hooks will be configured but need Claude Code to run.");
21716
22111
  }
21717
22112
  try {
21718
- (0, import_node_child_process10.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
22113
+ (0, import_node_child_process11.execSync)("which codacy-analysis", { encoding: "utf-8", stdio: "pipe" });
21719
22114
  printInfo(" @codacy/analysis-cli \u2713");
21720
22115
  } catch {
21721
22116
  printInfo(" Installing @codacy/analysis-cli...");
21722
22117
  try {
21723
- (0, import_node_child_process10.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
22118
+ (0, import_node_child_process11.execSync)("npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "pipe", timeout: 12e4 });
21724
22119
  printInfo(" @codacy/analysis-cli installed \u2713");
21725
22120
  } catch {
21726
22121
  try {
21727
22122
  printWarn(" Retrying with sudo...");
21728
- (0, import_node_child_process10.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
22123
+ (0, import_node_child_process11.execSync)("sudo npm install -g @codacy/analysis-cli", { encoding: "utf-8", stdio: "inherit", timeout: 12e4 });
21729
22124
  printInfo(" @codacy/analysis-cli installed \u2713");
21730
22125
  } catch {
21731
22126
  printWarn(" Could not install @codacy/analysis-cli automatically.");
@@ -21737,21 +22132,21 @@ function registerInitCommand(program2) {
21737
22132
  console.log("");
21738
22133
  printInfo("Installing skills...");
21739
22134
  const dataDir = resolveDataDir();
21740
- const skillsSource = (0, import_node_path27.join)(dataDir, "skills");
22135
+ const skillsSource = (0, import_node_path29.join)(dataDir, "skills");
21741
22136
  const skillsDest = ".claude/skills";
21742
22137
  const skills = ["verity-setup", "verity-analyze", "verity-status", "verity-feedback", "verity-learn", "verity-memory", "verity-insights", "verity-reflect"];
21743
22138
  let skillsInstalled = 0;
21744
22139
  for (const skill of skills) {
21745
- const src = (0, import_node_path27.join)(skillsSource, skill);
21746
- const dest = (0, import_node_path27.join)(skillsDest, skill);
21747
- if (!(0, import_node_fs36.existsSync)(src)) {
22140
+ const src = (0, import_node_path29.join)(skillsSource, skill);
22141
+ const dest = (0, import_node_path29.join)(skillsDest, skill);
22142
+ if (!(0, import_node_fs37.existsSync)(src)) {
21748
22143
  printWarn(` Skill data not found: ${skill}`);
21749
22144
  continue;
21750
22145
  }
21751
- if ((0, import_node_fs36.existsSync)(dest) && !force) {
21752
- const srcSkill = (0, import_node_path27.join)(src, "SKILL.md");
21753
- const destSkill = (0, import_node_path27.join)(dest, "SKILL.md");
21754
- if ((0, import_node_fs36.existsSync)(destSkill)) {
22146
+ if ((0, import_node_fs37.existsSync)(dest) && !force) {
22147
+ const srcSkill = (0, import_node_path29.join)(src, "SKILL.md");
22148
+ const destSkill = (0, import_node_path29.join)(dest, "SKILL.md");
22149
+ if ((0, import_node_fs37.existsSync)(destSkill)) {
21755
22150
  try {
21756
22151
  const srcContent = await (0, import_promises13.readFile)(srcSkill, "utf-8");
21757
22152
  const destContent = await (0, import_promises13.readFile)(destSkill, "utf-8");
@@ -21794,7 +22189,7 @@ function registerInitCommand(program2) {
21794
22189
  } catch (err) {
21795
22190
  printWarn(` Could not update CLAUDE.md: ${err.message}`);
21796
22191
  }
21797
- const globalVerityDir = (0, import_node_path27.join)(process.env.HOME ?? "", ".verity");
22192
+ const globalVerityDir = (0, import_node_path29.join)(process.env.HOME ?? "", ".verity");
21798
22193
  await (0, import_promises13.mkdir)(globalVerityDir, { recursive: true });
21799
22194
  console.log("");
21800
22195
  try {
@@ -21829,8 +22224,8 @@ function registerInitCommand(program2) {
21829
22224
  }
21830
22225
 
21831
22226
  // src/commands/uninstall.ts
21832
- var import_node_fs37 = require("node:fs");
21833
- var import_node_path28 = require("node:path");
22227
+ var import_node_fs38 = require("node:fs");
22228
+ var import_node_path30 = require("node:path");
21834
22229
  var SKILL_NAMES = [
21835
22230
  "verity-setup",
21836
22231
  "verity-analyze",
@@ -21849,11 +22244,11 @@ function registerUninstallCommand(program2) {
21849
22244
  const actions = [];
21850
22245
  const skillsRoot = projectPath(".claude/skills");
21851
22246
  for (const name of SKILL_NAMES) {
21852
- const dir = (0, import_node_path28.join)(skillsRoot, name);
21853
- if ((0, import_node_fs37.existsSync)(dir)) {
22247
+ const dir = (0, import_node_path30.join)(skillsRoot, name);
22248
+ if ((0, import_node_fs38.existsSync)(dir)) {
21854
22249
  actions.push({
21855
22250
  label: `Remove .claude/skills/${name}/`,
21856
- apply: () => (0, import_node_fs37.rmSync)(dir, { recursive: true, force: true })
22251
+ apply: () => (0, import_node_fs38.rmSync)(dir, { recursive: true, force: true })
21857
22252
  });
21858
22253
  }
21859
22254
  }
@@ -21867,24 +22262,24 @@ function registerUninstallCommand(program2) {
21867
22262
  });
21868
22263
  }
21869
22264
  const verityDir = projectPath(VERITY_DIR);
21870
- if ((0, import_node_fs37.existsSync)(verityDir)) {
22265
+ if ((0, import_node_fs38.existsSync)(verityDir)) {
21871
22266
  actions.push({
21872
22267
  label: `Remove ${VERITY_DIR}/`,
21873
- apply: () => (0, import_node_fs37.rmSync)(verityDir, { recursive: true, force: true })
22268
+ apply: () => (0, import_node_fs38.rmSync)(verityDir, { recursive: true, force: true })
21874
22269
  });
21875
22270
  }
21876
22271
  if (!keepVerityMd) {
21877
22272
  const verityMd = projectPath(VERITY_MD_FILE);
21878
- if ((0, import_node_fs37.existsSync)(verityMd)) {
22273
+ if ((0, import_node_fs38.existsSync)(verityMd)) {
21879
22274
  actions.push({
21880
22275
  label: `Remove ${VERITY_MD_FILE}`,
21881
- apply: () => (0, import_node_fs37.rmSync)(verityMd, { force: true })
22276
+ apply: () => (0, import_node_fs38.rmSync)(verityMd, { force: true })
21882
22277
  });
21883
22278
  }
21884
22279
  }
21885
22280
  const cleanupEmptyDir = (path) => {
21886
- if ((0, import_node_fs37.existsSync)(path) && (0, import_node_fs37.statSync)(path).isDirectory() && (0, import_node_fs37.readdirSync)(path).length === 0) {
21887
- (0, import_node_fs37.rmdirSync)(path);
22281
+ if ((0, import_node_fs38.existsSync)(path) && (0, import_node_fs38.statSync)(path).isDirectory() && (0, import_node_fs38.readdirSync)(path).length === 0) {
22282
+ (0, import_node_fs38.rmdirSync)(path);
21888
22283
  }
21889
22284
  };
21890
22285
  actions.push({
@@ -21895,11 +22290,11 @@ function registerUninstallCommand(program2) {
21895
22290
  }
21896
22291
  });
21897
22292
  const home = process.env.HOME ?? "";
21898
- const globalVerityDir = (0, import_node_path28.join)(home, ".verity");
21899
- if (purgeGlobal && (0, import_node_fs37.existsSync)(globalVerityDir)) {
22293
+ const globalVerityDir = (0, import_node_path30.join)(home, ".verity");
22294
+ if (purgeGlobal && (0, import_node_fs38.existsSync)(globalVerityDir)) {
21900
22295
  actions.push({
21901
22296
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
21902
- apply: () => (0, import_node_fs37.rmSync)(globalVerityDir, { recursive: true, force: true })
22297
+ apply: () => (0, import_node_fs38.rmSync)(globalVerityDir, { recursive: true, force: true })
21903
22298
  });
21904
22299
  }
21905
22300
  if (actions.length === 0) {
@@ -22093,8 +22488,8 @@ function registerTaskCommands(program2) {
22093
22488
  }
22094
22489
 
22095
22490
  // src/commands/reset.ts
22096
- var import_node_fs38 = require("node:fs");
22097
- var import_node_path29 = require("node:path");
22491
+ var import_node_fs39 = require("node:fs");
22492
+ var import_node_path31 = require("node:path");
22098
22493
  function registerResetCommand(program2) {
22099
22494
  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) => {
22100
22495
  const globals = program2.opts();
@@ -22131,11 +22526,11 @@ function registerResetCommand(program2) {
22131
22526
  }
22132
22527
  const cacheDir = projectPath(CACHE_DIR);
22133
22528
  let purged = 0;
22134
- if ((0, import_node_fs38.existsSync)(cacheDir)) {
22135
- for (const entry of (0, import_node_fs38.readdirSync)(cacheDir)) {
22529
+ if ((0, import_node_fs39.existsSync)(cacheDir)) {
22530
+ for (const entry of (0, import_node_fs39.readdirSync)(cacheDir)) {
22136
22531
  if (entry.startsWith("pending-")) {
22137
22532
  try {
22138
- (0, import_node_fs38.unlinkSync)((0, import_node_path29.join)(cacheDir, entry));
22533
+ (0, import_node_fs39.unlinkSync)((0, import_node_path31.join)(cacheDir, entry));
22139
22534
  purged++;
22140
22535
  } catch {
22141
22536
  }
@@ -22150,19 +22545,19 @@ function registerResetCommand(program2) {
22150
22545
  projectPath(`${VERITY_DIR}/.last-analysis`)
22151
22546
  ];
22152
22547
  for (const file of filesToClear) {
22153
- if ((0, import_node_fs38.existsSync)(file)) {
22548
+ if ((0, import_node_fs39.existsSync)(file)) {
22154
22549
  try {
22155
- (0, import_node_fs38.writeFileSync)(file, "");
22550
+ (0, import_node_fs39.writeFileSync)(file, "");
22156
22551
  } catch {
22157
22552
  }
22158
22553
  }
22159
22554
  }
22160
22555
  if (opts.all) {
22161
22556
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
22162
- if ((0, import_node_fs38.existsSync)(logsDir)) {
22163
- for (const entry of (0, import_node_fs38.readdirSync)(logsDir)) {
22557
+ if ((0, import_node_fs39.existsSync)(logsDir)) {
22558
+ for (const entry of (0, import_node_fs39.readdirSync)(logsDir)) {
22164
22559
  try {
22165
- (0, import_node_fs38.unlinkSync)((0, import_node_path29.join)(logsDir, entry));
22560
+ (0, import_node_fs39.unlinkSync)((0, import_node_path31.join)(logsDir, entry));
22166
22561
  } catch {
22167
22562
  }
22168
22563
  }
@@ -22470,8 +22865,8 @@ function registerTelemetryCommands(program2) {
22470
22865
  }
22471
22866
 
22472
22867
  // src/cli.ts
22473
- program.name("verity").description("CLI for Verity quality gate service").version("0.30.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
22474
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.30.0");
22868
+ program.name("verity").description("CLI for Verity quality gate service").version("0.30.1-experimental.e2137b9").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) => {
22869
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.30.1-experimental.e2137b9");
22475
22870
  setUserNamedServiceUrl(program.opts().serviceUrl);
22476
22871
  try {
22477
22872
  await foldLegacyLocalCredential();