@codacy/verity-cli 0.34.0-experimental.7e3f52d → 0.34.0-experimental.8b93a3c

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 (3) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/bin/verity.js +125 -93
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -64,6 +64,78 @@ installs are untouched.
64
64
  which is the ordinary case for someone whose first Verity install *is* the
65
65
  plugin.
66
66
 
67
+ ## [0.34.0] — 2026-09-30
68
+
69
+ **Formal verification at push: Verity can now prove a bug is real before it
70
+ blocks — and the code map and the knowledge loop tell the reviewer more about
71
+ the code around a change.**
72
+
73
+ ### 🧮 Formal verification, opt-in
74
+
75
+ A third review at `git push`, next to the one-shot and the agent. It picks the
76
+ riskiest function the push changed, has the Verity service write a small Lean 4
77
+ model of it, checks the model on your machine, and replays any counterexample
78
+ on the real code in an isolated container with the network off. **Only a
79
+ reproduced bug blocks;** a counterexample that does not reproduce on the real
80
+ code is reported, never enforced. Most pushes get no model at all.
81
+
82
+ - **Off until you say yes.** `verity init` asks once, on a terminal, with "no"
83
+ as the default, and remembers either answer. `--yes` and headless runs are not
84
+ asked and never probe for a toolchain. `verity config formal push` turns it on
85
+ for a checkout, `verity config formal off` turns it off. It needs you to be
86
+ signed in: ranking, model writing and replay run on the Verity service. The
87
+ function's source is sent for the replay; no code is stored.
88
+ - **`verity lean install | status | remove`** manages the pinned official Lean 4
89
+ release under `~/.verity/lean` (≈800 MB download, 2.7 GB on disk). The
90
+ download is checksum-verified, abandoned after 60 s with nothing received,
91
+ and refused up front when the disk is short. An elan install is used when it
92
+ already has the pinned toolchain; Verity never makes elan download one.
93
+ - **On demand:** `verity prove candidates | generate | check | replay | auto`,
94
+ and the `/verity-prove <worry>` skill, where the words after the command are
95
+ what you want checked. Under the plugin, `/verity:verity-prove` arrives with
96
+ the plugin's next release.
97
+ - **A finding holds until the code changes.** Pushing the same bytes again
98
+ re-blocks without a new model. `verity prove waive <file>` accepts the risk
99
+ for the file's current bytes, and voids when they change.
100
+ - **Yours, never the repository's.** A `.verity/config.json` that git tracks,
101
+ or that is reached through a symlink, cannot switch formal verification on —
102
+ `verity doctor`, `verity config formal` and `verity init` say why it is off.
103
+ Findings and spend records a repository ships are ignored, and Lean never runs
104
+ on a `.verity/proofs/` workspace the repository supplies.
105
+ - **Admins can switch it off** per project, organization or globally with the
106
+ `formal` flag in the dashboard; the push then reports `disabled-by-server`.
107
+
108
+ ### 🗺️ The code map
109
+
110
+ The CLI now parses TypeScript, TSX, JavaScript, Python, Go and Java with bundled
111
+ tree-sitter grammars (about 6 MB added to the package).
112
+
113
+ - **The reviewer sees what else touches the same state.** At commit and push,
114
+ the review's context names the other functions that write the state a change
115
+ writes, and the agent reviewer can ask for a function's callers and
116
+ definitions. Formal verification models the exact function, not a guess at
117
+ its extent.
118
+ - **Reads use the bytes under review:** at a push, the pushed commit; at a
119
+ commit, the staged files — not whatever is in the working tree.
120
+ - **Paths the project denies are never shown** by the code tools or in the
121
+ code-map context.
122
+
123
+ ### 🧠 The knowledge loop
124
+
125
+ - **The reviewer says what it did with each node it was shown** — applied,
126
+ violated, irrelevant or unclear, each tied to a line in the change — and
127
+ ranking learns from it which nodes help. One scorer now chooses the nodes for
128
+ both the review and your agent's prompt.
129
+ - **A known rule said back to the agent.** When a change breaks a rule the
130
+ project has already learned, Verity can tell the agent which one. This ships
131
+ in shadow: the decision is made and recorded, and nothing is sent.
132
+ - **Fewer, better nodes.** The extractor's rubric was rewritten from 143
133
+ human-graded nodes; it no longer records what the code already says, and it
134
+ checks each new node against the nearest existing ones before adding it.
135
+ - **A failed diff in `verity memory` sync no longer drops a node edit you made.**
136
+ - **A failed knowledge lookup no longer fails a review.** The review runs
137
+ without knowledge and records that it did.
138
+
67
139
  ### 🎯 `/verity:init` does everything `verity init` does, in the session
68
140
 
69
141
  Under the plugin, setup used to stop short of the terminal flow: `/verity:init`
@@ -89,6 +161,11 @@ sign-in meant leaving Claude Code for a terminal.
89
161
  - **`verity telemetry install|uninstall` update `.verity/setup.json`**, so a
90
162
  request deferred until sign-in stops being reported as still to do.
91
163
 
164
+ ### 🔧 Fixed
165
+
166
+ - **A swapped `.verity` directory cannot redirect a write.** File writes check
167
+ the file they opened is the one they meant to write, after opening it.
168
+
92
169
  ## [0.33.3] — 2026-09-24
93
170
 
94
171
  **The knowledge seed runs once per project, not once per checkout.**
package/bin/verity.js CHANGED
@@ -17940,7 +17940,7 @@ function registerHooksCommands(program2) {
17940
17940
  }
17941
17941
 
17942
17942
  // src/commands/intent.ts
17943
- var import_node_crypto9 = require("node:crypto");
17943
+ var import_node_crypto10 = require("node:crypto");
17944
17944
 
17945
17945
  // src/lib/conversation-buffer.ts
17946
17946
  var import_promises5 = require("node:fs/promises");
@@ -20544,7 +20544,7 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
20544
20544
 
20545
20545
  // src/lib/dossier-session.ts
20546
20546
  var import_node_fs26 = require("node:fs");
20547
- var import_node_crypto8 = require("node:crypto");
20547
+ var import_node_crypto9 = require("node:crypto");
20548
20548
  var import_node_path22 = require("node:path");
20549
20549
 
20550
20550
  // src/lib/pending-repeat.ts
@@ -20621,6 +20621,7 @@ function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20621
20621
  }
20622
20622
 
20623
20623
  // src/lib/dossier/bounds.ts
20624
+ var import_node_crypto5 = require("node:crypto");
20624
20625
  var MAX_LINE_BYTES = 4096;
20625
20626
  var MAX_GOAL_CHARS = 2e3;
20626
20627
  var GOAL_KEEP = 8;
@@ -20632,10 +20633,17 @@ var NOT_MINE_CAP = 300;
20632
20633
  var STATEMENTS_OPEN_CAP = 40;
20633
20634
  var COMMANDS_CAP = 12;
20634
20635
  var DIVERGENCE_CAP = 10;
20635
- var DIVERGENCE_SEEN_CAP = 300;
20636
+ var DIVERGENCE_BULK_AT = 300;
20637
+ var DIVERGENCE_KEYS_PER_LINE = 200;
20636
20638
  function divergenceKey(path, hash) {
20637
20639
  return `${path}@${hash ?? "unknown"}`;
20638
20640
  }
20641
+ function packedDivergenceDigest(key) {
20642
+ return (0, import_node_crypto5.createHash)("sha256").update(key).digest("hex").slice(0, 12);
20643
+ }
20644
+ function packedDivergenceKey(digest) {
20645
+ return `#${digest}`;
20646
+ }
20639
20647
  var MARKS_CAP = 50;
20640
20648
  var ROTATE_BYTES = 1048576;
20641
20649
  var ROTATE_KEEP = 2;
@@ -20649,7 +20657,7 @@ function statementAnchorKey(file, patternId) {
20649
20657
  }
20650
20658
 
20651
20659
  // src/lib/dossier/log.ts
20652
- var import_node_crypto5 = require("node:crypto");
20660
+ var import_node_crypto6 = require("node:crypto");
20653
20661
  var import_node_fs22 = require("node:fs");
20654
20662
  var import_node_path20 = require("node:path");
20655
20663
  var CRC_TABLE = (() => {
@@ -20691,7 +20699,7 @@ function nextSeq() {
20691
20699
  function encodeEvent(ev) {
20692
20700
  const full = {
20693
20701
  v: 1,
20694
- id: (0, import_node_crypto5.randomBytes)(4).toString("hex"),
20702
+ id: (0, import_node_crypto6.randomBytes)(4).toString("hex"),
20695
20703
  ...ev
20696
20704
  };
20697
20705
  let body2 = JSON.stringify(full);
@@ -20762,7 +20770,7 @@ function rotateIfNeeded2(d) {
20762
20770
  }
20763
20771
 
20764
20772
  // src/lib/dossier/fold-dossier.ts
20765
- var import_node_crypto6 = require("node:crypto");
20773
+ var import_node_crypto7 = require("node:crypto");
20766
20774
  var import_node_fs23 = require("node:fs");
20767
20775
  var import_node_path21 = require("node:path");
20768
20776
  var EMPTY_CAPABILITIES = () => ({
@@ -20854,7 +20862,7 @@ function reduce(state, events, now) {
20854
20862
  state.meta.seq = Math.max(state.meta.seq, ev.seq);
20855
20863
  switch (ev.k) {
20856
20864
  case "goal": {
20857
- const hash = (0, import_node_crypto6.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20865
+ const hash = (0, import_node_crypto7.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20858
20866
  const prev = state.goal[state.goal.length - 1];
20859
20867
  if (prev && prev.hash === hash) {
20860
20868
  prev.repeats = (prev.repeats ?? 0) + 1;
@@ -20982,12 +20990,13 @@ function reduce(state, events, now) {
20982
20990
  break;
20983
20991
  }
20984
20992
  case "divergence": {
20985
- state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20986
20993
  state.divergence.events.push({ kind: ev.kind, path: ev.path, at: ev.at });
20987
- const key = divergenceKey(ev.path, ev.hash ?? null);
20988
- if (!seenDivergence.has(key)) {
20994
+ const keys = Array.isArray(ev.keys) ? ev.keys.filter((k) => typeof k === "string").map(packedDivergenceKey) : [divergenceKey(ev.path, ev.hash ?? null)];
20995
+ for (const key of keys) {
20996
+ if (seenDivergence.has(key)) continue;
20989
20997
  seenDivergence.add(key);
20990
- if (state.divergence.seen.length < DIVERGENCE_SEEN_CAP) state.divergence.seen.push(key);
20998
+ state.divergence.seen.push(key);
20999
+ state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20991
21000
  }
20992
21001
  break;
20993
21002
  }
@@ -21294,14 +21303,14 @@ function assessContinuity(i2) {
21294
21303
  }
21295
21304
 
21296
21305
  // src/lib/dossier/reanchor.ts
21297
- var import_node_crypto7 = require("node:crypto");
21306
+ var import_node_crypto8 = require("node:crypto");
21298
21307
  var import_node_fs25 = require("node:fs");
21299
21308
  function lineSha(text) {
21300
- return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21309
+ return (0, import_node_crypto8.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21301
21310
  }
21302
21311
  function fileHash(path) {
21303
21312
  try {
21304
- return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21313
+ return (0, import_node_crypto8.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21305
21314
  } catch {
21306
21315
  return null;
21307
21316
  }
@@ -21798,7 +21807,7 @@ function recordTurn(d, t) {
21798
21807
  // Identity is the COMMAND, not its category — otherwise `npm test -- a` and
21799
21808
  // `npm test -- b` are one row and the streak counts two different commands
21800
21809
  // as a run of one.
21801
- cmd_hash: (0, import_node_crypto8.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21810
+ cmd_hash: (0, import_node_crypto9.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21802
21811
  head: c.head || c.class,
21803
21812
  status: toStatus(c.last_status)
21804
21813
  });
@@ -21816,10 +21825,23 @@ function recordTurn(d, t) {
21816
21825
  }
21817
21826
  }
21818
21827
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
21828
+ const fresh = [];
21819
21829
  for (const u of t.unobserved) {
21820
21830
  const hash = fileHash((0, import_node_path22.join)(root, u.p));
21821
- if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
21822
- appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
21831
+ const key = divergenceKey(u.p, hash);
21832
+ const digest = packedDivergenceDigest(key);
21833
+ if (seenDivergence.has(key) || seenDivergence.has(packedDivergenceKey(digest))) continue;
21834
+ fresh.push({ path: u.p, hash, digest });
21835
+ }
21836
+ if (fresh.length > DIVERGENCE_BULK_AT) {
21837
+ for (let i2 = 0; i2 < fresh.length; i2 += DIVERGENCE_KEYS_PER_LINE) {
21838
+ const slice2 = fresh.slice(i2, i2 + DIVERGENCE_KEYS_PER_LINE);
21839
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: slice2[0].path, keys: slice2.map((f) => f.digest) });
21840
+ }
21841
+ } else {
21842
+ for (const f of fresh) {
21843
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: f.path, hash: f.hash });
21844
+ }
21823
21845
  }
21824
21846
  const newCompactions = (t.compactions ?? 0) - (t.known?.compactions ?? 0);
21825
21847
  for (let i2 = 0; i2 < newCompactions; i2++) {
@@ -22084,7 +22106,7 @@ async function fireClassify(prompt, sessionId, globals) {
22084
22106
  logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
22085
22107
  return;
22086
22108
  }
22087
- const promptHash = (0, import_node_crypto9.createHash)("sha256").update(prompt).digest("hex");
22109
+ const promptHash = (0, import_node_crypto10.createHash)("sha256").update(prompt).digest("hex");
22088
22110
  const result = await apiRequest({
22089
22111
  method: "POST",
22090
22112
  path: "/classify-task",
@@ -22128,7 +22150,7 @@ var import_node_path26 = require("node:path");
22128
22150
  // src/lib/baseline.ts
22129
22151
  var import_node_fs28 = require("node:fs");
22130
22152
  var import_node_path25 = require("node:path");
22131
- var import_node_crypto10 = require("node:crypto");
22153
+ var import_node_crypto11 = require("node:crypto");
22132
22154
 
22133
22155
  // src/lib/snapshot.ts
22134
22156
  var import_node_fs27 = require("node:fs");
@@ -22397,7 +22419,7 @@ var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
22397
22419
  var DEFAULT_SESSION_KEY = "_default";
22398
22420
  function sessionKey(sessionId) {
22399
22421
  if (!sessionId) return DEFAULT_SESSION_KEY;
22400
- return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22422
+ return (0, import_node_crypto11.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22401
22423
  }
22402
22424
  function sessionDir(key) {
22403
22425
  return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
@@ -24317,10 +24339,10 @@ var import_node_fs38 = require("node:fs");
24317
24339
 
24318
24340
  // src/lib/debounce.ts
24319
24341
  var import_node_fs37 = require("node:fs");
24320
- var import_node_crypto11 = require("node:crypto");
24342
+ var import_node_crypto12 = require("node:crypto");
24321
24343
  function scopedFile(base, sessionId) {
24322
24344
  if (!sessionId) return base;
24323
- return `${base}.${(0, import_node_crypto11.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24345
+ return `${base}.${(0, import_node_crypto12.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24324
24346
  }
24325
24347
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
24326
24348
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
@@ -24361,7 +24383,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
24361
24383
  return "No files modified since last analysis";
24362
24384
  }
24363
24385
  function computeContentHash(files) {
24364
- const hash = (0, import_node_crypto11.createHash)("sha1");
24386
+ const hash = (0, import_node_crypto12.createHash)("sha1");
24365
24387
  const sorted = [...files].sort();
24366
24388
  for (const f of sorted) {
24367
24389
  const resolved = resolveFile(f) ?? f;
@@ -27073,7 +27095,7 @@ function channelSilence(input) {
27073
27095
  // src/lib/cli-version.ts
27074
27096
  function cliVersion() {
27075
27097
  try {
27076
- return true ? "0.34.0-experimental.7e3f52d" : "dev";
27098
+ return true ? "0.34.0-experimental.8b93a3c" : "dev";
27077
27099
  } catch {
27078
27100
  return "dev";
27079
27101
  }
@@ -28541,7 +28563,7 @@ async function contextFiles(run4) {
28541
28563
  }
28542
28564
 
28543
28565
  // src/lib/code/index.ts
28544
- var import_node_crypto12 = require("node:crypto");
28566
+ var import_node_crypto13 = require("node:crypto");
28545
28567
 
28546
28568
  // src/lib/code/languages.ts
28547
28569
  var JS_LIKE = {
@@ -30319,7 +30341,7 @@ function byPath(fns, name2) {
30319
30341
  function makeCodeMap(rt) {
30320
30342
  const cache = /* @__PURE__ */ new Map();
30321
30343
  const outline = (path, content, deadlineAt = Date.now() + DEFAULT_PARSE_MS) => {
30322
- const key = `${path}\0${(0, import_node_crypto12.createHash)("sha1").update(content).digest("hex")}`;
30344
+ const key = `${path}\0${(0, import_node_crypto13.createHash)("sha1").update(content).digest("hex")}`;
30323
30345
  const hit = cache.get(key);
30324
30346
  if (hit) return { source: "tree-sitter", value: hit, elapsedMs: 0 };
30325
30347
  let r;
@@ -31688,6 +31710,22 @@ async function workingMemory(run4) {
31688
31710
  Object.assign(run4, { incrementReport, memory: memory2, memorySession, reachability });
31689
31711
  }
31690
31712
 
31713
+ // src/lib/payload-bounds.ts
31714
+ var MAX_WIRE_PATHS = 500;
31715
+ function boundPaths(paths, first, max = MAX_WIRE_PATHS) {
31716
+ if (paths.length <= max) return [...paths];
31717
+ const present = new Set(paths);
31718
+ const kept = /* @__PURE__ */ new Set();
31719
+ const out2 = [];
31720
+ for (const p of [...first, ...paths]) {
31721
+ if (out2.length >= max) break;
31722
+ if (!present.has(p) || kept.has(p)) continue;
31723
+ kept.add(p);
31724
+ out2.push(p);
31725
+ }
31726
+ return out2;
31727
+ }
31728
+
31691
31729
  // src/lib/note-budget.ts
31692
31730
  var import_node_fs49 = require("node:fs");
31693
31731
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
@@ -31802,6 +31840,7 @@ async function buildRequest(run4) {
31802
31840
  (conversation?.prompts?.length ?? 0) > 0
31803
31841
  );
31804
31842
  const noteConfirmation = peekNoteOutcome();
31843
+ const unobserved = foldResult?.unobserved ?? [];
31805
31844
  const excludedByReason = {};
31806
31845
  for (const e of codeDelta.excluded ?? []) {
31807
31846
  excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
@@ -31846,7 +31885,9 @@ async function buildRequest(run4) {
31846
31885
  coverage_telemetry: coverageTelemetry,
31847
31886
  static_results: staticResults,
31848
31887
  code_delta: codeDelta,
31849
- changed_files: allForReview,
31888
+ // Bounded, reviewed paths first — the server applies the same bound. The
31889
+ // full count is `coverage_telemetry.for_review`. VRT-242.
31890
+ changed_files: boundPaths(allForReview, codeDelta.files.map((f) => f.path)),
31850
31891
  standard_version: "latest",
31851
31892
  analysis_mode: analysisMode,
31852
31893
  plan_only: analysisMode === "plan",
@@ -31897,7 +31938,9 @@ async function buildRequest(run4) {
31897
31938
  // `hash_at_last_verdict` is frozen at each verdict and `hash_now` tracks
31898
31939
  // disk, so their inequality IS "changed since we last spoke".
31899
31940
  authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
31900
- unobserved: foldResult?.unobserved ?? [],
31941
+ // The server reads only how many; a bulk change sent every path. VRT-242.
31942
+ unobserved: unobserved.slice(0, MAX_WIRE_PATHS),
31943
+ ...unobserved.length > MAX_WIRE_PATHS && { unobserved_total: unobserved.length },
31901
31944
  commands: foldResult?.commands ?? [],
31902
31945
  tools: foldResult?.tools ?? [],
31903
31946
  tasks: foldResult?.tasks ?? [],
@@ -32061,11 +32104,11 @@ async function buildRequest(run4) {
32061
32104
 
32062
32105
  // src/lib/offline.ts
32063
32106
  var import_node_fs50 = require("node:fs");
32064
- var import_node_crypto13 = require("node:crypto");
32107
+ var import_node_crypto14 = require("node:crypto");
32065
32108
  function cacheRequest(body2) {
32066
32109
  try {
32067
32110
  (0, import_node_fs50.mkdirSync)(CACHE_DIR, { recursive: true });
32068
- const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
32111
+ const suffix = (0, import_node_crypto14.randomBytes)(4).toString("hex");
32069
32112
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
32070
32113
  (0, import_node_fs50.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32071
32114
  } catch {
@@ -32108,8 +32151,10 @@ function buildOfflineFallback(reason, staticResults) {
32108
32151
  }
32109
32152
 
32110
32153
  // src/lib/retry.ts
32154
+ var WORKER_RESOURCE_LIMIT = 546;
32111
32155
  function shouldWarmRetryAnalyze(result) {
32112
32156
  if (result.ok) return false;
32157
+ if (result.http_status === WORKER_RESOURCE_LIMIT) return false;
32113
32158
  if (result.category === "network" || result.category === "timeout") return true;
32114
32159
  if (result.category === "http_5xx") return true;
32115
32160
  if (result.category === "invalid_json" && (result.http_status ?? 0) >= 500) return true;
@@ -32119,7 +32164,7 @@ function shouldWarmRetryAnalyze(result) {
32119
32164
  // src/commands/analyze/phases/12-transmit.ts
32120
32165
  async function transmit(run4) {
32121
32166
  const { globals } = run4;
32122
- const { codeDelta, requestBody, serviceUrl, staticResults, token } = run4;
32167
+ const { requestBody, serviceUrl, staticResults, token } = run4;
32123
32168
  const ANALYZE_TIMEOUT_MS = 1e5;
32124
32169
  let result = await analyzeRequest({
32125
32170
  serviceUrl,
@@ -32156,11 +32201,12 @@ async function transmit(run4) {
32156
32201
  }
32157
32202
  if (!result.ok) {
32158
32203
  cacheRequest(requestBody);
32204
+ const sentKb = () => Math.round(Buffer.byteLength(JSON.stringify(requestBody)) / 1024);
32159
32205
  let message;
32160
32206
  if (result.http_status === 413) {
32161
- const totalBytes = codeDelta.files.reduce((sum, f) => sum + f.content.length, 0);
32162
- const kb = Math.round(totalBytes / 1024);
32163
- message = `Verity: request rejected \u2014 payload too large (${kb}KB over the 190KB cap). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32207
+ message = `Verity: request rejected \u2014 payload too large (${sentKb()} KB sent: ${result.error}). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32208
+ } else if (result.http_status === WORKER_RESOURCE_LIMIT) {
32209
+ message = `Verity: the service ran out of CPU or memory on this request (HTTP 546, ${sentKb()} KB sent). This is not a cold start: the same change fails the same way, so it was not retried. Commit or stash unrelated changes to shrink the request (local analysis this run).`;
32164
32210
  } else if (result.category === "network" || result.category === "timeout") {
32165
32211
  message = `Verity offline \u2014 ${result.error}`;
32166
32212
  } else if (result.error.startsWith("STALE_VERIFICATION")) {
@@ -33461,7 +33507,7 @@ async function runAgentReview(options) {
33461
33507
 
33462
33508
  // src/lib/prove/auto.ts
33463
33509
  var import_node_path44 = require("node:path");
33464
- var import_node_crypto18 = require("node:crypto");
33510
+ var import_node_crypto19 = require("node:crypto");
33465
33511
 
33466
33512
  // src/lib/prove/signals.ts
33467
33513
  var DEFAULT_SINCE = "180 days ago";
@@ -33869,6 +33915,11 @@ async function rankViaServer(candidates2, ctx, auth2) {
33869
33915
  cmd: "prove-rank"
33870
33916
  });
33871
33917
  if (!res.ok) return { ok: false, ranker: "luna", error: res.error, ranked: fallback };
33918
+ const off = res.data;
33919
+ if (off?.enabled === false) {
33920
+ const why = typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled";
33921
+ return { ok: false, ranker: "luna", error: `formal is off for this project (${why})`, ranked: fallback, disabled: why };
33922
+ }
33872
33923
  const items = Array.isArray(res.data?.items) ? res.data.items : [];
33873
33924
  return { ok: true, ranker: "luna", ranked: applyAnnotations(candidates2, items), costUsd: typeof res.data?.cost_usd === "number" ? res.data.cost_usd : null };
33874
33925
  }
@@ -34593,6 +34644,8 @@ async function generateModel(target, opts) {
34593
34644
  });
34594
34645
  if (!res.ok) return { ok: false, error: res.error };
34595
34646
  const d = res.data ?? {};
34647
+ const off = d;
34648
+ if (off.enabled === false) return { ok: false, error: `formal is off for this project (${typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled"})` };
34596
34649
  if (d.error && typeof d.error === "object") return { ok: false, error: `${d.error.code ?? "SERVICE_ERROR"}: ${d.error.message ?? "the service failed"}` };
34597
34650
  const usage2 = d.usage && typeof d.usage === "object" ? { inputTokens: Number(d.usage.inputTokens ?? 0), outputTokens: Number(d.usage.outputTokens ?? 0) } : null;
34598
34651
  return acceptAnswer(d, usage2, typeof d.cost_usd === "number" ? d.cost_usd : null);
@@ -34772,8 +34825,7 @@ Rules:
34772
34825
  5. Write the harness as ONE file and run it in the SAME shell call that writes it (a heredoc followed by the run). TypeScript: node --experimental-strip-types harness.ts (detect runtimes only if that fails: node --version, python3 --version); if strip-types is unavailable, remove type annotations ONLY on lines that are not part of the function under test's logic, and say so. Python: python3 harness.py.
34773
34826
  6. Nothing you run can reach the network. Do not try.
34774
34827
  7. Keep it under about eight shell calls. Output tokens are time.
34775
- 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters), impact (one word, below).
34776
- 9. impact \u2014 AFTER the verdict, and never a reason to change it: what the violation you ran costs a user of this code, the most serious one the run showed. money: a balance, charge, refund, price or stock is wrong. access: someone gets access they should not have, or an auth check is bypassed. data: a user's records are lost, corrupted or wrongly duplicated. external: an effect outside the system happens twice or never (a charge, an email, a shipment, a webhook). count: a counter, metric or statistic is off. cache: a cached or derived value is stale until it refreshes. internal: the program's own bookkeeping is off, with no effect a user would see. none: the verdict is not reproduced.
34828
+ 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters).
34777
34829
 
34778
34830
  "reproduced" means the real code, driven by the trace, reached the property violation the model describes. "diverged" means it did not \u2014 the model is wrong about the code, which is a useful answer. "unreplayable" means you could not run the real function faithfully; say why.`;
34779
34831
  var REPLAY_SCHEMA = {
@@ -34791,10 +34843,9 @@ var REPLAY_SCHEMA = {
34791
34843
  required: ["path", "lines"]
34792
34844
  }
34793
34845
  },
34794
- executed_output: { type: "string" },
34795
- impact: { type: "string", enum: ["money", "access", "data", "external", "count", "cache", "internal", "none"] }
34846
+ executed_output: { type: "string" }
34796
34847
  },
34797
- required: ["verdict", "reason", "harness_files", "executed_output", "impact"]
34848
+ required: ["verdict", "reason", "harness_files", "executed_output"]
34798
34849
  };
34799
34850
  function renderBriefInput(brief) {
34800
34851
  const p = brief.property;
@@ -34821,8 +34872,6 @@ function renderBriefInput(brief) {
34821
34872
  }
34822
34873
  return parts2.join("\n");
34823
34874
  }
34824
- var IMPACTS = ["money", "access", "data", "external", "count", "cache", "internal", "none"];
34825
- var isImpact = (v) => typeof v === "string" && IMPACTS.includes(v);
34826
34875
  function stringsIn(value, out2 = [], depth = 0) {
34827
34876
  if (depth > 8) return out2;
34828
34877
  if (typeof value === "string") out2.push(value);
@@ -34864,8 +34913,7 @@ function parseReplayOutput(output) {
34864
34913
  verdict,
34865
34914
  reason: typeof o.reason === "string" ? o.reason.slice(0, 2e3) : "",
34866
34915
  harness_files: Array.isArray(o.harness_files) ? o.harness_files.filter((f) => typeof f.path === "string").map((f) => ({ path: String(f.path).slice(0, 200), lines: Number.isInteger(f.lines) ? f.lines : 0 })) : [],
34867
- executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : "",
34868
- impact: isImpact(o.impact) ? o.impact : "none"
34916
+ executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : ""
34869
34917
  };
34870
34918
  }
34871
34919
  } catch {
@@ -35066,7 +35114,6 @@ async function runReplayInContainer(brief, opts) {
35066
35114
  ...judged,
35067
35115
  executedCalls,
35068
35116
  shellCalls,
35069
- ...judged.verdict === "reproduced" && parsed.claim ? { impact: parsed.claim.impact } : {},
35070
35117
  executedOutput: parsed.claim?.executed_output ?? "",
35071
35118
  harnessFiles: parsed.claim?.harness_files ?? [],
35072
35119
  usage,
@@ -35113,6 +35160,11 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35113
35160
  return { claimed: null, verdict: "unverified", reason: "", downgrade: res.error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: res.error };
35114
35161
  }
35115
35162
  const d = res.data ?? {};
35163
+ if (d.enabled === false) {
35164
+ const why = d.reason;
35165
+ const msg = `formal is off for this project (${typeof why === "string" ? why.slice(0, 40) : "disabled"})`;
35166
+ return { claimed: null, verdict: "unverified", reason: "", downgrade: msg, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: msg };
35167
+ }
35116
35168
  if (d.error && typeof d.error === "object") {
35117
35169
  const e = d.error;
35118
35170
  const msg = `${e.code ?? "SERVICE_ERROR"}: ${e.message ?? "the service failed"}`;
@@ -35125,7 +35177,6 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35125
35177
  verdict: verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable" ? verdict : "unverified",
35126
35178
  reason: typeof d.reason === "string" ? d.reason : "",
35127
35179
  downgrade: typeof d.downgrade === "string" ? d.downgrade : null,
35128
- ...isImpact(d.impact) ? { impact: d.impact } : {},
35129
35180
  executedCalls: Number(d.executed_calls ?? 0),
35130
35181
  shellCalls: Number(d.shell_calls ?? 0),
35131
35182
  verbatim: { covered: Number(v.covered ?? 0), total: Number(v.total ?? 0), ratio: Number(v.ratio ?? 0), basis: v.basis === "symbol" || v.basis === "file" ? v.basis : "none" },
@@ -35192,7 +35243,7 @@ var import_node_path42 = require("node:path");
35192
35243
 
35193
35244
  // src/lib/prove/safe-write.ts
35194
35245
  var import_node_fs56 = require("node:fs");
35195
- var import_node_crypto14 = require("node:crypto");
35246
+ var import_node_crypto15 = require("node:crypto");
35196
35247
  var import_node_path41 = require("node:path");
35197
35248
  var SafeWriteError = class extends Error {
35198
35249
  constructor(reason, path) {
@@ -35253,7 +35304,7 @@ function writeFileInRootNoFollow(root, rel, content) {
35253
35304
  } catch {
35254
35305
  throw new SafeWriteError("unwritable", root);
35255
35306
  }
35256
- const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
35307
+ const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35257
35308
  let fd;
35258
35309
  try {
35259
35310
  fd = (0, import_node_fs56.openSync)(tmp, import_node_fs56.constants.O_WRONLY | import_node_fs56.constants.O_CREAT | import_node_fs56.constants.O_EXCL | NOFOLLOW2, 420);
@@ -35655,7 +35706,7 @@ function existsNoFollow(abs) {
35655
35706
  }
35656
35707
 
35657
35708
  // src/lib/prove/report.ts
35658
- var import_node_crypto15 = require("node:crypto");
35709
+ var import_node_crypto16 = require("node:crypto");
35659
35710
  var IDENT2 = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/;
35660
35711
  var SHA256 = /^(sha256:)?[0-9a-f]{64}$/;
35661
35712
  var KINDS2 = /* @__PURE__ */ new Set(["structural", "intent"]);
@@ -35803,7 +35854,7 @@ function sha256InRoot(root, file) {
35803
35854
  const opened = openRegularInRoot(root, file);
35804
35855
  if (!opened.ok) return null;
35805
35856
  try {
35806
- return (0, import_node_crypto15.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
35857
+ return (0, import_node_crypto16.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
35807
35858
  } catch {
35808
35859
  return null;
35809
35860
  }
@@ -36108,33 +36159,18 @@ function writeResult(root, report) {
36108
36159
  function isCrashTrace(trace) {
36109
36160
  return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
36110
36161
  }
36111
- var SEVERITY_BY_IMPACT = {
36112
- money: "high",
36113
- access: "high",
36114
- data: "high",
36115
- external: "high",
36116
- count: "medium",
36117
- cache: "medium",
36118
- internal: "medium",
36119
- // A reproduced finding always has a real code; 'none' here is a malformed answer, so it blocks.
36120
- none: "high"
36121
- };
36122
- function formalSeverity(f) {
36123
- return f.impact && SEVERITY_BY_IMPACT[f.impact] || "high";
36124
- }
36125
36162
  function mergeFormalFindings(response, outcome, pushedFiles) {
36126
- if (!outcome) return { blocking: 0, warning: 0 };
36163
+ if (!outcome) return { blocking: 0 };
36127
36164
  const norm2 = (p) => p.replace(/\\/g, "/");
36128
36165
  const pushed = new Set(pushedFiles.map(norm2));
36129
- const reproduced = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36130
- if (reproduced.length === 0) return { blocking: 0, warning: 0 };
36131
- const blocking = reproduced.filter((f) => formalSeverity(f) === "high");
36166
+ const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36167
+ if (blocking.length === 0) return { blocking: 0 };
36132
36168
  const existing = Array.isArray(response.findings) ? response.findings : [];
36133
36169
  response.findings = [
36134
36170
  ...existing,
36135
- ...reproduced.map((f) => ({
36171
+ ...blocking.map((f) => ({
36136
36172
  pattern_id: "formal-counterexample",
36137
- severity: formalSeverity(f),
36173
+ severity: "high",
36138
36174
  scope: "change",
36139
36175
  file: f.file,
36140
36176
  line: outcome.target?.lines?.from ?? null,
@@ -36142,19 +36178,18 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
36142
36178
  // as a title it read backwards (e2e, 2026-09-26). A trace that needs a
36143
36179
  // crash between two writes is labelled: reproducing it means injecting
36144
36180
  // the crash, so it is a crash-consistency finding, not a race.
36145
- title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code${f.impact && f.impact !== "none" ? ` (impact: ${f.impact})` : ""}`,
36181
+ title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code`,
36146
36182
  description: terminalText(f.reason ?? "", 2e3),
36147
36183
  fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
36148
36184
  source: "formal"
36149
36185
  }))
36150
36186
  ];
36151
- if (blocking.length > 0) response.gate_decision = "FAIL";
36152
- else if (response.gate_decision === "PASS" || response.gate_decision == null) response.gate_decision = "WARN";
36153
- return { blocking: blocking.length, warning: reproduced.length - blocking.length };
36187
+ if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
36188
+ return { blocking: blocking.length };
36154
36189
  }
36155
36190
 
36156
36191
  // src/lib/prove/scalpel.ts
36157
- var import_node_crypto16 = require("node:crypto");
36192
+ var import_node_crypto17 = require("node:crypto");
36158
36193
  var ARITHMETIC = /Math\.(?:round|floor|ceil|trunc)\(|\bround\(|\bdivmod\(|[\w)\]]\s*(?:\*|\/(?!\/)|%)\s*[\w(]/;
36159
36194
  function functionHazard(numbered2) {
36160
36195
  const sites = effectSites(numbered2);
@@ -36184,7 +36219,7 @@ function semanticFingerprint(numbered2) {
36184
36219
  if (LOG_LINE.test(t)) continue;
36185
36220
  kept.push(t.replace(/\s+/g, " "));
36186
36221
  }
36187
- return (0, import_node_crypto16.createHash)("sha256").update(kept.join("\n")).digest("hex");
36222
+ return (0, import_node_crypto17.createHash)("sha256").update(kept.join("\n")).digest("hex");
36188
36223
  }
36189
36224
  function readVerified(root, now = Date.now()) {
36190
36225
  const read2 = readRegularFileInRoot(root, VERIFIED_FILE, 256 * 1024);
@@ -36207,9 +36242,9 @@ function recordVerified(root, rec, now = Date.now()) {
36207
36242
  }
36208
36243
 
36209
36244
  // src/lib/prove/context.ts
36210
- var import_node_crypto17 = require("node:crypto");
36245
+ var import_node_crypto18 = require("node:crypto");
36211
36246
  var CONTEXT_BUDGET_MS = 2e3;
36212
- var sha256 = (s) => (0, import_node_crypto17.createHash)("sha256").update(s).digest("hex");
36247
+ var sha256 = (s) => (0, import_node_crypto18.createHash)("sha256").update(s).digest("hex");
36213
36248
  var TEST_PATH4 = /(^|\/)(tests?|__tests__|spec)\/|\.(test|spec)\.[a-z]+$/;
36214
36249
  function slice(content, f, maxLines) {
36215
36250
  const all = content.split("\n");
@@ -36398,7 +36433,7 @@ function workingTreeReader(root) {
36398
36433
  };
36399
36434
  }
36400
36435
  function sha256Of(content) {
36401
- return (0, import_node_crypto18.createHash)("sha256").update(content).digest("hex");
36436
+ return (0, import_node_crypto19.createHash)("sha256").update(content).digest("hex");
36402
36437
  }
36403
36438
  function defaultDeps(opts) {
36404
36439
  const env = opts.env ?? process.env;
@@ -36469,9 +36504,7 @@ async function runFormalPhase(input) {
36469
36504
  symbol: f.symbol,
36470
36505
  verdict: "reproduced",
36471
36506
  reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
36472
- ...f.waived ? { waived: true } : {},
36473
- // A hand-edited file cannot invent a code: unknown values read as absent (HIGH).
36474
- ...isImpact(f.impact) ? { impact: f.impact } : {}
36507
+ ...f.waived ? { waived: true } : {}
36475
36508
  });
36476
36509
  }
36477
36510
  }
@@ -36510,6 +36543,7 @@ async function runFormalPhase(input) {
36510
36543
  return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
36511
36544
  }
36512
36545
  const ranked = await deps.rank(eligible, root, input.changedLines);
36546
+ if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36513
36547
  if (ranked.ok) spend(ranked);
36514
36548
  candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
36515
36549
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
@@ -36744,7 +36778,7 @@ async function runFormalPhase(input) {
36744
36778
  continue;
36745
36779
  }
36746
36780
  const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
36747
- findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0, ...verdict === "reproduced" && r.impact ? { impact: r.impact } : {} });
36781
+ findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
36748
36782
  }
36749
36783
  const reproduced = findings.filter((f) => f.verdict === "reproduced");
36750
36784
  if (reproduced.length > 0 && !cancelled()) {
@@ -36752,7 +36786,7 @@ async function runFormalPhase(input) {
36752
36786
  const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
36753
36787
  writePersistedFindings(root, [
36754
36788
  ...others,
36755
- ...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...f.impact ? { impact: f.impact } : {}, ...lines ? { lines } : {}, at: now }))
36789
+ ...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...lines ? { lines } : {}, at: now }))
36756
36790
  ]);
36757
36791
  }
36758
36792
  const clean2 = findings.every((f) => f.verdict === "diverged");
@@ -37492,8 +37526,6 @@ async function runGuard(opts, globals) {
37492
37526
  rounds: formalOutcome.model?.rounds ?? null,
37493
37527
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
37494
37528
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
37495
- // Decision 82: the replay's impact code per reproduced finding; count/cache/internal warn, the rest block.
37496
- impacts: formalOutcome.findings.filter((f) => f.impact).map((f) => `${f.property}:${f.impact}`),
37497
37529
  // Decision 81: what each property rests on (a rule, or "line"), what was
37498
37530
  // sent back or dropped as ungrounded, and which counterexamples lack their
37499
37531
  // property's trigger (shadow). Ids and rule names only, never code.
@@ -37734,7 +37766,7 @@ function registerIgnoreCommand(program2) {
37734
37766
  }
37735
37767
 
37736
37768
  // src/commands/waive.ts
37737
- var import_node_crypto19 = require("node:crypto");
37769
+ var import_node_crypto20 = require("node:crypto");
37738
37770
  var import_node_fs60 = require("node:fs");
37739
37771
  function registerWaiveCommand(program2) {
37740
37772
  program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
@@ -37764,7 +37796,7 @@ function registerWaiveCommand(program2) {
37764
37796
  if (opts.file) {
37765
37797
  body2.file = opts.file;
37766
37798
  try {
37767
- body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
37799
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
37768
37800
  } catch {
37769
37801
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
37770
37802
  process.exit(1);
@@ -38795,7 +38827,7 @@ async function promptMultiSelect(question, choices, fallback) {
38795
38827
 
38796
38828
  // src/lib/prove/lean-install.ts
38797
38829
  var import_node_fs63 = require("node:fs");
38798
- var import_node_crypto20 = require("node:crypto");
38830
+ var import_node_crypto21 = require("node:crypto");
38799
38831
  var import_node_child_process18 = require("node:child_process");
38800
38832
  var import_node_os10 = require("node:os");
38801
38833
  var import_node_path47 = require("node:path");
@@ -38833,7 +38865,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
38833
38865
  }
38834
38866
  function sha256File(path) {
38835
38867
  return new Promise((resolve8, reject) => {
38836
- const hash = (0, import_node_crypto20.createHash)("sha256");
38868
+ const hash = (0, import_node_crypto21.createHash)("sha256");
38837
38869
  (0, import_node_fs63.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
38838
38870
  });
38839
38871
  }
@@ -39946,7 +39978,7 @@ function registerInitCommand(program2) {
39946
39978
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
39947
39979
  init: {
39948
39980
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
39949
- cli_version: true ? "0.34.0-experimental.7e3f52d" : "dev"
39981
+ cli_version: true ? "0.34.0-experimental.8b93a3c" : "dev"
39950
39982
  }
39951
39983
  });
39952
39984
  } catch (err2) {
@@ -41419,8 +41451,8 @@ function registerLeanCommand(program2) {
41419
41451
  }
41420
41452
 
41421
41453
  // src/cli.ts
41422
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.7e3f52d").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) => {
41423
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.7e3f52d");
41454
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.8b93a3c").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) => {
41455
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.8b93a3c");
41424
41456
  setUserNamedServiceUrl(program.opts().serviceUrl);
41425
41457
  try {
41426
41458
  await foldLegacyLocalCredential();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/verity-cli",
3
- "version": "0.34.0-experimental.7e3f52d",
3
+ "version": "0.34.0-experimental.8b93a3c",
4
4
  "description": "CLI for Verity quality gate service",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "homepage": "https://verity.md",