@neat.is/core 0.2.8 → 0.2.10

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/dist/cli.d.cts CHANGED
@@ -27,6 +27,8 @@ interface ParsedArgs {
27
27
  against: string | null;
28
28
  errorId: string | null;
29
29
  hypotheticalAction: string | null;
30
+ type: string | null;
31
+ minConfidence: number | null;
30
32
  positional: string[];
31
33
  }
32
34
  declare function parseArgs(rest: string[]): ParsedArgs;
package/dist/cli.d.ts CHANGED
@@ -27,6 +27,8 @@ interface ParsedArgs {
27
27
  against: string | null;
28
28
  errorId: string | null;
29
29
  hypotheticalAction: string | null;
30
+ type: string | null;
31
+ minConfidence: number | null;
30
32
  positional: string[];
31
33
  }
32
34
  declare function parseArgs(rest: string[]): ParsedArgs;
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-XOOCA5T7.js";
5
5
  import {
6
6
  buildApi
7
- } from "./chunk-FTKDVKBC.js";
7
+ } from "./chunk-W7ZYJZC7.js";
8
8
  import {
9
9
  DEFAULT_PROJECT,
10
10
  PolicyViolationsLog,
@@ -37,11 +37,12 @@ import {
37
37
  setStatus,
38
38
  startPersistLoop,
39
39
  startStalenessLoop
40
- } from "./chunk-GAYTAGEH.js";
40
+ } from "./chunk-JMLZOKCS.js";
41
41
  import {
42
42
  buildOtelReceiver,
43
43
  startOtelGrpcReceiver
44
- } from "./chunk-I5IMCXRO.js";
44
+ } from "./chunk-QYUB3FQL.js";
45
+ import "./chunk-DGUM43GV.js";
45
46
 
46
47
  // src/cli.ts
47
48
  import path4 from "path";
@@ -753,6 +754,9 @@ function renderPatch(sections) {
753
754
  return lines.join("\n");
754
755
  }
755
756
 
757
+ // src/cli.ts
758
+ import { DivergenceTypeSchema } from "@neat.is/types";
759
+
756
760
  // src/cli-client.ts
757
761
  import { Provenance as Provenance2 } from "@neat.is/types";
758
762
  var HttpError = class extends Error {
@@ -1169,6 +1173,54 @@ async function runPolicies(client, input) {
1169
1173
  provenance: severities.join(" ")
1170
1174
  };
1171
1175
  }
1176
+ function formatDivergenceLine(d) {
1177
+ switch (d.type) {
1178
+ case "missing-observed":
1179
+ case "missing-extracted":
1180
+ return ` \u2022 [${d.type}] ${d.source} \u2192 ${d.target} (${d.edgeType}) \u2014 confidence ${d.confidence.toFixed(2)}`;
1181
+ case "version-mismatch":
1182
+ return ` \u2022 [${d.type}] ${d.source} \u2192 ${d.target} \u2014 declared ${d.extractedVersion}, observed engine ${d.observedVersion} (${d.compatibility})`;
1183
+ case "host-mismatch":
1184
+ return ` \u2022 [${d.type}] ${d.source} \u2192 ${d.target} \u2014 declared host ${d.extractedHost}, observed host ${d.observedHost}`;
1185
+ case "compat-violation":
1186
+ return ` \u2022 [${d.type}] ${d.source} \u2192 ${d.target} \u2014 ${d.rule.kind}${d.rule.package ? ` (${d.rule.package})` : ""}`;
1187
+ }
1188
+ }
1189
+ async function runDivergences(client, input) {
1190
+ const params = new URLSearchParams();
1191
+ if (input.type && input.type.length > 0) params.set("type", input.type.join(","));
1192
+ if (input.minConfidence !== void 0) {
1193
+ params.set("minConfidence", String(input.minConfidence));
1194
+ }
1195
+ if (input.node) params.set("node", input.node);
1196
+ const qs = params.size > 0 ? `?${params.toString()}` : "";
1197
+ const result = await client.get(
1198
+ projectPath(input.project, `/graph/divergences${qs}`)
1199
+ );
1200
+ if (result.totalAffected === 0) {
1201
+ return {
1202
+ summary: "No divergences found between the declared (EXTRACTED) and observed (OBSERVED) views of the graph."
1203
+ };
1204
+ }
1205
+ const headline = result.divergences[0];
1206
+ const summary = `Found ${result.totalAffected} divergence${result.totalAffected === 1 ? "" : "s"} between code and production. Highest-confidence: ${headline.type} on ${headline.source} \u2192 ${headline.target}. ${headline.reason}`;
1207
+ const blockLines = [];
1208
+ for (const d of result.divergences) {
1209
+ blockLines.push(formatDivergenceLine(d));
1210
+ blockLines.push(` reason: ${d.reason}`);
1211
+ blockLines.push(` recommendation: ${d.recommendation}`);
1212
+ }
1213
+ const maxConfidence = result.divergences.reduce(
1214
+ (m, d) => Math.max(m, d.confidence),
1215
+ 0
1216
+ );
1217
+ return {
1218
+ summary,
1219
+ block: blockLines.join("\n"),
1220
+ confidence: maxConfidence,
1221
+ provenance: "composite (EXTRACTED + OBSERVED)"
1222
+ };
1223
+ }
1172
1224
  function formatFooter(confidence, provenance) {
1173
1225
  const c = confidence === void 0 ? "n/a" : confidence.toFixed(2);
1174
1226
  const p = provenance === void 0 ? "n/a" : Array.isArray(provenance) ? [...new Set(provenance)].join(", ") : provenance;
@@ -1247,6 +1299,9 @@ function usage() {
1247
1299
  console.log(" policies Current policy violations.");
1248
1300
  console.log(" Flags: --node <id>, --hypothetical-action <json>");
1249
1301
  console.log(" example: neat policies --node service:<name> --json");
1302
+ console.log(" divergences Where code (EXTRACTED) and production (OBSERVED) disagree.");
1303
+ console.log(" Flags: --type <list>, --min-confidence <0..1>, --node <id>");
1304
+ console.log(" example: neat divergences --min-confidence 0.7");
1250
1305
  console.log("");
1251
1306
  console.log("flags:");
1252
1307
  console.log(' --project <name> Name the project this command targets. Default: "default".');
@@ -1271,7 +1326,9 @@ var STRING_FLAGS = [
1271
1326
  ["--since", "since"],
1272
1327
  ["--against", "against"],
1273
1328
  ["--error-id", "errorId"],
1274
- ["--hypothetical-action", "hypotheticalAction"]
1329
+ ["--hypothetical-action", "hypotheticalAction"],
1330
+ ["--type", "type"],
1331
+ ["--min-confidence", "minConfidence"]
1275
1332
  ];
1276
1333
  function parseArgs(rest) {
1277
1334
  const positional = [];
@@ -1290,6 +1347,8 @@ function parseArgs(rest) {
1290
1347
  against: null,
1291
1348
  errorId: null,
1292
1349
  hypotheticalAction: null,
1350
+ type: null,
1351
+ minConfidence: null,
1293
1352
  positional: []
1294
1353
  };
1295
1354
  for (let i = 0; i < rest.length; i++) {
@@ -1349,6 +1408,15 @@ function assignFlag(out, field, value) {
1349
1408
  out[field] = n;
1350
1409
  return;
1351
1410
  }
1411
+ if (field === "minConfidence") {
1412
+ const n = Number(value);
1413
+ if (!Number.isFinite(n) || n < 0 || n > 1) {
1414
+ console.error("neat: --min-confidence must be a number in [0, 1]");
1415
+ process.exit(2);
1416
+ }
1417
+ out.minConfidence = n;
1418
+ return;
1419
+ }
1352
1420
  ;
1353
1421
  out[field] = value;
1354
1422
  }
@@ -1732,7 +1800,9 @@ var QUERY_VERBS = /* @__PURE__ */ new Set([
1732
1800
  "search",
1733
1801
  "diff",
1734
1802
  "stale-edges",
1735
- "policies"
1803
+ "policies",
1804
+ // Tenth verb (ADR-060) — amends ADR-050's locked allowlist of nine.
1805
+ "divergences"
1736
1806
  ]);
1737
1807
  function resolveProjectFlag(parsed) {
1738
1808
  if (parsed.project) return parsed.project;
@@ -1854,6 +1924,31 @@ async function runQueryVerb(cmd, parsed) {
1854
1924
  });
1855
1925
  break;
1856
1926
  }
1927
+ case "divergences": {
1928
+ let typeFilter;
1929
+ if (parsed.type) {
1930
+ const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
1931
+ const out = [];
1932
+ for (const p of parts) {
1933
+ const r = DivergenceTypeSchema.safeParse(p);
1934
+ if (!r.success) {
1935
+ console.error(
1936
+ `neat divergences: unknown --type "${p}". allowed: ${DivergenceTypeSchema.options.join(", ")}`
1937
+ );
1938
+ return 2;
1939
+ }
1940
+ out.push(r.data);
1941
+ }
1942
+ typeFilter = out;
1943
+ }
1944
+ work = runDivergences(client, {
1945
+ ...typeFilter ? { type: typeFilter } : {},
1946
+ ...parsed.minConfidence !== null ? { minConfidence: parsed.minConfidence } : {},
1947
+ ...parsed.node ? { node: parsed.node } : {},
1948
+ ...project ? { project } : {}
1949
+ });
1950
+ break;
1951
+ }
1857
1952
  default:
1858
1953
  console.error(`neat: unknown query verb "${cmd}"`);
1859
1954
  return 2;