@codacy/verity-cli 0.28.1-experimental.89ee5db → 0.28.1-experimental.902dbd9
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 +237 -17
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -10386,7 +10386,7 @@ function projectPath(relativePath) {
|
|
|
10386
10386
|
return (0, import_node_path.join)(repoRoot(), relativePath);
|
|
10387
10387
|
}
|
|
10388
10388
|
var MAX_DELTA_BYTES = 194560;
|
|
10389
|
-
var MAX_FILES =
|
|
10389
|
+
var MAX_FILES = 40;
|
|
10390
10390
|
var MAX_FILE_BYTES = 51200;
|
|
10391
10391
|
var DEBOUNCE_SECONDS = 30;
|
|
10392
10392
|
var MAX_SPEC_FILES = 10;
|
|
@@ -13654,6 +13654,79 @@ function shouldSkipForBareAck(input) {
|
|
|
13654
13654
|
return input.canSeeTurnAuthorship;
|
|
13655
13655
|
}
|
|
13656
13656
|
|
|
13657
|
+
// src/lib/pending-repeat.ts
|
|
13658
|
+
var STOP = /* @__PURE__ */ new Set([
|
|
13659
|
+
"the",
|
|
13660
|
+
"and",
|
|
13661
|
+
"that",
|
|
13662
|
+
"this",
|
|
13663
|
+
"with",
|
|
13664
|
+
"from",
|
|
13665
|
+
"have",
|
|
13666
|
+
"been",
|
|
13667
|
+
"were",
|
|
13668
|
+
"what",
|
|
13669
|
+
"when",
|
|
13670
|
+
"which",
|
|
13671
|
+
"their",
|
|
13672
|
+
"there",
|
|
13673
|
+
"these",
|
|
13674
|
+
"those",
|
|
13675
|
+
"would",
|
|
13676
|
+
"could",
|
|
13677
|
+
"should",
|
|
13678
|
+
"must",
|
|
13679
|
+
"will",
|
|
13680
|
+
"also",
|
|
13681
|
+
"just",
|
|
13682
|
+
"only",
|
|
13683
|
+
"into",
|
|
13684
|
+
"over",
|
|
13685
|
+
"than",
|
|
13686
|
+
"then",
|
|
13687
|
+
"them",
|
|
13688
|
+
"some",
|
|
13689
|
+
"such",
|
|
13690
|
+
"more",
|
|
13691
|
+
"most",
|
|
13692
|
+
"other",
|
|
13693
|
+
"about",
|
|
13694
|
+
"after",
|
|
13695
|
+
"before",
|
|
13696
|
+
"since",
|
|
13697
|
+
"because",
|
|
13698
|
+
"while",
|
|
13699
|
+
"where",
|
|
13700
|
+
"whether",
|
|
13701
|
+
"ensure",
|
|
13702
|
+
"confirm",
|
|
13703
|
+
"verify",
|
|
13704
|
+
"check"
|
|
13705
|
+
]);
|
|
13706
|
+
function pendingTokens(text) {
|
|
13707
|
+
if (!text || typeof text !== "string") return [];
|
|
13708
|
+
const out = /* @__PURE__ */ new Set();
|
|
13709
|
+
for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
13710
|
+
if (raw.length <= 3) continue;
|
|
13711
|
+
if (STOP.has(raw)) continue;
|
|
13712
|
+
out.add(raw);
|
|
13713
|
+
}
|
|
13714
|
+
return [...out].sort();
|
|
13715
|
+
}
|
|
13716
|
+
var REPEAT_THRESHOLD = 0.3;
|
|
13717
|
+
function overlapCoefficient(a, b) {
|
|
13718
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
13719
|
+
const setB = new Set(b);
|
|
13720
|
+
let shared = 0;
|
|
13721
|
+
for (const t of a) if (setB.has(t)) shared++;
|
|
13722
|
+
return shared / Math.min(a.length, b.length);
|
|
13723
|
+
}
|
|
13724
|
+
function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
|
|
13725
|
+
const tokens = pendingTokens(text);
|
|
13726
|
+
if (tokens.length === 0) return false;
|
|
13727
|
+
return priorFingerprints.some((prior) => overlapCoefficient(tokens, prior) >= threshold);
|
|
13728
|
+
}
|
|
13729
|
+
|
|
13657
13730
|
// src/lib/dossier.ts
|
|
13658
13731
|
var import_node_fs9 = require("node:fs");
|
|
13659
13732
|
var import_node_crypto4 = require("node:crypto");
|
|
@@ -13662,6 +13735,7 @@ var MAX_LINE_BYTES = 4096;
|
|
|
13662
13735
|
var MAX_GOAL_CHARS = 2e3;
|
|
13663
13736
|
var GOAL_KEEP = 8;
|
|
13664
13737
|
var GOAL_TOTAL_CAP = 32;
|
|
13738
|
+
var RECENT_PENDING_CAP = 20;
|
|
13665
13739
|
var HASH_WIDTH = 16;
|
|
13666
13740
|
var AUTHORED_CAP = 300;
|
|
13667
13741
|
var NOT_MINE_CAP = 300;
|
|
@@ -14030,6 +14104,10 @@ function reduce(state, events, now) {
|
|
|
14030
14104
|
consecutiveIdle: ev.idle === false ? 0 : (state.meta.channel?.consecutiveIdle ?? 0) + 1
|
|
14031
14105
|
};
|
|
14032
14106
|
state.meta.last_adjudication = ev.intent_verdict ? { verdict: ev.intent_verdict, score: ev.intent_score ?? null, at: ev.at, decision: ev.decision } : void 0;
|
|
14107
|
+
if (Array.isArray(ev.pending_sigs) && ev.pending_sigs.length > 0) {
|
|
14108
|
+
const prior = state.meta.recent_pending_sigs ?? [];
|
|
14109
|
+
state.meta.recent_pending_sigs = [...prior, ...ev.pending_sigs].slice(-RECENT_PENDING_CAP);
|
|
14110
|
+
}
|
|
14033
14111
|
if (ev.intent_sig) {
|
|
14034
14112
|
state.meta.intent_repeat = state.meta.intent_repeat && state.meta.intent_repeat.sig === ev.intent_sig ? { sig: ev.intent_sig, consecutive: state.meta.intent_repeat.consecutive + 1 } : { sig: ev.intent_sig, consecutive: 1 };
|
|
14035
14113
|
} else {
|
|
@@ -14886,6 +14964,13 @@ function recordVerdict(d, v) {
|
|
|
14886
14964
|
branch: v.branch,
|
|
14887
14965
|
decision: v.decision,
|
|
14888
14966
|
...sig && { intent_sig: sig },
|
|
14967
|
+
// Fingerprints of the pending items this verdict delivered, so the NEXT turn
|
|
14968
|
+
// can tell a repeat from a new requirement. Only recorded when the channel
|
|
14969
|
+
// actually spoke — a silenced turn delivered nothing, so nothing was "said
|
|
14970
|
+
// before" and labelling the next turn's items as repeats would be a lie.
|
|
14971
|
+
...v.emitted === true && v.pendingTexts && v.pendingTexts.length > 0 && {
|
|
14972
|
+
pending_sigs: v.pendingTexts.slice(0, 8).map((t) => pendingTokens(t).slice(0, 16))
|
|
14973
|
+
},
|
|
14889
14974
|
emitted: v.emitted === true,
|
|
14890
14975
|
idle: v.idle !== false,
|
|
14891
14976
|
...v.intent?.verdict && { intent_verdict: v.intent.verdict },
|
|
@@ -15542,6 +15627,34 @@ ${addedLines}`,
|
|
|
15542
15627
|
}
|
|
15543
15628
|
return { diffs, has_baseline: true };
|
|
15544
15629
|
}
|
|
15630
|
+
function absorbIntoBaseline(paths, sessionId) {
|
|
15631
|
+
const baseline = readBaseline(sessionId);
|
|
15632
|
+
if (!baseline || paths.length === 0) return 0;
|
|
15633
|
+
const dir = sessionDir(sessionKey(baseline.session_id));
|
|
15634
|
+
let adopted = 0;
|
|
15635
|
+
const dirty = new Set(baseline.dirty_paths);
|
|
15636
|
+
for (const p of paths) {
|
|
15637
|
+
try {
|
|
15638
|
+
const content = safeReadForMirror(projectPath(p));
|
|
15639
|
+
if (content === null) continue;
|
|
15640
|
+
const dest = mirrorPath(dir, p);
|
|
15641
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(dest), { recursive: true });
|
|
15642
|
+
(0, import_node_fs13.writeFileSync)(dest, content);
|
|
15643
|
+
dirty.add(p);
|
|
15644
|
+
adopted++;
|
|
15645
|
+
} catch {
|
|
15646
|
+
}
|
|
15647
|
+
}
|
|
15648
|
+
if (adopted === 0) return 0;
|
|
15649
|
+
try {
|
|
15650
|
+
const updated = { ...baseline, dirty_paths: [...dirty] };
|
|
15651
|
+
(0, import_node_fs13.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
|
|
15652
|
+
preImageCache.delete(baseline);
|
|
15653
|
+
} catch {
|
|
15654
|
+
return 0;
|
|
15655
|
+
}
|
|
15656
|
+
return adopted;
|
|
15657
|
+
}
|
|
15545
15658
|
function changedSinceBaseline(repoRelPath, baseline) {
|
|
15546
15659
|
const pre = preImage(repoRelPath, baseline);
|
|
15547
15660
|
let current;
|
|
@@ -16700,7 +16813,7 @@ function resolveTaskContext(opts) {
|
|
|
16700
16813
|
// src/lib/cli-version.ts
|
|
16701
16814
|
function cliVersion() {
|
|
16702
16815
|
try {
|
|
16703
|
-
return true ? "0.28.1-experimental.
|
|
16816
|
+
return true ? "0.28.1-experimental.902dbd9" : "dev";
|
|
16704
16817
|
} catch {
|
|
16705
16818
|
return "dev";
|
|
16706
16819
|
}
|
|
@@ -17374,9 +17487,13 @@ function buildAgentContext(input) {
|
|
|
17374
17487
|
}
|
|
17375
17488
|
for (const p of input.pendingItems ?? []) {
|
|
17376
17489
|
if (lines.length >= MAX_AGENT_ITEMS) break;
|
|
17490
|
+
if (p.pattern_id === "intent-misalignment") continue;
|
|
17377
17491
|
const text = p.description ?? p.title ?? p.reason;
|
|
17378
17492
|
if (!text) continue;
|
|
17379
|
-
|
|
17493
|
+
const seenBefore = isRepeatOfAny(text, input.priorPendingFingerprints ?? []);
|
|
17494
|
+
lines.push(
|
|
17495
|
+
renderItem("", text, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
|
|
17496
|
+
);
|
|
17380
17497
|
}
|
|
17381
17498
|
if (lines.length === 0) return null;
|
|
17382
17499
|
const body = `${REPORT_PREFIX}
|
|
@@ -17637,9 +17754,11 @@ var MAX_SUMMARY_BYTES = 4096;
|
|
|
17637
17754
|
var HOME = process.env.HOME ?? "";
|
|
17638
17755
|
async function extractActionSummary(transcriptPath) {
|
|
17639
17756
|
try {
|
|
17640
|
-
const
|
|
17641
|
-
if (!
|
|
17642
|
-
|
|
17757
|
+
const read = readTurnLines(transcriptPath);
|
|
17758
|
+
if (!read || read.lines.length === 0) return null;
|
|
17759
|
+
const summary = buildSummary(read.lines);
|
|
17760
|
+
if (summary) summary.transcript_windowed = read.window;
|
|
17761
|
+
return summary;
|
|
17643
17762
|
} catch {
|
|
17644
17763
|
return null;
|
|
17645
17764
|
}
|
|
@@ -17653,9 +17772,11 @@ function readTurnLines(transcriptPath) {
|
|
|
17653
17772
|
}
|
|
17654
17773
|
if (size === 0) return null;
|
|
17655
17774
|
let raw;
|
|
17775
|
+
let windowed = false;
|
|
17656
17776
|
if (size <= SMALL_FILE_BYTES) {
|
|
17657
17777
|
raw = (0, import_node_fs22.readFileSync)(transcriptPath, "utf-8");
|
|
17658
17778
|
} else {
|
|
17779
|
+
windowed = true;
|
|
17659
17780
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
17660
17781
|
const fd = require("node:fs").openSync(transcriptPath, "r");
|
|
17661
17782
|
try {
|
|
@@ -17673,17 +17794,22 @@ function readTurnLines(transcriptPath) {
|
|
|
17673
17794
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
17674
17795
|
if (allLines.length === 0) return null;
|
|
17675
17796
|
let turnStart = 0;
|
|
17797
|
+
let boundaryFound = false;
|
|
17676
17798
|
for (let i = allLines.length - 1; i >= 0; i--) {
|
|
17677
17799
|
try {
|
|
17678
17800
|
const parsed = JSON.parse(allLines[i]);
|
|
17679
17801
|
if (parsed.type === "user" && isRealUserMessage(parsed)) {
|
|
17680
17802
|
turnStart = i;
|
|
17803
|
+
boundaryFound = true;
|
|
17681
17804
|
break;
|
|
17682
17805
|
}
|
|
17683
17806
|
} catch {
|
|
17684
17807
|
}
|
|
17685
17808
|
}
|
|
17686
|
-
return
|
|
17809
|
+
return {
|
|
17810
|
+
lines: allLines.slice(turnStart),
|
|
17811
|
+
window: !windowed ? "whole" : boundaryFound ? "windowed" : "orphaned"
|
|
17812
|
+
};
|
|
17687
17813
|
}
|
|
17688
17814
|
function isRealUserMessage(parsed) {
|
|
17689
17815
|
const message = parsed.message;
|
|
@@ -18241,11 +18367,12 @@ async function readStopHookStdin() {
|
|
|
18241
18367
|
return empty;
|
|
18242
18368
|
}
|
|
18243
18369
|
}
|
|
18244
|
-
function agentContextFor(response, intentRepeat = 0) {
|
|
18370
|
+
function agentContextFor(response, intentRepeat = 0, priorPendingFingerprints = []) {
|
|
18245
18371
|
const metadata = response.metadata ?? {};
|
|
18246
18372
|
const intent = response.intent_alignment ?? {};
|
|
18247
18373
|
return buildAgentContext({
|
|
18248
18374
|
intentRepeat,
|
|
18375
|
+
priorPendingFingerprints,
|
|
18249
18376
|
gateDecision: String(response.gate_decision ?? ""),
|
|
18250
18377
|
findings: response.findings ?? [],
|
|
18251
18378
|
pendingItems: response.pending_items ?? [],
|
|
@@ -18381,13 +18508,21 @@ async function runAnalyze(opts, globals) {
|
|
|
18381
18508
|
const conversation = await readAndClearConversationBuffer(baselineSessionId);
|
|
18382
18509
|
const specs = discoverSpecs();
|
|
18383
18510
|
const plans = discoverPlans();
|
|
18511
|
+
const agentAuthoredCodeThisTurn = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0));
|
|
18512
|
+
const turnAuthoredCode = agentAuthoredCodeThisTurn || !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
|
|
18513
|
+
const canSeeTurnAuthorship = !!actionSummary || !!baseline;
|
|
18384
18514
|
const latestPrompt = conversation?.prompts?.[conversation.prompts.length - 1]?.prompt ?? "";
|
|
18385
18515
|
if (/^\s*\/verity-/i.test(latestPrompt)) {
|
|
18516
|
+
const setupAuthored = [
|
|
18517
|
+
...actionSummary?.files_edited ?? [],
|
|
18518
|
+
...actionSummary?.files_created ?? []
|
|
18519
|
+
];
|
|
18520
|
+
if (setupAuthored.length > 0) {
|
|
18521
|
+
const adopted = absorbIntoBaseline(setupAuthored, baselineSessionId);
|
|
18522
|
+
logEvent("baseline_absorbed", { skip: "verity-command", offered: setupAuthored.length, adopted });
|
|
18523
|
+
}
|
|
18386
18524
|
await passAndExit("Verity command \u2014 skipping analysis", "verity-command");
|
|
18387
18525
|
}
|
|
18388
|
-
const agentAuthoredCodeThisTurn = !!(actionSummary && (actionSummary.files_edited.length > 0 || actionSummary.files_created.length > 0));
|
|
18389
|
-
const turnAuthoredCode = agentAuthoredCodeThisTurn || !!baseline && allForReview.some((f) => changedSinceBaseline(f, baseline));
|
|
18390
|
-
const canSeeTurnAuthorship = !!actionSummary || !!baseline;
|
|
18391
18526
|
if (shouldSkipForBareAck({ prompt: latestPrompt, turnAuthoredCode, canSeeTurnAuthorship })) {
|
|
18392
18527
|
await passAndExit("Bare acknowledgment \u2014 skipping analysis", "bare-acknowledgment");
|
|
18393
18528
|
}
|
|
@@ -18437,7 +18572,11 @@ async function runAnalyze(opts, globals) {
|
|
|
18437
18572
|
);
|
|
18438
18573
|
}
|
|
18439
18574
|
if (analysisMode === "skip") {
|
|
18440
|
-
await passAndExit(
|
|
18575
|
+
await passAndExit(
|
|
18576
|
+
"Skip mode \u2014 no code work to analyze",
|
|
18577
|
+
"skip-mode",
|
|
18578
|
+
turnAuthoredCode ? "capacity" : void 0
|
|
18579
|
+
);
|
|
18441
18580
|
}
|
|
18442
18581
|
let staticResults = {
|
|
18443
18582
|
tool: "@codacy/analysis-cli",
|
|
@@ -18709,7 +18848,30 @@ async function runAnalyze(opts, globals) {
|
|
|
18709
18848
|
hasUserPrompt: (conversation?.prompts?.length ?? 0) > 0,
|
|
18710
18849
|
isTTY: process.stdout.isTTY === true
|
|
18711
18850
|
});
|
|
18851
|
+
const excludedByReason = {};
|
|
18852
|
+
for (const e of codeDelta.excluded ?? []) {
|
|
18853
|
+
excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
|
|
18854
|
+
}
|
|
18855
|
+
const coverageTelemetry = {
|
|
18856
|
+
// git's whole answer, before ANY narrowing. The number that has never been sent.
|
|
18857
|
+
changed_all: allChanged.length,
|
|
18858
|
+
analyzable: analyzable.length,
|
|
18859
|
+
reviewable: reviewable.length,
|
|
18860
|
+
security: securityFiles.length,
|
|
18861
|
+
// after the allowlist, before authorship scoping and the caps
|
|
18862
|
+
for_review: allForReview.length,
|
|
18863
|
+
// what actually reaches the reviewer
|
|
18864
|
+
sent: codeDelta.files.length,
|
|
18865
|
+
// the two silent narrowings, counted separately so they can be told apart
|
|
18866
|
+
capped_out: actionSummary?.capped_out?.length ?? 0,
|
|
18867
|
+
excluded: (codeDelta.excluded ?? []).length,
|
|
18868
|
+
excluded_by_reason: excludedByReason,
|
|
18869
|
+
// was the transcript itself truncated? The 256 KB window means "this turn"
|
|
18870
|
+
// can quietly mean "the last 256 KB of it".
|
|
18871
|
+
transcript_windowed: actionSummary?.transcript_windowed ?? null
|
|
18872
|
+
};
|
|
18712
18873
|
const requestBody = {
|
|
18874
|
+
coverage_telemetry: coverageTelemetry,
|
|
18713
18875
|
static_results: staticResults,
|
|
18714
18876
|
code_delta: codeDelta,
|
|
18715
18877
|
changed_files: allForReview,
|
|
@@ -18795,6 +18957,54 @@ async function runAnalyze(opts, globals) {
|
|
|
18795
18957
|
// replaced a population floor with ≈35% power that was sub-integer for
|
|
18796
18958
|
// three-quarters of the fleet.
|
|
18797
18959
|
conservation: foldConservation,
|
|
18960
|
+
// ⚠ VRT-52 — RECORDED, NOT APPLIED. The number nobody has.
|
|
18961
|
+
//
|
|
18962
|
+
// The whole "task-scoped delta" design space rests on an assumption that
|
|
18963
|
+
// has been observed exactly ONCE: that delta files routinely belong to
|
|
18964
|
+
// earlier work. Three designs were built on it and all three were killed
|
|
18965
|
+
// adversarially — two by measurement — so before another is attempted,
|
|
18966
|
+
// measure the base rate.
|
|
18967
|
+
//
|
|
18968
|
+
// `authored_under_earlier_goal` counts delta paths whose LAST authorship
|
|
18969
|
+
// event precedes the seq of the goal now in force. Both numbers come from
|
|
18970
|
+
// the same append-only counter (`nextSeq`), so the comparison is exact.
|
|
18971
|
+
//
|
|
18972
|
+
// Keyed on the GOAL, deliberately, not on the task id. The task classifier
|
|
18973
|
+
// reported `is_new_task` on two consecutive turns of one task 25 seconds
|
|
18974
|
+
// apart, so a task-keyed number would measure its unreliability rather
|
|
18975
|
+
// than the phenomenon. And this only became meaningful once `recordGoal`
|
|
18976
|
+
// stopped letting a bare "ok" supersede the goal — before that the seq
|
|
18977
|
+
// advanced every turn and this would have degenerated to "not edited this
|
|
18978
|
+
// turn", which is the exact mistake that sank one of the three designs.
|
|
18979
|
+
//
|
|
18980
|
+
// Changes no payload the reviewer sees, no narrowing, no verdict.
|
|
18981
|
+
vrt52: (() => {
|
|
18982
|
+
const goalSeq = memory?.projection.goal?.seq;
|
|
18983
|
+
if (goalSeq === void 0 || !memorySession) return { known: false };
|
|
18984
|
+
const lastSeq2 = new Map(
|
|
18985
|
+
foldDossier(memorySession.d).authored_all.map((a) => [a.path, a.last_seq])
|
|
18986
|
+
);
|
|
18987
|
+
let earlier = 0;
|
|
18988
|
+
let unknown = 0;
|
|
18989
|
+
for (const f of codeDelta.files) {
|
|
18990
|
+
const seen = lastSeq2.get(f.path);
|
|
18991
|
+
if (seen === void 0) unknown++;
|
|
18992
|
+
else if (seen < goalSeq) earlier++;
|
|
18993
|
+
}
|
|
18994
|
+
return {
|
|
18995
|
+
known: true,
|
|
18996
|
+
goal_seq: goalSeq,
|
|
18997
|
+
delta: codeDelta.files.length,
|
|
18998
|
+
// Files this delta carries that were last written under an EARLIER
|
|
18999
|
+
// instruction. If this stays near zero, VRT-52's code half is
|
|
19000
|
+
// unnecessary and should be closed saying so.
|
|
19001
|
+
authored_under_earlier_goal: earlier,
|
|
19002
|
+
// Delta files the dossier has no authorship record for at all —
|
|
19003
|
+
// pre-existing tree state, or an authorship channel the fold cannot
|
|
19004
|
+
// see. Reported separately so a blind spot is never counted as a zero.
|
|
19005
|
+
no_authorship_record: unknown
|
|
19006
|
+
};
|
|
19007
|
+
})(),
|
|
18798
19008
|
// P2 — RECORDED, NOT APPLIED. What this run WOULD have reviewed if it
|
|
18799
19009
|
// narrowed to the within-session increment: what changed since the last
|
|
18800
19010
|
// VERDICT rather than since task start.
|
|
@@ -19041,6 +19251,13 @@ async function runAnalyze(opts, globals) {
|
|
|
19041
19251
|
});
|
|
19042
19252
|
}
|
|
19043
19253
|
let intentRepeatCount = 0;
|
|
19254
|
+
const priorPendingFingerprints = memorySession ? (() => {
|
|
19255
|
+
try {
|
|
19256
|
+
return foldDossier(memorySession.d).meta.recent_pending_sigs ?? [];
|
|
19257
|
+
} catch {
|
|
19258
|
+
return [];
|
|
19259
|
+
}
|
|
19260
|
+
})() : [];
|
|
19044
19261
|
if (memorySession) {
|
|
19045
19262
|
try {
|
|
19046
19263
|
recordVerdict(memorySession.d, {
|
|
@@ -19063,7 +19280,10 @@ async function runAnalyze(opts, globals) {
|
|
|
19063
19280
|
// What next turn reads as `emittedLast`. A suppressed turn did not
|
|
19064
19281
|
// speak, so it cannot be the cause of the turn after it — which is what
|
|
19065
19282
|
// keeps this from becoming a permanent gag.
|
|
19066
|
-
emitted: !silenced
|
|
19283
|
+
emitted: !silenced,
|
|
19284
|
+
// Fingerprinted for the NEXT turn's repeat check. Reviewer pending items
|
|
19285
|
+
// carry no `pattern_id`, so their content is the only available key.
|
|
19286
|
+
pendingTexts: (response.pending_items ?? []).map((p) => String(p.description ?? p.title ?? p.reason ?? "")).filter(Boolean)
|
|
19067
19287
|
});
|
|
19068
19288
|
intentRepeatCount = Math.max(0, (foldDossier(memorySession.d).meta.intent_repeat?.consecutive ?? 1) - 1);
|
|
19069
19289
|
} catch {
|
|
@@ -19282,7 +19502,7 @@ ${YELLOW}${grantNudge.trim()}${NC}
|
|
|
19282
19502
|
// Subject to the SAME cycle cut as PASS/WARN. Suppressing here is safe:
|
|
19283
19503
|
// the findings themselves are rendered above by the blocking renderer,
|
|
19284
19504
|
// so what the cut removes is the repeated commentary, never the defect.
|
|
19285
|
-
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount),
|
|
19505
|
+
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount, priorPendingFingerprints),
|
|
19286
19506
|
// The coverage note is silenced with it — half a channel is still a channel.
|
|
19287
19507
|
silenced: !!silenced,
|
|
19288
19508
|
openElsewhere
|
|
@@ -19303,7 +19523,7 @@ ${YELLOW}${grantNudge.trim()}${NC}
|
|
|
19303
19523
|
changed: skipCoverageChanged,
|
|
19304
19524
|
coverage: reviewCoverage,
|
|
19305
19525
|
userSummary,
|
|
19306
|
-
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount),
|
|
19526
|
+
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount, priorPendingFingerprints),
|
|
19307
19527
|
// The coverage note is silenced with it — half a channel is still a channel.
|
|
19308
19528
|
silenced: !!silenced,
|
|
19309
19529
|
openElsewhere
|
|
@@ -19323,7 +19543,7 @@ ${YELLOW}${grantNudge.trim()}${NC}
|
|
|
19323
19543
|
changed: skipCoverageChanged,
|
|
19324
19544
|
coverage: reviewCoverage,
|
|
19325
19545
|
userSummary,
|
|
19326
|
-
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount),
|
|
19546
|
+
agentContext: silenced ? null : agentContextFor(response, intentRepeatCount, priorPendingFingerprints),
|
|
19327
19547
|
// The coverage note is silenced with it — half a channel is still a channel.
|
|
19328
19548
|
silenced: !!silenced,
|
|
19329
19549
|
openElsewhere
|
|
@@ -21127,7 +21347,7 @@ function registerTelemetryCommands(program2) {
|
|
|
21127
21347
|
}
|
|
21128
21348
|
|
|
21129
21349
|
// src/cli.ts
|
|
21130
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.28.1-experimental.
|
|
21350
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.28.1-experimental.902dbd9").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async () => {
|
|
21131
21351
|
try {
|
|
21132
21352
|
await foldLegacyLocalCredential();
|
|
21133
21353
|
} catch {
|