@neat.is/core 0.9.13 → 0.9.15-dev.20260902

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.cjs CHANGED
@@ -1292,13 +1292,19 @@ function resolveOwningService(graph, nodeId) {
1292
1292
  }
1293
1293
  return null;
1294
1294
  }
1295
+ function isFrontierEdge(e) {
1296
+ return e.provenance === import_types.Provenance.FRONTIER;
1297
+ }
1298
+ function rankOf(p) {
1299
+ return p === import_types.Provenance.FRONTIER ? -1 : import_types.PROV_RANK[p];
1300
+ }
1295
1301
  function bestEdgeBySource(graph, edgeIds) {
1296
1302
  const best = /* @__PURE__ */ new Map();
1297
1303
  for (const id of edgeIds) {
1298
1304
  const e = graph.getEdgeAttributes(id);
1299
- if (isFrontierNode(graph, e.source)) continue;
1305
+ if (isFrontierNode(graph, e.source) || isFrontierEdge(e)) continue;
1300
1306
  const cur = best.get(e.source);
1301
- if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
1307
+ if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
1302
1308
  best.set(e.source, e);
1303
1309
  }
1304
1310
  }
@@ -1308,9 +1314,9 @@ function bestEdgeByTarget(graph, edgeIds) {
1308
1314
  const best = /* @__PURE__ */ new Map();
1309
1315
  for (const id of edgeIds) {
1310
1316
  const e = graph.getEdgeAttributes(id);
1311
- if (isFrontierNode(graph, e.target)) continue;
1317
+ if (isFrontierNode(graph, e.target) || isFrontierEdge(e)) continue;
1312
1318
  const cur = best.get(e.target);
1313
- if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
1319
+ if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
1314
1320
  best.set(e.target, e);
1315
1321
  }
1316
1322
  }
@@ -1320,7 +1326,10 @@ var PROVENANCE_CEILING = {
1320
1326
  OBSERVED: 1,
1321
1327
  INFERRED: 0.7,
1322
1328
  EXTRACTED: 0.5,
1323
- STALE: 0.3
1329
+ STALE: 0.3,
1330
+ // A FRONTIER surface (ADR-226) is a proposal about a cause NEAT could not observe
1331
+ // — the least-trusted claim it makes, below STALE (which was at least once seen).
1332
+ FRONTIER: 0.2
1324
1333
  };
1325
1334
  function volumeWeight(spanCount) {
1326
1335
  if (!spanCount || spanCount <= 0) return 0.5;
@@ -1555,7 +1564,7 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
1555
1564
  });
1556
1565
  }
1557
1566
  function isFailingCallEdge(e) {
1558
- return e.type === import_types.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
1567
+ return e.type === import_types.EdgeType.CALLS && !isFrontierEdge(e) && (e.signal?.errorCount ?? 0) > 0;
1559
1568
  }
1560
1569
  function callSourcesForService(graph, serviceId17) {
1561
1570
  const ids = [serviceId17];
@@ -1578,8 +1587,8 @@ function failingCallDominates(e, id, curEdge, curId) {
1578
1587
  const ec = e.signal?.errorCount ?? 0;
1579
1588
  const cc = curEdge.signal?.errorCount ?? 0;
1580
1589
  if (ec !== cc) return ec > cc;
1581
- if (import_types.PROV_RANK[e.provenance] !== import_types.PROV_RANK[curEdge.provenance]) {
1582
- return import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[curEdge.provenance];
1590
+ if (rankOf(e.provenance) !== rankOf(curEdge.provenance)) {
1591
+ return rankOf(e.provenance) > rankOf(curEdge.provenance);
1583
1592
  }
1584
1593
  return id < curId;
1585
1594
  }
@@ -1630,11 +1639,11 @@ function dominantStaleCall(graph, serviceId17, visited) {
1630
1639
  for (const edgeId of graph.outboundEdges(src)) {
1631
1640
  const e = graph.getEdgeAttributes(edgeId);
1632
1641
  if (e.type !== import_types.EdgeType.CALLS) continue;
1633
- if (isFrontierNode(graph, e.target)) continue;
1642
+ if (isFrontierNode(graph, e.target) || isFrontierEdge(e)) continue;
1634
1643
  const owner = resolveOwningService(graph, e.target);
1635
1644
  if (!owner || visited.has(owner.id)) continue;
1636
1645
  const cur = bestByCallee.get(owner.id);
1637
- if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
1646
+ if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
1638
1647
  bestByCallee.set(owner.id, e);
1639
1648
  }
1640
1649
  }
@@ -1907,6 +1916,7 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
1907
1916
  for (const edgeId of graph.inboundEdges(n)) {
1908
1917
  const e = graph.getEdgeAttributes(edgeId);
1909
1918
  if (e.type === import_types.EdgeType.CONTAINS) continue;
1919
+ if (isFrontierEdge(e)) continue;
1910
1920
  errorsFromCallers += e.signal?.errorCount ?? 0;
1911
1921
  inboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
1912
1922
  if (e.provenance === import_types.Provenance.STALE) stale = true;
@@ -1920,6 +1930,7 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
1920
1930
  for (const edgeId of graph.outboundEdges(n)) {
1921
1931
  const e = graph.getEdgeAttributes(edgeId);
1922
1932
  if (e.type === import_types.EdgeType.CONTAINS) continue;
1933
+ if (isFrontierEdge(e)) continue;
1923
1934
  outboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
1924
1935
  if (e.type === import_types.EdgeType.CALLS) outboundErrors += e.signal?.errorCount ?? 0;
1925
1936
  if (e.provenance === import_types.Provenance.STALE) stale = true;
@@ -2203,22 +2214,44 @@ function routeMatches(declared, incident) {
2203
2214
  const b = normalizeRoute(incident);
2204
2215
  return a === b || a.startsWith(b) || b.startsWith(a);
2205
2216
  }
2206
- function structuralUpstreamPointer(graph, boundaryNode, incidents) {
2207
- const route = boundaryIncidentRoute(boundaryNode, incidents);
2208
- const callees = declaredOutboundCallees(graph, boundaryNode);
2217
+ function firstDeclaredCallee(graph, node, route) {
2218
+ const callees = declaredOutboundCallees(graph, node);
2209
2219
  if (callees.length === 0) return null;
2210
2220
  const narrowed = route !== void 0 ? callees.filter((c) => c.route !== void 0 && routeMatches(c.route, route)) : callees;
2211
2221
  const chosen = narrowed.length === 1 ? narrowed[0] : callees.length === 1 ? callees[0] : null;
2212
- if (!chosen) return null;
2213
- let node = chosen.target;
2214
- const seen = /* @__PURE__ */ new Set([boundaryNode, node]);
2215
- for (let depth = 0; depth < ROOT_CAUSE_MAX_DEPTH; depth++) {
2216
- const next = declaredOutboundCallees(graph, node);
2217
- if (next.length !== 1 || seen.has(next[0].target)) break;
2218
- node = next[0].target;
2219
- seen.add(node);
2222
+ return chosen ? chosen.target : null;
2223
+ }
2224
+ function observedOutboundNextServices(graph, nodeId) {
2225
+ const targets = /* @__PURE__ */ new Set();
2226
+ for (const n of nodeScope(graph, nodeId)) {
2227
+ if (!graph.hasNode(n)) continue;
2228
+ for (const edgeId of graph.outboundEdges(n)) {
2229
+ const e = graph.getEdgeAttributes(edgeId);
2230
+ if (!DEP_EDGE_TYPES.has(e.type)) continue;
2231
+ if (e.provenance !== import_types.Provenance.OBSERVED) continue;
2232
+ if (e.target !== nodeId) targets.add(e.target);
2233
+ }
2234
+ }
2235
+ return [...targets];
2236
+ }
2237
+ function resolveHangHop(graph, boundaryNode, incidents) {
2238
+ const route = boundaryIncidentRoute(boundaryNode, incidents);
2239
+ const own = firstDeclaredCallee(graph, boundaryNode, route);
2240
+ if (own) {
2241
+ return route !== void 0 ? { source: boundaryNode, target: own, route } : { source: boundaryNode, target: own };
2220
2242
  }
2221
- return route !== void 0 ? { node, route } : { node };
2243
+ const resolved = observedOutboundNextServices(graph, boundaryNode).map((n) => ({ source: n, target: firstDeclaredCallee(graph, n, route) })).filter((r) => r.target !== null);
2244
+ if (resolved.length === 1) {
2245
+ const hop = resolved[0];
2246
+ return route !== void 0 ? { ...hop, route } : hop;
2247
+ }
2248
+ return null;
2249
+ }
2250
+ function stagedHangProposal(graph, boundaryNode, incidents) {
2251
+ const hop = resolveHangHop(graph, boundaryNode, incidents);
2252
+ if (!hop) return null;
2253
+ if (!graph.hasEdge((0, import_types.frontierEdgeId)(hop.source, hop.target, import_types.EdgeType.CALLS))) return null;
2254
+ return hop.route !== void 0 ? { node: hop.target, route: hop.route } : { node: hop.target };
2222
2255
  }
2223
2256
  function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
2224
2257
  const legacy = tagged.result;
@@ -2264,28 +2297,28 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
2264
2297
  provenance: import_types.Provenance.OBSERVED
2265
2298
  });
2266
2299
  } else if (seedCtx && isBoundaryTimeoutSymptom(seedCtx)) {
2267
- const pointer = structuralUpstreamPointer(graph, seedNode, incidents);
2268
2300
  const seedName = displayNameOf(seedNode);
2269
- const routeNote = pointer?.route ? ` serving ${pointer.route}` : "";
2270
- if (pointer) {
2271
- const causeName = displayNameOf(pointer.node);
2272
- candidates.push({
2273
- node: pointer.node,
2274
- classification: "primary-failure",
2275
- reason: `${causeName} is the likely root cause (structural, INFERRED \u2014 not observed): the boundary ${seedName} only timed out waiting, and the actual culprit hung without exporting a span, so this is walked from the declared call graph${routeNote}, not from runtime signal. Restore instrumentation / inspect ${causeName} to confirm.`,
2276
- context: nodeContext(graph, pointer.node, incidents, now),
2277
- confidence: Math.min(legacy.confidence, PROVENANCE_CEILING.EXTRACTED),
2278
- provenance: import_types.Provenance.INFERRED
2279
- });
2280
- }
2301
+ const proposal = stagedHangProposal(graph, seedNode, incidents);
2302
+ const routeNote = proposal?.route ? ` serving ${proposal.route}` : "";
2281
2303
  candidates.push({
2282
2304
  node: seedNode,
2283
2305
  classification: "symptom-only",
2284
- reason: pointer ? `${seedName} timed out waiting on a downstream that hung and exported nothing \u2014 a boundary reporting an upstream fault, not the fault itself.` : `${seedName} timed out but nothing it can see downstream is erroring \u2014 the cause is downstream and unobserved (the culprit hung and exported no span). No single declared callee${routeNote} resolves, so no confident cause is named; inspect ${seedName}'s declared downstream.`,
2306
+ reason: proposal ? `${seedName} timed out waiting on a downstream that hung and exported no span \u2014 a boundary reporting an upstream fault, not the fault itself. The cause is unobservable; NEAT proposes the staged FRONTIER surface below, a hypothesis to confirm, not an observed cause.` : `${seedName} timed out but nothing it can see downstream is erroring \u2014 the cause is downstream and unobserved (the culprit hung and exported no span). No FRONTIER surface${routeNote} is staged, so no cause is proposed; inspect ${seedName}'s declared downstream and restore instrumentation.`,
2285
2307
  context: seedCtx,
2286
2308
  confidence: Math.min(legacy.confidence, 0.3),
2287
2309
  ...lastProv ? { provenance: lastProv } : {}
2288
2310
  });
2311
+ if (proposal) {
2312
+ const causeName = displayNameOf(proposal.node);
2313
+ candidates.push({
2314
+ node: proposal.node,
2315
+ classification: "primary-failure",
2316
+ reason: `${causeName} is the proposed hang cause (FRONTIER \u2014 a hypothesis, not observed): the boundary ${seedName} only timed out waiting and the culprit hung without exporting a span, so NEAT staged a FRONTIER surface on the unobservable hop${routeNote}. It graduates to OBSERVED when ${causeName} comes back; until then, inspect it / restore instrumentation to confirm, or it is culled.`,
2317
+ context: nodeContext(graph, proposal.node, incidents, now),
2318
+ confidence: Math.min(legacy.confidence, PROVENANCE_CEILING.FRONTIER),
2319
+ provenance: import_types.Provenance.FRONTIER
2320
+ });
2321
+ }
2289
2322
  } else if (staleChain) {
2290
2323
  const culprit = staleChain.culprit;
2291
2324
  const culpritName = displayNameOf(culprit);
@@ -2349,6 +2382,9 @@ function fixRecommendationForTop(top, seedNode, legacy) {
2349
2382
  return legacy.fixRecommendation;
2350
2383
  }
2351
2384
  const name = top.node.replace(/^service:/, "");
2385
+ if (top.classification === "symptom-only" && top.context.boundaryTimeout === true) {
2386
+ return `${name} timed out waiting on a downstream that hung and exported no span \u2014 the cause is unobservable from traces. Inspect the FRONTIER surface NEAT staged on the unobservable hop (see candidates); it graduates to OBSERVED when that service recovers. Restore instrumentation on that path to confirm, rather than treating ${name} as the fault.`;
2387
+ }
2352
2388
  if (top.provenance === import_types.Provenance.STALE) {
2353
2389
  return `Live telemetry for this path has gone quiet; the last-observed topology traces the failure downstream to ${name}. Restore instrumentation (or re-run with live traces) to confirm, then inspect ${name}.`;
2354
2390
  }
@@ -7026,6 +7062,32 @@ function promoteFrontierNodes(graph, opts = {}) {
7026
7062
  }
7027
7063
  return promoted;
7028
7064
  }
7065
+ function stageFrontierEdge(graph, source, target, type) {
7066
+ if (!graph.hasNode(source) || !graph.hasNode(target)) return false;
7067
+ if (graph.hasEdge((0, import_types8.observedEdgeId)(source, target, type))) return false;
7068
+ const key = (0, import_types8.frontierEdgeId)(source, target, type);
7069
+ if (graph.hasEdge(key)) return false;
7070
+ graph.addEdgeWithKey(key, source, target, {
7071
+ id: key,
7072
+ source,
7073
+ target,
7074
+ type,
7075
+ provenance: import_types8.Provenance.FRONTIER
7076
+ });
7077
+ return true;
7078
+ }
7079
+ function promoteFrontierEdges(graph) {
7080
+ const graduated = [];
7081
+ graph.forEachEdge((edgeId, attrs) => {
7082
+ const e = attrs;
7083
+ if (e.provenance !== import_types8.Provenance.FRONTIER) return;
7084
+ if (graph.hasEdge((0, import_types8.observedEdgeId)(e.source, e.target, e.type))) {
7085
+ graduated.push(edgeId);
7086
+ }
7087
+ });
7088
+ for (const edgeId of graduated) graph.dropEdge(edgeId);
7089
+ return graduated.length;
7090
+ }
7029
7091
  function rewireFrontierEdges(graph, frontierId2, serviceId17) {
7030
7092
  const inbound = [...graph.inboundEdges(frontierId2)];
7031
7093
  const outbound = [...graph.outboundEdges(frontierId2)];
@@ -7134,6 +7196,7 @@ function startStalenessLoop(graph, options = {}) {
7134
7196
  project: options.project
7135
7197
  });
7136
7198
  if (options.onPolicyTrigger) await options.onPolicyTrigger(graph);
7199
+ if (options.onReconcile) await options.onReconcile(graph);
7137
7200
  } catch (err) {
7138
7201
  console.error("staleness tick failed", err);
7139
7202
  }
@@ -23706,6 +23769,38 @@ async function buildApi(opts) {
23706
23769
 
23707
23770
  // src/watch.ts
23708
23771
  init_auth();
23772
+
23773
+ // src/hang-sensor.ts
23774
+ init_cjs_shims();
23775
+ var import_types102 = require("@neat.is/types");
23776
+ var RECONCILE_INCIDENT_LIMIT = 500;
23777
+ function stageHangSurfaces(graph, incidents) {
23778
+ const boundaries = /* @__PURE__ */ new Set();
23779
+ for (const ev of incidents) {
23780
+ if (ev.affectedNode && graph.hasNode(ev.affectedNode)) boundaries.add(ev.affectedNode);
23781
+ }
23782
+ let staged = 0;
23783
+ for (const boundary of boundaries) {
23784
+ const ctx = nodeContext(graph, boundary, incidents);
23785
+ if (!isBoundaryTimeoutSymptom(ctx)) continue;
23786
+ const hop = resolveHangHop(graph, boundary, incidents);
23787
+ if (!hop) continue;
23788
+ if (stageFrontierEdge(graph, hop.source, hop.target, import_types102.EdgeType.CALLS)) staged++;
23789
+ }
23790
+ return staged;
23791
+ }
23792
+ async function reconcileFrontierSurfaces(graph, errorsPath) {
23793
+ promoteFrontierEdges(graph);
23794
+ let incidents = [];
23795
+ try {
23796
+ incidents = await readErrorEvents(errorsPath, { limit: RECONCILE_INCIDENT_LIMIT });
23797
+ } catch {
23798
+ incidents = [];
23799
+ }
23800
+ stageHangSurfaces(graph, incidents);
23801
+ }
23802
+
23803
+ // src/watch.ts
23709
23804
  init_otel();
23710
23805
 
23711
23806
  // src/connectors/kubernetes/index.ts
@@ -24057,7 +24152,7 @@ function mapWorkloadsToSignals(deployments, pods, config) {
24057
24152
 
24058
24153
  // src/connectors/kubernetes/resolve.ts
24059
24154
  init_cjs_shims();
24060
- var import_types103 = require("@neat.is/types");
24155
+ var import_types104 = require("@neat.is/types");
24061
24156
  var NO_ENV3 = "unknown";
24062
24157
  function createK8sResolveTarget(graph) {
24063
24158
  return (signal) => {
@@ -24068,7 +24163,7 @@ function createK8sResolveTarget(graph) {
24068
24163
  return {
24069
24164
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV3),
24070
24165
  serviceName,
24071
- edgeType: import_types103.EdgeType.CALLS
24166
+ edgeType: import_types104.EdgeType.CALLS
24072
24167
  };
24073
24168
  };
24074
24169
  }
@@ -24192,7 +24287,7 @@ var import_node_fs42 = require("fs");
24192
24287
  var import_node_path78 = __toESM(require("path"), 1);
24193
24288
 
24194
24289
  // src/daemon.ts
24195
- var import_types106 = require("@neat.is/types");
24290
+ var import_types107 = require("@neat.is/types");
24196
24291
  function daemonJsonPath(scanPath) {
24197
24292
  return import_node_path79.default.join(scanPath, "neat-out", "daemon.json");
24198
24293
  }
@@ -24844,7 +24939,10 @@ async function startWatch(graph, opts) {
24844
24939
  const stopStaleness = startStalenessLoop(graph, {
24845
24940
  staleEventsPath: opts.staleEventsPath,
24846
24941
  project: projectName,
24847
- onPolicyTrigger
24942
+ onPolicyTrigger,
24943
+ // Graduate FRONTIER surfaces whose twin arrived + stage surfaces for current
24944
+ // hangs (ADR-226), each post-ingest tick.
24945
+ onReconcile: (g) => reconcileFrontierSurfaces(g, opts.errorsPath)
24848
24946
  });
24849
24947
  const stopConnectors = await startConnectorPolling({
24850
24948
  project: projectName,
@@ -29218,7 +29316,7 @@ var import_node_path89 = __toESM(require("path"), 1);
29218
29316
 
29219
29317
  // src/cli-client.ts
29220
29318
  init_cjs_shims();
29221
- var import_types107 = require("@neat.is/types");
29319
+ var import_types108 = require("@neat.is/types");
29222
29320
  var HttpError = class extends Error {
29223
29321
  constructor(status2, message, responseBody = "") {
29224
29322
  super(message);
@@ -29360,7 +29458,7 @@ async function runBlastRadius(client, input) {
29360
29458
  }
29361
29459
  }
29362
29460
  function formatBlastEntry(n) {
29363
- const tag = n.edgeProvenance === import_types107.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
29461
+ const tag = n.edgeProvenance === import_types108.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
29364
29462
  return ` \u2022 ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`;
29365
29463
  }
29366
29464
  async function runDependencies(client, input) {
@@ -29417,7 +29515,7 @@ async function runObservedDependencies(client, input) {
29417
29515
  if (result.observed) {
29418
29516
  return {
29419
29517
  summary: `${input.nodeId} makes no outbound runtime calls, but OTel has observed it receiving traffic on ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 it's a pure receiver.`,
29420
- provenance: import_types107.Provenance.OBSERVED
29518
+ provenance: import_types108.Provenance.OBSERVED
29421
29519
  };
29422
29520
  }
29423
29521
  const note = result.hasExtractedOutbound ? " Static (EXTRACTED) dependencies exist but no runtime traffic has been seen \u2014 is OTel running?" : "";
@@ -29427,7 +29525,7 @@ async function runObservedDependencies(client, input) {
29427
29525
  return {
29428
29526
  summary: `${input.nodeId} has ${result.dependencies.length} runtime dependenc${result.dependencies.length === 1 ? "y" : "ies"} confirmed by OTel.`,
29429
29527
  block: blockLines.join("\n"),
29430
- provenance: import_types107.Provenance.OBSERVED
29528
+ provenance: import_types108.Provenance.OBSERVED
29431
29529
  };
29432
29530
  } catch (err) {
29433
29531
  if (err instanceof HttpError && err.status === 404) {
@@ -29481,7 +29579,7 @@ async function runIncidents(client, input) {
29481
29579
  return {
29482
29580
  summary: `${target} has ${body.total} recorded incident${body.total === 1 ? "" : "s"}; showing the ${ordered.length} most recent.`,
29483
29581
  block: blockLines.join("\n"),
29484
- provenance: import_types107.Provenance.OBSERVED
29582
+ provenance: import_types108.Provenance.OBSERVED
29485
29583
  };
29486
29584
  } catch (err) {
29487
29585
  if (err instanceof HttpError && err.status === 404) {
@@ -29590,7 +29688,7 @@ async function runStaleEdges(client, input) {
29590
29688
  return {
29591
29689
  summary: `${events.length} stale-edge transition${events.length === 1 ? "" : "s"} recorded${input.edgeType ? ` for ${input.edgeType}` : ""}.`,
29592
29690
  block: blockLines.join("\n"),
29593
- provenance: import_types107.Provenance.STALE
29691
+ provenance: import_types108.Provenance.STALE
29594
29692
  };
29595
29693
  }
29596
29694
  async function runPolicies(client, input) {
@@ -30887,12 +30985,12 @@ async function runEditorCommand(clientId, args, projectDir = process.cwd()) {
30887
30985
 
30888
30986
  // src/monitor.ts
30889
30987
  init_cjs_shims();
30890
- var import_types108 = require("@neat.is/types");
30988
+ var import_types109 = require("@neat.is/types");
30891
30989
  var OBSERVED_DEP_EDGE_TYPES = /* @__PURE__ */ new Set([
30892
- import_types108.EdgeType.CALLS,
30893
- import_types108.EdgeType.CONNECTS_TO,
30894
- import_types108.EdgeType.PUBLISHES_TO,
30895
- import_types108.EdgeType.CONSUMES_FROM
30990
+ import_types109.EdgeType.CALLS,
30991
+ import_types109.EdgeType.CONNECTS_TO,
30992
+ import_types109.EdgeType.PUBLISHES_TO,
30993
+ import_types109.EdgeType.CONSUMES_FROM
30896
30994
  ]);
30897
30995
  function divergenceKey(d) {
30898
30996
  const column = "column" in d && d.column ? d.column : "";
@@ -30953,7 +31051,7 @@ function formatDivergenceLine2(d) {
30953
31051
  }
30954
31052
  }
30955
31053
  function formatStaleLine(edgeId) {
30956
- const parsed = (0, import_types108.parseEdgeId)(edgeId);
31054
+ const parsed = (0, import_types109.parseEdgeId)(edgeId);
30957
31055
  if (parsed) {
30958
31056
  return `\u22EF stale ${parsed.source} \u2192 ${parsed.target} (observed edge went quiet)`;
30959
31057
  }
@@ -30966,7 +31064,7 @@ function divergenceJson(d) {
30966
31064
  return JSON.stringify({ kind: "divergence", ...d });
30967
31065
  }
30968
31066
  function staleJson(edgeId) {
30969
- const parsed = (0, import_types108.parseEdgeId)(edgeId);
31067
+ const parsed = (0, import_types109.parseEdgeId)(edgeId);
30970
31068
  return JSON.stringify({
30971
31069
  kind: "stale",
30972
31070
  edgeId,
@@ -31049,7 +31147,7 @@ var MonitorEmitter = class {
31049
31147
  // ignores non-OBSERVED edges and non-dependency edge types (structural
31050
31148
  // ownership), so only real runtime dependencies reach stdout.
31051
31149
  emitObservedEdge(edge) {
31052
- if (edge.provenance !== import_types108.Provenance.OBSERVED) return false;
31150
+ if (edge.provenance !== import_types109.Provenance.OBSERVED) return false;
31053
31151
  if (!OBSERVED_DEP_EDGE_TYPES.has(edge.type)) return false;
31054
31152
  const key = `edge|${edge.id}`;
31055
31153
  if (this.seen.has(key)) return false;
@@ -31230,7 +31328,7 @@ async function runMonitor(opts) {
31230
31328
  case "edge-added": {
31231
31329
  const payload = safeParse(frame.data);
31232
31330
  const edge = payload?.edge;
31233
- if (edge && edge.provenance === import_types108.Provenance.OBSERVED) {
31331
+ if (edge && edge.provenance === import_types109.Provenance.OBSERVED) {
31234
31332
  emitter.emitObservedEdge(edge);
31235
31333
  divergences.schedule();
31236
31334
  }
@@ -31480,7 +31578,7 @@ async function runSync(opts) {
31480
31578
  }
31481
31579
 
31482
31580
  // src/cli.ts
31483
- var import_types109 = require("@neat.is/types");
31581
+ var import_types110 = require("@neat.is/types");
31484
31582
  function isNpxInvocation() {
31485
31583
  if (process.env.npm_command === "exec") return true;
31486
31584
  const execpath = process.env.npm_execpath ?? "";
@@ -32564,10 +32662,10 @@ async function runQueryVerb(cmd, parsed) {
32564
32662
  const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
32565
32663
  const out = [];
32566
32664
  for (const p of parts) {
32567
- const r = import_types109.DivergenceTypeSchema.safeParse(p);
32665
+ const r = import_types110.DivergenceTypeSchema.safeParse(p);
32568
32666
  if (!r.success) {
32569
32667
  console.error(
32570
- `neat divergences: unknown --type "${p}". allowed: ${import_types109.DivergenceTypeSchema.options.join(", ")}`
32668
+ `neat divergences: unknown --type "${p}". allowed: ${import_types110.DivergenceTypeSchema.options.join(", ")}`
32571
32669
  );
32572
32670
  return 2;
32573
32671
  }