@codacy/verity-cli 0.29.4-experimental.9a4e14c → 0.29.4-experimental.cfb4bd2

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 +216 -18
  2. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -10390,11 +10390,11 @@ var MAX_DELTA_BYTES = 194560;
10390
10390
  var MAX_FILES = 40;
10391
10391
  var MAX_FILE_BYTES = 51200;
10392
10392
  var DEBOUNCE_SECONDS = 30;
10393
- var MAX_SPEC_FILES = 10;
10394
- var MAX_SPEC_FILE_BYTES = 10240;
10395
- var MAX_TOTAL_SPEC_BYTES = 30720;
10393
+ var MAX_SPEC_FILES = 6;
10394
+ var MAX_SPEC_FILE_BYTES = 512e3;
10395
+ var MAX_TOTAL_SPEC_BYTES = 512e3;
10396
10396
  var MAX_PLAN_FILES = 3;
10397
- var MAX_PLAN_FILE_BYTES = 10240;
10397
+ var MAX_PLAN_FILE_BYTES = 512e3;
10398
10398
  var MAX_INTENT_CHARS = 2e3;
10399
10399
  var SNAPSHOT_DIR = `${VERITY_DIR}/.snapshot`;
10400
10400
  var BASELINE_DIR = `${VERITY_DIR}/.baseline`;
@@ -15060,8 +15060,10 @@ function recordVerdict(d, v) {
15060
15060
  if (summary) appendEvent(d, { k: "goal_delivered", summary });
15061
15061
  }
15062
15062
  const lines = /* @__PURE__ */ new Map();
15063
+ const sent = new Set(v.sentPaths);
15063
15064
  for (const f of v.findings) {
15064
15065
  if (!f.file || typeof f.line !== "number" || !f.pattern_id) continue;
15066
+ if (!sent.has(f.file)) continue;
15065
15067
  if (!lines.has(f.file)) {
15066
15068
  try {
15067
15069
  const abs = (0, import_node_path12.join)(root, f.file);
@@ -16570,6 +16572,7 @@ function createRun(opts, globals) {
16570
16572
  opts,
16571
16573
  globals,
16572
16574
  phaseReached: "",
16575
+ phasesCompleted: [],
16573
16576
  skipReason: null,
16574
16577
  turnId: "",
16575
16578
  // The value `resolveReachability` itself returns when every rung declines.
@@ -16600,6 +16603,7 @@ function createRun(opts, globals) {
16600
16603
  urlResult: { ok: false, error: "unresolved" },
16601
16604
  serviceUrl: "",
16602
16605
  token: "",
16606
+ modeDecision: null,
16603
16607
  sessionIdForMemory: "",
16604
16608
  contextFilePaths: [],
16605
16609
  analysisMode: "standard",
@@ -16710,7 +16714,19 @@ function formatRunEvidence(run, startedAt) {
16710
16714
  out += row("turn", `${run.turnId || "(unminted)"}${run.sessionId ? ` \xB7 session ${run.sessionId}` : ""}`);
16711
16715
  out += row("reached", `${run.phaseReached || "(none)"}${run.skipReason ? ` \xB7 SKIPPED: ${run.skipReason}` : ""} \xB7 ${ms}ms`);
16712
16716
  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}`);
16713
- out += row("signals", `mode=${run.analysisMode} \xB7 baseline=${run.baseline ? "yes" : "no"} \xB7 authored=${run.turnAuthoredCode ? "yes" : "no"} \xB7 observable=${run.authorshipIsObservable ? "yes" : "no"}` + (run.actionSummary?.transcript_windowed ? ` \xB7 window=${run.actionSummary.transcript_windowed}` : ""));
16717
+ const done = (phase) => run.phasesCompleted.includes(phase);
16718
+ const ifDone = (phase, value) => done(phase) ? value : "?";
16719
+ const md = run.modeDecision;
16720
+ if (md) {
16721
+ const how = md.forced ? "forced by --mode" : `predicted=${md.predicted ?? "none"} \u2192 ${md.resolved}`;
16722
+ out += row("mode", `${md.resolved} \xB7 ${how} \xB7 authored=${md.authored ? "yes" : "no"} \xB7 investigated=${md.investigated ? "yes" : "no"}`);
16723
+ } else {
16724
+ out += row("mode", `? (this run stopped in ${run.phaseReached || "no phase"}, before the mode was decided)`);
16725
+ }
16726
+ out += row("signals", `baseline=${ifDone("bootstrap", run.baseline ? "yes" : "no")} \xB7 authored=${ifDone("intentInputs", run.turnAuthoredCode ? "yes" : "no")} \xB7 observable=${ifDone("intentInputs", run.authorshipIsObservable ? "yes" : "no")}` + (run.actionSummary?.transcript_windowed ? ` \xB7 window=${run.actionSummary.transcript_windowed}` : ""));
16727
+ if (!done("intentInputs")) {
16728
+ out += row("", `(\`?\` = the phase that determines it did not complete \u2014 this run stopped in ${run.phaseReached})`);
16729
+ }
16714
16730
  out += row("sent", `${sent.length} \xB7 ${list(sent)}`);
16715
16731
  if (context.length > 0) out += row("context", `${context.length} \xB7 ${list(context)}`);
16716
16732
  const withheld = run.reviewCoverage.notReviewed;
@@ -16735,6 +16751,46 @@ function formatRunEvidence(run, startedAt) {
16735
16751
  out += row("withheld", "(nothing \u2014 every changed file was reviewed)");
16736
16752
  }
16737
16753
  }
16754
+ const cov = run.foldResult?.coverage;
16755
+ if (cov) {
16756
+ const delegated = run.foldResult.authored.filter((a) => a.owner === "subagent").length;
16757
+ if (cov.dispatched > 0 || cov.subagentFiles > 0 || cov.subagentSkipped > 0) {
16758
+ out += row("delegated", `${cov.dispatched} dispatched \xB7 ${cov.subagentFiles} agent log(s) read \xB7 ${delegated} path(s) attributed to subagents`);
16759
+ }
16760
+ if (cov.subagentSkipped > 0) {
16761
+ out += row("", `\u26A0 ${cov.subagentSkipped} agent log(s) REFUSED by the byte budget \u2014 the authored set above is PARTIAL`);
16762
+ }
16763
+ if (cov.dispatched > 0 && cov.subagentFiles === 0) {
16764
+ out += row("", `\u26A0 this turn dispatched ${cov.dispatched} agent(s) but no agent log was found \u2014 delegated work is unattributed (has the transcript layout moved?)`);
16765
+ }
16766
+ if (cov.outsideRepo > 0) {
16767
+ out += row("", `${cov.outsideRepo} authored path(s) refused as outside the repo`);
16768
+ }
16769
+ }
16770
+ if (run.foldResult?.tools?.length) {
16771
+ const shown = run.foldResult.tools.slice(0, 6).map((t) => {
16772
+ const outcome = t.failed > 0 ? `${t.failed} failed` : t.last_status === 0 ? "ok" : "?";
16773
+ const where = t.targets.length > 0 ? ` \u2192 ${t.targets.slice(0, 2).join(", ")}` : "";
16774
+ return `${t.runs}\xD7 ${t.name} (${outcome})${where}`;
16775
+ });
16776
+ const more = run.foldResult.tools.length > 6 ? ` \u2026 +${run.foldResult.tools.length - 6} more` : "";
16777
+ out += row("tools", shown.join(" \xB7 ") + more);
16778
+ if (run.foldResult.coverage.toolNamesDropped > 0) {
16779
+ out += row("", `\u26A0 ${run.foldResult.coverage.toolNamesDropped} tool name(s) refused by the cap`);
16780
+ }
16781
+ }
16782
+ if (run.foldResult?.tasks?.length) {
16783
+ const t = run.foldResult.tasks;
16784
+ const done2 = t.filter((x) => x.status === "completed").length;
16785
+ out += row("tasks", `${t.length} \xB7 ${done2} completed \xB7 ` + list(t.slice(0, 4).map((x) => `#${x.id} ${x.name} [${x.status}]`), 4));
16786
+ }
16787
+ if (run.specs?.length) {
16788
+ const readThisSession = new Set(run.actionSummary?.files_read ?? []);
16789
+ const labelled = run.specs.map(
16790
+ (s) => `${s.path}${readThisSession.has(s.path) ? " (read)" : " (positional)"}`
16791
+ );
16792
+ out += row("specs", `${run.specs.length} \xB7 ${list(labelled, 5)}`);
16793
+ }
16738
16794
  if (run.staticResults.findings.length > 0) {
16739
16795
  out += row("static", `${run.staticResults.findings.length} finding(s) from ${run.staticResults.summary.tools_run.join(", ") || "no tools"}`);
16740
16796
  }
@@ -16930,6 +16986,8 @@ function buildSummary(lines) {
16930
16986
  break;
16931
16987
  case "Agent":
16932
16988
  case "Task":
16989
+ case "Workflow":
16990
+ case "SendMessage":
16933
16991
  subagents++;
16934
16992
  break;
16935
16993
  case "WebFetch":
@@ -17184,7 +17242,7 @@ function channelSilence(input) {
17184
17242
  // src/lib/cli-version.ts
17185
17243
  function cliVersion() {
17186
17244
  try {
17187
- return true ? "0.29.4-experimental.9a4e14c" : "dev";
17245
+ return true ? "0.29.4-experimental.cfb4bd2" : "dev";
17188
17246
  } catch {
17189
17247
  return "dev";
17190
17248
  }
@@ -17535,18 +17593,26 @@ var SPEC_CANDIDATES = [
17535
17593
  "docs/API.md",
17536
17594
  "spec/ARCHITECTURE.md"
17537
17595
  ];
17538
- function discoverSpecs() {
17596
+ var DOC_EXT = /\.(md|mdx|ya?ml|txt|rst|adoc)$/i;
17597
+ var UNCONSULTED_FILE_BYTES = 10240;
17598
+ var UNCONSULTED_TOTAL_BYTES = 30720;
17599
+ function discoverSpecs(consulted = []) {
17539
17600
  const result = [];
17540
17601
  const seen = /* @__PURE__ */ new Set();
17541
17602
  let totalBytes = 0;
17542
- const addSpec = (specPath) => {
17603
+ const consultedDocs = new Set(
17604
+ consulted.filter((p) => DOC_EXT.test(p) && !p.startsWith("/") && !p.includes(".."))
17605
+ );
17606
+ const addSpec = (specPath, relevant = false) => {
17543
17607
  if (result.length >= MAX_SPEC_FILES) return false;
17544
- if (totalBytes >= MAX_TOTAL_SPEC_BYTES) return false;
17608
+ const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
17609
+ if (totalBytes >= totalCap) return false;
17545
17610
  if (seen.has(specPath)) return true;
17546
17611
  if (!(0, import_node_fs21.existsSync)(specPath)) return true;
17547
17612
  seen.add(specPath);
17548
- const remaining = MAX_TOTAL_SPEC_BYTES - totalBytes;
17549
- const readBytes = Math.min(MAX_SPEC_FILE_BYTES, remaining);
17613
+ const remaining = totalCap - totalBytes;
17614
+ const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
17615
+ const readBytes = Math.min(fileCap, remaining);
17550
17616
  try {
17551
17617
  const buf = Buffer.alloc(readBytes);
17552
17618
  const fd = (0, import_node_fs21.openSync)(specPath, "r");
@@ -17560,6 +17626,9 @@ function discoverSpecs() {
17560
17626
  }
17561
17627
  return true;
17562
17628
  };
17629
+ for (const doc of consultedDocs) {
17630
+ if (!addSpec(doc, true)) break;
17631
+ }
17563
17632
  for (const candidate of SPEC_CANDIDATES) {
17564
17633
  if (!addSpec(candidate)) break;
17565
17634
  }
@@ -17630,7 +17699,7 @@ function discoverPlans() {
17630
17699
  async function intentInputs(run) {
17631
17700
  const { actionSummary, allForReview, assistantResponse, baseline, baselineSessionId } = run;
17632
17701
  const conversation = await readAndClearConversationBuffer(baselineSessionId);
17633
- const specs = discoverSpecs();
17702
+ const specs = discoverSpecs(actionSummary?.files_read ?? []);
17634
17703
  const plans = discoverPlans();
17635
17704
  const agentAuthoredCodeThisTurn = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0));
17636
17705
  const turnAuthoredCode = agentAuthoredCodeThisTurn || !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
@@ -17853,7 +17922,8 @@ async function mode(run) {
17853
17922
  let analysisMode;
17854
17923
  const sessionAuthoredCode = !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
17855
17924
  const modeOverride = opts.mode;
17856
- if (modeOverride && ["standard", "plan", "debug", "skip"].includes(modeOverride)) {
17925
+ const forced = !!modeOverride && ["standard", "plan", "debug", "skip"].includes(modeOverride);
17926
+ if (forced) {
17857
17927
  analysisMode = modeOverride;
17858
17928
  } else {
17859
17929
  analysisMode = reconcileAnalysisMode(
@@ -17861,6 +17931,25 @@ async function mode(run) {
17861
17931
  { noFilesChanged, assistantResponse, actionSummary, conversationPrompts, sessionAuthoredCode }
17862
17932
  );
17863
17933
  }
17934
+ const investigated = didAgentInvestigate(actionSummary);
17935
+ run.modeDecision = {
17936
+ predicted: predictedMode ?? null,
17937
+ resolved: analysisMode,
17938
+ authored: turnAuthoredCode,
17939
+ investigated,
17940
+ forced
17941
+ };
17942
+ logEvent("mode_resolved", {
17943
+ predicted: predictedMode ?? null,
17944
+ resolved: analysisMode,
17945
+ forced,
17946
+ authored: turnAuthoredCode,
17947
+ investigated,
17948
+ // The two counters that decide `investigated`, so a false reading is
17949
+ // traceable to the tool that was not recognised.
17950
+ subagents: actionSummary?.subagents ?? null,
17951
+ files_read: actionSummary?.files_read.length ?? null
17952
+ });
17864
17953
  if (analysisMode === "skip") {
17865
17954
  await passAndExit(
17866
17955
  run,
@@ -18126,6 +18215,18 @@ function commandShape(cmd) {
18126
18215
  return out.join(" ").slice(0, COMMAND_HEAD_CHARS);
18127
18216
  }
18128
18217
  var COMMAND_HEAD_CHARS = 80;
18218
+ var MAX_TOOL_NAMES = 64;
18219
+ var MAX_TOOL_TARGETS = 3;
18220
+ var MAX_TASKS = 64;
18221
+ var TASK_NAME_CHARS = 120;
18222
+ function toolTarget(name, input) {
18223
+ if (name === "Bash") return null;
18224
+ for (const key of ["file_path", "notebook_path", "path", "filePath"]) {
18225
+ const v = input[key];
18226
+ if (typeof v === "string" && v) return v.slice(0, 120);
18227
+ }
18228
+ return null;
18229
+ }
18129
18230
  var rootCandidateCache = /* @__PURE__ */ new Map();
18130
18231
  function candidateRoots(repoRoot2) {
18131
18232
  const cached2 = rootCandidateCache.get(repoRoot2);
@@ -18154,17 +18255,30 @@ function toRepoRelative(path, repoRoot2) {
18154
18255
  }
18155
18256
  return p.replace(/^\/+/, "");
18156
18257
  }
18258
+ function isInsideRepo(path, repoRoot2) {
18259
+ const p = path.replace(/\\/g, "/");
18260
+ if (!isAbsolutePath(p)) return true;
18261
+ if (!repoRoot2) return true;
18262
+ return candidateRoots(repoRoot2).some((root) => p === root || p.startsWith(root + "/"));
18263
+ }
18264
+ function isAbsolutePath(p) {
18265
+ return p.startsWith("/") || /^[A-Za-z]:\//.test(p);
18266
+ }
18157
18267
  function fold(transcriptPath, opts = {}) {
18158
18268
  const result = {
18159
18269
  authored: [],
18160
18270
  unobserved: [],
18161
18271
  commands: [],
18272
+ tools: [],
18273
+ tasks: [],
18162
18274
  unknownTypes: [],
18163
18275
  coverage: {
18164
18276
  recordCounts: {},
18165
18277
  totalRecords: 0,
18166
18278
  malformed: 0,
18167
18279
  subagentFiles: 0,
18280
+ outsideRepo: 0,
18281
+ toolNamesDropped: 0,
18168
18282
  dispatched: 0,
18169
18283
  userMessages: 0,
18170
18284
  subagentSkipped: 0,
@@ -18175,6 +18289,10 @@ function fold(transcriptPath, opts = {}) {
18175
18289
  const byPath = /* @__PURE__ */ new Map();
18176
18290
  const commandStats = /* @__PURE__ */ new Map();
18177
18291
  const pendingByToolUse = /* @__PURE__ */ new Map();
18292
+ const toolStats = /* @__PURE__ */ new Map();
18293
+ const pendingToolName = /* @__PURE__ */ new Map();
18294
+ const taskById = /* @__PURE__ */ new Map();
18295
+ const pendingTaskName = /* @__PURE__ */ new Map();
18178
18296
  const unknown = /* @__PURE__ */ new Set();
18179
18297
  const ingest = (raw, owner) => {
18180
18298
  for (const line of raw.split("\n")) {
@@ -18194,7 +18312,7 @@ function fold(transcriptPath, opts = {}) {
18194
18312
  result.coverage.compactions++;
18195
18313
  }
18196
18314
  if (type === "user" && hasUserText(record)) result.coverage.userMessages++;
18197
- collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, opts.repoRoot, result.coverage);
18315
+ collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, toolStats, pendingToolName, taskById, pendingTaskName, opts.repoRoot, result.coverage);
18198
18316
  }
18199
18317
  };
18200
18318
  try {
@@ -18205,7 +18323,11 @@ function fold(transcriptPath, opts = {}) {
18205
18323
  return result;
18206
18324
  }
18207
18325
  try {
18208
- const sidecarDir = (0, import_node_path18.join)((0, import_node_path18.dirname)(transcriptPath), "subagents");
18326
+ const sidecarDir = (0, import_node_path18.join)(
18327
+ (0, import_node_path18.dirname)(transcriptPath),
18328
+ (0, import_node_path18.basename)(transcriptPath).replace(/\.jsonl$/, ""),
18329
+ "subagents"
18330
+ );
18209
18331
  if ((0, import_node_fs23.existsSync)(sidecarDir)) {
18210
18332
  const maxFiles = opts.maxSidecars ?? 200;
18211
18333
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
@@ -18248,6 +18370,14 @@ function fold(transcriptPath, opts = {}) {
18248
18370
  result.authored = [...byPath.values()].sort((a, b) => a.p.localeCompare(b.p));
18249
18371
  result.unknownTypes = [...unknown].sort();
18250
18372
  result.commands = [...commandStats.entries()].map(([cls, s]) => ({ class: cls, ...s })).sort((a, b) => a.class.localeCompare(b.class));
18373
+ result.tools = [...toolStats.entries()].map(([name, s]) => ({
18374
+ name,
18375
+ runs: s.runs,
18376
+ failed: s.failed,
18377
+ last_status: s.last_status,
18378
+ targets: [...s.targets].map((t) => toRepoRelative(t, opts.repoRoot)).sort()
18379
+ })).sort((a, b) => b.runs - a.runs || a.name.localeCompare(b.name));
18380
+ result.tasks = [...taskById.entries()].map(([id, t]) => ({ id, name: t.name, status: t.status })).sort((a, b) => (Number(a.id) || 0) - (Number(b.id) || 0));
18251
18381
  const authoredPaths = new Set(result.authored.map((a) => a.p));
18252
18382
  for (const raw of opts.changedFiles ?? []) {
18253
18383
  const p = toRepoRelative(raw, opts.repoRoot);
@@ -18266,7 +18396,7 @@ function classifyUnobserved(path) {
18266
18396
  if (/\.(png|jpg|jpeg|gif|pdf|zip|woff2?|ico|mp4)$/i.test(path)) return "binary";
18267
18397
  return "no_edit_record";
18268
18398
  }
18269
- function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, repoRoot2, tally) {
18399
+ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, toolStats, pendingToolName, taskById, pendingTaskName, repoRoot2, tally) {
18270
18400
  const message = record.message;
18271
18401
  const content = message?.content ?? record.content;
18272
18402
  const blocks = Array.isArray(content) ? content : content && typeof content === "object" ? [content] : [];
@@ -18275,8 +18405,38 @@ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse
18275
18405
  if (blockType === "tool_use") {
18276
18406
  const name = String(block.name ?? "");
18277
18407
  const input = block.input ?? {};
18408
+ if (name && toolStats.size < MAX_TOOL_NAMES) {
18409
+ const prev = toolStats.get(name) ?? { runs: 0, failed: 0, last_status: null, targets: /* @__PURE__ */ new Set() };
18410
+ prev.targets = prev.targets ?? /* @__PURE__ */ new Set();
18411
+ if (prev.targets.size < MAX_TOOL_TARGETS) {
18412
+ const target = toolTarget(name, input);
18413
+ if (target) prev.targets.add(target);
18414
+ }
18415
+ toolStats.set(name, { runs: prev.runs + 1, failed: prev.failed, last_status: null, targets: prev.targets });
18416
+ const toolId = typeof block.id === "string" ? block.id : null;
18417
+ if (toolId) pendingToolName.set(toolId, name);
18418
+ } else if (name && tally) {
18419
+ tally.toolNamesDropped += 1;
18420
+ }
18421
+ if (name === "TaskCreate") {
18422
+ const subject = typeof input.subject === "string" ? input.subject : "";
18423
+ const taskId = typeof block.id === "string" ? block.id : null;
18424
+ if (subject && taskId) pendingTaskName.set(taskId, subject.slice(0, TASK_NAME_CHARS));
18425
+ }
18426
+ if (name === "TaskUpdate") {
18427
+ const id = typeof input.taskId === "string" ? input.taskId : "";
18428
+ const status = typeof input.status === "string" ? input.status : "";
18429
+ if (id && status) {
18430
+ const entry = taskById.get(id);
18431
+ taskById.set(id, { name: entry?.name ?? `#${id}`, status });
18432
+ }
18433
+ }
18278
18434
  if (EDIT_TOOLS.has(name)) {
18279
18435
  const rawPath = typeof input.notebook_path === "string" ? input.notebook_path : typeof input.file_path === "string" ? input.file_path : null;
18436
+ if (rawPath && !isInsideRepo(rawPath, repoRoot2)) {
18437
+ if (tally) tally.outsideRepo += 1;
18438
+ continue;
18439
+ }
18280
18440
  const path = rawPath ? toRepoRelative(rawPath, repoRoot2) : null;
18281
18441
  if (path) {
18282
18442
  const entry = byPath.get(path) ?? { p: path, h: 0, a: 0, d: 0, owner };
@@ -18310,6 +18470,31 @@ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse
18310
18470
  }
18311
18471
  if (blockType === "tool_result") {
18312
18472
  const id = typeof block.tool_use_id === "string" ? block.tool_use_id : null;
18473
+ const taskName = id ? pendingTaskName.get(id) : void 0;
18474
+ if (taskName) {
18475
+ pendingTaskName.delete(id);
18476
+ const body = typeof block.content === "string" ? block.content : "";
18477
+ const created = /Task #(\d+)/.exec(body);
18478
+ if (created && taskById.size < MAX_TASKS) {
18479
+ taskById.set(created[1], { name: taskName, status: taskById.get(created[1])?.status ?? "created" });
18480
+ }
18481
+ }
18482
+ const toolName = id ? pendingToolName.get(id) : void 0;
18483
+ if (toolName) {
18484
+ pendingToolName.delete(id);
18485
+ const prevTool = toolStats.get(toolName);
18486
+ if (prevTool) {
18487
+ const failed = block.is_error === true;
18488
+ toolStats.set(toolName, {
18489
+ runs: prevTool.runs,
18490
+ failed: prevTool.failed + (failed ? 1 : 0),
18491
+ last_status: block.is_error === true ? 1 : block.is_error === false ? 0 : null,
18492
+ // Carried, not rebuilt: the targets were collected on the `tool_use`
18493
+ // side and dropping them here would empty the ledger on every result.
18494
+ targets: prevTool.targets
18495
+ });
18496
+ }
18497
+ }
18313
18498
  const cls = id ? pendingByToolUse.get(id) : void 0;
18314
18499
  if (!cls) continue;
18315
18500
  pendingByToolUse.delete(id);
@@ -18529,6 +18714,10 @@ function gatherContextFiles(contextPaths, deltaFiles) {
18529
18714
  for (const filePath of contextPaths) {
18530
18715
  if (result.length >= MAX_CONTEXT_FILES) break;
18531
18716
  if (deltaPaths.has(filePath)) continue;
18717
+ if (isVerityOwnedPath(filePath)) {
18718
+ logEvent("context_file_skipped", { path: filePath, reason: "verity_owned" });
18719
+ continue;
18720
+ }
18532
18721
  try {
18533
18722
  const content = (0, import_node_fs25.readFileSync)(filePath, "utf8");
18534
18723
  const bytes = Buffer.byteLength(content);
@@ -19299,6 +19488,8 @@ async function buildRequest(run) {
19299
19488
  authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
19300
19489
  unobserved: foldResult?.unobserved ?? [],
19301
19490
  commands: foldResult?.commands ?? [],
19491
+ tools: foldResult?.tools ?? [],
19492
+ tasks: foldResult?.tasks ?? [],
19302
19493
  unknown_types: foldResult?.unknownTypes ?? [],
19303
19494
  coverage: foldResult?.coverage ?? { recordCounts: {}, totalRecords: 0, malformed: 0, subagentFiles: 0, subagentSkipped: 0, complete: false },
19304
19495
  // INV-19, computed client-side and sent so a conservation failure is
@@ -19672,6 +19863,11 @@ async function reconcile(run) {
19672
19863
  decision,
19673
19864
  branch: getCurrentBranch(),
19674
19865
  watermarkSha: watermarkIsPartial ? null : watermarkHash,
19866
+ // The byte witness — the same "only honest definition of reviewed" the
19867
+ // coverage column uses. A finding on a path outside this set records no
19868
+ // statement (plan-mode prose anchored to unsent files must not become
19869
+ // "STILL OPEN … the tree is not clean").
19870
+ sentPaths,
19675
19871
  findings: response.findings?.map((f) => ({
19676
19872
  file: f.file,
19677
19873
  line: f.line,
@@ -20123,10 +20319,12 @@ async function runAnalyze(opts, globals) {
20123
20319
  run.phaseReached = name;
20124
20320
  if (!tracing()) {
20125
20321
  await phase(run);
20322
+ run.phasesCompleted.push(name);
20126
20323
  continue;
20127
20324
  }
20128
20325
  const started = Date.now();
20129
20326
  await phase(run);
20327
+ run.phasesCompleted.push(name);
20130
20328
  process.stderr.write(`verity\xB7phase ${name} ${Date.now() - started}ms
20131
20329
  `);
20132
20330
  }
@@ -21923,8 +22121,8 @@ function registerTelemetryCommands(program2) {
21923
22121
  }
21924
22122
 
21925
22123
  // src/cli.ts
21926
- program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.9a4e14c").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) => {
21927
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.9a4e14c");
22124
+ program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.cfb4bd2").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) => {
22125
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.cfb4bd2");
21928
22126
  setUserNamedServiceUrl(program.opts().serviceUrl);
21929
22127
  try {
21930
22128
  await foldLegacyLocalCredential();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/verity-cli",
3
- "version": "0.29.4-experimental.9a4e14c",
3
+ "version": "0.29.4-experimental.cfb4bd2",
4
4
  "description": "CLI for Verity quality gate service",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://verity.md",