@codacy/verity-cli 0.29.4-experimental.6726d0f → 0.29.4-experimental.7126d67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/verity.js +242 -26
- 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 =
|
|
10394
|
-
var MAX_SPEC_FILE_BYTES =
|
|
10395
|
-
var MAX_TOTAL_SPEC_BYTES =
|
|
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 =
|
|
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);
|
|
@@ -16601,6 +16603,7 @@ function createRun(opts, globals) {
|
|
|
16601
16603
|
urlResult: { ok: false, error: "unresolved" },
|
|
16602
16604
|
serviceUrl: "",
|
|
16603
16605
|
token: "",
|
|
16606
|
+
modeDecision: null,
|
|
16604
16607
|
sessionIdForMemory: "",
|
|
16605
16608
|
contextFilePaths: [],
|
|
16606
16609
|
analysisMode: "standard",
|
|
@@ -16713,8 +16716,15 @@ function formatRunEvidence(run, startedAt) {
|
|
|
16713
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}`);
|
|
16714
16717
|
const done = (phase) => run.phasesCompleted.includes(phase);
|
|
16715
16718
|
const ifDone = (phase, value) => done(phase) ? value : "?";
|
|
16716
|
-
|
|
16717
|
-
if (
|
|
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}` + (md.flip ? ` (flipped to plan: no delta at ${md.flip})` : "") + ` \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")) {
|
|
16718
16728
|
out += row("", `(\`?\` = the phase that determines it did not complete \u2014 this run stopped in ${run.phaseReached})`);
|
|
16719
16729
|
}
|
|
16720
16730
|
out += row("sent", `${sent.length} \xB7 ${list(sent)}`);
|
|
@@ -16741,6 +16751,46 @@ function formatRunEvidence(run, startedAt) {
|
|
|
16741
16751
|
out += row("withheld", "(nothing \u2014 every changed file was reviewed)");
|
|
16742
16752
|
}
|
|
16743
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
|
+
}
|
|
16744
16794
|
if (run.staticResults.findings.length > 0) {
|
|
16745
16795
|
out += row("static", `${run.staticResults.findings.length} finding(s) from ${run.staticResults.summary.tools_run.join(", ") || "no tools"}`);
|
|
16746
16796
|
}
|
|
@@ -16936,6 +16986,8 @@ function buildSummary(lines) {
|
|
|
16936
16986
|
break;
|
|
16937
16987
|
case "Agent":
|
|
16938
16988
|
case "Task":
|
|
16989
|
+
case "Workflow":
|
|
16990
|
+
case "SendMessage":
|
|
16939
16991
|
subagents++;
|
|
16940
16992
|
break;
|
|
16941
16993
|
case "WebFetch":
|
|
@@ -17190,7 +17242,7 @@ function channelSilence(input) {
|
|
|
17190
17242
|
// src/lib/cli-version.ts
|
|
17191
17243
|
function cliVersion() {
|
|
17192
17244
|
try {
|
|
17193
|
-
return true ? "0.29.4-experimental.
|
|
17245
|
+
return true ? "0.29.4-experimental.7126d67" : "dev";
|
|
17194
17246
|
} catch {
|
|
17195
17247
|
return "dev";
|
|
17196
17248
|
}
|
|
@@ -17541,18 +17593,26 @@ var SPEC_CANDIDATES = [
|
|
|
17541
17593
|
"docs/API.md",
|
|
17542
17594
|
"spec/ARCHITECTURE.md"
|
|
17543
17595
|
];
|
|
17544
|
-
|
|
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 = []) {
|
|
17545
17600
|
const result = [];
|
|
17546
17601
|
const seen = /* @__PURE__ */ new Set();
|
|
17547
17602
|
let totalBytes = 0;
|
|
17548
|
-
const
|
|
17603
|
+
const consultedDocs = new Set(
|
|
17604
|
+
consulted.filter((p) => DOC_EXT.test(p) && !p.startsWith("/") && !p.includes(".."))
|
|
17605
|
+
);
|
|
17606
|
+
const addSpec = (specPath, relevant = false) => {
|
|
17549
17607
|
if (result.length >= MAX_SPEC_FILES) return false;
|
|
17550
|
-
|
|
17608
|
+
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
17609
|
+
if (totalBytes >= totalCap) return false;
|
|
17551
17610
|
if (seen.has(specPath)) return true;
|
|
17552
17611
|
if (!(0, import_node_fs21.existsSync)(specPath)) return true;
|
|
17553
17612
|
seen.add(specPath);
|
|
17554
|
-
const remaining =
|
|
17555
|
-
const
|
|
17613
|
+
const remaining = totalCap - totalBytes;
|
|
17614
|
+
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
17615
|
+
const readBytes = Math.min(fileCap, remaining);
|
|
17556
17616
|
try {
|
|
17557
17617
|
const buf = Buffer.alloc(readBytes);
|
|
17558
17618
|
const fd = (0, import_node_fs21.openSync)(specPath, "r");
|
|
@@ -17566,6 +17626,9 @@ function discoverSpecs() {
|
|
|
17566
17626
|
}
|
|
17567
17627
|
return true;
|
|
17568
17628
|
};
|
|
17629
|
+
for (const doc of consultedDocs) {
|
|
17630
|
+
if (!addSpec(doc, true)) break;
|
|
17631
|
+
}
|
|
17569
17632
|
for (const candidate of SPEC_CANDIDATES) {
|
|
17570
17633
|
if (!addSpec(candidate)) break;
|
|
17571
17634
|
}
|
|
@@ -17636,7 +17699,7 @@ function discoverPlans() {
|
|
|
17636
17699
|
async function intentInputs(run) {
|
|
17637
17700
|
const { actionSummary, allForReview, assistantResponse, baseline, baselineSessionId } = run;
|
|
17638
17701
|
const conversation = await readAndClearConversationBuffer(baselineSessionId);
|
|
17639
|
-
const specs = discoverSpecs();
|
|
17702
|
+
const specs = discoverSpecs(actionSummary?.files_read ?? []);
|
|
17640
17703
|
const plans = discoverPlans();
|
|
17641
17704
|
const agentAuthoredCodeThisTurn = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0));
|
|
17642
17705
|
const turnAuthoredCode = agentAuthoredCodeThisTurn || !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
|
|
@@ -17859,7 +17922,8 @@ async function mode(run) {
|
|
|
17859
17922
|
let analysisMode;
|
|
17860
17923
|
const sessionAuthoredCode = !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
|
|
17861
17924
|
const modeOverride = opts.mode;
|
|
17862
|
-
|
|
17925
|
+
const forced = !!modeOverride && ["standard", "plan", "debug", "skip"].includes(modeOverride);
|
|
17926
|
+
if (forced) {
|
|
17863
17927
|
analysisMode = modeOverride;
|
|
17864
17928
|
} else {
|
|
17865
17929
|
analysisMode = reconcileAnalysisMode(
|
|
@@ -17867,6 +17931,25 @@ async function mode(run) {
|
|
|
17867
17931
|
{ noFilesChanged, assistantResponse, actionSummary, conversationPrompts, sessionAuthoredCode }
|
|
17868
17932
|
);
|
|
17869
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
|
+
});
|
|
17870
17953
|
if (analysisMode === "skip") {
|
|
17871
17954
|
await passAndExit(
|
|
17872
17955
|
run,
|
|
@@ -18132,6 +18215,18 @@ function commandShape(cmd) {
|
|
|
18132
18215
|
return out.join(" ").slice(0, COMMAND_HEAD_CHARS);
|
|
18133
18216
|
}
|
|
18134
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
|
+
}
|
|
18135
18230
|
var rootCandidateCache = /* @__PURE__ */ new Map();
|
|
18136
18231
|
function candidateRoots(repoRoot2) {
|
|
18137
18232
|
const cached2 = rootCandidateCache.get(repoRoot2);
|
|
@@ -18160,27 +18255,46 @@ function toRepoRelative(path, repoRoot2) {
|
|
|
18160
18255
|
}
|
|
18161
18256
|
return p.replace(/^\/+/, "");
|
|
18162
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
|
+
}
|
|
18163
18267
|
function fold(transcriptPath, opts = {}) {
|
|
18164
18268
|
const result = {
|
|
18165
18269
|
authored: [],
|
|
18166
18270
|
unobserved: [],
|
|
18167
18271
|
commands: [],
|
|
18272
|
+
tools: [],
|
|
18273
|
+
tasks: [],
|
|
18168
18274
|
unknownTypes: [],
|
|
18169
18275
|
coverage: {
|
|
18170
18276
|
recordCounts: {},
|
|
18171
18277
|
totalRecords: 0,
|
|
18172
18278
|
malformed: 0,
|
|
18173
18279
|
subagentFiles: 0,
|
|
18280
|
+
outsideRepo: 0,
|
|
18281
|
+
toolNamesDropped: 0,
|
|
18174
18282
|
dispatched: 0,
|
|
18175
18283
|
userMessages: 0,
|
|
18176
18284
|
subagentSkipped: 0,
|
|
18177
18285
|
compactions: 0,
|
|
18178
18286
|
complete: false
|
|
18179
|
-
}
|
|
18287
|
+
},
|
|
18288
|
+
planApproval: { approvals: 0, activeSinceLastPrompt: false }
|
|
18180
18289
|
};
|
|
18290
|
+
const flow = { seq: 0, lastPrompt: -1, lastApproval: -1, approvals: 0 };
|
|
18181
18291
|
const byPath = /* @__PURE__ */ new Map();
|
|
18182
18292
|
const commandStats = /* @__PURE__ */ new Map();
|
|
18183
18293
|
const pendingByToolUse = /* @__PURE__ */ new Map();
|
|
18294
|
+
const toolStats = /* @__PURE__ */ new Map();
|
|
18295
|
+
const pendingToolName = /* @__PURE__ */ new Map();
|
|
18296
|
+
const taskById = /* @__PURE__ */ new Map();
|
|
18297
|
+
const pendingTaskName = /* @__PURE__ */ new Map();
|
|
18184
18298
|
const unknown = /* @__PURE__ */ new Set();
|
|
18185
18299
|
const ingest = (raw, owner) => {
|
|
18186
18300
|
for (const line of raw.split("\n")) {
|
|
@@ -18199,8 +18313,12 @@ function fold(transcriptPath, opts = {}) {
|
|
|
18199
18313
|
if (type === "system" && record.subtype === "compact_boundary") {
|
|
18200
18314
|
result.coverage.compactions++;
|
|
18201
18315
|
}
|
|
18202
|
-
if (type === "user" && hasUserText(record))
|
|
18203
|
-
|
|
18316
|
+
if (type === "user" && hasUserText(record)) {
|
|
18317
|
+
result.coverage.userMessages++;
|
|
18318
|
+
if (owner === "agent") flow.lastPrompt = flow.seq;
|
|
18319
|
+
}
|
|
18320
|
+
if (owner === "agent") flow.seq++;
|
|
18321
|
+
collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, toolStats, pendingToolName, taskById, pendingTaskName, opts.repoRoot, result.coverage, flow);
|
|
18204
18322
|
}
|
|
18205
18323
|
};
|
|
18206
18324
|
try {
|
|
@@ -18211,7 +18329,11 @@ function fold(transcriptPath, opts = {}) {
|
|
|
18211
18329
|
return result;
|
|
18212
18330
|
}
|
|
18213
18331
|
try {
|
|
18214
|
-
const sidecarDir = (0, import_node_path18.join)(
|
|
18332
|
+
const sidecarDir = (0, import_node_path18.join)(
|
|
18333
|
+
(0, import_node_path18.dirname)(transcriptPath),
|
|
18334
|
+
(0, import_node_path18.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
18335
|
+
"subagents"
|
|
18336
|
+
);
|
|
18215
18337
|
if ((0, import_node_fs23.existsSync)(sidecarDir)) {
|
|
18216
18338
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
18217
18339
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
@@ -18254,12 +18376,24 @@ function fold(transcriptPath, opts = {}) {
|
|
|
18254
18376
|
result.authored = [...byPath.values()].sort((a, b) => a.p.localeCompare(b.p));
|
|
18255
18377
|
result.unknownTypes = [...unknown].sort();
|
|
18256
18378
|
result.commands = [...commandStats.entries()].map(([cls, s]) => ({ class: cls, ...s })).sort((a, b) => a.class.localeCompare(b.class));
|
|
18379
|
+
result.tools = [...toolStats.entries()].map(([name, s]) => ({
|
|
18380
|
+
name,
|
|
18381
|
+
runs: s.runs,
|
|
18382
|
+
failed: s.failed,
|
|
18383
|
+
last_status: s.last_status,
|
|
18384
|
+
targets: [...s.targets].map((t) => toRepoRelative(t, opts.repoRoot)).sort()
|
|
18385
|
+
})).sort((a, b) => b.runs - a.runs || a.name.localeCompare(b.name));
|
|
18386
|
+
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));
|
|
18257
18387
|
const authoredPaths = new Set(result.authored.map((a) => a.p));
|
|
18258
18388
|
for (const raw of opts.changedFiles ?? []) {
|
|
18259
18389
|
const p = toRepoRelative(raw, opts.repoRoot);
|
|
18260
18390
|
if (!p || authoredPaths.has(p)) continue;
|
|
18261
18391
|
result.unobserved.push({ p, cause: classifyUnobserved(raw) });
|
|
18262
18392
|
}
|
|
18393
|
+
result.planApproval = {
|
|
18394
|
+
approvals: flow.approvals,
|
|
18395
|
+
activeSinceLastPrompt: flow.lastApproval >= 0 && flow.lastApproval > flow.lastPrompt
|
|
18396
|
+
};
|
|
18263
18397
|
return result;
|
|
18264
18398
|
}
|
|
18265
18399
|
function classifyUnobserved(path) {
|
|
@@ -18272,7 +18406,7 @@ function classifyUnobserved(path) {
|
|
|
18272
18406
|
if (/\.(png|jpg|jpeg|gif|pdf|zip|woff2?|ico|mp4)$/i.test(path)) return "binary";
|
|
18273
18407
|
return "no_edit_record";
|
|
18274
18408
|
}
|
|
18275
|
-
function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, repoRoot2, tally) {
|
|
18409
|
+
function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse, toolStats, pendingToolName, taskById, pendingTaskName, repoRoot2, tally, flow) {
|
|
18276
18410
|
const message = record.message;
|
|
18277
18411
|
const content = message?.content ?? record.content;
|
|
18278
18412
|
const blocks = Array.isArray(content) ? content : content && typeof content === "object" ? [content] : [];
|
|
@@ -18281,8 +18415,38 @@ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse
|
|
|
18281
18415
|
if (blockType === "tool_use") {
|
|
18282
18416
|
const name = String(block.name ?? "");
|
|
18283
18417
|
const input = block.input ?? {};
|
|
18418
|
+
if (name && toolStats.size < MAX_TOOL_NAMES) {
|
|
18419
|
+
const prev = toolStats.get(name) ?? { runs: 0, failed: 0, last_status: null, targets: /* @__PURE__ */ new Set() };
|
|
18420
|
+
prev.targets = prev.targets ?? /* @__PURE__ */ new Set();
|
|
18421
|
+
if (prev.targets.size < MAX_TOOL_TARGETS) {
|
|
18422
|
+
const target = toolTarget(name, input);
|
|
18423
|
+
if (target) prev.targets.add(target);
|
|
18424
|
+
}
|
|
18425
|
+
toolStats.set(name, { runs: prev.runs + 1, failed: prev.failed, last_status: null, targets: prev.targets });
|
|
18426
|
+
const toolId = typeof block.id === "string" ? block.id : null;
|
|
18427
|
+
if (toolId) pendingToolName.set(toolId, name);
|
|
18428
|
+
} else if (name && tally) {
|
|
18429
|
+
tally.toolNamesDropped += 1;
|
|
18430
|
+
}
|
|
18431
|
+
if (name === "TaskCreate") {
|
|
18432
|
+
const subject = typeof input.subject === "string" ? input.subject : "";
|
|
18433
|
+
const taskId = typeof block.id === "string" ? block.id : null;
|
|
18434
|
+
if (subject && taskId) pendingTaskName.set(taskId, subject.slice(0, TASK_NAME_CHARS));
|
|
18435
|
+
}
|
|
18436
|
+
if (name === "TaskUpdate") {
|
|
18437
|
+
const id = typeof input.taskId === "string" ? input.taskId : "";
|
|
18438
|
+
const status = typeof input.status === "string" ? input.status : "";
|
|
18439
|
+
if (id && status) {
|
|
18440
|
+
const entry = taskById.get(id);
|
|
18441
|
+
taskById.set(id, { name: entry?.name ?? `#${id}`, status });
|
|
18442
|
+
}
|
|
18443
|
+
}
|
|
18284
18444
|
if (EDIT_TOOLS.has(name)) {
|
|
18285
18445
|
const rawPath = typeof input.notebook_path === "string" ? input.notebook_path : typeof input.file_path === "string" ? input.file_path : null;
|
|
18446
|
+
if (rawPath && !isInsideRepo(rawPath, repoRoot2)) {
|
|
18447
|
+
if (tally) tally.outsideRepo += 1;
|
|
18448
|
+
continue;
|
|
18449
|
+
}
|
|
18286
18450
|
const path = rawPath ? toRepoRelative(rawPath, repoRoot2) : null;
|
|
18287
18451
|
if (path) {
|
|
18288
18452
|
const entry = byPath.get(path) ?? { p: path, h: 0, a: 0, d: 0, owner };
|
|
@@ -18316,6 +18480,38 @@ function collectFromRecord(record, owner, byPath, commandStats, pendingByToolUse
|
|
|
18316
18480
|
}
|
|
18317
18481
|
if (blockType === "tool_result") {
|
|
18318
18482
|
const id = typeof block.tool_use_id === "string" ? block.tool_use_id : null;
|
|
18483
|
+
const taskName = id ? pendingTaskName.get(id) : void 0;
|
|
18484
|
+
if (taskName) {
|
|
18485
|
+
pendingTaskName.delete(id);
|
|
18486
|
+
const body = typeof block.content === "string" ? block.content : "";
|
|
18487
|
+
const created = /Task #(\d+)/.exec(body);
|
|
18488
|
+
if (created && taskById.size < MAX_TASKS) {
|
|
18489
|
+
taskById.set(created[1], { name: taskName, status: taskById.get(created[1])?.status ?? "created" });
|
|
18490
|
+
}
|
|
18491
|
+
}
|
|
18492
|
+
const toolName = id ? pendingToolName.get(id) : void 0;
|
|
18493
|
+
if (toolName === "ExitPlanMode" && flow && block.is_error !== true) {
|
|
18494
|
+
const body = typeof block.content === "string" ? block.content : Array.isArray(block.content) ? block.content.map((c) => typeof c.text === "string" ? c.text : "").join(" ") : "";
|
|
18495
|
+
if (/approved your plan/i.test(body)) {
|
|
18496
|
+
flow.lastApproval = flow.seq;
|
|
18497
|
+
flow.approvals += 1;
|
|
18498
|
+
}
|
|
18499
|
+
}
|
|
18500
|
+
if (toolName) {
|
|
18501
|
+
pendingToolName.delete(id);
|
|
18502
|
+
const prevTool = toolStats.get(toolName);
|
|
18503
|
+
if (prevTool) {
|
|
18504
|
+
const failed = block.is_error === true;
|
|
18505
|
+
toolStats.set(toolName, {
|
|
18506
|
+
runs: prevTool.runs,
|
|
18507
|
+
failed: prevTool.failed + (failed ? 1 : 0),
|
|
18508
|
+
last_status: block.is_error === true ? 1 : block.is_error === false ? 0 : null,
|
|
18509
|
+
// Carried, not rebuilt: the targets were collected on the `tool_use`
|
|
18510
|
+
// side and dropping them here would empty the ledger on every result.
|
|
18511
|
+
targets: prevTool.targets
|
|
18512
|
+
});
|
|
18513
|
+
}
|
|
18514
|
+
}
|
|
18319
18515
|
const cls = id ? pendingByToolUse.get(id) : void 0;
|
|
18320
18516
|
if (!cls) continue;
|
|
18321
18517
|
pendingByToolUse.delete(id);
|
|
@@ -18358,8 +18554,13 @@ function checkConservation(changedFiles, result, repoRoot2) {
|
|
|
18358
18554
|
// src/commands/analyze/phases/06-evidence.ts
|
|
18359
18555
|
async function evidence(run) {
|
|
18360
18556
|
const { opts } = run;
|
|
18361
|
-
const { actionSummary, allForReview, analyzable, assistantResponse, authorshipIsObservable, baseline, baselineSessionId, hasRecentCommitFiles, reviewable, securityFiles, sessionAuthoredCode, transcriptPath } = run;
|
|
18557
|
+
const { actionSummary, allForReview, analyzable, assistantResponse, authorshipIsObservable, baseline, baselineSessionId, hasRecentCommitFiles, reviewable, securityFiles, sessionAuthoredCode, transcriptPath, turnAuthoredCode } = run;
|
|
18362
18558
|
let { analysisMode, earlyFold } = run;
|
|
18559
|
+
const recordFlip = (stage) => {
|
|
18560
|
+
if (run.modeDecision) run.modeDecision = { ...run.modeDecision, resolved: "plan", flip: stage };
|
|
18561
|
+
logEvent("mode_flipped", { stage, to: "plan" });
|
|
18562
|
+
};
|
|
18563
|
+
const planWorthy = !!assistantResponse && !turnAuthoredCode;
|
|
18363
18564
|
let staticResults = {
|
|
18364
18565
|
tool: "@codacy/analysis-cli",
|
|
18365
18566
|
findings: [],
|
|
@@ -18379,8 +18580,9 @@ async function evidence(run) {
|
|
|
18379
18580
|
const debounceSeconds = parseInt(opts.debounce, 10);
|
|
18380
18581
|
const debounceSkip = checkDebounce(debounceSeconds, baselineSessionId);
|
|
18381
18582
|
if (debounceSkip) {
|
|
18382
|
-
if (
|
|
18583
|
+
if (planWorthy) {
|
|
18383
18584
|
analysisMode = "plan";
|
|
18585
|
+
recordFlip("debounce");
|
|
18384
18586
|
} else {
|
|
18385
18587
|
await passAndExit(run, debounceSkip, "debounce");
|
|
18386
18588
|
}
|
|
@@ -18389,8 +18591,9 @@ async function evidence(run) {
|
|
|
18389
18591
|
const allCheckable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...reviewable, ...securityFiles]));
|
|
18390
18592
|
const mtimeSkip = checkMtime(allCheckable, hasRecentCommitFiles, baselineSessionId);
|
|
18391
18593
|
if (mtimeSkip) {
|
|
18392
|
-
if (
|
|
18594
|
+
if (planWorthy) {
|
|
18393
18595
|
analysisMode = "plan";
|
|
18596
|
+
recordFlip("mtime");
|
|
18394
18597
|
} else {
|
|
18395
18598
|
await passAndExit(run, mtimeSkip, "no-delta-since-last-review");
|
|
18396
18599
|
}
|
|
@@ -18401,8 +18604,9 @@ async function evidence(run) {
|
|
|
18401
18604
|
const allCheckable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...reviewable, ...securityFiles]));
|
|
18402
18605
|
const hashResult = checkContentHash(allCheckable, baselineSessionId);
|
|
18403
18606
|
if (hashResult.skip) {
|
|
18404
|
-
if (
|
|
18607
|
+
if (planWorthy) {
|
|
18405
18608
|
analysisMode = "plan";
|
|
18609
|
+
recordFlip("content-hash");
|
|
18406
18610
|
} else {
|
|
18407
18611
|
await passAndExit(run, hashResult.skip, "no-delta-since-last-review");
|
|
18408
18612
|
}
|
|
@@ -18464,8 +18668,9 @@ async function evidence(run) {
|
|
|
18464
18668
|
maxTotalBytes: parseInt(opts.maxTotalSize, 10)
|
|
18465
18669
|
});
|
|
18466
18670
|
if (codeDelta.files.length === 0 && staticResults.findings.length === 0) {
|
|
18467
|
-
if (
|
|
18671
|
+
if (planWorthy) {
|
|
18468
18672
|
analysisMode = "plan";
|
|
18673
|
+
recordFlip("empty-after-scoping");
|
|
18469
18674
|
} else {
|
|
18470
18675
|
await passAndExit(
|
|
18471
18676
|
run,
|
|
@@ -19309,6 +19514,8 @@ async function buildRequest(run) {
|
|
|
19309
19514
|
authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
|
|
19310
19515
|
unobserved: foldResult?.unobserved ?? [],
|
|
19311
19516
|
commands: foldResult?.commands ?? [],
|
|
19517
|
+
tools: foldResult?.tools ?? [],
|
|
19518
|
+
tasks: foldResult?.tasks ?? [],
|
|
19312
19519
|
unknown_types: foldResult?.unknownTypes ?? [],
|
|
19313
19520
|
coverage: foldResult?.coverage ?? { recordCounts: {}, totalRecords: 0, malformed: 0, subagentFiles: 0, subagentSkipped: 0, complete: false },
|
|
19314
19521
|
// INV-19, computed client-side and sent so a conservation failure is
|
|
@@ -19419,6 +19626,10 @@ async function buildRequest(run) {
|
|
|
19419
19626
|
intentContext.user_prompt = w4Task.goal;
|
|
19420
19627
|
logEvent("w4_issue_anchor", { issue: w4Task.number, via: w4Task.via });
|
|
19421
19628
|
}
|
|
19629
|
+
if (foldResult?.planApproval?.activeSinceLastPrompt && intentContext.user_prompt) {
|
|
19630
|
+
intentContext.plan_approved = true;
|
|
19631
|
+
logEvent("plan_approval_carried", { approvals: foldResult.planApproval.approvals });
|
|
19632
|
+
}
|
|
19422
19633
|
if (assistantResponse) {
|
|
19423
19634
|
const cap = analysisMode === "plan" ? MAX_ASSISTANT_RESPONSE_CHARS_PLAN : MAX_ASSISTANT_RESPONSE_CHARS_DEFAULT;
|
|
19424
19635
|
intentContext.assistant_response = assistantResponse.length > cap ? assistantResponse.slice(0, cap) : assistantResponse;
|
|
@@ -19682,6 +19893,11 @@ async function reconcile(run) {
|
|
|
19682
19893
|
decision,
|
|
19683
19894
|
branch: getCurrentBranch(),
|
|
19684
19895
|
watermarkSha: watermarkIsPartial ? null : watermarkHash,
|
|
19896
|
+
// The byte witness — the same "only honest definition of reviewed" the
|
|
19897
|
+
// coverage column uses. A finding on a path outside this set records no
|
|
19898
|
+
// statement (plan-mode prose anchored to unsent files must not become
|
|
19899
|
+
// "STILL OPEN … the tree is not clean").
|
|
19900
|
+
sentPaths,
|
|
19685
19901
|
findings: response.findings?.map((f) => ({
|
|
19686
19902
|
file: f.file,
|
|
19687
19903
|
line: f.line,
|
|
@@ -21935,8 +22151,8 @@ function registerTelemetryCommands(program2) {
|
|
|
21935
22151
|
}
|
|
21936
22152
|
|
|
21937
22153
|
// src/cli.ts
|
|
21938
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.
|
|
21939
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.
|
|
22154
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.29.4-experimental.7126d67").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) => {
|
|
22155
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.29.4-experimental.7126d67");
|
|
21940
22156
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
21941
22157
|
try {
|
|
21942
22158
|
await foldLegacyLocalCredential();
|
package/package.json
CHANGED