@neat.is/core 0.10.6-dev.20261010 → 0.10.7-dev.20261011

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/server.cjs CHANGED
@@ -797,7 +797,7 @@ init_cjs_shims();
797
797
  var import_fastify2 = __toESM(require("fastify"), 1);
798
798
  var import_node_crypto6 = require("crypto");
799
799
  var import_cors = __toESM(require("@fastify/cors"), 1);
800
- var import_types103 = require("@neat.is/types");
800
+ var import_types104 = require("@neat.is/types");
801
801
 
802
802
  // src/extend/index.ts
803
803
  init_cjs_shims();
@@ -1144,7 +1144,7 @@ async function rollbackExtension(ctx, args) {
1144
1144
 
1145
1145
  // src/divergences.ts
1146
1146
  init_cjs_shims();
1147
- var import_types9 = require("@neat.is/types");
1147
+ var import_types10 = require("@neat.is/types");
1148
1148
 
1149
1149
  // src/columns.ts
1150
1150
  init_cjs_shims();
@@ -2061,7 +2061,7 @@ var PolicyViolationsLog = class {
2061
2061
  };
2062
2062
 
2063
2063
  // src/ingest.ts
2064
- var import_types7 = require("@neat.is/types");
2064
+ var import_types8 = require("@neat.is/types");
2065
2065
 
2066
2066
  // src/extract/routes.ts
2067
2067
  init_cjs_shims();
@@ -4821,6 +4821,92 @@ async function addRoutes(graph, services) {
4821
4821
  return { nodesAdded, edgesAdded };
4822
4822
  }
4823
4823
 
4824
+ // src/extract/source-baseline.ts
4825
+ init_cjs_shims();
4826
+ var import_types7 = require("@neat.is/types");
4827
+ var states = /* @__PURE__ */ new WeakMap();
4828
+ var REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
4829
+ function validCommit(commit, repository) {
4830
+ return !!commit && commit.repository === repository && /^[0-9a-f]{40}$/.test(commit.sha);
4831
+ }
4832
+ function stateOf(graph) {
4833
+ let state = states.get(graph);
4834
+ if (!state) {
4835
+ state = { repos: /* @__PURE__ */ new Map(), active: /* @__PURE__ */ new Set(), conflicted: /* @__PURE__ */ new Set() };
4836
+ states.set(graph, state);
4837
+ }
4838
+ return state;
4839
+ }
4840
+ function setEntry(state, repository, baseline, generation = /* @__PURE__ */ Symbol()) {
4841
+ state.repos.set(repository, {
4842
+ baseline,
4843
+ generation,
4844
+ services: state.repos.get(repository)?.services ?? /* @__PURE__ */ new Set()
4845
+ });
4846
+ }
4847
+ function readSourceBaselines(graph) {
4848
+ const state = states.get(graph);
4849
+ if (!state) return [];
4850
+ return [...state.repos.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, entry]) => ({ ...entry.baseline }));
4851
+ }
4852
+ function invalidateSourceBaseline(graph, repository, status2 = "unavailable") {
4853
+ if (repository !== void 0) {
4854
+ if (REPOSITORY.test(repository)) setEntry(stateOf(graph), repository, { status: status2, repository });
4855
+ return;
4856
+ }
4857
+ const state = states.get(graph);
4858
+ if (!state) return;
4859
+ for (const generation of state.active) state.conflicted.add(generation);
4860
+ for (const name of state.repos.keys()) {
4861
+ setEntry(state, name, { status: "unavailable", repository: name });
4862
+ }
4863
+ }
4864
+ function beginSourceExtraction(graph, source, commit) {
4865
+ const generation = /* @__PURE__ */ Symbol();
4866
+ const state = stateOf(graph);
4867
+ if (source === void 0) {
4868
+ invalidateSourceBaseline(graph);
4869
+ state.active.add(generation);
4870
+ return generation;
4871
+ }
4872
+ state.active.add(generation);
4873
+ if (!REPOSITORY.test(source)) return generation;
4874
+ setEntry(
4875
+ state,
4876
+ source,
4877
+ validCommit(commit, source) ? { status: "syncing", repository: source } : { status: "unavailable", repository: source },
4878
+ generation
4879
+ );
4880
+ return generation;
4881
+ }
4882
+ function servicesOf(graph, repository) {
4883
+ const services = /* @__PURE__ */ new Set();
4884
+ graph.forEachNode((_id, attrs) => {
4885
+ const node = attrs;
4886
+ if (node.type === import_types7.NodeType.FileNode && node.source === repository && node.service) {
4887
+ services.add(node.service);
4888
+ }
4889
+ });
4890
+ return services;
4891
+ }
4892
+ function finishSourceExtraction(graph, generation, source, commit, result) {
4893
+ const state = states.get(graph);
4894
+ if (!state) return;
4895
+ state.active.delete(generation);
4896
+ const conflicted = state.conflicted.delete(generation);
4897
+ if (source === void 0 || !REPOSITORY.test(source)) return;
4898
+ const entry = state.repos.get(source);
4899
+ if (!entry || entry.generation !== generation) return;
4900
+ entry.services = servicesOf(graph, source);
4901
+ let shared = false;
4902
+ for (const [name, other] of state.repos) {
4903
+ if (name === source || ![...entry.services].some((s) => other.services.has(s))) continue;
4904
+ shared = true;
4905
+ setEntry(state, name, { status: "unavailable", repository: name }, other.generation);
4906
+ }
4907
+ entry.baseline = !conflicted && !shared && validCommit(commit, source) && result.extractionErrors === 0 && result.skippedFiles === 0 ? { status: "ready", repository: source, sha: commit.sha } : { status: "unavailable", repository: source };
4908
+ }
4909
+
4824
4910
  // src/latency-digest.ts
4825
4911
  init_cjs_shims();
4826
4912
  var SUB = 16;
@@ -5282,11 +5368,11 @@ function callSiteFromSpan(span, serviceNode, scanPath) {
5282
5368
  };
5283
5369
  }
5284
5370
  function reconcileObservedRelPath(graph, serviceName, relPath) {
5285
- if (graph.hasNode((0, import_types7.fileId)(serviceName, relPath))) return relPath;
5371
+ if (graph.hasNode((0, import_types8.fileId)(serviceName, relPath))) return relPath;
5286
5372
  let best = null;
5287
5373
  graph.forEachNode((_id, attrs) => {
5288
5374
  const a = attrs;
5289
- if (a.type !== import_types7.NodeType.FileNode || a.service !== serviceName) return;
5375
+ if (a.type !== import_types8.NodeType.FileNode || a.service !== serviceName) return;
5290
5376
  if (a.discoveredVia === "otel") return;
5291
5377
  const p = a.path;
5292
5378
  if (!p) return;
@@ -5298,14 +5384,14 @@ function reconcileObservedRelPath(graph, serviceName, relPath) {
5298
5384
  }
5299
5385
  function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
5300
5386
  const svcAttrs = graph.hasNode(serviceNodeId) ? graph.getNodeAttributes(serviceNodeId) : void 0;
5301
- const canonicalService = svcAttrs && svcAttrs.type === import_types7.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
5387
+ const canonicalService = svcAttrs && svcAttrs.type === import_types8.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
5302
5388
  const relPath = reconcileObservedRelPath(graph, canonicalService, callSite.relPath);
5303
- const fileNodeId = (0, import_types7.fileId)(canonicalService, relPath);
5389
+ const fileNodeId = (0, import_types8.fileId)(canonicalService, relPath);
5304
5390
  if (!graph.hasNode(fileNodeId)) {
5305
5391
  const language = languageForExt(relPath);
5306
5392
  const node = {
5307
5393
  id: fileNodeId,
5308
- type: import_types7.NodeType.FileNode,
5394
+ type: import_types8.NodeType.FileNode,
5309
5395
  service: canonicalService,
5310
5396
  path: relPath,
5311
5397
  ...language ? { language } : {},
@@ -5314,14 +5400,14 @@ function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
5314
5400
  };
5315
5401
  graph.addNode(fileNodeId, node);
5316
5402
  }
5317
- const containsId = makeObservedEdgeId(import_types7.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
5403
+ const containsId = makeObservedEdgeId(import_types8.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
5318
5404
  if (!graph.hasEdge(containsId)) {
5319
5405
  const edge = {
5320
5406
  id: containsId,
5321
5407
  source: serviceNodeId,
5322
5408
  target: fileNodeId,
5323
- type: import_types7.EdgeType.CONTAINS,
5324
- provenance: import_types7.Provenance.OBSERVED
5409
+ type: import_types8.EdgeType.CONTAINS,
5410
+ provenance: import_types8.Provenance.OBSERVED
5325
5411
  };
5326
5412
  graph.addEdgeWithKey(containsId, serviceNodeId, fileNodeId, edge);
5327
5413
  }
@@ -5345,11 +5431,11 @@ function pickContainingSymbol(candidates, fn) {
5345
5431
  return [...candidates].sort(bySpan)[0].id;
5346
5432
  }
5347
5433
  function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line) {
5348
- const sid = (0, import_types7.symbolId)(service, relPath, fn);
5434
+ const sid = (0, import_types8.symbolId)(service, relPath, fn);
5349
5435
  if (!graph.hasNode(sid)) {
5350
5436
  const node = {
5351
5437
  id: sid,
5352
- type: import_types7.NodeType.SymbolNode,
5438
+ type: import_types8.NodeType.SymbolNode,
5353
5439
  kind: "function",
5354
5440
  qualname: fn,
5355
5441
  span: { startLine: line, endLine: line },
@@ -5359,14 +5445,14 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
5359
5445
  };
5360
5446
  graph.addNode(sid, node);
5361
5447
  }
5362
- const containsId = makeObservedEdgeId(import_types7.EdgeType.CONTAINS, fileNodeId, sid);
5448
+ const containsId = makeObservedEdgeId(import_types8.EdgeType.CONTAINS, fileNodeId, sid);
5363
5449
  if (!graph.hasEdge(containsId)) {
5364
5450
  const edge = {
5365
5451
  id: containsId,
5366
5452
  source: fileNodeId,
5367
5453
  target: sid,
5368
- type: import_types7.EdgeType.CONTAINS,
5369
- provenance: import_types7.Provenance.OBSERVED
5454
+ type: import_types8.EdgeType.CONTAINS,
5455
+ provenance: import_types8.Provenance.OBSERVED
5370
5456
  };
5371
5457
  graph.addEdgeWithKey(containsId, fileNodeId, sid, edge);
5372
5458
  }
@@ -5378,9 +5464,9 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
5378
5464
  let sawSymbol = false;
5379
5465
  const candidates = [];
5380
5466
  graph.forEachOutboundEdge(fileNodeId, (_edge, edgeAttrs, _source, target) => {
5381
- if (edgeAttrs.type !== import_types7.EdgeType.CONTAINS) return;
5467
+ if (edgeAttrs.type !== import_types8.EdgeType.CONTAINS) return;
5382
5468
  const t = graph.getNodeAttributes(target);
5383
- if (t.type !== import_types7.NodeType.SymbolNode) return;
5469
+ if (t.type !== import_types8.NodeType.SymbolNode) return;
5384
5470
  sawSymbol = true;
5385
5471
  if (line >= t.span.startLine && line <= t.span.endLine) {
5386
5472
  candidates.push({ id: target, symbol: t });
@@ -5393,17 +5479,17 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
5393
5479
  return fileNodeId;
5394
5480
  }
5395
5481
  function makeObservedEdgeId(type, source, target) {
5396
- return (0, import_types7.observedEdgeId)(source, target, type);
5482
+ return (0, import_types8.observedEdgeId)(source, target, type);
5397
5483
  }
5398
5484
  function makeInferredEdgeId(type, source, target) {
5399
- return (0, import_types7.inferredEdgeId)(source, target, type);
5485
+ return (0, import_types8.inferredEdgeId)(source, target, type);
5400
5486
  }
5401
5487
  var INFERRED_CONFIDENCE = 0.6;
5402
5488
  var STITCH_MAX_DEPTH = 2;
5403
5489
  var STITCH_EDGE_TYPES = /* @__PURE__ */ new Set([
5404
- import_types7.EdgeType.CALLS,
5405
- import_types7.EdgeType.CONNECTS_TO,
5406
- import_types7.EdgeType.DEPENDS_ON
5490
+ import_types8.EdgeType.CALLS,
5491
+ import_types8.EdgeType.CONNECTS_TO,
5492
+ import_types8.EdgeType.DEPENDS_ON
5407
5493
  ]);
5408
5494
  var WIRE_SPAN_KIND_CLIENT = 3;
5409
5495
  var WIRE_SPAN_KIND_PRODUCER = 4;
@@ -5419,11 +5505,11 @@ function spanServesGraphqlOperation(kind) {
5419
5505
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
5420
5506
  }
5421
5507
  function ensureGraphqlOperationNode(graph, serviceName, operationType, operationName) {
5422
- const id = (0, import_types7.graphqlOperationId)(serviceName, operationType, operationName);
5508
+ const id = (0, import_types8.graphqlOperationId)(serviceName, operationType, operationName);
5423
5509
  if (graph.hasNode(id)) return id;
5424
5510
  const node = {
5425
5511
  id,
5426
- type: import_types7.NodeType.GraphQLOperationNode,
5512
+ type: import_types8.NodeType.GraphQLOperationNode,
5427
5513
  name: operationName,
5428
5514
  service: serviceName,
5429
5515
  operationType: operationType.toLowerCase(),
@@ -5437,11 +5523,11 @@ function spanServesGrpcMethod(kind) {
5437
5523
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
5438
5524
  }
5439
5525
  function ensureGrpcMethodNode(graph, rpcService, rpcMethod) {
5440
- const id = (0, import_types7.grpcMethodId)(rpcService, rpcMethod);
5526
+ const id = (0, import_types8.grpcMethodId)(rpcService, rpcMethod);
5441
5527
  if (graph.hasNode(id)) return id;
5442
5528
  const node = {
5443
5529
  id,
5444
- type: import_types7.NodeType.GrpcMethodNode,
5530
+ type: import_types8.NodeType.GrpcMethodNode,
5445
5531
  name: `${rpcService}/${rpcMethod}`,
5446
5532
  rpcService,
5447
5533
  rpcMethod,
@@ -5454,11 +5540,11 @@ function spanServesWebsocketChannel(kind) {
5454
5540
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
5455
5541
  }
5456
5542
  function ensureWebsocketChannelNode(graph, serviceName, channel) {
5457
- const id = (0, import_types7.websocketChannelId)(serviceName, channel);
5543
+ const id = (0, import_types8.websocketChannelId)(serviceName, channel);
5458
5544
  if (graph.hasNode(id)) return id;
5459
5545
  const node = {
5460
5546
  id,
5461
- type: import_types7.NodeType.WebSocketChannelNode,
5547
+ type: import_types8.NodeType.WebSocketChannelNode,
5462
5548
  name: channel,
5463
5549
  service: serviceName,
5464
5550
  channel,
@@ -5471,11 +5557,11 @@ function messagingDestinationKind(system) {
5471
5557
  return `${system}-topic`;
5472
5558
  }
5473
5559
  function ensureMessagingDestinationNode(graph, system, destination) {
5474
- const id = (0, import_types7.infraId)(messagingDestinationKind(system), destination);
5560
+ const id = (0, import_types8.infraId)(messagingDestinationKind(system), destination);
5475
5561
  if (graph.hasNode(id)) return id;
5476
5562
  const node = {
5477
5563
  id,
5478
- type: import_types7.NodeType.InfraNode,
5564
+ type: import_types8.NodeType.InfraNode,
5479
5565
  name: destination,
5480
5566
  provider: "self",
5481
5567
  kind: messagingDestinationKind(system)
@@ -5519,9 +5605,9 @@ function lookupParentSpan(traceId, parentSpanId, now) {
5519
5605
  };
5520
5606
  }
5521
5607
  function resolveServiceId(graph, host, env) {
5522
- const envTagged = (0, import_types7.serviceId)(host, env);
5608
+ const envTagged = (0, import_types8.serviceId)(host, env);
5523
5609
  if (graph.hasNode(envTagged)) return envTagged;
5524
- const envLess = (0, import_types7.serviceId)(host);
5610
+ const envLess = (0, import_types8.serviceId)(host);
5525
5611
  if (envLess !== envTagged && graph.hasNode(envLess)) return envLess;
5526
5612
  let sameEnv = null;
5527
5613
  let envLessMatch = null;
@@ -5529,7 +5615,7 @@ function resolveServiceId(graph, host, env) {
5529
5615
  graph.forEachNode((id, attrs) => {
5530
5616
  if (sameEnv) return;
5531
5617
  const a = attrs;
5532
- if (a.type !== import_types7.NodeType.ServiceNode) return;
5618
+ if (a.type !== import_types8.NodeType.ServiceNode) return;
5533
5619
  const matchesByName = a.name === host;
5534
5620
  const matchesByAlias = a.aliases ? a.aliases.includes(host) : false;
5535
5621
  if (!matchesByName && !matchesByAlias) return;
@@ -5544,14 +5630,14 @@ function resolveServiceId(graph, host, env) {
5544
5630
  return sameEnv ?? envLessMatch ?? anyMatch;
5545
5631
  }
5546
5632
  function frontierIdFor(host) {
5547
- return (0, import_types7.frontierId)(host);
5633
+ return (0, import_types8.frontierId)(host);
5548
5634
  }
5549
5635
  function resolveFusedServiceId(graph, serviceName, env) {
5550
- const id = (0, import_types7.serviceId)(serviceName, env);
5636
+ const id = (0, import_types8.serviceId)(serviceName, env);
5551
5637
  if (graph.hasNode(id)) return id;
5552
5638
  const wanted = serviceName.toLowerCase();
5553
5639
  const extractedId = graph.findNode((_nid, attrs) => {
5554
- if (attrs.type !== import_types7.NodeType.ServiceNode) return false;
5640
+ if (attrs.type !== import_types8.NodeType.ServiceNode) return false;
5555
5641
  const svc = attrs;
5556
5642
  if (svc.discoveredVia === "otel") return false;
5557
5643
  return typeof svc.name === "string" && svc.name.toLowerCase() === wanted;
@@ -5563,7 +5649,7 @@ function ensureServiceNode(graph, serviceName, env) {
5563
5649
  if (graph.hasNode(resolved)) return resolved;
5564
5650
  const node = {
5565
5651
  id: resolved,
5566
- type: import_types7.NodeType.ServiceNode,
5652
+ type: import_types8.NodeType.ServiceNode,
5567
5653
  name: serviceName,
5568
5654
  language: "unknown",
5569
5655
  discoveredVia: "otel",
@@ -5573,11 +5659,11 @@ function ensureServiceNode(graph, serviceName, env) {
5573
5659
  return resolved;
5574
5660
  }
5575
5661
  function ensureInfraNode(graph, kind, name, provider) {
5576
- const id = (0, import_types7.infraId)(kind, name);
5662
+ const id = (0, import_types8.infraId)(kind, name);
5577
5663
  if (graph.hasNode(id)) return id;
5578
5664
  const node = {
5579
5665
  id,
5580
- type: import_types7.NodeType.InfraNode,
5666
+ type: import_types8.NodeType.InfraNode,
5581
5667
  name,
5582
5668
  provider,
5583
5669
  kind
@@ -5589,7 +5675,7 @@ var COLUMN_BEARING_INFRA_KINDS = /* @__PURE__ */ new Set(["sql-table", "supabase
5589
5675
  function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
5590
5676
  if (!columns || columns.length === 0 || !graph.hasNode(tableNodeId)) return;
5591
5677
  const node = graph.getNodeAttributes(tableNodeId);
5592
- if (node.type !== import_types7.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
5678
+ if (node.type !== import_types8.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
5593
5679
  return;
5594
5680
  }
5595
5681
  graph.replaceNodeAttributes(tableNodeId, {
@@ -5598,7 +5684,7 @@ function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
5598
5684
  });
5599
5685
  }
5600
5686
  function mergeObservedColumns(graph, tableNodeId, columns) {
5601
- mergeColumnsAt(graph, tableNodeId, columns, import_types7.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
5687
+ mergeColumnsAt(graph, tableNodeId, columns, import_types8.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
5602
5688
  }
5603
5689
  function mergeObservedDeployState(graph, serviceNodeId, state) {
5604
5690
  if (!graph.hasNode(serviceNodeId)) return;
@@ -5609,11 +5695,11 @@ function mergeObservedDeployState(graph, serviceNodeId, state) {
5609
5695
  graph.mergeNodeAttributes(serviceNodeId, attrs);
5610
5696
  }
5611
5697
  function ensureDatabaseNode(graph, host, engine) {
5612
- const id = (0, import_types7.databaseId)(host);
5698
+ const id = (0, import_types8.databaseId)(host);
5613
5699
  if (graph.hasNode(id)) return id;
5614
5700
  const node = {
5615
5701
  id,
5616
- type: import_types7.NodeType.DatabaseNode,
5702
+ type: import_types8.NodeType.DatabaseNode,
5617
5703
  name: host,
5618
5704
  engine,
5619
5705
  engineVersion: "unknown",
@@ -5625,11 +5711,11 @@ function ensureDatabaseNode(graph, host, engine) {
5625
5711
  return id;
5626
5712
  }
5627
5713
  function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
5628
- const id = (0, import_types7.localDatabaseId)(serviceName, name);
5714
+ const id = (0, import_types8.localDatabaseId)(serviceName, name);
5629
5715
  if (graph.hasNode(id)) return id;
5630
5716
  const node = {
5631
5717
  id,
5632
- type: import_types7.NodeType.DatabaseNode,
5718
+ type: import_types8.NodeType.DatabaseNode,
5633
5719
  name,
5634
5720
  engine,
5635
5721
  engineVersion: "unknown",
@@ -5644,17 +5730,17 @@ function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
5644
5730
  const sources = [serviceNodeId];
5645
5731
  for (const edgeId of graph.outboundEdges(serviceNodeId)) {
5646
5732
  const e = graph.getEdgeAttributes(edgeId);
5647
- if (e.type === import_types7.EdgeType.CONTAINS) sources.push(e.target);
5733
+ if (e.type === import_types8.EdgeType.CONTAINS) sources.push(e.target);
5648
5734
  }
5649
5735
  const matches = /* @__PURE__ */ new Set();
5650
5736
  for (const src of sources) {
5651
5737
  if (!graph.hasNode(src)) continue;
5652
5738
  for (const edgeId of graph.outboundEdges(src)) {
5653
5739
  const edge = graph.getEdgeAttributes(edgeId);
5654
- if (edge.type !== import_types7.EdgeType.CONNECTS_TO || edge.provenance !== import_types7.Provenance.EXTRACTED) continue;
5740
+ if (edge.type !== import_types8.EdgeType.CONNECTS_TO || edge.provenance !== import_types8.Provenance.EXTRACTED) continue;
5655
5741
  if (!graph.hasNode(edge.target)) continue;
5656
5742
  const target = graph.getNodeAttributes(edge.target);
5657
- if (target.type !== import_types7.NodeType.DatabaseNode || target.engine !== engine) continue;
5743
+ if (target.type !== import_types8.NodeType.DatabaseNode || target.engine !== engine) continue;
5658
5744
  matches.add(edge.target);
5659
5745
  }
5660
5746
  }
@@ -5669,7 +5755,7 @@ function ensureFrontierNode(graph, host, ts) {
5669
5755
  }
5670
5756
  const node = {
5671
5757
  id,
5672
- type: import_types7.NodeType.FrontierNode,
5758
+ type: import_types8.NodeType.FrontierNode,
5673
5759
  name: host,
5674
5760
  host,
5675
5761
  firstObserved: ts,
@@ -5722,11 +5808,11 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
5722
5808
  };
5723
5809
  const updated = {
5724
5810
  ...existing,
5725
- provenance: import_types7.Provenance.OBSERVED,
5811
+ provenance: import_types8.Provenance.OBSERVED,
5726
5812
  lastObserved: ts,
5727
5813
  callCount: newSpanCount,
5728
5814
  signal: newSignal,
5729
- confidence: (0, import_types7.confidenceForObservedSignal)(newSignal),
5815
+ confidence: (0, import_types8.confidenceForObservedSignal)(newSignal),
5730
5816
  grain
5731
5817
  // backfills legacy edges that predate ADR-142
5732
5818
  };
@@ -5749,8 +5835,8 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
5749
5835
  source,
5750
5836
  target,
5751
5837
  type,
5752
- provenance: import_types7.Provenance.OBSERVED,
5753
- confidence: (0, import_types7.confidenceForObservedSignal)(signal),
5838
+ provenance: import_types8.Provenance.OBSERVED,
5839
+ confidence: (0, import_types8.confidenceForObservedSignal)(signal),
5754
5840
  lastObserved: ts,
5755
5841
  callCount: 1,
5756
5842
  signal,
@@ -5772,9 +5858,9 @@ function stitchTrace(graph, sourceServiceId, ts) {
5772
5858
  const outbound = graph.outboundEdges(nodeId);
5773
5859
  for (const edgeId of outbound) {
5774
5860
  const edge = graph.getEdgeAttributes(edgeId);
5775
- if (edge.provenance !== import_types7.Provenance.EXTRACTED) continue;
5861
+ if (edge.provenance !== import_types8.Provenance.EXTRACTED) continue;
5776
5862
  if (!STITCH_EDGE_TYPES.has(edge.type)) continue;
5777
- if (graph.hasEdge((0, import_types7.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
5863
+ if (graph.hasEdge((0, import_types8.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
5778
5864
  upsertInferredEdge(graph, edge.type, edge.source, edge.target, ts);
5779
5865
  if (!visited.has(edge.target)) {
5780
5866
  visited.add(edge.target);
@@ -5796,7 +5882,7 @@ function upsertInferredEdge(graph, type, source, target, ts) {
5796
5882
  source,
5797
5883
  target,
5798
5884
  type,
5799
- provenance: import_types7.Provenance.INFERRED,
5885
+ provenance: import_types8.Provenance.INFERRED,
5800
5886
  confidence: INFERRED_CONFIDENCE,
5801
5887
  lastObserved: ts
5802
5888
  };
@@ -5810,7 +5896,7 @@ function emitIncidentEvent(project, ev) {
5810
5896
  incidentId: ev.id,
5811
5897
  affectedNode: ev.affectedNode,
5812
5898
  service: ev.service,
5813
- incidentKind: (0, import_types7.incidentKindOf)(ev),
5899
+ incidentKind: (0, import_types8.incidentKindOf)(ev),
5814
5900
  at: ev.timestamp
5815
5901
  }
5816
5902
  });
@@ -5839,7 +5925,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
5839
5925
  const canonicalService = serviceNodeName(graph, span) ?? span.service;
5840
5926
  const recovered = !trusted;
5841
5927
  if (graph) {
5842
- const fusedFileId = (0, import_types7.fileId)(canonicalService, relPath);
5928
+ const fusedFileId = (0, import_types8.fileId)(canonicalService, relPath);
5843
5929
  if (graph.hasNode(fusedFileId)) {
5844
5930
  const node = landObservedSymbol(
5845
5931
  graph,
@@ -5859,7 +5945,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
5859
5945
  }
5860
5946
  if (recovered) return null;
5861
5947
  }
5862
- return { affectedNode: (0, import_types7.fileId)(span.service, relPath) };
5948
+ return { affectedNode: (0, import_types8.fileId)(span.service, relPath) };
5863
5949
  }
5864
5950
  function serviceNodeName(graph, span) {
5865
5951
  if (!graph) return void 0;
@@ -5876,7 +5962,7 @@ function stacktraceCallSite(span, serviceNode, scanPath) {
5876
5962
  return { relPath, line: frame.line, ...frame.fn ? { fn: frame.fn } : {} };
5877
5963
  }
5878
5964
  function incidentLocus(span, graph, scanPath) {
5879
- const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types7.serviceId)(span.service, span.env);
5965
+ const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types8.serviceId)(span.service, span.env);
5880
5966
  const serviceNode = graph && graph.hasNode(sid) ? graph.getNodeAttributes(sid) : void 0;
5881
5967
  const callSite = callSiteFromSpan(span, serviceNode, scanPath);
5882
5968
  if (callSite) {
@@ -6059,7 +6145,7 @@ function findRouteNodeByHttpRoute(graph, serviceName, method, httpRoute) {
6059
6145
  graph.forEachNode((id, attrs) => {
6060
6146
  if (found) return;
6061
6147
  const a = attrs;
6062
- if (a.type !== import_types7.NodeType.RouteNode || a.service !== serviceName) return;
6148
+ if (a.type !== import_types8.NodeType.RouteNode || a.service !== serviceName) return;
6063
6149
  if (m && a.method !== "ALL" && a.method !== m) return;
6064
6150
  if (normalizePathTemplate(a.pathTemplate) === target) found = id;
6065
6151
  });
@@ -6092,7 +6178,7 @@ async function handleSpan(ctx, span) {
6092
6178
  let targetId;
6093
6179
  if (host) {
6094
6180
  ensureDatabaseNode(ctx.graph, host, span.dbSystem);
6095
- targetId = (0, import_types7.databaseId)(host);
6181
+ targetId = (0, import_types8.databaseId)(host);
6096
6182
  } else {
6097
6183
  const declared = findDeclaredDatabaseForService(ctx.graph, sourceId, span.dbSystem);
6098
6184
  if (declared) {
@@ -6109,7 +6195,7 @@ async function handleSpan(ctx, span) {
6109
6195
  }
6110
6196
  const result = upsertObservedEdge(
6111
6197
  ctx.graph,
6112
- import_types7.EdgeType.CONNECTS_TO,
6198
+ import_types8.EdgeType.CONNECTS_TO,
6113
6199
  observedSource(),
6114
6200
  targetId,
6115
6201
  ts,
@@ -6123,7 +6209,7 @@ async function handleSpan(ctx, span) {
6123
6209
  const collectionId = ensureInfraNode(ctx.graph, "mongodb-collection", span.dbCollection, "self");
6124
6210
  upsertObservedEdge(
6125
6211
  ctx.graph,
6126
- import_types7.EdgeType.CALLS,
6212
+ import_types8.EdgeType.CALLS,
6127
6213
  observedSource(),
6128
6214
  collectionId,
6129
6215
  ts,
@@ -6137,7 +6223,7 @@ async function handleSpan(ctx, span) {
6137
6223
  const tableId = ensureInfraNode(ctx.graph, "sql-table", span.dbTable, "self");
6138
6224
  upsertObservedEdge(
6139
6225
  ctx.graph,
6140
- import_types7.EdgeType.CALLS,
6226
+ import_types8.EdgeType.CALLS,
6141
6227
  observedSource(),
6142
6228
  tableId,
6143
6229
  ts,
@@ -6155,7 +6241,7 @@ async function handleSpan(ctx, span) {
6155
6241
  span.messagingSystem,
6156
6242
  span.messagingDestination
6157
6243
  );
6158
- const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types7.EdgeType.CONSUMES_FROM : import_types7.EdgeType.PUBLISHES_TO;
6244
+ const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types8.EdgeType.CONSUMES_FROM : import_types8.EdgeType.PUBLISHES_TO;
6159
6245
  const result = upsertObservedEdge(
6160
6246
  ctx.graph,
6161
6247
  edgeType,
@@ -6177,7 +6263,7 @@ async function handleSpan(ctx, span) {
6177
6263
  );
6178
6264
  const result = upsertObservedEdge(
6179
6265
  ctx.graph,
6180
- import_types7.EdgeType.CONTAINS,
6266
+ import_types8.EdgeType.CONTAINS,
6181
6267
  observedSource(),
6182
6268
  targetId,
6183
6269
  ts,
@@ -6191,7 +6277,7 @@ async function handleSpan(ctx, span) {
6191
6277
  const targetId = ensureGrpcMethodNode(ctx.graph, span.rpcService, span.rpcMethod);
6192
6278
  const result = upsertObservedEdge(
6193
6279
  ctx.graph,
6194
- import_types7.EdgeType.CONTAINS,
6280
+ import_types8.EdgeType.CONTAINS,
6195
6281
  observedSource(),
6196
6282
  targetId,
6197
6283
  ts,
@@ -6209,7 +6295,7 @@ async function handleSpan(ctx, span) {
6209
6295
  );
6210
6296
  const result = upsertObservedEdge(
6211
6297
  ctx.graph,
6212
- import_types7.EdgeType.CONNECTS_TO,
6298
+ import_types8.EdgeType.CONNECTS_TO,
6213
6299
  observedSource(),
6214
6300
  targetId,
6215
6301
  ts,
@@ -6227,7 +6313,7 @@ async function handleSpan(ctx, span) {
6227
6313
  if (targetId && targetId !== sourceId) {
6228
6314
  upsertObservedEdge(
6229
6315
  ctx.graph,
6230
- import_types7.EdgeType.CALLS,
6316
+ import_types8.EdgeType.CALLS,
6231
6317
  observedSource(),
6232
6318
  targetId,
6233
6319
  ts,
@@ -6242,7 +6328,7 @@ async function handleSpan(ctx, span) {
6242
6328
  const frontierNodeId = ensureFrontierNode(ctx.graph, host, ts);
6243
6329
  upsertObservedEdge(
6244
6330
  ctx.graph,
6245
- import_types7.EdgeType.CALLS,
6331
+ import_types8.EdgeType.CALLS,
6246
6332
  observedSource(),
6247
6333
  frontierNodeId,
6248
6334
  ts,
@@ -6270,7 +6356,7 @@ async function handleSpan(ctx, span) {
6270
6356
  } : void 0;
6271
6357
  upsertObservedEdge(
6272
6358
  ctx.graph,
6273
- import_types7.EdgeType.CALLS,
6359
+ import_types8.EdgeType.CALLS,
6274
6360
  fallbackSource,
6275
6361
  sourceId,
6276
6362
  ts,
@@ -6292,7 +6378,7 @@ async function handleSpan(ctx, span) {
6292
6378
  );
6293
6379
  if (routeNodeId) {
6294
6380
  const routeSvc = ctx.graph.getNodeAttributes(routeNodeId).service;
6295
- upsertObservedEdge(ctx.graph, import_types7.EdgeType.CONTAINS, (0, import_types7.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
6381
+ upsertObservedEdge(ctx.graph, import_types8.EdgeType.CONTAINS, (0, import_types8.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
6296
6382
  }
6297
6383
  }
6298
6384
  if (span.statusCode === 2) {
@@ -6322,7 +6408,7 @@ function promoteFrontierNodes(graph, opts = {}) {
6322
6408
  const aliasIndex = /* @__PURE__ */ new Map();
6323
6409
  graph.forEachNode((id, attrs) => {
6324
6410
  const a = attrs;
6325
- if (a.type !== import_types7.NodeType.ServiceNode) return;
6411
+ if (a.type !== import_types8.NodeType.ServiceNode) return;
6326
6412
  aliasIndex.set(a.name, id);
6327
6413
  if (a.aliases) {
6328
6414
  for (const alias of a.aliases) aliasIndex.set(alias, id);
@@ -6331,7 +6417,7 @@ function promoteFrontierNodes(graph, opts = {}) {
6331
6417
  const toPromote = [];
6332
6418
  graph.forEachNode((id, attrs) => {
6333
6419
  const a = attrs;
6334
- if (a.type !== import_types7.NodeType.FrontierNode) return;
6420
+ if (a.type !== import_types8.NodeType.FrontierNode) return;
6335
6421
  const target = aliasIndex.get(a.host);
6336
6422
  if (!target) return;
6337
6423
  if (target === id) return;
@@ -6365,7 +6451,7 @@ function rewireFrontierEdges(graph, frontierId2, serviceId17) {
6365
6451
  }
6366
6452
  function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
6367
6453
  graph.dropEdge(oldEdgeId);
6368
- const newId = edge.provenance === import_types7.Provenance.OBSERVED ? (0, import_types7.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types7.Provenance.INFERRED ? (0, import_types7.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types7.extractedEdgeId)(newSource, newTarget, edge.type);
6454
+ const newId = edge.provenance === import_types8.Provenance.OBSERVED ? (0, import_types8.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types8.Provenance.INFERRED ? (0, import_types8.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types8.extractedEdgeId)(newSource, newTarget, edge.type);
6369
6455
  if (graph.hasEdge(newId)) {
6370
6456
  const existing = graph.getEdgeAttributes(newId);
6371
6457
  const merged = {
@@ -6399,12 +6485,12 @@ async function markStaleEdges(graph, options = {}) {
6399
6485
  const project = options.project ?? DEFAULT_PROJECT;
6400
6486
  graph.forEachEdge((id, attrs) => {
6401
6487
  const e = attrs;
6402
- if (e.provenance !== import_types7.Provenance.OBSERVED) return;
6488
+ if (e.provenance !== import_types8.Provenance.OBSERVED) return;
6403
6489
  if (!e.lastObserved) return;
6404
6490
  const threshold = thresholdForEdgeType(e.type, thresholds);
6405
6491
  const age = now - new Date(e.lastObserved).getTime();
6406
6492
  if (age > threshold) {
6407
- const updated = { ...e, provenance: import_types7.Provenance.STALE, confidence: 0.3 };
6493
+ const updated = { ...e, provenance: import_types8.Provenance.STALE, confidence: 0.3 };
6408
6494
  graph.replaceEdgeAttributes(id, updated);
6409
6495
  events.push({
6410
6496
  edgeId: id,
@@ -6421,8 +6507,8 @@ async function markStaleEdges(graph, options = {}) {
6421
6507
  project,
6422
6508
  payload: {
6423
6509
  edgeId: id,
6424
- from: import_types7.Provenance.OBSERVED,
6425
- to: import_types7.Provenance.STALE
6510
+ from: import_types8.Provenance.OBSERVED,
6511
+ to: import_types8.Provenance.STALE
6426
6512
  }
6427
6513
  });
6428
6514
  }
@@ -6570,6 +6656,7 @@ function describeZodIssues(error) {
6570
6656
  return error.issues.map((issue) => issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message).join("; ");
6571
6657
  }
6572
6658
  function mergeSnapshot(graph, snapshot) {
6659
+ invalidateSourceBaseline(graph);
6573
6660
  const exported = snapshot.graph;
6574
6661
  const incomingNodes = Array.isArray(exported.nodes) ? exported.nodes : [];
6575
6662
  const incomingEdges = Array.isArray(exported.edges) ? exported.edges : [];
@@ -6578,7 +6665,7 @@ function mergeSnapshot(graph, snapshot) {
6578
6665
  const validEdges = [];
6579
6666
  for (const node of incomingNodes) {
6580
6667
  if (node.attributes === void 0) continue;
6581
- const parsed = import_types7.GraphNodeSchema.safeParse(node.attributes);
6668
+ const parsed = import_types8.GraphNodeSchema.safeParse(node.attributes);
6582
6669
  if (!parsed.success) {
6583
6670
  issues.push(`node "${node.key}": ${describeZodIssues(parsed.error)}`);
6584
6671
  continue;
@@ -6587,7 +6674,7 @@ function mergeSnapshot(graph, snapshot) {
6587
6674
  }
6588
6675
  for (const edge of incomingEdges) {
6589
6676
  if (edge.attributes === void 0) continue;
6590
- const parsed = import_types7.GraphEdgeSchema.safeParse(edge.attributes);
6677
+ const parsed = import_types8.GraphEdgeSchema.safeParse(edge.attributes);
6591
6678
  if (!parsed.success) {
6592
6679
  const label = edge.key ?? `${edge.source}->${edge.target}`;
6593
6680
  issues.push(`edge "${label}": ${describeZodIssues(parsed.error)}`);
@@ -6616,29 +6703,29 @@ function mergeSnapshot(graph, snapshot) {
6616
6703
  }
6617
6704
 
6618
6705
  // src/traverse.ts
6619
- var import_types8 = require("@neat.is/types");
6706
+ var import_types9 = require("@neat.is/types");
6620
6707
  var ROOT_CAUSE_MAX_DEPTH = 5;
6621
6708
  var BLAST_RADIUS_DEFAULT_DEPTH = 10;
6622
6709
  function isFrontierNode(graph, nodeId) {
6623
6710
  if (!graph.hasNode(nodeId)) return false;
6624
6711
  const attrs = graph.getNodeAttributes(nodeId);
6625
- return attrs.type === import_types8.NodeType.FrontierNode;
6712
+ return attrs.type === import_types9.NodeType.FrontierNode;
6626
6713
  }
6627
6714
  function resolveOwningService(graph, nodeId) {
6628
6715
  if (!graph.hasNode(nodeId)) return null;
6629
6716
  const attrs = graph.getNodeAttributes(nodeId);
6630
- if (attrs.type === import_types8.NodeType.ServiceNode) {
6717
+ if (attrs.type === import_types9.NodeType.ServiceNode) {
6631
6718
  return { id: nodeId, svc: attrs };
6632
6719
  }
6633
- if (attrs.type === import_types8.NodeType.FileNode || attrs.type === import_types8.NodeType.SymbolNode) {
6720
+ if (attrs.type === import_types9.NodeType.FileNode || attrs.type === import_types9.NodeType.SymbolNode) {
6634
6721
  for (const edgeId of graph.inboundEdges(nodeId)) {
6635
6722
  const e = graph.getEdgeAttributes(edgeId);
6636
- if (e.type !== import_types8.EdgeType.CONTAINS) continue;
6723
+ if (e.type !== import_types9.EdgeType.CONTAINS) continue;
6637
6724
  const owner = graph.getNodeAttributes(e.source);
6638
- if (owner.type === import_types8.NodeType.ServiceNode) {
6725
+ if (owner.type === import_types9.NodeType.ServiceNode) {
6639
6726
  return { id: e.source, svc: owner };
6640
6727
  }
6641
- if (owner.type === import_types8.NodeType.FileNode) {
6728
+ if (owner.type === import_types9.NodeType.FileNode) {
6642
6729
  return resolveOwningService(graph, e.source);
6643
6730
  }
6644
6731
  }
@@ -6646,10 +6733,10 @@ function resolveOwningService(graph, nodeId) {
6646
6733
  return null;
6647
6734
  }
6648
6735
  function isFrontierEdge(e) {
6649
- return e.provenance === import_types8.Provenance.FRONTIER;
6736
+ return e.provenance === import_types9.Provenance.FRONTIER;
6650
6737
  }
6651
6738
  function rankOf(p) {
6652
- return p === import_types8.Provenance.FRONTIER ? -1 : import_types8.PROV_RANK[p];
6739
+ return p === import_types9.Provenance.FRONTIER ? -1 : import_types9.PROV_RANK[p];
6653
6740
  }
6654
6741
  function bestEdgeBySource(graph, edgeIds) {
6655
6742
  const best = /* @__PURE__ */ new Map();
@@ -6834,10 +6921,10 @@ function symbolRootCauseShape(graph, origin, walk11) {
6834
6921
  return serviceRootCauseShape(graph, owner.svc, walk11);
6835
6922
  }
6836
6923
  var rootCauseShapes = {
6837
- [import_types8.NodeType.DatabaseNode]: databaseRootCauseShape,
6838
- [import_types8.NodeType.ServiceNode]: serviceRootCauseShape,
6839
- [import_types8.NodeType.FileNode]: fileRootCauseShape,
6840
- [import_types8.NodeType.SymbolNode]: symbolRootCauseShape
6924
+ [import_types9.NodeType.DatabaseNode]: databaseRootCauseShape,
6925
+ [import_types9.NodeType.ServiceNode]: serviceRootCauseShape,
6926
+ [import_types9.NodeType.FileNode]: fileRootCauseShape,
6927
+ [import_types9.NodeType.SymbolNode]: symbolRootCauseShape
6841
6928
  };
6842
6929
  function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
6843
6930
  if (!graph.hasNode(errorNodeId)) return null;
@@ -6850,7 +6937,7 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
6850
6937
  const reason = errorEvent ? `${match.rootCauseReason} (observed error: ${errorEvent.errorMessage})` : match.rootCauseReason;
6851
6938
  return {
6852
6939
  source: "compat",
6853
- result: import_types8.RootCauseResultSchema.parse({
6940
+ result: import_types9.RootCauseResultSchema.parse({
6854
6941
  rootCauseNode: match.rootCauseNode,
6855
6942
  rootCauseReason: reason,
6856
6943
  traversalPath: walk11.path,
@@ -6861,7 +6948,7 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
6861
6948
  };
6862
6949
  }
6863
6950
  }
6864
- if (origin.type === import_types8.NodeType.ServiceNode) {
6951
+ if (origin.type === import_types9.NodeType.ServiceNode) {
6865
6952
  const crossService = crossServiceRootCause(graph, errorNodeId, incidents, errorEvent);
6866
6953
  if (crossService) return { result: crossService, source: "cross-service" };
6867
6954
  }
@@ -6872,8 +6959,8 @@ var INCIDENT_ROOT_CAUSE_CONFIDENCE = 0.6;
6872
6959
  function incidentMatchesNode(ev, nodeId) {
6873
6960
  if (ev.affectedNode === nodeId) return true;
6874
6961
  if (ev.service === nodeId.replace(/^service:/, "")) return true;
6875
- const sym = (0, import_types8.parseSymbolId)(ev.affectedNode);
6876
- if (sym && (0, import_types8.fileId)(sym.service, sym.relPath) === nodeId) return true;
6962
+ const sym = (0, import_types9.parseSymbolId)(ev.affectedNode);
6963
+ if (sym && (0, import_types9.fileId)(sym.service, sym.relPath) === nodeId) return true;
6877
6964
  return false;
6878
6965
  }
6879
6966
  function localizeFromIncidents(nodeId, incidents, errorEvent) {
@@ -6906,8 +6993,8 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
6906
6993
  const loc = localizeFromIncidents(nodeId, incidents, errorEvent);
6907
6994
  if (!loc) return null;
6908
6995
  const traversalPath = loc.fileNode ? [nodeId, loc.fileNode] : [nodeId];
6909
- const edgeProvenances = loc.fileNode ? [import_types8.Provenance.OBSERVED] : [];
6910
- return import_types8.RootCauseResultSchema.parse({
6996
+ const edgeProvenances = loc.fileNode ? [import_types9.Provenance.OBSERVED] : [];
6997
+ return import_types9.RootCauseResultSchema.parse({
6911
6998
  rootCauseNode: loc.rootCauseNode,
6912
6999
  rootCauseReason: loc.rootCauseReason,
6913
7000
  traversalPath,
@@ -6917,21 +7004,21 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
6917
7004
  });
6918
7005
  }
6919
7006
  function isFailingCallEdge(e) {
6920
- return e.type === import_types8.EdgeType.CALLS && !isFrontierEdge(e) && (e.signal?.errorCount ?? 0) > 0;
7007
+ return e.type === import_types9.EdgeType.CALLS && !isFrontierEdge(e) && (e.signal?.errorCount ?? 0) > 0;
6921
7008
  }
6922
7009
  function callSourcesForService(graph, serviceId17) {
6923
7010
  const ids = [serviceId17];
6924
7011
  for (const edgeId of graph.outboundEdges(serviceId17)) {
6925
7012
  const e = graph.getEdgeAttributes(edgeId);
6926
- if (e.type !== import_types8.EdgeType.CONTAINS) continue;
7013
+ if (e.type !== import_types9.EdgeType.CONTAINS) continue;
6927
7014
  const tgt = graph.getNodeAttributes(e.target);
6928
- if (tgt.type !== import_types8.NodeType.FileNode) continue;
7015
+ if (tgt.type !== import_types9.NodeType.FileNode) continue;
6929
7016
  ids.push(e.target);
6930
7017
  for (const symEdgeId of graph.outboundEdges(e.target)) {
6931
7018
  const se = graph.getEdgeAttributes(symEdgeId);
6932
- if (se.type !== import_types8.EdgeType.CONTAINS) continue;
7019
+ if (se.type !== import_types9.EdgeType.CONTAINS) continue;
6933
7020
  const sym = graph.getNodeAttributes(se.target);
6934
- if (sym.type === import_types8.NodeType.SymbolNode) ids.push(se.target);
7021
+ if (sym.type === import_types9.NodeType.SymbolNode) ids.push(se.target);
6935
7022
  }
6936
7023
  }
6937
7024
  return ids;
@@ -6978,7 +7065,7 @@ function followFailingCallChain(graph, originServiceId, maxDepth) {
6978
7065
  return { path: path81, edges, culprit: current };
6979
7066
  }
6980
7067
  function isStaleCallEdge(e) {
6981
- return e.type === import_types8.EdgeType.CALLS && e.provenance === import_types8.Provenance.STALE;
7068
+ return e.type === import_types9.EdgeType.CALLS && e.provenance === import_types9.Provenance.STALE;
6982
7069
  }
6983
7070
  function staleCallDominates(e, id, curEdge, curId) {
6984
7071
  const ev = e.signal?.spanCount ?? e.callCount ?? 0;
@@ -6991,7 +7078,7 @@ function dominantStaleCall(graph, serviceId17, visited) {
6991
7078
  for (const src of callSourcesForService(graph, serviceId17)) {
6992
7079
  for (const edgeId of graph.outboundEdges(src)) {
6993
7080
  const e = graph.getEdgeAttributes(edgeId);
6994
- if (e.type !== import_types8.EdgeType.CALLS) continue;
7081
+ if (e.type !== import_types9.EdgeType.CALLS) continue;
6995
7082
  if (isFrontierNode(graph, e.target) || isFrontierEdge(e)) continue;
6996
7083
  const owner = resolveOwningService(graph, e.target);
6997
7084
  if (!owner || visited.has(owner.id)) continue;
@@ -7039,10 +7126,10 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
7039
7126
  let rootCauseNode = culprit;
7040
7127
  if (loc.fileNode) {
7041
7128
  path81.push(loc.fileNode);
7042
- edgeProvenances.push(import_types8.Provenance.OBSERVED);
7129
+ edgeProvenances.push(import_types9.Provenance.OBSERVED);
7043
7130
  rootCauseNode = loc.fileNode;
7044
7131
  }
7045
- return import_types8.RootCauseResultSchema.parse({
7132
+ return import_types9.RootCauseResultSchema.parse({
7046
7133
  rootCauseNode,
7047
7134
  rootCauseReason: loc.rootCauseReason,
7048
7135
  traversalPath: path81,
@@ -7054,7 +7141,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
7054
7141
  const lastEdge = chain.edges[chain.edges.length - 1];
7055
7142
  const errs = lastEdge.signal?.errorCount ?? 0;
7056
7143
  const culpritName = culprit.replace(/^service:/, "");
7057
- return import_types8.RootCauseResultSchema.parse({
7144
+ return import_types9.RootCauseResultSchema.parse({
7058
7145
  rootCauseNode: culprit,
7059
7146
  rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
7060
7147
  traversalPath: path81,
@@ -7065,7 +7152,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
7065
7152
  }
7066
7153
  function getBlastRadius(graph, nodeId, maxDepth = BLAST_RADIUS_DEFAULT_DEPTH) {
7067
7154
  if (!graph.hasNode(nodeId)) {
7068
- return import_types8.BlastRadiusResultSchema.parse({ origin: nodeId, affectedNodes: [], totalAffected: 0 });
7155
+ return import_types9.BlastRadiusResultSchema.parse({ origin: nodeId, affectedNodes: [], totalAffected: 0 });
7069
7156
  }
7070
7157
  const seen = /* @__PURE__ */ new Map();
7071
7158
  const queue = [{ nodeId, distance: 0, path: [nodeId], pathEdges: [] }];
@@ -7098,7 +7185,7 @@ function getBlastRadius(graph, nodeId, maxDepth = BLAST_RADIUS_DEFAULT_DEPTH) {
7098
7185
  const affectedNodes = [...seen.values()].sort(
7099
7186
  (a, b) => a.distance - b.distance || a.nodeId.localeCompare(b.nodeId)
7100
7187
  );
7101
- return import_types8.BlastRadiusResultSchema.parse({
7188
+ return import_types9.BlastRadiusResultSchema.parse({
7102
7189
  origin: nodeId,
7103
7190
  affectedNodes,
7104
7191
  totalAffected: affectedNodes.length
@@ -7108,7 +7195,7 @@ var TRANSITIVE_DEPENDENCIES_DEFAULT_DEPTH = 3;
7108
7195
  var TRANSITIVE_DEPENDENCIES_MAX_DEPTH = 10;
7109
7196
  function getTransitiveDependencies(graph, nodeId, depth = TRANSITIVE_DEPENDENCIES_DEFAULT_DEPTH) {
7110
7197
  if (!graph.hasNode(nodeId)) {
7111
- return import_types8.TransitiveDependenciesResultSchema.parse({
7198
+ return import_types9.TransitiveDependenciesResultSchema.parse({
7112
7199
  origin: nodeId,
7113
7200
  depth,
7114
7201
  dependencies: [],
@@ -7120,7 +7207,7 @@ function getTransitiveDependencies(graph, nodeId, depth = TRANSITIVE_DEPENDENCIE
7120
7207
  const enqueued = /* @__PURE__ */ new Set([nodeId]);
7121
7208
  while (queue.length > 0) {
7122
7209
  const frame = queue.shift();
7123
- if (frame.distance > 0 && frame.edge && frame.edge.type !== import_types8.EdgeType.CONTAINS) {
7210
+ if (frame.distance > 0 && frame.edge && frame.edge.type !== import_types9.EdgeType.CONTAINS) {
7124
7211
  seen.set(frame.nodeId, {
7125
7212
  nodeId: frame.nodeId,
7126
7213
  distance: frame.distance,
@@ -7139,7 +7226,7 @@ function getTransitiveDependencies(graph, nodeId, depth = TRANSITIVE_DEPENDENCIE
7139
7226
  const dependencies = [...seen.values()].sort(
7140
7227
  (a, b) => a.distance - b.distance || a.nodeId.localeCompare(b.nodeId)
7141
7228
  );
7142
- return import_types8.TransitiveDependenciesResultSchema.parse({
7229
+ return import_types9.TransitiveDependenciesResultSchema.parse({
7143
7230
  origin: nodeId,
7144
7231
  depth,
7145
7232
  dependencies,
@@ -7148,7 +7235,7 @@ function getTransitiveDependencies(graph, nodeId, depth = TRANSITIVE_DEPENDENCIE
7148
7235
  }
7149
7236
  function getObservedDependencies(graph, nodeId) {
7150
7237
  if (!graph.hasNode(nodeId)) {
7151
- return import_types8.ObservedDependenciesResultSchema.parse({
7238
+ return import_types9.ObservedDependenciesResultSchema.parse({
7152
7239
  origin: nodeId,
7153
7240
  dependencies: [],
7154
7241
  observed: false,
@@ -7160,12 +7247,12 @@ function getObservedDependencies(graph, nodeId) {
7160
7247
  }
7161
7248
  const attrs = graph.getNodeAttributes(nodeId);
7162
7249
  const scope = [nodeId];
7163
- if (attrs.type === import_types8.NodeType.ServiceNode) {
7250
+ if (attrs.type === import_types9.NodeType.ServiceNode) {
7164
7251
  for (const edgeId of graph.outboundEdges(nodeId)) {
7165
7252
  const e = graph.getEdgeAttributes(edgeId);
7166
- if (e.type !== import_types8.EdgeType.CONTAINS) continue;
7253
+ if (e.type !== import_types9.EdgeType.CONTAINS) continue;
7167
7254
  const owned = graph.getNodeAttributes(e.target);
7168
- if (owned.type === import_types8.NodeType.FileNode) scope.push(e.target);
7255
+ if (owned.type === import_types9.NodeType.FileNode) scope.push(e.target);
7169
7256
  }
7170
7257
  }
7171
7258
  const dependencies = [];
@@ -7174,13 +7261,13 @@ function getObservedDependencies(graph, nodeId) {
7174
7261
  for (const src of scope) {
7175
7262
  for (const edgeId of graph.outboundEdges(src)) {
7176
7263
  const e = graph.getEdgeAttributes(edgeId);
7177
- if (e.type === import_types8.EdgeType.CONTAINS) continue;
7178
- if (e.provenance === import_types8.Provenance.OBSERVED) {
7264
+ if (e.type === import_types9.EdgeType.CONTAINS) continue;
7265
+ if (e.provenance === import_types9.Provenance.OBSERVED) {
7179
7266
  if (!seenEdge.has(e.id)) {
7180
7267
  seenEdge.add(e.id);
7181
7268
  dependencies.push(e);
7182
7269
  }
7183
- } else if (e.provenance === import_types8.Provenance.EXTRACTED) {
7270
+ } else if (e.provenance === import_types9.Provenance.EXTRACTED) {
7184
7271
  hasExtractedOutbound = true;
7185
7272
  }
7186
7273
  }
@@ -7191,8 +7278,8 @@ function getObservedDependencies(graph, nodeId) {
7191
7278
  for (const tgt of scope) {
7192
7279
  for (const edgeId of graph.inboundEdges(tgt)) {
7193
7280
  const e = graph.getEdgeAttributes(edgeId);
7194
- if (e.type === import_types8.EdgeType.CONTAINS) continue;
7195
- if (e.provenance === import_types8.Provenance.OBSERVED) {
7281
+ if (e.type === import_types9.EdgeType.CONTAINS) continue;
7282
+ if (e.provenance === import_types9.Provenance.OBSERVED) {
7196
7283
  inboundObservedCount += 1;
7197
7284
  inboundVolume += e.callCount ?? e.signal?.spanCount ?? 1;
7198
7285
  if (e.lastObserved && (!inboundLastObserved || e.lastObserved > inboundLastObserved)) {
@@ -7204,7 +7291,7 @@ function getObservedDependencies(graph, nodeId) {
7204
7291
  dependencies.sort(
7205
7292
  (a, b) => a.target.localeCompare(b.target) || a.source.localeCompare(b.source) || a.id.localeCompare(b.id)
7206
7293
  );
7207
- return import_types8.ObservedDependenciesResultSchema.parse({
7294
+ return import_types9.ObservedDependenciesResultSchema.parse({
7208
7295
  origin: nodeId,
7209
7296
  dependencies,
7210
7297
  observed: dependencies.length > 0 || inboundObservedCount > 0,
@@ -7221,12 +7308,12 @@ function nodeScope(graph, nodeId) {
7221
7308
  const scope = [nodeId];
7222
7309
  if (!graph.hasNode(nodeId)) return scope;
7223
7310
  const attrs = graph.getNodeAttributes(nodeId);
7224
- if (attrs.type === import_types8.NodeType.ServiceNode) {
7311
+ if (attrs.type === import_types9.NodeType.ServiceNode) {
7225
7312
  for (const edgeId of graph.outboundEdges(nodeId)) {
7226
7313
  const e = graph.getEdgeAttributes(edgeId);
7227
- if (e.type !== import_types8.EdgeType.CONTAINS) continue;
7314
+ if (e.type !== import_types9.EdgeType.CONTAINS) continue;
7228
7315
  const owned = graph.getNodeAttributes(e.target);
7229
- if (owned.type === import_types8.NodeType.FileNode) scope.push(e.target);
7316
+ if (owned.type === import_types9.NodeType.FileNode) scope.push(e.target);
7230
7317
  }
7231
7318
  }
7232
7319
  return scope;
@@ -7236,10 +7323,10 @@ function incidentCountForNode(nodeId, incidents) {
7236
7323
  return incidents.filter((ev) => incidentMatchesNode(ev, nodeId)).length;
7237
7324
  }
7238
7325
  var DEP_EDGE_TYPES = /* @__PURE__ */ new Set([
7239
- import_types8.EdgeType.CALLS,
7240
- import_types8.EdgeType.CONNECTS_TO,
7241
- import_types8.EdgeType.PUBLISHES_TO,
7242
- import_types8.EdgeType.CONSUMES_FROM
7326
+ import_types9.EdgeType.CALLS,
7327
+ import_types9.EdgeType.CONNECTS_TO,
7328
+ import_types9.EdgeType.PUBLISHES_TO,
7329
+ import_types9.EdgeType.CONSUMES_FROM
7243
7330
  ]);
7244
7331
  var TIMEOUT_ERROR_PATTERNS = [
7245
7332
  /\bDEADLINE_EXCEEDED\b/i,
@@ -7268,11 +7355,11 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
7268
7355
  if (!graph.hasNode(n)) continue;
7269
7356
  for (const edgeId of graph.inboundEdges(n)) {
7270
7357
  const e = graph.getEdgeAttributes(edgeId);
7271
- if (e.type === import_types8.EdgeType.CONTAINS) continue;
7358
+ if (e.type === import_types9.EdgeType.CONTAINS) continue;
7272
7359
  if (isFrontierEdge(e)) continue;
7273
7360
  errorsFromCallers += e.signal?.errorCount ?? 0;
7274
7361
  inboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
7275
- if (e.provenance === import_types8.Provenance.STALE) stale = true;
7362
+ if (e.provenance === import_types9.Provenance.STALE) stale = true;
7276
7363
  const p95 = e.signal?.latencyMs?.p95;
7277
7364
  if (p95 !== void 0) latencyP95Ms = Math.max(latencyP95Ms ?? 0, p95);
7278
7365
  if (e.lastObserved) {
@@ -7282,11 +7369,11 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
7282
7369
  }
7283
7370
  for (const edgeId of graph.outboundEdges(n)) {
7284
7371
  const e = graph.getEdgeAttributes(edgeId);
7285
- if (e.type === import_types8.EdgeType.CONTAINS) continue;
7372
+ if (e.type === import_types9.EdgeType.CONTAINS) continue;
7286
7373
  if (isFrontierEdge(e)) continue;
7287
7374
  outboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
7288
- if (e.type === import_types8.EdgeType.CALLS) outboundErrors += e.signal?.errorCount ?? 0;
7289
- if (e.provenance === import_types8.Provenance.STALE) stale = true;
7375
+ if (e.type === import_types9.EdgeType.CALLS) outboundErrors += e.signal?.errorCount ?? 0;
7376
+ if (e.provenance === import_types9.Provenance.STALE) stale = true;
7290
7377
  if (DEP_EDGE_TYPES.has(e.type)) {
7291
7378
  hasOutboundDeps = true;
7292
7379
  if ((e.signal?.errorCount ?? 0) > 0) observedErroringDownstream = true;
@@ -7367,7 +7454,7 @@ function hasFailingOutbound(graph, nodeId, seedSource, incidents) {
7367
7454
  if (!graph.hasNode(n)) continue;
7368
7455
  for (const edgeId of graph.outboundEdges(n)) {
7369
7456
  const e = graph.getEdgeAttributes(edgeId);
7370
- if (e.type === import_types8.EdgeType.CONTAINS) continue;
7457
+ if (e.type === import_types9.EdgeType.CONTAINS) continue;
7371
7458
  if ((e.signal?.errorCount ?? 0) > 0) return true;
7372
7459
  }
7373
7460
  }
@@ -7381,9 +7468,9 @@ function hasFailingOutbound(graph, nodeId, seedSource, incidents) {
7381
7468
  function grainOf(graph, nodeId) {
7382
7469
  if (!graph.hasNode(nodeId)) return "unknown";
7383
7470
  const t = graph.getNodeAttributes(nodeId).type;
7384
- if (t === import_types8.NodeType.ServiceNode) return "service";
7385
- if (t === import_types8.NodeType.FileNode) return "file";
7386
- if (t === import_types8.NodeType.SymbolNode) return "symbol";
7471
+ if (t === import_types9.NodeType.ServiceNode) return "service";
7472
+ if (t === import_types9.NodeType.FileNode) return "file";
7473
+ if (t === import_types9.NodeType.SymbolNode) return "symbol";
7387
7474
  return t;
7388
7475
  }
7389
7476
  function findPath(graph, from, to, direction, maxDepth) {
@@ -7419,7 +7506,7 @@ var EMPTY_CONTEXT = {
7419
7506
  };
7420
7507
  function expandNode(graph, nodeId, direction, incidents, now = Date.now()) {
7421
7508
  if (!graph.hasNode(nodeId)) {
7422
- return import_types8.ExpandResultSchema.parse({
7509
+ return import_types9.ExpandResultSchema.parse({
7423
7510
  origin: nodeId,
7424
7511
  direction,
7425
7512
  node: { id: nodeId, classification: "unrelated", context: EMPTY_CONTEXT },
@@ -7430,7 +7517,7 @@ function expandNode(graph, nodeId, direction, incidents, now = Date.now()) {
7430
7517
  const best = direction === "up" ? bestEdgeBySource(graph, graph.inboundEdges(nodeId)) : bestEdgeByTarget(graph, graph.outboundEdges(nodeId));
7431
7518
  const neighbours = [];
7432
7519
  for (const [nid, edge] of best) {
7433
- if (edge.type === import_types8.EdgeType.CONTAINS) continue;
7520
+ if (edge.type === import_types9.EdgeType.CONTAINS) continue;
7434
7521
  const nctx = nodeContext(graph, nid, incidents, now);
7435
7522
  neighbours.push({
7436
7523
  node: nid,
@@ -7441,7 +7528,7 @@ function expandNode(graph, nodeId, direction, incidents, now = Date.now()) {
7441
7528
  });
7442
7529
  }
7443
7530
  neighbours.sort((a, b) => a.node.localeCompare(b.node));
7444
- return import_types8.ExpandResultSchema.parse({
7531
+ return import_types9.ExpandResultSchema.parse({
7445
7532
  origin: nodeId,
7446
7533
  direction,
7447
7534
  node: { id: nodeId, classification: classifyNode(ctx), context: ctx },
@@ -7461,7 +7548,7 @@ function relate(graph, a, b, maxDepth = ROOT_CAUSE_MAX_DEPTH) {
7461
7548
  )
7462
7549
  });
7463
7550
  if (!graph.hasNode(a) || !graph.hasNode(b)) {
7464
- return import_types8.RelateResultSchema.parse({
7551
+ return import_types9.RelateResultSchema.parse({
7465
7552
  a,
7466
7553
  b,
7467
7554
  related: false,
@@ -7473,7 +7560,7 @@ function relate(graph, a, b, maxDepth = ROOT_CAUSE_MAX_DEPTH) {
7473
7560
  const down = findPath(graph, a, b, "down", maxDepth);
7474
7561
  const up = findPath(graph, a, b, "up", maxDepth);
7475
7562
  if (!down && !up) {
7476
- return import_types8.RelateResultSchema.parse({
7563
+ return import_types9.RelateResultSchema.parse({
7477
7564
  a,
7478
7565
  b,
7479
7566
  related: false,
@@ -7488,7 +7575,7 @@ function relate(graph, a, b, maxDepth = ROOT_CAUSE_MAX_DEPTH) {
7488
7575
  if (up) paths.push(buildPath(up));
7489
7576
  const endpointsFine = grainOf(graph, a) !== "service" && grainOf(graph, b) !== "service";
7490
7577
  const grainGap = endpointsFine && paths[0].grain.some((g) => g === "service");
7491
- return import_types8.RelateResultSchema.parse({
7578
+ return import_types9.RelateResultSchema.parse({
7492
7579
  a,
7493
7580
  b,
7494
7581
  related: true,
@@ -7548,7 +7635,7 @@ function declaredOutboundCallees(graph, nodeId) {
7548
7635
  for (const edgeId of graph.outboundEdges(n)) {
7549
7636
  const e = graph.getEdgeAttributes(edgeId);
7550
7637
  if (!DEP_EDGE_TYPES.has(e.type)) continue;
7551
- if (e.provenance !== import_types8.Provenance.EXTRACTED) continue;
7638
+ if (e.provenance !== import_types9.Provenance.EXTRACTED) continue;
7552
7639
  if (e.target === nodeId || byTarget.has(e.target)) continue;
7553
7640
  const route = e.evidence?.pathTemplate;
7554
7641
  byTarget.set(
@@ -7581,7 +7668,7 @@ function observedOutboundNextServices(graph, nodeId) {
7581
7668
  for (const edgeId of graph.outboundEdges(n)) {
7582
7669
  const e = graph.getEdgeAttributes(edgeId);
7583
7670
  if (!DEP_EDGE_TYPES.has(e.type)) continue;
7584
- if (e.provenance !== import_types8.Provenance.OBSERVED) continue;
7671
+ if (e.provenance !== import_types9.Provenance.OBSERVED) continue;
7585
7672
  if (e.target !== nodeId) targets.add(e.target);
7586
7673
  }
7587
7674
  }
@@ -7603,7 +7690,7 @@ function resolveHangHop(graph, boundaryNode, incidents) {
7603
7690
  function stagedHangProposal(graph, boundaryNode, incidents) {
7604
7691
  const hop = resolveHangHop(graph, boundaryNode, incidents);
7605
7692
  if (!hop) return null;
7606
- if (!graph.hasEdge((0, import_types8.frontierEdgeId)(hop.source, hop.target, import_types8.EdgeType.CALLS))) return null;
7693
+ if (!graph.hasEdge((0, import_types9.frontierEdgeId)(hop.source, hop.target, import_types9.EdgeType.CALLS))) return null;
7607
7694
  return hop.route !== void 0 ? { node: hop.target, route: hop.route } : { node: hop.target };
7608
7695
  }
7609
7696
  function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
@@ -7628,7 +7715,7 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7628
7715
  reason: `${originName} is the root cause: it overloads the failing subgraph, and the alerting node ${seedName} is a downstream symptom, not the fault \u2014 errors reach ${seedName} from its callers (${seedCtx.errorsFromCallers}), none originate there${staleNote}${satNote}. ${originName} is the upstream source driving that load (${origin.ctx.outboundVolume} observed outbound calls).`,
7629
7716
  context: origin.ctx,
7630
7717
  confidence: loadOriginConfidence(origin.ctx, seedCtx),
7631
- provenance: import_types8.Provenance.OBSERVED
7718
+ provenance: import_types9.Provenance.OBSERVED
7632
7719
  });
7633
7720
  }
7634
7721
  candidates.push({
@@ -7647,7 +7734,7 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7647
7734
  reason: `${name} is unreachable: its callers' requests fail (${seedCtx.errorsFromCallers} erroring inbound calls) and it produced no telemetry of its own \u2014 no server spans, no outbound calls \u2014 so it never served. The failure is observed, but its cause is not in the trace: a startup failure, a crash before the first span, or an unschedulable / unhealthy pod. Inspect ${name}'s deploy state and logs \u2014 there is no code fault to find in the graph here.`,
7648
7735
  context: seedCtx,
7649
7736
  confidence: legacy.confidence,
7650
- provenance: import_types8.Provenance.OBSERVED
7737
+ provenance: import_types9.Provenance.OBSERVED
7651
7738
  });
7652
7739
  } else if (seedCtx && isBoundaryTimeoutSymptom(seedCtx)) {
7653
7740
  const seedName = displayNameOf(seedNode);
@@ -7669,7 +7756,7 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7669
7756
  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.`,
7670
7757
  context: nodeContext(graph, proposal.node, incidents, now),
7671
7758
  confidence: Math.min(legacy.confidence, PROVENANCE_CEILING.FRONTIER),
7672
- provenance: import_types8.Provenance.FRONTIER
7759
+ provenance: import_types9.Provenance.FRONTIER
7673
7760
  });
7674
7761
  }
7675
7762
  } else if (staleChain) {
@@ -7683,7 +7770,7 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7683
7770
  reason: `${culpritName} is the stale-derived root cause (low confidence): live telemetry for this subgraph has gone quiet, but the last-observed topology traces the failure surfacing at ${seedName} downstream through a STALE call chain to ${culpritName}. Provenance is STALE, so confidence is capped low \u2014 restore instrumentation and re-run to confirm before acting.`,
7684
7771
  context: nodeContext(graph, culprit, incidents, now),
7685
7772
  confidence: staleConfidence,
7686
- provenance: import_types8.Provenance.STALE
7773
+ provenance: import_types9.Provenance.STALE
7687
7774
  });
7688
7775
  candidates.push({
7689
7776
  node: seedNode,
@@ -7716,11 +7803,11 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7716
7803
  edgeProvenances = path81.edges.map((e) => e.provenance);
7717
7804
  } else {
7718
7805
  traversalPath = [errorNodeId, top.node];
7719
- edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
7806
+ edgeProvenances = [top.provenance ?? import_types9.Provenance.OBSERVED];
7720
7807
  }
7721
7808
  }
7722
7809
  const fixRecommendation = fixRecommendationForTop(top, seedNode, legacy);
7723
- return import_types8.RootCauseResultSchema.parse({
7810
+ return import_types9.RootCauseResultSchema.parse({
7724
7811
  rootCauseNode: top.node,
7725
7812
  rootCauseReason: top.reason,
7726
7813
  traversalPath,
@@ -7738,7 +7825,7 @@ function fixRecommendationForTop(top, seedNode, legacy) {
7738
7825
  if (top.classification === "symptom-only" && top.context.boundaryTimeout === true) {
7739
7826
  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.`;
7740
7827
  }
7741
- if (top.provenance === import_types8.Provenance.STALE) {
7828
+ if (top.provenance === import_types9.Provenance.STALE) {
7742
7829
  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}.`;
7743
7830
  }
7744
7831
  if (top.classification === "primary-failure") {
@@ -7752,34 +7839,34 @@ function bucketKey(source, target, type) {
7752
7839
  return `${type}|${source}|${target}`;
7753
7840
  }
7754
7841
  function bucketSourceFor(graph, edge) {
7755
- if (edge.type !== import_types9.EdgeType.CONNECTS_TO) return edge.source;
7756
- const parsed = (0, import_types9.parseFileId)(edge.source);
7842
+ if (edge.type !== import_types10.EdgeType.CONNECTS_TO) return edge.source;
7843
+ const parsed = (0, import_types10.parseFileId)(edge.source);
7757
7844
  if (!parsed || !graph.hasNode(edge.target)) return edge.source;
7758
7845
  const target = graph.getNodeAttributes(edge.target);
7759
- if (target.type !== import_types9.NodeType.DatabaseNode) return edge.source;
7760
- return (0, import_types9.serviceId)(parsed.service);
7846
+ if (target.type !== import_types10.NodeType.DatabaseNode) return edge.source;
7847
+ return (0, import_types10.serviceId)(parsed.service);
7761
7848
  }
7762
7849
  function bucketEdges(graph) {
7763
7850
  const buckets2 = /* @__PURE__ */ new Map();
7764
7851
  graph.forEachEdge((id, attrs) => {
7765
7852
  const e = attrs;
7766
- const parsed = (0, import_types9.parseEdgeId)(id);
7853
+ const parsed = (0, import_types10.parseEdgeId)(id);
7767
7854
  const provenance = parsed?.provenance ?? e.provenance;
7768
7855
  const source = bucketSourceFor(graph, e);
7769
7856
  const key = bucketKey(source, e.target, e.type);
7770
7857
  const cur = buckets2.get(key) ?? { source, target: e.target, type: e.type };
7771
7858
  switch (provenance) {
7772
- case import_types9.Provenance.EXTRACTED:
7859
+ case import_types10.Provenance.EXTRACTED:
7773
7860
  cur.extracted = e;
7774
7861
  break;
7775
- case import_types9.Provenance.OBSERVED:
7862
+ case import_types10.Provenance.OBSERVED:
7776
7863
  cur.observed = e;
7777
7864
  break;
7778
- case import_types9.Provenance.INFERRED:
7865
+ case import_types10.Provenance.INFERRED:
7779
7866
  cur.inferred = e;
7780
7867
  break;
7781
7868
  default:
7782
- if (e.provenance === import_types9.Provenance.STALE) cur.stale = e;
7869
+ if (e.provenance === import_types10.Provenance.STALE) cur.stale = e;
7783
7870
  }
7784
7871
  buckets2.set(key, cur);
7785
7872
  });
@@ -7788,22 +7875,22 @@ function bucketEdges(graph) {
7788
7875
  function nodeIsFrontier(graph, nodeId) {
7789
7876
  if (!graph.hasNode(nodeId)) return false;
7790
7877
  const attrs = graph.getNodeAttributes(nodeId);
7791
- return attrs.type === import_types9.NodeType.FrontierNode;
7878
+ return attrs.type === import_types10.NodeType.FrontierNode;
7792
7879
  }
7793
7880
  function nodeIsWebsocketChannel(graph, nodeId) {
7794
7881
  if (!graph.hasNode(nodeId)) return false;
7795
7882
  const attrs = graph.getNodeAttributes(nodeId);
7796
- return attrs.type === import_types9.NodeType.WebSocketChannelNode;
7883
+ return attrs.type === import_types10.NodeType.WebSocketChannelNode;
7797
7884
  }
7798
7885
  function nodeIsServerAction(graph, nodeId) {
7799
7886
  if (!graph.hasNode(nodeId)) return false;
7800
7887
  const attrs = graph.getNodeAttributes(nodeId);
7801
- return attrs.type === import_types9.NodeType.ServerActionNode;
7888
+ return attrs.type === import_types10.NodeType.ServerActionNode;
7802
7889
  }
7803
7890
  function nodeIsSymbol(graph, nodeId) {
7804
7891
  if (!graph.hasNode(nodeId)) return false;
7805
7892
  const attrs = graph.getNodeAttributes(nodeId);
7806
- return attrs.type === import_types9.NodeType.SymbolNode;
7893
+ return attrs.type === import_types10.NodeType.SymbolNode;
7807
7894
  }
7808
7895
  function clampConfidence(n) {
7809
7896
  if (!Number.isFinite(n)) return 0;
@@ -7823,14 +7910,14 @@ function gradedConfidence(edge) {
7823
7910
  return clampConfidence(confidenceForEdge(edge));
7824
7911
  }
7825
7912
  var OBSERVABLE_EDGE_TYPES = /* @__PURE__ */ new Set([
7826
- import_types9.EdgeType.CALLS,
7827
- import_types9.EdgeType.CONNECTS_TO,
7828
- import_types9.EdgeType.PUBLISHES_TO,
7829
- import_types9.EdgeType.CONSUMES_FROM
7913
+ import_types10.EdgeType.CALLS,
7914
+ import_types10.EdgeType.CONNECTS_TO,
7915
+ import_types10.EdgeType.PUBLISHES_TO,
7916
+ import_types10.EdgeType.CONSUMES_FROM
7830
7917
  ]);
7831
7918
  function detectMissingDivergences(graph, bucket) {
7832
7919
  const out = [];
7833
- if (bucket.type === import_types9.EdgeType.CONTAINS) return out;
7920
+ if (bucket.type === import_types10.EdgeType.CONTAINS) return out;
7834
7921
  if (nodeIsSymbol(graph, bucket.source) || nodeIsSymbol(graph, bucket.target)) return out;
7835
7922
  if (bucket.extracted && !bucket.observed && OBSERVABLE_EDGE_TYPES.has(bucket.type)) {
7836
7923
  if (!nodeIsFrontier(graph, bucket.target) && !nodeIsServerAction(graph, bucket.target)) {
@@ -7872,7 +7959,7 @@ function declaredHostFor(svc) {
7872
7959
  function hasExtractedConfiguredBy(graph, svcId) {
7873
7960
  for (const edgeId of graph.outboundEdges(svcId)) {
7874
7961
  const e = graph.getEdgeAttributes(edgeId);
7875
- if (e.type === import_types9.EdgeType.CONFIGURED_BY && e.provenance === import_types9.Provenance.EXTRACTED) {
7962
+ if (e.type === import_types10.EdgeType.CONFIGURED_BY && e.provenance === import_types10.Provenance.EXTRACTED) {
7876
7963
  return true;
7877
7964
  }
7878
7965
  }
@@ -7885,10 +7972,10 @@ function detectHostMismatch(graph, svcId, svc) {
7885
7972
  const out = [];
7886
7973
  for (const edgeId of graph.outboundEdges(svcId)) {
7887
7974
  const edge = graph.getEdgeAttributes(edgeId);
7888
- if (edge.type !== import_types9.EdgeType.CONNECTS_TO) continue;
7889
- if (edge.provenance !== import_types9.Provenance.OBSERVED) continue;
7975
+ if (edge.type !== import_types10.EdgeType.CONNECTS_TO) continue;
7976
+ if (edge.provenance !== import_types10.Provenance.OBSERVED) continue;
7890
7977
  const target = graph.getNodeAttributes(edge.target);
7891
- if (target.type !== import_types9.NodeType.DatabaseNode) continue;
7978
+ if (target.type !== import_types10.NodeType.DatabaseNode) continue;
7892
7979
  const observedHost = target.host?.trim();
7893
7980
  if (!observedHost) continue;
7894
7981
  if (observedHost === declaredHost) continue;
@@ -7910,10 +7997,10 @@ function detectCompatDivergences(graph, svcId, svc) {
7910
7997
  const deps = svc.dependencies ?? {};
7911
7998
  for (const edgeId of graph.outboundEdges(svcId)) {
7912
7999
  const edge = graph.getEdgeAttributes(edgeId);
7913
- if (edge.type !== import_types9.EdgeType.CONNECTS_TO) continue;
7914
- if (edge.provenance !== import_types9.Provenance.OBSERVED) continue;
8000
+ if (edge.type !== import_types10.EdgeType.CONNECTS_TO) continue;
8001
+ if (edge.provenance !== import_types10.Provenance.OBSERVED) continue;
7915
8002
  const target = graph.getNodeAttributes(edge.target);
7916
- if (target.type !== import_types9.NodeType.DatabaseNode) continue;
8003
+ if (target.type !== import_types10.NodeType.DatabaseNode) continue;
7917
8004
  for (const pair of compatPairs()) {
7918
8005
  if (pair.engine !== target.engine) continue;
7919
8006
  const declared = deps[pair.driver];
@@ -8076,11 +8163,11 @@ function symbolLocus(graph, ev) {
8076
8163
  const location = filepath ? `${filepath}${lineno !== void 0 ? `:${lineno}` : ""}` : void 0;
8077
8164
  const affected = ev.affectedNode;
8078
8165
  const affectedInGraph = affected.length > 0 && graph.hasNode(affected);
8079
- const affectedIsCode = affectedInGraph && ((0, import_types9.parseSymbolId)(affected) !== null || (0, import_types9.parseFileId)(affected) !== null);
8166
+ const affectedIsCode = affectedInGraph && ((0, import_types10.parseSymbolId)(affected) !== null || (0, import_types10.parseFileId)(affected) !== null);
8080
8167
  if (affectedIsCode) return { node: affected, ...location ? { location } : {} };
8081
8168
  if (!location) return null;
8082
8169
  if (affectedInGraph) return { node: affected, location };
8083
- const svc = (0, import_types9.serviceId)(ev.service);
8170
+ const svc = (0, import_types10.serviceId)(ev.service);
8084
8171
  if (graph.hasNode(svc)) return { node: svc, location };
8085
8172
  return null;
8086
8173
  }
@@ -8123,7 +8210,7 @@ function detectSymbolMismatches(graph, incidents) {
8123
8210
  mismatchKind: g.kind,
8124
8211
  ...g.symbol ? { symbol: g.symbol } : {},
8125
8212
  ...g.location ? { location: g.location } : {},
8126
- provenance: import_types9.Provenance.INFERRED,
8213
+ provenance: import_types10.Provenance.INFERRED,
8127
8214
  incidentId: g.latest.id,
8128
8215
  errorMessage: g.latest.errorMessage,
8129
8216
  incidentCount: g.count,
@@ -8140,7 +8227,7 @@ var OBSERVED_FAILING_CONFIDENCE = 0.6;
8140
8227
  function detectObservedFailingEdge(graph, bucket) {
8141
8228
  if (!bucket.extracted || !bucket.observed) return [];
8142
8229
  if (!OBSERVABLE_EDGE_TYPES.has(bucket.type)) return [];
8143
- if (bucket.observed.provenance !== import_types9.Provenance.OBSERVED) return [];
8230
+ if (bucket.observed.provenance !== import_types10.Provenance.OBSERVED) return [];
8144
8231
  const signal = bucket.observed.signal;
8145
8232
  if (!signal) return [];
8146
8233
  const { spanCount, errorCount } = signal;
@@ -8154,7 +8241,7 @@ function detectObservedFailingEdge(graph, bucket) {
8154
8241
  source: bucket.source,
8155
8242
  target: bucket.target,
8156
8243
  failureKind: "error-rate",
8157
- provenance: import_types9.Provenance.INFERRED,
8244
+ provenance: import_types10.Provenance.INFERRED,
8158
8245
  edgeType: bucket.type,
8159
8246
  observed: bucket.observed,
8160
8247
  spanCount,
@@ -8259,7 +8346,7 @@ function detectObservedFailingIncidents(graph, incidents) {
8259
8346
  source: g.node,
8260
8347
  target: g.node,
8261
8348
  failureKind: g.kind,
8262
- provenance: import_types9.Provenance.INFERRED,
8349
+ provenance: import_types10.Provenance.INFERRED,
8263
8350
  ...g.location ? { location: g.location } : {},
8264
8351
  incidentId: g.latest.id,
8265
8352
  errorMessage: g.latest.errorMessage,
@@ -8278,24 +8365,24 @@ function involvesNode(d, nodeId) {
8278
8365
  function datastoreEverObserved(graph, nodeId) {
8279
8366
  if (!graph.hasNode(nodeId)) return false;
8280
8367
  const n = graph.getNodeAttributes(nodeId);
8281
- if (n.type === import_types9.NodeType.DatabaseNode) {
8368
+ if (n.type === import_types10.NodeType.DatabaseNode) {
8282
8369
  const via = n.discoveredVia;
8283
8370
  if (via === "otel" || via === "merged") return true;
8284
8371
  }
8285
8372
  for (const edgeId of graph.inboundEdges(nodeId)) {
8286
8373
  const e = graph.getEdgeAttributes(edgeId);
8287
- if (e.provenance === import_types9.Provenance.OBSERVED || e.provenance === import_types9.Provenance.STALE) return true;
8374
+ if (e.provenance === import_types10.Provenance.OBSERVED || e.provenance === import_types10.Provenance.STALE) return true;
8288
8375
  }
8289
8376
  return false;
8290
8377
  }
8291
8378
  function serviceHasObservedSameEngineStore(graph, buckets2, serviceId17, engine, excludeTarget) {
8292
8379
  for (const bucket of buckets2.values()) {
8293
- if (bucket.type !== import_types9.EdgeType.CONNECTS_TO) continue;
8380
+ if (bucket.type !== import_types10.EdgeType.CONNECTS_TO) continue;
8294
8381
  if (bucket.source !== serviceId17) continue;
8295
8382
  if (bucket.target === excludeTarget) continue;
8296
8383
  if (!graph.hasNode(bucket.target)) continue;
8297
8384
  const target = graph.getNodeAttributes(bucket.target);
8298
- if (target.type !== import_types9.NodeType.DatabaseNode) continue;
8385
+ if (target.type !== import_types10.NodeType.DatabaseNode) continue;
8299
8386
  if (target.engine !== engine) continue;
8300
8387
  if (bucket.observed || datastoreEverObserved(graph, bucket.target)) return true;
8301
8388
  }
@@ -8305,10 +8392,10 @@ var DEAD_CODE_PROBE_CONFIDENCE = 0.1;
8305
8392
  function dampenDeadCodeProbes(graph, buckets2, all) {
8306
8393
  return all.map((d) => {
8307
8394
  if (d.type !== "missing-observed") return d;
8308
- if (!d.extracted || d.edgeType !== import_types9.EdgeType.CONNECTS_TO) return d;
8395
+ if (!d.extracted || d.edgeType !== import_types10.EdgeType.CONNECTS_TO) return d;
8309
8396
  if (!graph.hasNode(d.target)) return d;
8310
8397
  const target = graph.getNodeAttributes(d.target);
8311
- if (target.type !== import_types9.NodeType.DatabaseNode) return d;
8398
+ if (target.type !== import_types10.NodeType.DatabaseNode) return d;
8312
8399
  if (d.extracted.evidence?.hostSource !== "literal") return d;
8313
8400
  if (datastoreEverObserved(graph, d.target)) return d;
8314
8401
  const engine = target.engine;
@@ -8328,7 +8415,7 @@ function suppressHostMismatchHalves(all) {
8328
8415
  for (const d of all) {
8329
8416
  if (d.type !== "host-mismatch") continue;
8330
8417
  observedHalf.add(`${d.source}->${d.target}`);
8331
- declaredHalf.add((0, import_types9.databaseId)(d.extractedHost));
8418
+ declaredHalf.add((0, import_types10.databaseId)(d.extractedHost));
8332
8419
  }
8333
8420
  if (observedHalf.size === 0) return all;
8334
8421
  return all.filter((d) => {
@@ -8348,14 +8435,14 @@ function computeDivergences(graph, opts = {}) {
8348
8435
  }
8349
8436
  graph.forEachNode((nodeId, attrs) => {
8350
8437
  const n = attrs;
8351
- if (n.type === import_types9.NodeType.ServiceNode) {
8438
+ if (n.type === import_types10.NodeType.ServiceNode) {
8352
8439
  const svc = n;
8353
8440
  for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
8354
8441
  for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
8355
8442
  for (const d of detectDeployDivergence(svc)) all.push(d);
8356
8443
  return;
8357
8444
  }
8358
- if (n.type === import_types9.NodeType.InfraNode && n.kind === "sql-table") {
8445
+ if (n.type === import_types10.NodeType.InfraNode && n.kind === "sql-table") {
8359
8446
  for (const d of detectColumnDrift(n)) all.push(d);
8360
8447
  }
8361
8448
  });
@@ -8420,7 +8507,7 @@ function computeDivergences(graph, opts = {}) {
8420
8507
  const bloc = "location" in b && b.location ? b.location : "";
8421
8508
  return aloc.localeCompare(bloc);
8422
8509
  });
8423
- return import_types9.DivergenceResultSchema.parse({
8510
+ return import_types10.DivergenceResultSchema.parse({
8424
8511
  divergences: filtered,
8425
8512
  totalAffected: filtered.length,
8426
8513
  computedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -8484,7 +8571,7 @@ var import_node_fs22 = require("fs");
8484
8571
  var import_node_path24 = __toESM(require("path"), 1);
8485
8572
  var import_ignore2 = __toESM(require("ignore"), 1);
8486
8573
  var import_minimatch2 = require("minimatch");
8487
- var import_types19 = require("@neat.is/types");
8574
+ var import_types20 = require("@neat.is/types");
8488
8575
 
8489
8576
  // src/extract/python.ts
8490
8577
  init_cjs_shims();
@@ -8557,7 +8644,7 @@ function pythonToPackage(service) {
8557
8644
  init_cjs_shims();
8558
8645
  var import_node_fs13 = require("fs");
8559
8646
  var import_node_path14 = __toESM(require("path"), 1);
8560
- var import_types10 = require("@neat.is/types");
8647
+ var import_types11 = require("@neat.is/types");
8561
8648
  function parseGoMod(source) {
8562
8649
  const module2 = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
8563
8650
  if (!module2) return null;
@@ -8593,8 +8680,8 @@ async function discoverGoService(scanPath, dir) {
8593
8680
  const pkg = { name, dependencies: mod.dependencies };
8594
8681
  const framework = goFramework(mod.dependencies);
8595
8682
  const node = {
8596
- id: (0, import_types10.serviceId)(name),
8597
- type: import_types10.NodeType.ServiceNode,
8683
+ id: (0, import_types11.serviceId)(name),
8684
+ type: import_types11.NodeType.ServiceNode,
8598
8685
  name,
8599
8686
  language: "go",
8600
8687
  dependencies: mod.dependencies,
@@ -8608,7 +8695,7 @@ async function discoverGoService(scanPath, dir) {
8608
8695
  init_cjs_shims();
8609
8696
  var import_node_fs14 = require("fs");
8610
8697
  var import_node_path15 = __toESM(require("path"), 1);
8611
- var import_types11 = require("@neat.is/types");
8698
+ var import_types12 = require("@neat.is/types");
8612
8699
  function parseGemfile(source) {
8613
8700
  const dependencies = {};
8614
8701
  for (const raw of source.split(/\r?\n/)) {
@@ -8632,8 +8719,8 @@ async function discoverRubyService(scanPath, dir) {
8632
8719
  const name = import_node_path15.default.basename(dir);
8633
8720
  const pkg = { name, dependencies: gemfile.dependencies };
8634
8721
  const node = {
8635
- id: (0, import_types11.serviceId)(name),
8636
- type: import_types11.NodeType.ServiceNode,
8722
+ id: (0, import_types12.serviceId)(name),
8723
+ type: import_types12.NodeType.ServiceNode,
8637
8724
  name,
8638
8725
  language: "ruby",
8639
8726
  dependencies: gemfile.dependencies,
@@ -8646,7 +8733,7 @@ async function discoverRubyService(scanPath, dir) {
8646
8733
  // src/extract/php.ts
8647
8734
  init_cjs_shims();
8648
8735
  var import_node_path16 = __toESM(require("path"), 1);
8649
- var import_types12 = require("@neat.is/types");
8736
+ var import_types13 = require("@neat.is/types");
8650
8737
  function parseComposerJson(composer) {
8651
8738
  return {
8652
8739
  dependencies: {
@@ -8666,8 +8753,8 @@ async function discoverPhpService(scanPath, dir) {
8666
8753
  const name = import_node_path16.default.basename(dir);
8667
8754
  const pkg = { name, dependencies };
8668
8755
  const node = {
8669
- id: (0, import_types12.serviceId)(name),
8670
- type: import_types12.NodeType.ServiceNode,
8756
+ id: (0, import_types13.serviceId)(name),
8757
+ type: import_types13.NodeType.ServiceNode,
8671
8758
  name,
8672
8759
  language: "php",
8673
8760
  dependencies,
@@ -8681,7 +8768,7 @@ async function discoverPhpService(scanPath, dir) {
8681
8768
  init_cjs_shims();
8682
8769
  var import_node_fs15 = require("fs");
8683
8770
  var import_node_path17 = __toESM(require("path"), 1);
8684
- var import_types13 = require("@neat.is/types");
8771
+ var import_types14 = require("@neat.is/types");
8685
8772
  var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
8686
8773
  async function projectFiles(dir) {
8687
8774
  const entries = await import_node_fs15.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
@@ -8728,8 +8815,8 @@ async function discoverCsharpService(scanPath, dir) {
8728
8815
  }
8729
8816
  const pkg = { name, dependencies };
8730
8817
  const node = {
8731
- id: (0, import_types13.serviceId)(name),
8732
- type: import_types13.NodeType.ServiceNode,
8818
+ id: (0, import_types14.serviceId)(name),
8819
+ type: import_types14.NodeType.ServiceNode,
8733
8820
  name,
8734
8821
  language: "csharp",
8735
8822
  dependencies,
@@ -8744,7 +8831,7 @@ async function discoverCsharpService(scanPath, dir) {
8744
8831
  init_cjs_shims();
8745
8832
  var import_node_fs16 = require("fs");
8746
8833
  var import_node_path18 = __toESM(require("path"), 1);
8747
- var import_types14 = require("@neat.is/types");
8834
+ var import_types15 = require("@neat.is/types");
8748
8835
  var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
8749
8836
  async function hasJavaManifest(dir) {
8750
8837
  for (const manifest of JAVA_MANIFESTS) {
@@ -8799,8 +8886,8 @@ async function discoverJavaService(scanPath, dir) {
8799
8886
  const dependencies = manifest.dependencies;
8800
8887
  const pkg = { name, dependencies };
8801
8888
  const node = {
8802
- id: (0, import_types14.serviceId)(name),
8803
- type: import_types14.NodeType.ServiceNode,
8889
+ id: (0, import_types15.serviceId)(name),
8890
+ type: import_types15.NodeType.ServiceNode,
8804
8891
  name,
8805
8892
  language: "java",
8806
8893
  dependencies,
@@ -8813,7 +8900,7 @@ async function discoverJavaService(scanPath, dir) {
8813
8900
  init_cjs_shims();
8814
8901
  var import_node_fs17 = require("fs");
8815
8902
  var import_node_path19 = __toESM(require("path"), 1);
8816
- var import_types15 = require("@neat.is/types");
8903
+ var import_types16 = require("@neat.is/types");
8817
8904
  var KOTLIN_SOURCE_EXT = ".kt";
8818
8905
  var JAVA_SOURCE_EXT = ".java";
8819
8906
  var SOURCE_PROBE_MAX_DEPTH = 8;
@@ -8864,8 +8951,8 @@ async function discoverKotlinService(scanPath, dir) {
8864
8951
  const dependencies = manifest.dependencies;
8865
8952
  const pkg = { name, dependencies };
8866
8953
  const node = {
8867
- id: (0, import_types15.serviceId)(name),
8868
- type: import_types15.NodeType.ServiceNode,
8954
+ id: (0, import_types16.serviceId)(name),
8955
+ type: import_types16.NodeType.ServiceNode,
8869
8956
  name,
8870
8957
  language: "kotlin",
8871
8958
  dependencies,
@@ -8879,7 +8966,7 @@ init_cjs_shims();
8879
8966
  var import_node_fs18 = require("fs");
8880
8967
  var import_node_path20 = __toESM(require("path"), 1);
8881
8968
  var import_smol_toml2 = require("smol-toml");
8882
- var import_types16 = require("@neat.is/types");
8969
+ var import_types17 = require("@neat.is/types");
8883
8970
  var CARGO_MANIFEST = "Cargo.toml";
8884
8971
  async function hasRustManifest(dir) {
8885
8972
  return exists2(import_node_path20.default.join(dir, CARGO_MANIFEST));
@@ -8914,8 +9001,8 @@ async function discoverRustService(scanPath, dir) {
8914
9001
  const dependencies = manifest.dependencies;
8915
9002
  const pkg = { name, dependencies };
8916
9003
  const node = {
8917
- id: (0, import_types16.serviceId)(name),
8918
- type: import_types16.NodeType.ServiceNode,
9004
+ id: (0, import_types17.serviceId)(name),
9005
+ type: import_types17.NodeType.ServiceNode,
8919
9006
  name,
8920
9007
  language: "rust",
8921
9008
  dependencies,
@@ -8928,7 +9015,7 @@ async function discoverRustService(scanPath, dir) {
8928
9015
  init_cjs_shims();
8929
9016
  var import_node_fs19 = require("fs");
8930
9017
  var import_node_path21 = __toESM(require("path"), 1);
8931
- var import_types17 = require("@neat.is/types");
9018
+ var import_types18 = require("@neat.is/types");
8932
9019
  var CMAKE_MANIFEST = "CMakeLists.txt";
8933
9020
  async function hasCppManifest(dir) {
8934
9021
  return exists2(import_node_path21.default.join(dir, CMAKE_MANIFEST));
@@ -8946,8 +9033,8 @@ async function discoverCppService(scanPath, dir) {
8946
9033
  const dependencies = {};
8947
9034
  const pkg = { name, dependencies };
8948
9035
  const node = {
8949
- id: (0, import_types17.serviceId)(name),
8950
- type: import_types17.NodeType.ServiceNode,
9036
+ id: (0, import_types18.serviceId)(name),
9037
+ type: import_types18.NodeType.ServiceNode,
8951
9038
  name,
8952
9039
  language: "cpp",
8953
9040
  dependencies,
@@ -8960,7 +9047,7 @@ async function discoverCppService(scanPath, dir) {
8960
9047
  init_cjs_shims();
8961
9048
  var import_node_fs20 = require("fs");
8962
9049
  var import_node_path22 = __toESM(require("path"), 1);
8963
- var import_types18 = require("@neat.is/types");
9050
+ var import_types19 = require("@neat.is/types");
8964
9051
  function languageForSourceExt(ext) {
8965
9052
  switch (ext) {
8966
9053
  case ".py":
@@ -9046,8 +9133,8 @@ async function discoverDockerfileService(scanPath, dir) {
9046
9133
  const name = import_node_path22.default.basename(dir);
9047
9134
  const pkg = { name, dependencies: {} };
9048
9135
  const node = {
9049
- id: (0, import_types18.serviceId)(name),
9050
- type: import_types18.NodeType.ServiceNode,
9136
+ id: (0, import_types19.serviceId)(name),
9137
+ type: import_types19.NodeType.ServiceNode,
9051
9138
  name,
9052
9139
  language,
9053
9140
  dependencies: {},
@@ -9241,8 +9328,8 @@ async function discoverNodeService(scanPath, dir) {
9241
9328
  const framework = detectJsFramework(pkg);
9242
9329
  const language = await detectJsServiceLanguage(dir, pkg);
9243
9330
  const node = {
9244
- id: (0, import_types19.serviceId)(pkg.name),
9245
- type: import_types19.NodeType.ServiceNode,
9331
+ id: (0, import_types20.serviceId)(pkg.name),
9332
+ type: import_types20.NodeType.ServiceNode,
9246
9333
  name: pkg.name,
9247
9334
  language,
9248
9335
  version: pkg.version,
@@ -9258,8 +9345,8 @@ async function discoverPyService(scanPath, dir) {
9258
9345
  if (!py) return null;
9259
9346
  const pkg = pythonToPackage(py);
9260
9347
  const node = {
9261
- id: (0, import_types19.serviceId)(py.name),
9262
- type: import_types19.NodeType.ServiceNode,
9348
+ id: (0, import_types20.serviceId)(py.name),
9349
+ type: import_types20.NodeType.ServiceNode,
9263
9350
  name: py.name,
9264
9351
  language: "python",
9265
9352
  version: py.version,
@@ -9378,7 +9465,7 @@ init_cjs_shims();
9378
9465
  var import_node_path25 = __toESM(require("path"), 1);
9379
9466
  var import_node_fs23 = require("fs");
9380
9467
  var import_yaml2 = require("yaml");
9381
- var import_types20 = require("@neat.is/types");
9468
+ var import_types21 = require("@neat.is/types");
9382
9469
  var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
9383
9470
  "Service",
9384
9471
  "Deployment",
@@ -9388,7 +9475,7 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
9388
9475
  function addAliases(graph, serviceId17, candidates) {
9389
9476
  if (!graph.hasNode(serviceId17)) return;
9390
9477
  const node = graph.getNodeAttributes(serviceId17);
9391
- if (node.type !== import_types20.NodeType.ServiceNode) return;
9478
+ if (node.type !== import_types21.NodeType.ServiceNode) return;
9392
9479
  const set = new Set(node.aliases ?? []);
9393
9480
  for (const c of candidates) {
9394
9481
  if (!c) continue;
@@ -9578,7 +9665,7 @@ var import_tree_sitter_java = __toESM(require("tree-sitter-java"), 1);
9578
9665
  var import_tree_sitter_kotlin = __toESM(require("tree-sitter-kotlin"), 1);
9579
9666
  var import_tree_sitter_rust2 = __toESM(require("tree-sitter-rust"), 1);
9580
9667
  var import_tree_sitter_cpp = __toESM(require("tree-sitter-cpp"), 1);
9581
- var import_types21 = require("@neat.is/types");
9668
+ var import_types22 = require("@neat.is/types");
9582
9669
  var PARSE_CHUNK3 = 16384;
9583
9670
  var GRAMMAR_BY_EXT = {
9584
9671
  ".ts": import_tree_sitter_typescript.default.typescript,
@@ -9631,7 +9718,9 @@ function collectSymbolDefs(root) {
9631
9718
  kind,
9632
9719
  qualname,
9633
9720
  startLine: node.startPosition.row + 1,
9634
- endLine: node.endPosition.row + 1
9721
+ endLine: node.endPosition.row + 1,
9722
+ startIndex: node.startIndex,
9723
+ endIndex: node.endIndex
9635
9724
  });
9636
9725
  };
9637
9726
  const visit = (node, classCtx) => {
@@ -9690,7 +9779,9 @@ function collectPythonSymbolDefs(root) {
9690
9779
  kind,
9691
9780
  qualname,
9692
9781
  startLine: node.startPosition.row + 1,
9693
- endLine: node.endPosition.row + 1
9782
+ endLine: node.endPosition.row + 1,
9783
+ startIndex: node.startIndex,
9784
+ endIndex: node.endIndex
9694
9785
  });
9695
9786
  };
9696
9787
  const visit = (node, classCtx) => {
@@ -9763,7 +9854,9 @@ function collectGoSymbolDefs(root) {
9763
9854
  kind,
9764
9855
  qualname,
9765
9856
  startLine: node.startPosition.row + 1,
9766
- endLine: node.endPosition.row + 1
9857
+ endLine: node.endPosition.row + 1,
9858
+ startIndex: node.startIndex,
9859
+ endIndex: node.endIndex
9767
9860
  });
9768
9861
  };
9769
9862
  const visit = (node) => {
@@ -9797,7 +9890,9 @@ function collectRubySymbolDefs(root) {
9797
9890
  kind,
9798
9891
  qualname,
9799
9892
  startLine: node.startPosition.row + 1,
9800
- endLine: node.endPosition.row + 1
9893
+ endLine: node.endPosition.row + 1,
9894
+ startIndex: node.startIndex,
9895
+ endIndex: node.endIndex
9801
9896
  });
9802
9897
  };
9803
9898
  const nameText = (node) => node.childForFieldName("name")?.text.replace(/::/g, ".");
@@ -9848,7 +9943,9 @@ function collectPhpSymbolDefs(root) {
9848
9943
  kind,
9849
9944
  qualname,
9850
9945
  startLine: node.startPosition.row + 1,
9851
- endLine: node.endPosition.row + 1
9946
+ endLine: node.endPosition.row + 1,
9947
+ startIndex: node.startIndex,
9948
+ endIndex: node.endIndex
9852
9949
  });
9853
9950
  };
9854
9951
  const dot = (s) => s.replace(/\\/g, ".").replace(/::/g, ".").replace(/^\.+/, "");
@@ -9914,7 +10011,9 @@ function collectCsharpSymbolDefs(root) {
9914
10011
  kind,
9915
10012
  qualname,
9916
10013
  startLine: node.startPosition.row + 1,
9917
- endLine: node.endPosition.row + 1
10014
+ endLine: node.endPosition.row + 1,
10015
+ startIndex: node.startIndex,
10016
+ endIndex: node.endIndex
9918
10017
  });
9919
10018
  };
9920
10019
  const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9976,7 +10075,9 @@ function collectJavaSymbolDefs(root) {
9976
10075
  kind,
9977
10076
  qualname,
9978
10077
  startLine: node.startPosition.row + 1,
9979
- endLine: node.endPosition.row + 1
10078
+ endLine: node.endPosition.row + 1,
10079
+ startIndex: node.startIndex,
10080
+ endIndex: node.endIndex
9980
10081
  });
9981
10082
  };
9982
10083
  const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -10033,7 +10134,9 @@ function collectKotlinSymbolDefs(root) {
10033
10134
  kind,
10034
10135
  qualname,
10035
10136
  startLine: node.startPosition.row + 1,
10036
- endLine: node.endPosition.row + 1
10137
+ endLine: node.endPosition.row + 1,
10138
+ startIndex: node.startIndex,
10139
+ endIndex: node.endIndex
10037
10140
  });
10038
10141
  };
10039
10142
  const join = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -10103,7 +10206,9 @@ function collectRustSymbolDefs(root) {
10103
10206
  kind,
10104
10207
  qualname,
10105
10208
  startLine: node.startPosition.row + 1,
10106
- endLine: node.endPosition.row + 1
10209
+ endLine: node.endPosition.row + 1,
10210
+ startIndex: node.startIndex,
10211
+ endIndex: node.endIndex
10107
10212
  });
10108
10213
  };
10109
10214
  const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -10171,7 +10276,9 @@ function collectCppSymbolDefs(root) {
10171
10276
  kind,
10172
10277
  qualname,
10173
10278
  startLine: node.startPosition.row + 1,
10174
- endLine: node.endPosition.row + 1
10279
+ endLine: node.endPosition.row + 1,
10280
+ startIndex: node.startIndex,
10281
+ endIndex: node.endIndex
10175
10282
  });
10176
10283
  };
10177
10284
  const join = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -10299,6 +10406,22 @@ function disambiguate(defs) {
10299
10406
  return { def, disambiguator: ordinal };
10300
10407
  });
10301
10408
  }
10409
+ function utf8Offsets(content, defs) {
10410
+ if (content.includes("\uFFFD")) return /* @__PURE__ */ new Map();
10411
+ const indices = [...new Set(defs.flatMap(({ startIndex, endIndex }) => [startIndex, endIndex]))].sort(
10412
+ (a, b) => a - b
10413
+ );
10414
+ const offsets = /* @__PURE__ */ new Map();
10415
+ let cursor = 0;
10416
+ let bytes = 0;
10417
+ for (const index of indices) {
10418
+ if (index < cursor || index > content.length) return /* @__PURE__ */ new Map();
10419
+ bytes += Buffer.byteLength(content.slice(cursor, index), "utf8");
10420
+ offsets.set(index, bytes);
10421
+ cursor = index;
10422
+ }
10423
+ return offsets;
10424
+ }
10302
10425
  async function addSymbols(graph, services) {
10303
10426
  const parsers = /* @__PURE__ */ new Map();
10304
10427
  const parserForExt5 = (ext) => {
@@ -10322,47 +10445,59 @@ async function addSymbols(graph, services) {
10322
10445
  if (!parser) continue;
10323
10446
  const relPath = toPosix(import_node_path27.default.relative(service.dir, file.path));
10324
10447
  let defs;
10448
+ let completeParse;
10325
10449
  try {
10326
10450
  const tree = parseSource3(parser, file.content);
10327
10451
  defs = collectSymbolDefsForExt(ext, tree.rootNode);
10452
+ completeParse = !tree.rootNode.hasError;
10328
10453
  } catch (err) {
10329
10454
  recordExtractionError("symbol extraction", file.path, err);
10330
10455
  continue;
10331
10456
  }
10332
10457
  if (defs.length === 0) continue;
10333
- const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
10334
- graph,
10335
- service.pkg.name,
10336
- service.node.id,
10337
- relPath
10338
- );
10458
+ const offsets = completeParse ? utf8Offsets(file.content, defs) : /* @__PURE__ */ new Map();
10459
+ const {
10460
+ fileNodeId,
10461
+ nodesAdded: fn,
10462
+ edgesAdded: fe
10463
+ } = ensureFileNode(graph, service.pkg.name, service.node.id, relPath);
10339
10464
  nodesAdded += fn;
10340
10465
  edgesAdded += fe;
10341
10466
  for (const { def, disambiguator } of disambiguate(defs)) {
10342
- const sid = (0, import_types21.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
10467
+ const sid = (0, import_types22.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
10468
+ const startByte = offsets.get(def.startIndex);
10469
+ const endByte = offsets.get(def.endIndex);
10470
+ const precise = startByte !== void 0 && endByte !== void 0 && endByte > startByte ? { startByte, endByte } : {};
10471
+ const node = {
10472
+ id: sid,
10473
+ type: import_types22.NodeType.SymbolNode,
10474
+ kind: def.kind,
10475
+ qualname: def.qualname,
10476
+ span: { startLine: def.startLine, endLine: def.endLine, ...precise },
10477
+ service: service.pkg.name,
10478
+ relPath,
10479
+ discoveredVia: "static"
10480
+ };
10343
10481
  if (!graph.hasNode(sid)) {
10344
- const node = {
10345
- id: sid,
10346
- type: import_types21.NodeType.SymbolNode,
10347
- kind: def.kind,
10348
- qualname: def.qualname,
10349
- span: { startLine: def.startLine, endLine: def.endLine },
10350
- service: service.pkg.name,
10351
- relPath,
10352
- discoveredVia: "static"
10353
- };
10354
10482
  graph.addNode(sid, node);
10355
10483
  nodesAdded++;
10484
+ } else {
10485
+ const previous = graph.getNodeAttributes(sid);
10486
+ const discoveredVia = previous.discoveredVia === "otel" || previous.discoveredVia === "merged" ? "merged" : "static";
10487
+ const moved = previous.span.startLine !== node.span.startLine || previous.span.endLine !== node.span.endLine || previous.span.startByte !== node.span.startByte || previous.span.endByte !== node.span.endByte;
10488
+ if (moved || previous.kind !== node.kind || previous.qualname !== node.qualname || previous.discoveredVia !== discoveredVia || previous.service !== node.service || previous.relPath !== node.relPath) {
10489
+ graph.replaceNodeAttributes(sid, { ...previous, ...node, discoveredVia });
10490
+ }
10356
10491
  }
10357
- const containsId = (0, import_types21.extractedEdgeId)(fileNodeId, sid, import_types21.EdgeType.CONTAINS);
10492
+ const containsId = (0, import_types22.extractedEdgeId)(fileNodeId, sid, import_types22.EdgeType.CONTAINS);
10358
10493
  if (!graph.hasEdge(containsId)) {
10359
10494
  const edge = {
10360
10495
  id: containsId,
10361
10496
  source: fileNodeId,
10362
10497
  target: sid,
10363
- type: import_types21.EdgeType.CONTAINS,
10364
- provenance: import_types21.Provenance.EXTRACTED,
10365
- confidence: (0, import_types21.confidenceForExtracted)("structural"),
10498
+ type: import_types22.EdgeType.CONTAINS,
10499
+ provenance: import_types22.Provenance.EXTRACTED,
10500
+ confidence: (0, import_types22.confidenceForExtracted)("structural"),
10366
10501
  evidence: {
10367
10502
  file: relPath,
10368
10503
  line: def.startLine,
@@ -10382,7 +10517,7 @@ async function addSymbols(graph, services) {
10382
10517
  init_cjs_shims();
10383
10518
  var import_node_path28 = __toESM(require("path"), 1);
10384
10519
  var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
10385
- var import_types22 = require("@neat.is/types");
10520
+ var import_types23 = require("@neat.is/types");
10386
10521
  function extendsInfo(classHeritage) {
10387
10522
  for (let i = 0; i < classHeritage.namedChildCount; i++) {
10388
10523
  const child = classHeritage.namedChild(i);
@@ -10500,7 +10635,7 @@ async function addSymbolEdges(graph, services) {
10500
10635
  }
10501
10636
  const disambiguated = disambiguate(collectSymbolDefs(root));
10502
10637
  const locals = disambiguated.map(({ def, disambiguator }) => ({
10503
- sid: (0, import_types22.symbolId)(serviceName, relPath, def.qualname, disambiguator),
10638
+ sid: (0, import_types23.symbolId)(serviceName, relPath, def.qualname, disambiguator),
10504
10639
  qualname: def.qualname,
10505
10640
  kind: def.kind,
10506
10641
  startLine: def.startLine,
@@ -10529,10 +10664,10 @@ async function addSymbolEdges(graph, services) {
10529
10664
  if (local) return local.kind === wantKind ? local.sid : null;
10530
10665
  const imp = resolvedImports.get(name);
10531
10666
  if (imp) {
10532
- const candidate = (0, import_types22.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
10667
+ const candidate = (0, import_types23.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
10533
10668
  if (graph.hasNode(candidate)) {
10534
10669
  const node = graph.getNodeAttributes(candidate);
10535
- if (node.type === import_types22.NodeType.SymbolNode && node.kind === wantKind) return candidate;
10670
+ if (node.type === import_types23.NodeType.SymbolNode && node.kind === wantKind) return candidate;
10536
10671
  }
10537
10672
  }
10538
10673
  return null;
@@ -10559,7 +10694,7 @@ async function addSymbolEdges(graph, services) {
10559
10694
  sourceSid: self.sid,
10560
10695
  targetName: ext.name,
10561
10696
  wantKind: "class",
10562
- edgeType: import_types22.EdgeType.INHERITS,
10697
+ edgeType: import_types23.EdgeType.INHERITS,
10563
10698
  line: ext.line
10564
10699
  });
10565
10700
  }
@@ -10568,7 +10703,7 @@ async function addSymbolEdges(graph, services) {
10568
10703
  sourceSid: self.sid,
10569
10704
  targetName: impl.name,
10570
10705
  wantKind: "class",
10571
- edgeType: import_types22.EdgeType.IMPLEMENTS,
10706
+ edgeType: import_types23.EdgeType.IMPLEMENTS,
10572
10707
  line: impl.line
10573
10708
  });
10574
10709
  }
@@ -10584,7 +10719,7 @@ async function addSymbolEdges(graph, services) {
10584
10719
  sourceSid: caller.sid,
10585
10720
  targetName: fn.text,
10586
10721
  wantKind: "function",
10587
- edgeType: import_types22.EdgeType.CALLS,
10722
+ edgeType: import_types23.EdgeType.CALLS,
10588
10723
  line
10589
10724
  });
10590
10725
  }
@@ -10600,15 +10735,15 @@ async function addSymbolEdges(graph, services) {
10600
10735
  const targetSid = resolveTarget(req.targetName, req.wantKind);
10601
10736
  if (!targetSid) continue;
10602
10737
  if (targetSid === req.sourceSid) continue;
10603
- const edgeId = (0, import_types22.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
10738
+ const edgeId = (0, import_types23.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
10604
10739
  if (graph.hasEdge(edgeId)) continue;
10605
10740
  const edge = {
10606
10741
  id: edgeId,
10607
10742
  source: req.sourceSid,
10608
10743
  target: targetSid,
10609
10744
  type: req.edgeType,
10610
- provenance: import_types22.Provenance.EXTRACTED,
10611
- confidence: (0, import_types22.confidenceForExtracted)("structural"),
10745
+ provenance: import_types23.Provenance.EXTRACTED,
10746
+ confidence: (0, import_types23.confidenceForExtracted)("structural"),
10612
10747
  evidence: {
10613
10748
  file: relPath,
10614
10749
  line: req.line,
@@ -10627,7 +10762,7 @@ async function addSymbolEdges(graph, services) {
10627
10762
  init_cjs_shims();
10628
10763
  var import_node_path29 = __toESM(require("path"), 1);
10629
10764
  var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
10630
- var import_types23 = require("@neat.is/types");
10765
+ var import_types24 = require("@neat.is/types");
10631
10766
  function stringLiteralText2(node) {
10632
10767
  for (let i = 0; i < node.childCount; i++) {
10633
10768
  const child = node.child(i);
@@ -10797,11 +10932,11 @@ async function addServerActions(graph, services) {
10797
10932
  nodesAdded += fn;
10798
10933
  edgesAdded += fe;
10799
10934
  for (const action of actions) {
10800
- const aid = (0, import_types23.serverActionId)(service.pkg.name, relPath, action.exportName);
10935
+ const aid = (0, import_types24.serverActionId)(service.pkg.name, relPath, action.exportName);
10801
10936
  if (!graph.hasNode(aid)) {
10802
10937
  const node = {
10803
10938
  id: aid,
10804
- type: import_types23.NodeType.ServerActionNode,
10939
+ type: import_types24.NodeType.ServerActionNode,
10805
10940
  name: action.exportName,
10806
10941
  service: service.pkg.name,
10807
10942
  module: relPath,
@@ -10813,15 +10948,15 @@ async function addServerActions(graph, services) {
10813
10948
  graph.addNode(aid, node);
10814
10949
  nodesAdded++;
10815
10950
  }
10816
- const containsId = (0, import_types23.extractedEdgeId)(fileNodeId, aid, import_types23.EdgeType.CONTAINS);
10951
+ const containsId = (0, import_types24.extractedEdgeId)(fileNodeId, aid, import_types24.EdgeType.CONTAINS);
10817
10952
  if (!graph.hasEdge(containsId)) {
10818
10953
  const edge = {
10819
10954
  id: containsId,
10820
10955
  source: fileNodeId,
10821
10956
  target: aid,
10822
- type: import_types23.EdgeType.CONTAINS,
10823
- provenance: import_types23.Provenance.EXTRACTED,
10824
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
10957
+ type: import_types24.EdgeType.CONTAINS,
10958
+ provenance: import_types24.Provenance.EXTRACTED,
10959
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10825
10960
  evidence: {
10826
10961
  file: relPath,
10827
10962
  line: action.line,
@@ -10851,7 +10986,7 @@ async function addServerActions(graph, services) {
10851
10986
  for (const [local, binding] of bindings) {
10852
10987
  const target = await resolveJsImport(binding.specifier, fileDir, service.dir, tsPaths);
10853
10988
  if (!target) continue;
10854
- const aid = (0, import_types23.serverActionId)(service.pkg.name, target, binding.importedName);
10989
+ const aid = (0, import_types24.serverActionId)(service.pkg.name, target, binding.importedName);
10855
10990
  if (graph.hasNode(aid)) actionBindings.set(local, aid);
10856
10991
  }
10857
10992
  if (actionBindings.size === 0) continue;
@@ -10866,15 +11001,15 @@ async function addServerActions(graph, services) {
10866
11001
  nodesAdded += ensured.nodesAdded;
10867
11002
  edgesAdded += ensured.edgesAdded;
10868
11003
  }
10869
- const callsId = (0, import_types23.extractedEdgeId)(clientFileId, aid, import_types23.EdgeType.CALLS);
11004
+ const callsId = (0, import_types24.extractedEdgeId)(clientFileId, aid, import_types24.EdgeType.CALLS);
10870
11005
  if (graph.hasEdge(callsId)) continue;
10871
11006
  const edge = {
10872
11007
  id: callsId,
10873
11008
  source: clientFileId,
10874
11009
  target: aid,
10875
- type: import_types23.EdgeType.CALLS,
10876
- provenance: import_types23.Provenance.EXTRACTED,
10877
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
11010
+ type: import_types24.EdgeType.CALLS,
11011
+ provenance: import_types24.Provenance.EXTRACTED,
11012
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10878
11013
  evidence: {
10879
11014
  file: relPath,
10880
11015
  line,
@@ -10892,7 +11027,7 @@ async function addServerActions(graph, services) {
10892
11027
  // src/extract/databases/index.ts
10893
11028
  init_cjs_shims();
10894
11029
  var import_node_path38 = __toESM(require("path"), 1);
10895
- var import_types24 = require("@neat.is/types");
11030
+ var import_types25 = require("@neat.is/types");
10896
11031
 
10897
11032
  // src/extract/databases/db-config-yaml.ts
10898
11033
  init_cjs_shims();
@@ -11551,8 +11686,8 @@ function compatibleDriversFor(engine) {
11551
11686
  }
11552
11687
  function toDatabaseNode(config) {
11553
11688
  return {
11554
- id: (0, import_types24.databaseId)(config.host),
11555
- type: import_types24.NodeType.DatabaseNode,
11689
+ id: (0, import_types25.databaseId)(config.host),
11690
+ type: import_types25.NodeType.DatabaseNode,
11556
11691
  name: config.database || config.host,
11557
11692
  engine: config.engine,
11558
11693
  engineVersion: config.engineVersion,
@@ -11693,12 +11828,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
11693
11828
  edgesAdded += fe;
11694
11829
  const evidenceFile = toPosix(import_node_path38.default.relative(scanPath, config.sourceFile));
11695
11830
  const edge = {
11696
- id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types24.EdgeType.CONNECTS_TO),
11831
+ id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types25.EdgeType.CONNECTS_TO),
11697
11832
  source: fileNodeId,
11698
11833
  target: dbNode.id,
11699
- type: import_types24.EdgeType.CONNECTS_TO,
11700
- provenance: import_types24.Provenance.EXTRACTED,
11701
- confidence: (0, import_types24.confidenceForExtracted)("structural"),
11834
+ type: import_types25.EdgeType.CONNECTS_TO,
11835
+ provenance: import_types25.Provenance.EXTRACTED,
11836
+ confidence: (0, import_types25.confidenceForExtracted)("structural"),
11702
11837
  // Carry how the host was recovered (ADR-213) so the divergence ranker
11703
11838
  // can tell a real declared store from a hardcoded fault-injection /
11704
11839
  // flag-gated probe. Only set when the parser distinguished the two.
@@ -11713,11 +11848,11 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
11713
11848
  const primary = allConfigs[0];
11714
11849
  service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
11715
11850
  const relPath = import_node_path38.default.relative(scanPath, primary.sourceFile);
11716
- const cfgId = (0, import_types24.configId)(relPath);
11851
+ const cfgId = (0, import_types25.configId)(relPath);
11717
11852
  if (!graph.hasNode(cfgId)) {
11718
11853
  const cfgNode = {
11719
11854
  id: cfgId,
11720
- type: import_types24.NodeType.ConfigNode,
11855
+ type: import_types25.NodeType.ConfigNode,
11721
11856
  name: import_node_path38.default.basename(primary.sourceFile),
11722
11857
  path: relPath,
11723
11858
  fileType: isConfigFile(import_node_path38.default.basename(primary.sourceFile)).fileType || "config"
@@ -11726,12 +11861,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
11726
11861
  nodesAdded++;
11727
11862
  }
11728
11863
  const cfgEdge = {
11729
- id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types24.EdgeType.CONFIGURED_BY),
11864
+ id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types25.EdgeType.CONFIGURED_BY),
11730
11865
  source: service.node.id,
11731
11866
  target: cfgId,
11732
- type: import_types24.EdgeType.CONFIGURED_BY,
11733
- provenance: import_types24.Provenance.EXTRACTED,
11734
- confidence: (0, import_types24.confidenceForExtracted)("structural"),
11867
+ type: import_types25.EdgeType.CONFIGURED_BY,
11868
+ provenance: import_types25.Provenance.EXTRACTED,
11869
+ confidence: (0, import_types25.confidenceForExtracted)("structural"),
11735
11870
  evidence: { file: toPosix(relPath) }
11736
11871
  };
11737
11872
  if (!graph.hasEdge(cfgEdge.id)) {
@@ -11763,7 +11898,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
11763
11898
  init_cjs_shims();
11764
11899
  var import_node_fs27 = require("fs");
11765
11900
  var import_node_path39 = __toESM(require("path"), 1);
11766
- var import_types25 = require("@neat.is/types");
11901
+ var import_types26 = require("@neat.is/types");
11767
11902
  async function walkConfigFiles(dir, excludeDirs = []) {
11768
11903
  const excluded = new Set(excludeDirs.map((d) => import_node_path39.default.resolve(d)));
11769
11904
  const out = [];
@@ -11792,8 +11927,8 @@ async function addConfigNodes(graph, services, scanPath) {
11792
11927
  for (const file of configFiles) {
11793
11928
  const relPath = import_node_path39.default.relative(scanPath, file);
11794
11929
  const node = {
11795
- id: (0, import_types25.configId)(relPath),
11796
- type: import_types25.NodeType.ConfigNode,
11930
+ id: (0, import_types26.configId)(relPath),
11931
+ type: import_types26.NodeType.ConfigNode,
11797
11932
  name: import_node_path39.default.basename(file),
11798
11933
  path: relPath,
11799
11934
  fileType: isConfigFile(import_node_path39.default.basename(file)).fileType
@@ -11812,12 +11947,12 @@ async function addConfigNodes(graph, services, scanPath) {
11812
11947
  nodesAdded += fn;
11813
11948
  edgesAdded += fe;
11814
11949
  const edge = {
11815
- id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types25.EdgeType.CONFIGURED_BY),
11950
+ id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types26.EdgeType.CONFIGURED_BY),
11816
11951
  source: fileNodeId,
11817
11952
  target: node.id,
11818
- type: import_types25.EdgeType.CONFIGURED_BY,
11819
- provenance: import_types25.Provenance.EXTRACTED,
11820
- confidence: (0, import_types25.confidenceForExtracted)("structural"),
11953
+ type: import_types26.EdgeType.CONFIGURED_BY,
11954
+ provenance: import_types26.Provenance.EXTRACTED,
11955
+ confidence: (0, import_types26.confidenceForExtracted)("structural"),
11821
11956
  evidence: { file: relPath.split(import_node_path39.default.sep).join("/") }
11822
11957
  };
11823
11958
  if (!graph.hasEdge(edge.id)) {
@@ -11833,7 +11968,7 @@ async function addConfigNodes(graph, services, scanPath) {
11833
11968
  init_cjs_shims();
11834
11969
  var import_node_fs28 = require("fs");
11835
11970
  var import_node_path40 = __toESM(require("path"), 1);
11836
- var import_types26 = require("@neat.is/types");
11971
+ var import_types27 = require("@neat.is/types");
11837
11972
  var PROTO_EXTENSION = ".proto";
11838
11973
  function packageOf(content) {
11839
11974
  const m = content.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_.]*)\s*;/m);
@@ -11913,11 +12048,11 @@ async function addGrpcMethods(graph, services) {
11913
12048
  }
11914
12049
  if (methods.length === 0) continue;
11915
12050
  for (const method of methods) {
11916
- const mid = (0, import_types26.grpcMethodId)(method.rpcService, method.rpcMethod);
12051
+ const mid = (0, import_types27.grpcMethodId)(method.rpcService, method.rpcMethod);
11917
12052
  if (!graph.hasNode(mid)) {
11918
12053
  const node = {
11919
12054
  id: mid,
11920
- type: import_types26.NodeType.GrpcMethodNode,
12055
+ type: import_types27.NodeType.GrpcMethodNode,
11921
12056
  name: `${method.rpcService}/${method.rpcMethod}`,
11922
12057
  rpcService: method.rpcService,
11923
12058
  rpcMethod: method.rpcMethod,
@@ -11928,15 +12063,15 @@ async function addGrpcMethods(graph, services) {
11928
12063
  graph.addNode(mid, node);
11929
12064
  nodesAdded++;
11930
12065
  }
11931
- const containsId = (0, import_types26.extractedEdgeId)(service.node.id, mid, import_types26.EdgeType.CONTAINS);
12066
+ const containsId = (0, import_types27.extractedEdgeId)(service.node.id, mid, import_types27.EdgeType.CONTAINS);
11932
12067
  if (!graph.hasEdge(containsId)) {
11933
12068
  const edge = {
11934
12069
  id: containsId,
11935
12070
  source: service.node.id,
11936
12071
  target: mid,
11937
- type: import_types26.EdgeType.CONTAINS,
11938
- provenance: import_types26.Provenance.EXTRACTED,
11939
- confidence: (0, import_types26.confidenceForExtracted)("structural"),
12072
+ type: import_types27.EdgeType.CONTAINS,
12073
+ provenance: import_types27.Provenance.EXTRACTED,
12074
+ confidence: (0, import_types27.confidenceForExtracted)("structural"),
11940
12075
  evidence: {
11941
12076
  file: relFile,
11942
12077
  line: method.line,
@@ -11954,7 +12089,7 @@ async function addGrpcMethods(graph, services) {
11954
12089
 
11955
12090
  // src/extract/calls/index.ts
11956
12091
  init_cjs_shims();
11957
- var import_types46 = require("@neat.is/types");
12092
+ var import_types47 = require("@neat.is/types");
11958
12093
 
11959
12094
  // src/extract/calls/http.ts
11960
12095
  init_cjs_shims();
@@ -11963,7 +12098,7 @@ var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
11963
12098
  var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
11964
12099
  var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
11965
12100
  var import_tree_sitter_python4 = __toESM(require("tree-sitter-python"), 1);
11966
- var import_types27 = require("@neat.is/types");
12101
+ var import_types28 = require("@neat.is/types");
11967
12102
  var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
11968
12103
  var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
11969
12104
  function isInsideJsxExternalLink(node) {
@@ -12057,7 +12192,7 @@ async function addHttpCallEdges(graph, services) {
12057
12192
  const dedupKey = `${relFile}|${targetId}`;
12058
12193
  if (seen.has(dedupKey)) continue;
12059
12194
  seen.add(dedupKey);
12060
- const confidence = (0, import_types27.confidenceForExtracted)("url-literal-service-target");
12195
+ const confidence = (0, import_types28.confidenceForExtracted)("url-literal-service-target");
12061
12196
  const ev = {
12062
12197
  file: relFile,
12063
12198
  line: site.line,
@@ -12071,25 +12206,25 @@ async function addHttpCallEdges(graph, services) {
12071
12206
  );
12072
12207
  nodesAdded += n;
12073
12208
  edgesAdded += e;
12074
- if (!(0, import_types27.passesExtractedFloor)(confidence)) {
12209
+ if (!(0, import_types28.passesExtractedFloor)(confidence)) {
12075
12210
  noteExtractedDropped({
12076
12211
  source: fileNodeId,
12077
12212
  target: targetId,
12078
- type: import_types27.EdgeType.CALLS,
12213
+ type: import_types28.EdgeType.CALLS,
12079
12214
  confidence,
12080
12215
  confidenceKind: "url-literal-service-target",
12081
12216
  evidence: ev
12082
12217
  });
12083
12218
  continue;
12084
12219
  }
12085
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types27.EdgeType.CALLS);
12220
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types28.EdgeType.CALLS);
12086
12221
  if (!graph.hasEdge(edgeId)) {
12087
12222
  const edge = {
12088
12223
  id: edgeId,
12089
12224
  source: fileNodeId,
12090
12225
  target: targetId,
12091
- type: import_types27.EdgeType.CALLS,
12092
- provenance: import_types27.Provenance.EXTRACTED,
12226
+ type: import_types28.EdgeType.CALLS,
12227
+ provenance: import_types28.Provenance.EXTRACTED,
12093
12228
  confidence,
12094
12229
  evidence: ev
12095
12230
  };
@@ -12107,7 +12242,7 @@ init_cjs_shims();
12107
12242
  var import_node_path42 = __toESM(require("path"), 1);
12108
12243
  var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
12109
12244
  var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
12110
- var import_types28 = require("@neat.is/types");
12245
+ var import_types29 = require("@neat.is/types");
12111
12246
  var PARSE_CHUNK5 = 16384;
12112
12247
  function parseSource5(parser, source) {
12113
12248
  return parser.parse(
@@ -12351,9 +12486,9 @@ function buildRouteIndex(graph) {
12351
12486
  const index = /* @__PURE__ */ new Map();
12352
12487
  graph.forEachNode((_id, attrs) => {
12353
12488
  const node = attrs;
12354
- if (node.type !== import_types28.NodeType.RouteNode) return;
12489
+ if (node.type !== import_types29.NodeType.RouteNode) return;
12355
12490
  const route = attrs;
12356
- const owner = (0, import_types28.serviceId)(route.service);
12491
+ const owner = (0, import_types29.serviceId)(route.service);
12357
12492
  const entry = {
12358
12493
  method: route.method.toUpperCase(),
12359
12494
  normalizedPath: normalizePathTemplate(route.pathTemplate),
@@ -12408,8 +12543,8 @@ async function addRouteCallEdges(graph, services) {
12408
12543
  noteExtractedDropped({
12409
12544
  source: fileNodeId2,
12410
12545
  target: "route:unresolved",
12411
- type: import_types28.EdgeType.CALLS,
12412
- confidence: (0, import_types28.confidenceForExtracted)("reconstructed-approximate"),
12546
+ type: import_types29.EdgeType.CALLS,
12547
+ confidence: (0, import_types29.confidenceForExtracted)("reconstructed-approximate"),
12413
12548
  confidenceKind: "reconstructed-approximate",
12414
12549
  evidence: {
12415
12550
  file: relFile,
@@ -12442,7 +12577,7 @@ async function addRouteCallEdges(graph, services) {
12442
12577
  edgesAdded += e;
12443
12578
  const anchored = pathHasLiteralAnchor(site.pathTemplate);
12444
12579
  const confidenceKind = site.approximate && !anchored ? "reconstructed-approximate" : "verified-call-site";
12445
- const confidence = (0, import_types28.confidenceForExtracted)(confidenceKind);
12580
+ const confidence = (0, import_types29.confidenceForExtracted)(confidenceKind);
12446
12581
  const ev = {
12447
12582
  file: relFile,
12448
12583
  line: site.line,
@@ -12451,25 +12586,25 @@ async function addRouteCallEdges(graph, services) {
12451
12586
  pathTemplate: site.pathTemplate,
12452
12587
  ...confidenceKind === "reconstructed-approximate" ? { approximate: true, reason: site.reason } : {}
12453
12588
  };
12454
- if (!(0, import_types28.passesExtractedFloor)(confidence)) {
12589
+ if (!(0, import_types29.passesExtractedFloor)(confidence)) {
12455
12590
  noteExtractedDropped({
12456
12591
  source: fileNodeId,
12457
12592
  target: match.routeNodeId,
12458
- type: import_types28.EdgeType.CALLS,
12593
+ type: import_types29.EdgeType.CALLS,
12459
12594
  confidence,
12460
12595
  confidenceKind,
12461
12596
  evidence: ev
12462
12597
  });
12463
12598
  continue;
12464
12599
  }
12465
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types28.EdgeType.CALLS);
12600
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types29.EdgeType.CALLS);
12466
12601
  if (!graph.hasEdge(edgeId)) {
12467
12602
  const edge = {
12468
12603
  id: edgeId,
12469
12604
  source: fileNodeId,
12470
12605
  target: match.routeNodeId,
12471
- type: import_types28.EdgeType.CALLS,
12472
- provenance: import_types28.Provenance.EXTRACTED,
12606
+ type: import_types29.EdgeType.CALLS,
12607
+ provenance: import_types29.Provenance.EXTRACTED,
12473
12608
  confidence,
12474
12609
  evidence: ev
12475
12610
  };
@@ -12485,7 +12620,7 @@ async function addRouteCallEdges(graph, services) {
12485
12620
  // src/extract/calls/kafka.ts
12486
12621
  init_cjs_shims();
12487
12622
  var import_node_path43 = __toESM(require("path"), 1);
12488
- var import_types29 = require("@neat.is/types");
12623
+ var import_types30 = require("@neat.is/types");
12489
12624
  var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
12490
12625
  var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
12491
12626
  var SARAMA_IMPORT_RE = /"[^"]*\/sarama"/;
@@ -12562,7 +12697,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
12562
12697
  seen.add(key);
12563
12698
  const line = anchor !== void 0 ? file.content.slice(0, anchor).split("\n").length : lineOf(file.content, topic);
12564
12699
  out.push({
12565
- infraId: (0, import_types29.infraId)("kafka-topic", topic),
12700
+ infraId: (0, import_types30.infraId)("kafka-topic", topic),
12566
12701
  name: topic,
12567
12702
  kind: "kafka-topic",
12568
12703
  edgeType,
@@ -12590,7 +12725,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
12590
12725
  // src/extract/calls/redis.ts
12591
12726
  init_cjs_shims();
12592
12727
  var import_node_path44 = __toESM(require("path"), 1);
12593
- var import_types30 = require("@neat.is/types");
12728
+ var import_types31 = require("@neat.is/types");
12594
12729
  var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
12595
12730
  function redisEndpointsFromFile(file, serviceDir) {
12596
12731
  const out = [];
@@ -12603,7 +12738,7 @@ function redisEndpointsFromFile(file, serviceDir) {
12603
12738
  seen.add(host);
12604
12739
  const line = lineOf(file.content, host);
12605
12740
  out.push({
12606
- infraId: (0, import_types30.infraId)("redis", host),
12741
+ infraId: (0, import_types31.infraId)("redis", host),
12607
12742
  name: host,
12608
12743
  kind: "redis",
12609
12744
  edgeType: "CALLS",
@@ -12624,7 +12759,7 @@ function redisEndpointsFromFile(file, serviceDir) {
12624
12759
  // src/extract/calls/aws.ts
12625
12760
  init_cjs_shims();
12626
12761
  var import_node_path45 = __toESM(require("path"), 1);
12627
- var import_types31 = require("@neat.is/types");
12762
+ var import_types32 = require("@neat.is/types");
12628
12763
  var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
12629
12764
  var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
12630
12765
  function hasMarker(text, markers) {
@@ -12648,7 +12783,7 @@ function awsEndpointsFromFile(file, serviceDir) {
12648
12783
  seen.add(key);
12649
12784
  const line = lineOf(file.content, name);
12650
12785
  out.push({
12651
- infraId: (0, import_types31.infraId)(kind, name),
12786
+ infraId: (0, import_types32.infraId)(kind, name),
12652
12787
  name,
12653
12788
  kind,
12654
12789
  edgeType: "CALLS",
@@ -12683,7 +12818,7 @@ function awsEndpointsFromFile(file, serviceDir) {
12683
12818
  // src/extract/calls/grpc.ts
12684
12819
  init_cjs_shims();
12685
12820
  var import_node_path46 = __toESM(require("path"), 1);
12686
- var import_types32 = require("@neat.is/types");
12821
+ var import_types33 = require("@neat.is/types");
12687
12822
  var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
12688
12823
  var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
12689
12824
  var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
@@ -12732,7 +12867,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
12732
12867
  const { kind } = classified;
12733
12868
  const line = lineOf(file.content, m[0]);
12734
12869
  out.push({
12735
- infraId: (0, import_types32.infraId)(kind, name),
12870
+ infraId: (0, import_types33.infraId)(kind, name),
12736
12871
  name,
12737
12872
  kind,
12738
12873
  edgeType: "CALLS",
@@ -12753,7 +12888,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
12753
12888
  // src/extract/calls/supabase.ts
12754
12889
  init_cjs_shims();
12755
12890
  var import_node_path47 = __toESM(require("path"), 1);
12756
- var import_types33 = require("@neat.is/types");
12891
+ var import_types34 = require("@neat.is/types");
12757
12892
  var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
12758
12893
  var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
12759
12894
  var SUPABASE_CLIENT_RE = /\b(createClient|createServerClient|createBrowserClient)\s*\(\s*(?:['"`]([^'"`]*)['"`])?/g;
@@ -12801,7 +12936,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
12801
12936
  seen.add(name);
12802
12937
  const line = lineOf(file.content, m[0]);
12803
12938
  out.push({
12804
- infraId: (0, import_types33.infraId)("supabase", name),
12939
+ infraId: (0, import_types34.infraId)("supabase", name),
12805
12940
  name,
12806
12941
  kind: "supabase",
12807
12942
  edgeType: "CALLS",
@@ -12832,7 +12967,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
12832
12967
  seen.add(key);
12833
12968
  const line = lineOf(file.content, am[0]);
12834
12969
  out.push({
12835
- infraId: (0, import_types33.infraId)(kind, resource),
12970
+ infraId: (0, import_types34.infraId)(kind, resource),
12836
12971
  name: resource,
12837
12972
  kind,
12838
12973
  edgeType: "CALLS",
@@ -12853,7 +12988,7 @@ init_cjs_shims();
12853
12988
  var import_node_path48 = __toESM(require("path"), 1);
12854
12989
  var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
12855
12990
  var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
12856
- var import_types34 = require("@neat.is/types");
12991
+ var import_types35 = require("@neat.is/types");
12857
12992
  var FIRESTORE_CLIENT_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase\/firestore['"`]/;
12858
12993
  var FIRESTORE_ADMIN_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase-admin(?:\/firestore)?['"`]/;
12859
12994
  function parserForExt2(ext) {
@@ -13117,7 +13252,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
13117
13252
  }
13118
13253
  }
13119
13254
  out.push({
13120
- infraId: (0, import_types34.infraId)("firestore-collection", collPath),
13255
+ infraId: (0, import_types35.infraId)("firestore-collection", collPath),
13121
13256
  name: collPath,
13122
13257
  kind: "firestore-collection",
13123
13258
  edgeType: "CALLS",
@@ -13233,7 +13368,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
13233
13368
  // src/extract/calls/mongoose.ts
13234
13369
  init_cjs_shims();
13235
13370
  var import_node_path49 = __toESM(require("path"), 1);
13236
- var import_types35 = require("@neat.is/types");
13371
+ var import_types36 = require("@neat.is/types");
13237
13372
  var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
13238
13373
  var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
13239
13374
  var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
@@ -13378,7 +13513,7 @@ function collectModelDefs(content, pluralizeOn) {
13378
13513
  function endpoint(r, file, serviceDir, matchText) {
13379
13514
  const line = lineOf(file.content, matchText);
13380
13515
  return {
13381
- infraId: (0, import_types35.infraId)(r.kind, r.name),
13516
+ infraId: (0, import_types36.infraId)(r.kind, r.name),
13382
13517
  name: r.name,
13383
13518
  kind: r.kind,
13384
13519
  edgeType: "CALLS",
@@ -13531,7 +13666,7 @@ init_cjs_shims();
13531
13666
  var import_node_path50 = __toESM(require("path"), 1);
13532
13667
  var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
13533
13668
  var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
13534
- var import_types36 = require("@neat.is/types");
13669
+ var import_types37 = require("@neat.is/types");
13535
13670
  var SQLALCHEMY_IMPORT_RE = /(?:from|import)\s+(?:flask_sqlalchemy|sqlalchemy)\b/;
13536
13671
  var PARSE_CHUNK6 = 16384;
13537
13672
  function makePyParser3() {
@@ -13685,7 +13820,7 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
13685
13820
  if (seen.has(name)) return;
13686
13821
  seen.add(name);
13687
13822
  out.push({
13688
- infraId: (0, import_types36.infraId)("sql-table", name),
13823
+ infraId: (0, import_types37.infraId)("sql-table", name),
13689
13824
  name,
13690
13825
  kind: "sql-table",
13691
13826
  edgeType: "CALLS",
@@ -13793,7 +13928,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
13793
13928
  if (seen.has(key)) continue;
13794
13929
  seen.add(key);
13795
13930
  out.push({
13796
- infraId: (0, import_types36.infraId)("sql-table", t),
13931
+ infraId: (0, import_types37.infraId)("sql-table", t),
13797
13932
  name: t,
13798
13933
  kind: "sql-table",
13799
13934
  edgeType: "CALLS",
@@ -13814,7 +13949,7 @@ init_cjs_shims();
13814
13949
  var import_node_path51 = __toESM(require("path"), 1);
13815
13950
  var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
13816
13951
  var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
13817
- var import_types37 = require("@neat.is/types");
13952
+ var import_types38 = require("@neat.is/types");
13818
13953
  var SOCKET_IMPORT_RE = /(?:^|\n)\s*(?:import\s+socket\b|from\s+socket\s+import\b)/;
13819
13954
  var PARSE_CHUNK7 = 16384;
13820
13955
  function makePyParser4() {
@@ -13880,7 +14015,7 @@ function socketEndpointsFromFile(file, serviceDir) {
13880
14015
  seen.add(name);
13881
14016
  const line = node.startPosition.row + 1;
13882
14017
  out.push({
13883
- infraId: (0, import_types37.infraId)("socket", name),
14018
+ infraId: (0, import_types38.infraId)("socket", name),
13884
14019
  name,
13885
14020
  kind: "socket",
13886
14021
  edgeType: "CALLS",
@@ -13901,7 +14036,7 @@ init_cjs_shims();
13901
14036
  var import_node_path52 = __toESM(require("path"), 1);
13902
14037
  var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
13903
14038
  var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
13904
- var import_types38 = require("@neat.is/types");
14039
+ var import_types39 = require("@neat.is/types");
13905
14040
  var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
13906
14041
  var PARSE_CHUNK8 = 16384;
13907
14042
  function makePyParser5() {
@@ -13981,7 +14116,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
13981
14116
  seen.add(table);
13982
14117
  const line = node.startPosition.row + 1;
13983
14118
  out.push({
13984
- infraId: (0, import_types38.infraId)("sql-table", table),
14119
+ infraId: (0, import_types39.infraId)("sql-table", table),
13985
14120
  name: table,
13986
14121
  kind: "sql-table",
13987
14122
  edgeType: "CALLS",
@@ -13997,7 +14132,7 @@ init_cjs_shims();
13997
14132
  var import_node_path53 = __toESM(require("path"), 1);
13998
14133
  var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
13999
14134
  var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
14000
- var import_types39 = require("@neat.is/types");
14135
+ var import_types40 = require("@neat.is/types");
14001
14136
  var DRIZZLE_IMPORT_RE = /drizzle-orm/;
14002
14137
  var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
14003
14138
  function parserForExt3(ext) {
@@ -14088,7 +14223,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
14088
14223
  const columns = columnsFromObject(obj);
14089
14224
  const line = node.startPosition.row + 1;
14090
14225
  out.push({
14091
- infraId: (0, import_types39.infraId)("sql-table", tableName),
14226
+ infraId: (0, import_types40.infraId)("sql-table", tableName),
14092
14227
  name: tableName,
14093
14228
  kind: "sql-table",
14094
14229
  edgeType: "CALLS",
@@ -14198,7 +14333,7 @@ function drizzleForeignKeys(file, serviceDir) {
14198
14333
  // src/extract/calls/prisma.ts
14199
14334
  init_cjs_shims();
14200
14335
  var import_node_path54 = __toESM(require("path"), 1);
14201
- var import_types40 = require("@neat.is/types");
14336
+ var import_types41 = require("@neat.is/types");
14202
14337
  var SCALAR_TYPES = /* @__PURE__ */ new Set([
14203
14338
  "Int",
14204
14339
  "String",
@@ -14246,7 +14381,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
14246
14381
  if (seenTable.has(b.tableName)) return;
14247
14382
  seenTable.add(b.tableName);
14248
14383
  out.push({
14249
- infraId: (0, import_types40.infraId)("sql-table", b.tableName),
14384
+ infraId: (0, import_types41.infraId)("sql-table", b.tableName),
14250
14385
  name: b.tableName,
14251
14386
  kind: "sql-table",
14252
14387
  edgeType: "CALLS",
@@ -14418,7 +14553,7 @@ init_cjs_shims();
14418
14553
  var import_node_path55 = __toESM(require("path"), 1);
14419
14554
  var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
14420
14555
  var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
14421
- var import_types41 = require("@neat.is/types");
14556
+ var import_types42 = require("@neat.is/types");
14422
14557
  var AR_SCHEMA_RE = /ActiveRecord::Schema/;
14423
14558
  var PARSE_CHUNK9 = 16384;
14424
14559
  function makeRubyParser2() {
@@ -14616,7 +14751,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
14616
14751
  if (!table || seen.has(table.name)) return;
14617
14752
  seen.add(table.name);
14618
14753
  out.push({
14619
- infraId: (0, import_types41.infraId)("sql-table", table.name),
14754
+ infraId: (0, import_types42.infraId)("sql-table", table.name),
14620
14755
  name: table.name,
14621
14756
  kind: "sql-table",
14622
14757
  edgeType: "CALLS",
@@ -14722,7 +14857,7 @@ function railsModelEndpointsFromFile(file, serviceDir) {
14722
14857
  seen.add(table);
14723
14858
  const line = node.startPosition.row + 1;
14724
14859
  out.push({
14725
- infraId: (0, import_types41.infraId)("sql-table", table),
14860
+ infraId: (0, import_types42.infraId)("sql-table", table),
14726
14861
  name: table,
14727
14862
  kind: "sql-table",
14728
14863
  edgeType: "CALLS",
@@ -14780,7 +14915,7 @@ init_cjs_shims();
14780
14915
  var import_node_path56 = __toESM(require("path"), 1);
14781
14916
  var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
14782
14917
  var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
14783
- var import_types42 = require("@neat.is/types");
14918
+ var import_types43 = require("@neat.is/types");
14784
14919
  var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
14785
14920
  var PARSE_CHUNK10 = 16384;
14786
14921
  function makePhpParser2() {
@@ -15027,7 +15162,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
15027
15162
  }
15028
15163
  }
15029
15164
  out.push({
15030
- infraId: (0, import_types42.infraId)("sql-table", bp.table),
15165
+ infraId: (0, import_types43.infraId)("sql-table", bp.table),
15031
15166
  name: bp.table,
15032
15167
  kind: "sql-table",
15033
15168
  edgeType: "CALLS",
@@ -15170,7 +15305,7 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
15170
15305
  seen.add(table);
15171
15306
  const line = node.startPosition.row + 1;
15172
15307
  out.push({
15173
- infraId: (0, import_types42.infraId)("sql-table", table),
15308
+ infraId: (0, import_types43.infraId)("sql-table", table),
15174
15309
  name: table,
15175
15310
  kind: "sql-table",
15176
15311
  edgeType: "CALLS",
@@ -15227,7 +15362,7 @@ init_cjs_shims();
15227
15362
  var import_node_path59 = __toESM(require("path"), 1);
15228
15363
  var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
15229
15364
  var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
15230
- var import_types43 = require("@neat.is/types");
15365
+ var import_types44 = require("@neat.is/types");
15231
15366
  init_otel();
15232
15367
  var PARSE_CHUNK11 = 16384;
15233
15368
  var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
@@ -15321,7 +15456,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
15321
15456
  const columns = columnsFromSqlStatement(sql);
15322
15457
  const line = node.startPosition.row + 1;
15323
15458
  out.push({
15324
- infraId: (0, import_types43.infraId)("sql-table", table),
15459
+ infraId: (0, import_types44.infraId)("sql-table", table),
15325
15460
  name: table,
15326
15461
  kind: "sql-table",
15327
15462
  edgeType: "CALLS",
@@ -15342,7 +15477,7 @@ init_cjs_shims();
15342
15477
  var import_node_path60 = __toESM(require("path"), 1);
15343
15478
  var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
15344
15479
  var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
15345
- var import_types44 = require("@neat.is/types");
15480
+ var import_types45 = require("@neat.is/types");
15346
15481
  var GORM_IMPORT_RE = /gorm\.io\/gorm/;
15347
15482
  var PARSE_CHUNK12 = 16384;
15348
15483
  function makeGoParser4() {
@@ -15787,7 +15922,7 @@ function gormEndpointsFromFile(file, serviceDir) {
15787
15922
  const columns = [];
15788
15923
  collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
15789
15924
  out.push({
15790
- infraId: (0, import_types44.infraId)("sql-table", table),
15925
+ infraId: (0, import_types45.infraId)("sql-table", table),
15791
15926
  name: table,
15792
15927
  kind: "sql-table",
15793
15928
  edgeType: "CALLS",
@@ -15858,7 +15993,7 @@ init_cjs_shims();
15858
15993
  var import_node_path61 = __toESM(require("path"), 1);
15859
15994
  var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
15860
15995
  var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
15861
- var import_types45 = require("@neat.is/types");
15996
+ var import_types46 = require("@neat.is/types");
15862
15997
  var EFCORE_GATE = /Microsoft\.EntityFrameworkCore|DataAnnotations\.Schema|\bDbContext\b|\bDbSet\s*</;
15863
15998
  var PARSE_CHUNK13 = 16384;
15864
15999
  function makeCsParser() {
@@ -15943,7 +16078,7 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15943
16078
  if (!name || seen.has(name)) return;
15944
16079
  seen.add(name);
15945
16080
  out.push({
15946
- infraId: (0, import_types45.infraId)("sql-table", name),
16081
+ infraId: (0, import_types46.infraId)("sql-table", name),
15947
16082
  name,
15948
16083
  kind: "sql-table",
15949
16084
  edgeType: "CALLS",
@@ -15973,11 +16108,11 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15973
16108
  function edgeTypeFromEndpoint(ep) {
15974
16109
  switch (ep.edgeType) {
15975
16110
  case "PUBLISHES_TO":
15976
- return import_types46.EdgeType.PUBLISHES_TO;
16111
+ return import_types47.EdgeType.PUBLISHES_TO;
15977
16112
  case "CONSUMES_FROM":
15978
- return import_types46.EdgeType.CONSUMES_FROM;
16113
+ return import_types47.EdgeType.CONSUMES_FROM;
15979
16114
  default:
15980
- return import_types46.EdgeType.CALLS;
16115
+ return import_types47.EdgeType.CALLS;
15981
16116
  }
15982
16117
  }
15983
16118
  function isAwsKind(kind) {
@@ -16048,7 +16183,7 @@ async function addExternalEndpointEdges(graph, services) {
16048
16183
  if (!graph.hasNode(ep.infraId)) {
16049
16184
  const node = {
16050
16185
  id: ep.infraId,
16051
- type: import_types46.NodeType.InfraNode,
16186
+ type: import_types47.NodeType.InfraNode,
16052
16187
  name: ep.name,
16053
16188
  // #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
16054
16189
  // aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
@@ -16061,21 +16196,21 @@ async function addExternalEndpointEdges(graph, services) {
16061
16196
  }
16062
16197
  if (ep.columns && ep.columns.length > 0) {
16063
16198
  const node = graph.getNodeAttributes(ep.infraId);
16064
- if (node.type === import_types46.NodeType.InfraNode) {
16199
+ if (node.type === import_types47.NodeType.InfraNode) {
16065
16200
  graph.replaceNodeAttributes(ep.infraId, {
16066
16201
  ...node,
16067
16202
  columns: foldColumns(
16068
16203
  node.columns,
16069
16204
  ep.columns,
16070
- import_types46.Provenance.EXTRACTED,
16071
- (0, import_types46.confidenceForExtracted)(ep.confidenceKind)
16205
+ import_types47.Provenance.EXTRACTED,
16206
+ (0, import_types47.confidenceForExtracted)(ep.confidenceKind)
16072
16207
  )
16073
16208
  });
16074
16209
  }
16075
16210
  }
16076
16211
  if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
16077
16212
  const node = graph.getNodeAttributes(ep.infraId);
16078
- if (node.type === import_types46.NodeType.InfraNode) {
16213
+ if (node.type === import_types47.NodeType.InfraNode) {
16079
16214
  graph.replaceNodeAttributes(ep.infraId, {
16080
16215
  ...node,
16081
16216
  columns: foldSdkWrites(node.columns, ep.sdkWrites)
@@ -16083,7 +16218,7 @@ async function addExternalEndpointEdges(graph, services) {
16083
16218
  }
16084
16219
  }
16085
16220
  const edgeType = edgeTypeFromEndpoint(ep);
16086
- const confidence = (0, import_types46.confidenceForExtracted)(ep.confidenceKind);
16221
+ const confidence = (0, import_types47.confidenceForExtracted)(ep.confidenceKind);
16087
16222
  const relFile = toPosix(ep.evidence.file);
16088
16223
  const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
16089
16224
  graph,
@@ -16093,7 +16228,7 @@ async function addExternalEndpointEdges(graph, services) {
16093
16228
  );
16094
16229
  nodesAdded += n;
16095
16230
  edgesAdded += e;
16096
- if (!(0, import_types46.passesExtractedFloor)(confidence)) {
16231
+ if (!(0, import_types47.passesExtractedFloor)(confidence)) {
16097
16232
  noteExtractedDropped({
16098
16233
  source: fileNodeId,
16099
16234
  target: ep.infraId,
@@ -16113,7 +16248,7 @@ async function addExternalEndpointEdges(graph, services) {
16113
16248
  source: fileNodeId,
16114
16249
  target: ep.infraId,
16115
16250
  type: edgeType,
16116
- provenance: import_types46.Provenance.EXTRACTED,
16251
+ provenance: import_types47.Provenance.EXTRACTED,
16117
16252
  confidence,
16118
16253
  evidence: ep.evidence
16119
16254
  };
@@ -16136,7 +16271,7 @@ async function addCallEdges(graph, services) {
16136
16271
 
16137
16272
  // src/extract/table-edges.ts
16138
16273
  init_cjs_shims();
16139
- var import_types47 = require("@neat.is/types");
16274
+ var import_types48 = require("@neat.is/types");
16140
16275
  async function addTableEdges(graph, services) {
16141
16276
  let nodesAdded = 0;
16142
16277
  let edgesAdded = 0;
@@ -16164,20 +16299,20 @@ async function addTableEdges(graph, services) {
16164
16299
  }
16165
16300
  refs.push(...modelRefs);
16166
16301
  for (const ref of refs) {
16167
- const childId = (0, import_types47.infraId)("sql-table", ref.childTable);
16168
- const parentId = (0, import_types47.infraId)("sql-table", ref.parentTable);
16302
+ const childId = (0, import_types48.infraId)("sql-table", ref.childTable);
16303
+ const parentId = (0, import_types48.infraId)("sql-table", ref.parentTable);
16169
16304
  if (childId === parentId) continue;
16170
16305
  nodesAdded += ensureTableNode(graph, childId, ref.childTable);
16171
16306
  nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
16172
- const edgeId = (0, import_types47.extractedEdgeId)(childId, parentId, import_types47.EdgeType.REFERENCES);
16307
+ const edgeId = (0, import_types48.extractedEdgeId)(childId, parentId, import_types48.EdgeType.REFERENCES);
16173
16308
  if (graph.hasEdge(edgeId)) continue;
16174
16309
  const edge = {
16175
16310
  id: edgeId,
16176
16311
  source: childId,
16177
16312
  target: parentId,
16178
- type: import_types47.EdgeType.REFERENCES,
16179
- provenance: import_types47.Provenance.EXTRACTED,
16180
- confidence: (0, import_types47.confidenceForExtracted)("structural"),
16313
+ type: import_types48.EdgeType.REFERENCES,
16314
+ provenance: import_types48.Provenance.EXTRACTED,
16315
+ confidence: (0, import_types48.confidenceForExtracted)("structural"),
16181
16316
  evidence: ref.evidence
16182
16317
  };
16183
16318
  graph.addEdgeWithKey(edgeId, childId, parentId, edge);
@@ -16190,7 +16325,7 @@ function ensureTableNode(graph, id, name) {
16190
16325
  if (graph.hasNode(id)) return 0;
16191
16326
  const node = {
16192
16327
  id,
16193
- type: import_types47.NodeType.InfraNode,
16328
+ type: import_types48.NodeType.InfraNode,
16194
16329
  name,
16195
16330
  provider: "self",
16196
16331
  kind: "sql-table"
@@ -16205,15 +16340,15 @@ init_cjs_shims();
16205
16340
  // src/extract/infra/docker-compose.ts
16206
16341
  init_cjs_shims();
16207
16342
  var import_node_path62 = __toESM(require("path"), 1);
16208
- var import_types49 = require("@neat.is/types");
16343
+ var import_types50 = require("@neat.is/types");
16209
16344
 
16210
16345
  // src/extract/infra/shared.ts
16211
16346
  init_cjs_shims();
16212
- var import_types48 = require("@neat.is/types");
16347
+ var import_types49 = require("@neat.is/types");
16213
16348
  function makeInfraNode(kind, name, provider = "self", extras) {
16214
16349
  return {
16215
- id: (0, import_types48.infraId)(kind, name),
16216
- type: import_types48.NodeType.InfraNode,
16350
+ id: (0, import_types49.infraId)(kind, name),
16351
+ type: import_types49.NodeType.InfraNode,
16217
16352
  name,
16218
16353
  provider,
16219
16354
  kind,
@@ -16257,8 +16392,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
16257
16392
  source: anchorId,
16258
16393
  target: node.id,
16259
16394
  type: edgeType,
16260
- provenance: import_types48.Provenance.EXTRACTED,
16261
- confidence: (0, import_types48.confidenceForExtracted)("structural"),
16395
+ provenance: import_types49.Provenance.EXTRACTED,
16396
+ confidence: (0, import_types49.confidenceForExtracted)("structural"),
16262
16397
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
16263
16398
  };
16264
16399
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16325,15 +16460,15 @@ async function addComposeInfra(graph, scanPath, services) {
16325
16460
  for (const dep of dependsOnList(svc.depends_on)) {
16326
16461
  const targetId = composeNameToNodeId.get(dep);
16327
16462
  if (!targetId) continue;
16328
- const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types49.EdgeType.DEPENDS_ON);
16463
+ const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types50.EdgeType.DEPENDS_ON);
16329
16464
  if (graph.hasEdge(edgeId)) continue;
16330
16465
  const edge = {
16331
16466
  id: edgeId,
16332
16467
  source: sourceId,
16333
16468
  target: targetId,
16334
- type: import_types49.EdgeType.DEPENDS_ON,
16335
- provenance: import_types49.Provenance.EXTRACTED,
16336
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
16469
+ type: import_types50.EdgeType.DEPENDS_ON,
16470
+ provenance: import_types50.Provenance.EXTRACTED,
16471
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
16337
16472
  evidence: { file: evidenceFile }
16338
16473
  };
16339
16474
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16347,7 +16482,7 @@ async function addComposeInfra(graph, scanPath, services) {
16347
16482
  init_cjs_shims();
16348
16483
  var import_node_path63 = __toESM(require("path"), 1);
16349
16484
  var import_node_fs29 = require("fs");
16350
- var import_types50 = require("@neat.is/types");
16485
+ var import_types51 = require("@neat.is/types");
16351
16486
  function readDockerfile(content) {
16352
16487
  let image = null;
16353
16488
  const ports = [];
@@ -16406,15 +16541,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
16406
16541
  );
16407
16542
  nodesAdded += fn;
16408
16543
  edgesAdded += fe;
16409
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types50.EdgeType.RUNS_ON);
16544
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types51.EdgeType.RUNS_ON);
16410
16545
  if (!graph.hasEdge(edgeId)) {
16411
16546
  const edge = {
16412
16547
  id: edgeId,
16413
16548
  source: fileNodeId,
16414
16549
  target: node.id,
16415
- type: import_types50.EdgeType.RUNS_ON,
16416
- provenance: import_types50.Provenance.EXTRACTED,
16417
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
16550
+ type: import_types51.EdgeType.RUNS_ON,
16551
+ provenance: import_types51.Provenance.EXTRACTED,
16552
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
16418
16553
  evidence: {
16419
16554
  file: evidenceFile,
16420
16555
  ...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
@@ -16429,15 +16564,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
16429
16564
  graph.addNode(portNode.id, portNode);
16430
16565
  nodesAdded++;
16431
16566
  }
16432
- const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types50.EdgeType.CONNECTS_TO);
16567
+ const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types51.EdgeType.CONNECTS_TO);
16433
16568
  if (graph.hasEdge(portEdgeId)) continue;
16434
16569
  const portEdge = {
16435
16570
  id: portEdgeId,
16436
16571
  source: fileNodeId,
16437
16572
  target: portNode.id,
16438
- type: import_types50.EdgeType.CONNECTS_TO,
16439
- provenance: import_types50.Provenance.EXTRACTED,
16440
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
16573
+ type: import_types51.EdgeType.CONNECTS_TO,
16574
+ provenance: import_types51.Provenance.EXTRACTED,
16575
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
16441
16576
  evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
16442
16577
  };
16443
16578
  graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
@@ -16451,7 +16586,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
16451
16586
  init_cjs_shims();
16452
16587
  var import_node_fs30 = require("fs");
16453
16588
  var import_node_path64 = __toESM(require("path"), 1);
16454
- var import_types51 = require("@neat.is/types");
16589
+ var import_types52 = require("@neat.is/types");
16455
16590
  var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
16456
16591
  var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
16457
16592
  async function walkTfFiles(start, depth = 0, max = 5) {
@@ -16532,16 +16667,16 @@ async function addTerraformResources(graph, scanPath) {
16532
16667
  if (!target) continue;
16533
16668
  if (seen.has(target.nodeId)) continue;
16534
16669
  seen.add(target.nodeId);
16535
- const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types51.EdgeType.DEPENDS_ON);
16670
+ const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types52.EdgeType.DEPENDS_ON);
16536
16671
  if (graph.hasEdge(edgeId)) continue;
16537
16672
  const line = lineAt2(content, resource.bodyOffset + ref.index);
16538
16673
  const edge = {
16539
16674
  id: edgeId,
16540
16675
  source: resource.nodeId,
16541
16676
  target: target.nodeId,
16542
- type: import_types51.EdgeType.DEPENDS_ON,
16543
- provenance: import_types51.Provenance.EXTRACTED,
16544
- confidence: (0, import_types51.confidenceForExtracted)("structural"),
16677
+ type: import_types52.EdgeType.DEPENDS_ON,
16678
+ provenance: import_types52.Provenance.EXTRACTED,
16679
+ confidence: (0, import_types52.confidenceForExtracted)("structural"),
16545
16680
  evidence: { file: evidenceFile, line, snippet: key }
16546
16681
  };
16547
16682
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16557,7 +16692,7 @@ init_cjs_shims();
16557
16692
  var import_node_fs31 = require("fs");
16558
16693
  var import_node_path65 = __toESM(require("path"), 1);
16559
16694
  var import_yaml3 = require("yaml");
16560
- var import_types52 = require("@neat.is/types");
16695
+ var import_types53 = require("@neat.is/types");
16561
16696
  var K8S_KIND_TO_INFRA_KIND = {
16562
16697
  Service: "k8s-service",
16563
16698
  Deployment: "k8s-deployment",
@@ -16617,7 +16752,7 @@ async function addK8sResources(graph, scanPath) {
16617
16752
  nodesAdded++;
16618
16753
  }
16619
16754
  if (isWorkload) {
16620
- const svcId = (0, import_types52.serviceId)(name);
16755
+ const svcId = (0, import_types53.serviceId)(name);
16621
16756
  if (graph.hasNode(svcId)) {
16622
16757
  const svc = graph.getNodeAttributes(svcId);
16623
16758
  graph.replaceNodeAttributes(svcId, {
@@ -16629,7 +16764,7 @@ async function addK8sResources(graph, scanPath) {
16629
16764
  edgesAdded += emitPlatformResourceEdge(
16630
16765
  graph,
16631
16766
  svcId,
16632
- import_types52.EdgeType.RUNS_ON,
16767
+ import_types53.EdgeType.RUNS_ON,
16633
16768
  infraKind,
16634
16769
  name,
16635
16770
  "kubernetes",
@@ -16648,7 +16783,7 @@ init_cjs_shims();
16648
16783
  var import_node_fs32 = require("fs");
16649
16784
  var import_node_path66 = __toESM(require("path"), 1);
16650
16785
  var import_smol_toml3 = require("smol-toml");
16651
- var import_types53 = require("@neat.is/types");
16786
+ var import_types54 = require("@neat.is/types");
16652
16787
  var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
16653
16788
  async function readWranglerConfig(dir) {
16654
16789
  for (const filename of WRANGLER_FILENAMES) {
@@ -16696,8 +16831,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
16696
16831
  source: anchorId,
16697
16832
  target: node.id,
16698
16833
  type: edgeType,
16699
- provenance: import_types53.Provenance.EXTRACTED,
16700
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16834
+ provenance: import_types54.Provenance.EXTRACTED,
16835
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
16701
16836
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
16702
16837
  };
16703
16838
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16758,15 +16893,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16758
16893
  nodesAdded++;
16759
16894
  }
16760
16895
  if (runtimeNode.id !== anchorId) {
16761
- const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types53.EdgeType.RUNS_ON);
16896
+ const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types54.EdgeType.RUNS_ON);
16762
16897
  if (!graph.hasEdge(runsOnId)) {
16763
16898
  const edge = {
16764
16899
  id: runsOnId,
16765
16900
  source: anchorId,
16766
16901
  target: runtimeNode.id,
16767
- type: import_types53.EdgeType.RUNS_ON,
16768
- provenance: import_types53.Provenance.EXTRACTED,
16769
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16902
+ type: import_types54.EdgeType.RUNS_ON,
16903
+ provenance: import_types54.Provenance.EXTRACTED,
16904
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
16770
16905
  evidence: {
16771
16906
  file: evidenceFile,
16772
16907
  ...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
@@ -16780,7 +16915,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16780
16915
  const result = addResourceEdge(
16781
16916
  graph,
16782
16917
  anchorId,
16783
- import_types53.EdgeType.CONNECTS_TO,
16918
+ import_types54.EdgeType.CONNECTS_TO,
16784
16919
  "cloudflare-route",
16785
16920
  route,
16786
16921
  evidenceFile,
@@ -16804,7 +16939,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16804
16939
  const result = addResourceEdge(
16805
16940
  graph,
16806
16941
  anchorId,
16807
- import_types53.EdgeType.DEPENDS_ON,
16942
+ import_types54.EdgeType.DEPENDS_ON,
16808
16943
  group.kind,
16809
16944
  name,
16810
16945
  evidenceFile,
@@ -16818,7 +16953,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16818
16953
  const result = addResourceEdge(
16819
16954
  graph,
16820
16955
  anchorId,
16821
- import_types53.EdgeType.DEPENDS_ON,
16956
+ import_types54.EdgeType.DEPENDS_ON,
16822
16957
  "cloudflare-cron",
16823
16958
  cron,
16824
16959
  evidenceFile,
@@ -16831,7 +16966,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16831
16966
  const result = addResourceEdge(
16832
16967
  graph,
16833
16968
  anchorId,
16834
- import_types53.EdgeType.DEPENDS_ON,
16969
+ import_types54.EdgeType.DEPENDS_ON,
16835
16970
  "cloudflare-env-var",
16836
16971
  varName,
16837
16972
  evidenceFile,
@@ -16844,15 +16979,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16844
16979
  if (!svc.service) continue;
16845
16980
  const target = workerIndex.get(svc.service);
16846
16981
  if (target && target.anchorId !== anchorId) {
16847
- const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types53.EdgeType.CALLS);
16982
+ const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types54.EdgeType.CALLS);
16848
16983
  if (!graph.hasEdge(edgeId)) {
16849
16984
  const edge = {
16850
16985
  id: edgeId,
16851
16986
  source: anchorId,
16852
16987
  target: target.anchorId,
16853
- type: import_types53.EdgeType.CALLS,
16854
- provenance: import_types53.Provenance.EXTRACTED,
16855
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16988
+ type: import_types54.EdgeType.CALLS,
16989
+ provenance: import_types54.Provenance.EXTRACTED,
16990
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
16856
16991
  evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
16857
16992
  };
16858
16993
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16863,7 +16998,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16863
16998
  const result = addResourceEdge(
16864
16999
  graph,
16865
17000
  anchorId,
16866
- import_types53.EdgeType.DEPENDS_ON,
17001
+ import_types54.EdgeType.DEPENDS_ON,
16867
17002
  "cloudflare-service-binding",
16868
17003
  svc.service,
16869
17004
  evidenceFile,
@@ -16880,7 +17015,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16880
17015
  init_cjs_shims();
16881
17016
  var import_node_fs33 = require("fs");
16882
17017
  var import_node_path67 = __toESM(require("path"), 1);
16883
- var import_types54 = require("@neat.is/types");
17018
+ var import_types55 = require("@neat.is/types");
16884
17019
  var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
16885
17020
  async function readVercelConfig(dir) {
16886
17021
  for (const filename of VERCEL_CONFIG_FILENAMES) {
@@ -16943,12 +17078,12 @@ async function addVercelServices(graph, services, scanPath) {
16943
17078
  nodesAdded += result.nodesAdded;
16944
17079
  edgesAdded += result.edgesAdded;
16945
17080
  };
16946
- add(import_types54.EdgeType.RUNS_ON, "vercel", "vercel");
16947
- for (const cron of config.crons ?? []) add(import_types54.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16948
- for (const varName of Object.keys(config.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16949
- for (const varName of Object.keys(config.build?.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
17081
+ add(import_types55.EdgeType.RUNS_ON, "vercel", "vercel");
17082
+ for (const cron of config.crons ?? []) add(import_types55.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
17083
+ for (const varName of Object.keys(config.env ?? {})) add(import_types55.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
17084
+ for (const varName of Object.keys(config.build?.env ?? {})) add(import_types55.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16950
17085
  for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
16951
- add(import_types54.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
17086
+ add(import_types55.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16952
17087
  }
16953
17088
  }
16954
17089
  return { nodesAdded, edgesAdded };
@@ -16959,7 +17094,7 @@ init_cjs_shims();
16959
17094
  var import_node_fs34 = require("fs");
16960
17095
  var import_node_path68 = __toESM(require("path"), 1);
16961
17096
  var import_smol_toml4 = require("smol-toml");
16962
- var import_types55 = require("@neat.is/types");
17097
+ var import_types56 = require("@neat.is/types");
16963
17098
  var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
16964
17099
  async function readRailwayConfig(dir) {
16965
17100
  for (const filename of RAILWAY_FILENAMES) {
@@ -17005,9 +17140,9 @@ async function addRailwayServices(graph, services, scanPath) {
17005
17140
  nodesAdded += result.nodesAdded;
17006
17141
  edgesAdded += result.edgesAdded;
17007
17142
  };
17008
- add(import_types55.EdgeType.RUNS_ON, "railway", "railway");
17009
- add(import_types55.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
17010
- add(import_types55.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
17143
+ add(import_types56.EdgeType.RUNS_ON, "railway", "railway");
17144
+ add(import_types56.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
17145
+ add(import_types56.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
17011
17146
  }
17012
17147
  return { nodesAdded, edgesAdded };
17013
17148
  }
@@ -17017,7 +17152,7 @@ init_cjs_shims();
17017
17152
  var import_node_fs35 = require("fs");
17018
17153
  var import_node_path69 = __toESM(require("path"), 1);
17019
17154
  var import_smol_toml5 = require("smol-toml");
17020
- var import_types56 = require("@neat.is/types");
17155
+ var import_types57 = require("@neat.is/types");
17021
17156
  async function readSupabaseConfig(dir) {
17022
17157
  const relFile = import_node_path69.default.join("supabase", "config.toml");
17023
17158
  const abs = import_node_path69.default.join(dir, relFile);
@@ -17065,10 +17200,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
17065
17200
  nodesAdded += result.nodesAdded;
17066
17201
  edgesAdded += result.edgesAdded;
17067
17202
  };
17068
- add(import_types56.EdgeType.RUNS_ON, "supabase", "supabase");
17069
- for (const fn of Object.keys(config.functions ?? {})) add(import_types56.EdgeType.DEPENDS_ON, "supabase-function", fn);
17070
- if (config.storage) add(import_types56.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
17071
- if (config.auth) add(import_types56.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
17203
+ add(import_types57.EdgeType.RUNS_ON, "supabase", "supabase");
17204
+ for (const fn of Object.keys(config.functions ?? {})) add(import_types57.EdgeType.DEPENDS_ON, "supabase-function", fn);
17205
+ if (config.storage) add(import_types57.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
17206
+ if (config.auth) add(import_types57.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
17072
17207
  }
17073
17208
  return { nodesAdded, edgesAdded };
17074
17209
  }
@@ -17094,7 +17229,7 @@ init_cjs_shims();
17094
17229
  var import_node_path70 = __toESM(require("path"), 1);
17095
17230
  var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
17096
17231
  var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
17097
- var import_types57 = require("@neat.is/types");
17232
+ var import_types58 = require("@neat.is/types");
17098
17233
  var ZOD_IMPORT_RE = /\bzod\b/;
17099
17234
  var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
17100
17235
  function parserForExt4(ext) {
@@ -17200,7 +17335,7 @@ function zodShapesFromFile(file, serviceDir) {
17200
17335
  seen.add(name);
17201
17336
  const line = call.startPosition.row + 1;
17202
17337
  out.push({
17203
- infraId: (0, import_types57.infraId)("zod-schema", name),
17338
+ infraId: (0, import_types58.infraId)("zod-schema", name),
17204
17339
  name,
17205
17340
  fields,
17206
17341
  evidence: {
@@ -17235,7 +17370,7 @@ async function addZodShapes(graph, services) {
17235
17370
  if (!graph.hasNode(shape.infraId)) {
17236
17371
  const node = {
17237
17372
  id: shape.infraId,
17238
- type: import_types57.NodeType.InfraNode,
17373
+ type: import_types58.NodeType.InfraNode,
17239
17374
  name: shape.name,
17240
17375
  provider: "self",
17241
17376
  kind: "zod-schema"
@@ -17245,14 +17380,14 @@ async function addZodShapes(graph, services) {
17245
17380
  }
17246
17381
  if (shape.fields.length > 0) {
17247
17382
  const node = graph.getNodeAttributes(shape.infraId);
17248
- if (node.type === import_types57.NodeType.InfraNode) {
17383
+ if (node.type === import_types58.NodeType.InfraNode) {
17249
17384
  graph.replaceNodeAttributes(shape.infraId, {
17250
17385
  ...node,
17251
17386
  columns: foldColumns(
17252
17387
  node.columns,
17253
17388
  shape.fields,
17254
- import_types57.Provenance.EXTRACTED,
17255
- (0, import_types57.confidenceForExtracted)("structural")
17389
+ import_types58.Provenance.EXTRACTED,
17390
+ (0, import_types58.confidenceForExtracted)("structural")
17256
17391
  )
17257
17392
  });
17258
17393
  }
@@ -17266,15 +17401,15 @@ async function addZodShapes(graph, services) {
17266
17401
  );
17267
17402
  nodesAdded += n;
17268
17403
  edgesAdded += e;
17269
- const edgeId = (0, import_types57.extractedEdgeId)(fileNodeId, shape.infraId, import_types57.EdgeType.CONTAINS);
17404
+ const edgeId = (0, import_types58.extractedEdgeId)(fileNodeId, shape.infraId, import_types58.EdgeType.CONTAINS);
17270
17405
  if (!graph.hasEdge(edgeId)) {
17271
17406
  const edge = {
17272
17407
  id: edgeId,
17273
17408
  source: fileNodeId,
17274
17409
  target: shape.infraId,
17275
- type: import_types57.EdgeType.CONTAINS,
17276
- provenance: import_types57.Provenance.EXTRACTED,
17277
- confidence: (0, import_types57.confidenceForExtracted)("structural"),
17410
+ type: import_types58.EdgeType.CONTAINS,
17411
+ provenance: import_types58.Provenance.EXTRACTED,
17412
+ confidence: (0, import_types58.confidenceForExtracted)("structural"),
17278
17413
  evidence: shape.evidence
17279
17414
  };
17280
17415
  graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
@@ -17288,7 +17423,7 @@ async function addZodShapes(graph, services) {
17288
17423
 
17289
17424
  // src/extract/firestore-rules.ts
17290
17425
  init_cjs_shims();
17291
- var import_types58 = require("@neat.is/types");
17426
+ var import_types59 = require("@neat.is/types");
17292
17427
  var FIRESTORE_COLLECTION_KIND = "firestore-collection";
17293
17428
  var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
17294
17429
  function stripComments(src) {
@@ -17459,7 +17594,7 @@ async function addFirestoreRules(graph, services) {
17459
17594
  if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
17460
17595
  graph.forEachNode((id, attrs) => {
17461
17596
  const node = attrs;
17462
- if (node.type !== import_types58.NodeType.InfraNode) return;
17597
+ if (node.type !== import_types59.NodeType.InfraNode) return;
17463
17598
  if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
17464
17599
  const fields = guards.get(collectionKeyFromName(node.name));
17465
17600
  if (!fields || fields.size === 0) return;
@@ -17478,12 +17613,12 @@ var import_node_path72 = __toESM(require("path"), 1);
17478
17613
  init_cjs_shims();
17479
17614
  var import_node_fs36 = require("fs");
17480
17615
  var import_node_path71 = __toESM(require("path"), 1);
17481
- var import_types59 = require("@neat.is/types");
17616
+ var import_types60 = require("@neat.is/types");
17482
17617
  function dropOrphanedFileNodes(graph, source) {
17483
17618
  const orphans = [];
17484
17619
  graph.forEachNode((id, attrs) => {
17485
17620
  const node = attrs;
17486
- if (node.type !== import_types59.NodeType.FileNode) return;
17621
+ if (node.type !== import_types60.NodeType.FileNode) return;
17487
17622
  if (source && node.source !== source) return;
17488
17623
  if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
17489
17624
  orphans.push(id);
@@ -17497,7 +17632,7 @@ function outOfScope(graph, edge, source) {
17497
17632
  for (const endpoint2 of [edge.source, edge.target]) {
17498
17633
  if (!graph.hasNode(endpoint2)) continue;
17499
17634
  const node = graph.getNodeAttributes(endpoint2);
17500
- if (node.type !== import_types59.NodeType.FileNode) continue;
17635
+ if (node.type !== import_types60.NodeType.FileNode) continue;
17501
17636
  return node.source !== source;
17502
17637
  }
17503
17638
  return false;
@@ -17507,7 +17642,7 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
17507
17642
  const bases = [scanPath, ...serviceDirs];
17508
17643
  graph.forEachEdge((id, attrs) => {
17509
17644
  const edge = attrs;
17510
- if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
17645
+ if (edge.provenance !== import_types60.Provenance.EXTRACTED) return;
17511
17646
  if (outOfScope(graph, edge, source)) return;
17512
17647
  const evidenceFile = edge.evidence?.file;
17513
17648
  if (!evidenceFile) return;
@@ -17526,7 +17661,23 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
17526
17661
  // src/extract/index.ts
17527
17662
  var passQueue = Promise.resolve();
17528
17663
  function extractFromDirectory(graph, scanPath, opts = {}) {
17529
- const pass = passQueue.then(() => runExtractionPass(graph, scanPath, opts));
17664
+ invalidateSourceBaseline(graph, opts.source, "syncing");
17665
+ const pass = passQueue.then(async () => {
17666
+ const sourceGeneration = beginSourceExtraction(graph, opts.source, opts.sourceCommit);
17667
+ let result;
17668
+ try {
17669
+ result = await runExtractionPass(graph, scanPath, opts);
17670
+ return result;
17671
+ } finally {
17672
+ finishSourceExtraction(
17673
+ graph,
17674
+ sourceGeneration,
17675
+ opts.source,
17676
+ opts.sourceCommit,
17677
+ result ?? { extractionErrors: 1, skippedFiles: 0 }
17678
+ );
17679
+ }
17680
+ });
17530
17681
  passQueue = pass.catch(() => {
17531
17682
  });
17532
17683
  return pass;
@@ -17620,10 +17771,40 @@ async function runExtractionPass(graph, scanPath, opts) {
17620
17771
 
17621
17772
  // src/goodybag.ts
17622
17773
  init_cjs_shims();
17623
- var import_types60 = require("@neat.is/types");
17774
+ var import_types61 = require("@neat.is/types");
17624
17775
  var CODE_FILEPATH_ATTR2 = "code.filepath";
17625
17776
  var CODE_LINENO_ATTR2 = "code.lineno";
17626
17777
  var BLAST_NEAREST_LIMIT = 5;
17778
+ function deployContextOf(ev) {
17779
+ const a = ev.attributes;
17780
+ if (!a) return void 0;
17781
+ const str = (k) => typeof a[k] === "string" ? a[k] : void 0;
17782
+ const int = (k) => typeof a[k] === "number" && Number.isFinite(a[k]) ? Math.trunc(a[k]) : void 0;
17783
+ const strs = (k) => {
17784
+ const v = a[k];
17785
+ return Array.isArray(v) && v.every((x) => typeof x === "string") && v.length > 0 ? v : void 0;
17786
+ };
17787
+ const ctx = {};
17788
+ const fault = str("k8s.fault");
17789
+ if (fault) ctx.fault = fault;
17790
+ const waiting = str("k8s.waitingReason");
17791
+ if (waiting) ctx.waitingReason = waiting;
17792
+ const image = str("k8s.image");
17793
+ if (image) ctx.image = image;
17794
+ const restarts = int("k8s.restartCount");
17795
+ if (restarts !== void 0) ctx.restartCount = restarts;
17796
+ const termReason = str("k8s.terminatedReason");
17797
+ if (termReason) ctx.terminatedReason = termReason;
17798
+ const exitCode = int("k8s.exitCode");
17799
+ if (exitCode !== void 0) ctx.exitCode = exitCode;
17800
+ const env = strs("k8s.containerEnv");
17801
+ if (env) ctx.containerEnv = env;
17802
+ const args = strs("k8s.containerArgs");
17803
+ if (args) ctx.containerArgs = args;
17804
+ const log = str("k8s.processLog");
17805
+ if (log) ctx.processLog = log;
17806
+ return Object.keys(ctx).length > 0 ? ctx : void 0;
17807
+ }
17627
17808
  function grainOf2(graph, nodeId) {
17628
17809
  if (graph.hasNode(nodeId)) {
17629
17810
  const t = graph.getNodeAttributes(nodeId).type;
@@ -17646,7 +17827,7 @@ function locusOf(graph, ev) {
17646
17827
  ...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
17647
17828
  ...symbol ? { symbol } : {},
17648
17829
  service: node?.service ?? ev.service,
17649
- provenance: import_types60.Provenance.OBSERVED
17830
+ provenance: import_types61.Provenance.OBSERVED
17650
17831
  };
17651
17832
  }
17652
17833
  function locusFromNode(graph, nodeId) {
@@ -17662,7 +17843,7 @@ function locusFromNode(graph, nodeId) {
17662
17843
  ...typeof end === "number" ? { lineEnd: end } : {},
17663
17844
  ...n.qualname ? { symbol: shortLabel(graph, nodeId) } : {},
17664
17845
  ...n.service ? { service: n.service } : {},
17665
- provenance: import_types60.Provenance.INFERRED
17846
+ provenance: import_types61.Provenance.INFERRED
17666
17847
  };
17667
17848
  }
17668
17849
  function promoteCauseLocus(graph, causeNode, incidents) {
@@ -17671,11 +17852,16 @@ function promoteCauseLocus(graph, causeNode, incidents) {
17671
17852
  );
17672
17853
  if (native) {
17673
17854
  const l = locusOf(graph, native);
17674
- if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types60.Provenance.INFERRED };
17855
+ if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types61.Provenance.INFERRED };
17675
17856
  }
17676
17857
  return locusFromNode(graph, causeNode);
17677
17858
  }
17678
17859
  function divergenceSummary(d) {
17860
+ if (d.type === "observed-symbol-mismatch" || d.source === d.target) {
17861
+ const symbol = "symbol" in d && d.symbol ? d.symbol : d.source;
17862
+ const at = "location" in d && d.location ? ` at ${d.location}` : "";
17863
+ return `${symbol}${at}`;
17864
+ }
17679
17865
  const column = "column" in d && d.column ? `.${d.column}` : "";
17680
17866
  const label = "table" in d && d.table ? `${d.table}${column}` : `${d.source} \u2192 ${d.target}`;
17681
17867
  return label;
@@ -17720,7 +17906,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17720
17906
  const chain = (rc.traversalPath ?? []).map((node, i) => ({
17721
17907
  node,
17722
17908
  grain: grainOf2(graph, node),
17723
- provenance: provs[i] ?? provs[provs.length - 1] ?? import_types60.Provenance.INFERRED
17909
+ provenance: provs[i] ?? provs[provs.length - 1] ?? import_types61.Provenance.INFERRED
17724
17910
  }));
17725
17911
  rootCause = {
17726
17912
  node: rc.rootCauseNode,
@@ -17751,7 +17937,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17751
17937
  kind: "incident",
17752
17938
  id: errorEvent.id,
17753
17939
  at: errorEvent.timestamp,
17754
- incidentKind: (0, import_types60.incidentKindOf)(errorEvent),
17940
+ incidentKind: (0, import_types61.incidentKindOf)(errorEvent),
17755
17941
  service: errorEvent.service,
17756
17942
  affectedNode: affected,
17757
17943
  message: errorEvent.errorMessage,
@@ -17766,10 +17952,14 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17766
17952
  ...nearest.length > 0 ? { blastRadius: { totalAffected: blast.totalAffected, nearest } } : {},
17767
17953
  ...policyCards.length > 0 ? { policies: policyCards } : {},
17768
17954
  ...divergences.length > 0 ? { divergence: divergences } : {},
17955
+ ...(() => {
17956
+ const dc = deployContextOf(errorEvent);
17957
+ return dc ? { deployContext: dc } : {};
17958
+ })(),
17769
17959
  headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
17770
17960
  };
17771
17961
  card.grade = gradeIncidentCard(card);
17772
- return import_types60.IncidentCardSchema.parse(card);
17962
+ return import_types61.IncidentCardSchema.parse(card);
17773
17963
  }
17774
17964
  var GRADE_PRIORS_VERSION = "sniper-architecture-priors-2026-10-08";
17775
17965
  var GRADE_WEIGHTS = {
@@ -17876,7 +18066,7 @@ function gradeIncidentCard(card) {
17876
18066
 
17877
18067
  // src/ask.ts
17878
18068
  init_cjs_shims();
17879
- var import_types61 = require("@neat.is/types");
18069
+ var import_types62 = require("@neat.is/types");
17880
18070
  var DEFAULT_MAX_NODES = 3;
17881
18071
  var MAX_FACTS_PER_SECTION = 6;
17882
18072
  var INTENT_RULES = [
@@ -18112,14 +18302,23 @@ function idBody(id) {
18112
18302
  return colon >= 0 ? id.slice(colon + 1) : id;
18113
18303
  }
18114
18304
  var TYPE_NOUNS = [
18115
- { nouns: ["database", "db", "table"], type: import_types61.NodeType.DatabaseNode },
18116
- { nouns: ["service", "api", "backend"], type: import_types61.NodeType.ServiceNode },
18117
- { nouns: ["route", "endpoint"], type: import_types61.NodeType.RouteNode },
18118
- { nouns: ["file"], type: import_types61.NodeType.FileNode },
18119
- { nouns: ["config"], type: import_types61.NodeType.ConfigNode }
18305
+ { nouns: ["database", "db", "table"], type: import_types62.NodeType.DatabaseNode },
18306
+ { nouns: ["service", "api", "backend"], type: import_types62.NodeType.ServiceNode },
18307
+ { nouns: ["route", "endpoint"], type: import_types62.NodeType.RouteNode },
18308
+ { nouns: ["file"], type: import_types62.NodeType.FileNode },
18309
+ { nouns: ["config"], type: import_types62.NodeType.ConfigNode }
18120
18310
  ];
18121
18311
  var EMBED_MIN_SCORE = 0.35;
18122
18312
  async function resolveEntities(graph, question, searchIndex, maxNodes) {
18313
+ const verbatim = [];
18314
+ for (const word of question.split(/\s+/)) {
18315
+ const id = word.replace(/^["'`(<]+|["'`)>?!.,;]+$/g, "");
18316
+ if (!id || !graph.hasNode(id) || verbatim.some((m) => m.nodeId === id)) continue;
18317
+ const node = graph.getNodeAttributes(id);
18318
+ if (node.type === import_types62.NodeType.FrontierNode) continue;
18319
+ verbatim.push({ nodeId: id, label: nodeName(node), via: "id", score: 1 });
18320
+ }
18321
+ if (verbatim.length > 0) return { matched: verbatim.slice(0, maxNodes) };
18123
18322
  const qTokens = queryTokens(question);
18124
18323
  const normalized = question.toLowerCase();
18125
18324
  const best = /* @__PURE__ */ new Map();
@@ -18130,7 +18329,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18130
18329
  };
18131
18330
  graph.forEachNode((id, attrs) => {
18132
18331
  const node = attrs;
18133
- if (node.type === import_types61.NodeType.FrontierNode) return;
18332
+ if (node.type === import_types62.NodeType.FrontierNode) return;
18134
18333
  const name = nodeName(node);
18135
18334
  const body = idBody(id);
18136
18335
  const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
@@ -18149,7 +18348,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18149
18348
  const res = await searchIndex.search(question, 10);
18150
18349
  if (res.provider !== "substring") {
18151
18350
  for (const m of res.matches) {
18152
- if (m.node.type === import_types61.NodeType.FrontierNode) continue;
18351
+ if (m.node.type === import_types62.NodeType.FrontierNode) continue;
18153
18352
  if (!graph.hasNode(m.node.id)) continue;
18154
18353
  const already = best.get(m.node.id);
18155
18354
  if (!already && m.score < EMBED_MIN_SCORE) continue;
@@ -18209,7 +18408,7 @@ function edgeSignalNote(e) {
18209
18408
  function buildRootCauseSection(graph, node, incidents, now) {
18210
18409
  const result = getRootCause(graph, node, void 0, incidents, { now });
18211
18410
  if (!result) return null;
18212
- const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types61.Provenance.OBSERVED;
18411
+ const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types62.Provenance.OBSERVED;
18213
18412
  const facts = [
18214
18413
  {
18215
18414
  text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
@@ -18259,7 +18458,7 @@ function buildObservedSection(graph, node) {
18259
18458
  if (result.observed && result.inboundObservedCount > 0) {
18260
18459
  facts.push({
18261
18460
  text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
18262
- provenance: import_types61.Provenance.OBSERVED
18461
+ provenance: import_types62.Provenance.OBSERVED
18263
18462
  });
18264
18463
  } else {
18265
18464
  return null;
@@ -18282,10 +18481,10 @@ function buildBlastSection(graph, node) {
18282
18481
  }
18283
18482
  function buildDatabaseCallersSection(graph, node) {
18284
18483
  const callers = getBlastRadius(graph, node).affectedNodes.filter((item) => {
18285
- if (graph.getNodeAttributes(item.nodeId).type !== import_types61.NodeType.ServiceNode) return false;
18484
+ if (graph.getNodeAttributes(item.nodeId).type !== import_types62.NodeType.ServiceNode) return false;
18286
18485
  return item.path.slice(1, -1).every((id) => {
18287
18486
  const type = graph.getNodeAttributes(id).type;
18288
- return type === import_types61.NodeType.FileNode || type === import_types61.NodeType.SymbolNode;
18487
+ return type === import_types62.NodeType.FileNode || type === import_types62.NodeType.SymbolNode;
18289
18488
  });
18290
18489
  });
18291
18490
  return {
@@ -18304,7 +18503,7 @@ function buildIncidentsSection(node, incidents) {
18304
18503
  const facts = ordered.map((ev) => ({
18305
18504
  text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
18306
18505
  // ErrorEvents are observation records — OBSERVED by definition.
18307
- provenance: import_types61.Provenance.OBSERVED
18506
+ provenance: import_types62.Provenance.OBSERVED
18308
18507
  }));
18309
18508
  return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
18310
18509
  }
@@ -18327,8 +18526,8 @@ function runtimeEdgeState(graph) {
18327
18526
  let observed = false;
18328
18527
  let stale = false;
18329
18528
  graph.forEachEdge((_id, attrs) => {
18330
- if (attrs.provenance === import_types61.Provenance.OBSERVED) observed = true;
18331
- if (attrs.provenance === import_types61.Provenance.STALE) stale = true;
18529
+ if (attrs.provenance === import_types62.Provenance.OBSERVED) observed = true;
18530
+ if (attrs.provenance === import_types62.Provenance.STALE) stale = true;
18332
18531
  });
18333
18532
  return { observed, stale };
18334
18533
  }
@@ -18396,7 +18595,7 @@ function buildGlobalIncidentsSection(incidents) {
18396
18595
  }
18397
18596
  const byKey = /* @__PURE__ */ new Map();
18398
18597
  for (const ev of incidents) {
18399
- const key = ev.affectedNode || (0, import_types61.serviceId)(ev.service);
18598
+ const key = ev.affectedNode || (0, import_types62.serviceId)(ev.service);
18400
18599
  const cur = byKey.get(key);
18401
18600
  if (!cur) {
18402
18601
  byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
@@ -18411,7 +18610,7 @@ function buildGlobalIncidentsSection(incidents) {
18411
18610
  const rows = [...byKey.values()].sort((a, b) => b.count - a.count || b.latest.localeCompare(a.latest) || a.key.localeCompare(b.key)).slice(0, MAX_FACTS_PER_SECTION);
18412
18611
  const facts = rows.map((r) => ({
18413
18612
  text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
18414
- provenance: import_types61.Provenance.OBSERVED
18613
+ provenance: import_types62.Provenance.OBSERVED
18415
18614
  }));
18416
18615
  return {
18417
18616
  heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
@@ -18424,7 +18623,7 @@ function buildOverviewSections(graph, incidents) {
18424
18623
  graph.forEachNode((_id, attrs) => {
18425
18624
  const node = attrs;
18426
18625
  nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
18427
- if (node.type === import_types61.NodeType.ServiceNode) services.push(node.id);
18626
+ if (node.type === import_types62.NodeType.ServiceNode) services.push(node.id);
18428
18627
  });
18429
18628
  const edgeByProv = /* @__PURE__ */ new Map();
18430
18629
  graph.forEachEdge((_id, attrs) => {
@@ -18436,10 +18635,10 @@ function buildOverviewSections(graph, incidents) {
18436
18635
  const shapeFacts = [
18437
18636
  { text: `${graph.order} nodes, ${graph.size} edges` },
18438
18637
  {
18439
- text: `${count(import_types61.NodeType.ServiceNode)} services, ${count(import_types61.NodeType.FileNode)} files, ${count(import_types61.NodeType.SymbolNode)} symbols, ${count(import_types61.NodeType.DatabaseNode)} databases`
18638
+ text: `${count(import_types62.NodeType.ServiceNode)} services, ${count(import_types62.NodeType.FileNode)} files, ${count(import_types62.NodeType.SymbolNode)} symbols, ${count(import_types62.NodeType.DatabaseNode)} databases`
18440
18639
  }
18441
18640
  ];
18442
- for (const p of [import_types61.Provenance.EXTRACTED, import_types61.Provenance.OBSERVED, import_types61.Provenance.INFERRED, import_types61.Provenance.STALE]) {
18641
+ for (const p of [import_types62.Provenance.EXTRACTED, import_types62.Provenance.OBSERVED, import_types62.Provenance.INFERRED, import_types62.Provenance.STALE]) {
18443
18642
  const n = edgeByProv.get(p) ?? 0;
18444
18643
  if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
18445
18644
  }
@@ -18456,7 +18655,7 @@ function buildOverviewSections(graph, incidents) {
18456
18655
  if (incidents && incidents.length > 0) {
18457
18656
  const incCount = /* @__PURE__ */ new Map();
18458
18657
  for (const ev of incidents) {
18459
- const key = ev.affectedNode || (0, import_types61.serviceId)(ev.service);
18658
+ const key = ev.affectedNode || (0, import_types62.serviceId)(ev.service);
18460
18659
  incCount.set(key, (incCount.get(key) ?? 0) + 1);
18461
18660
  }
18462
18661
  const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
@@ -18464,7 +18663,7 @@ function buildOverviewSections(graph, incidents) {
18464
18663
  heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
18465
18664
  facts: top.map(([k, n]) => ({
18466
18665
  text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
18467
- provenance: import_types61.Provenance.OBSERVED
18666
+ provenance: import_types62.Provenance.OBSERVED
18468
18667
  }))
18469
18668
  });
18470
18669
  }
@@ -18595,7 +18794,7 @@ async function askGraph(graph, question, opts = {}) {
18595
18794
  let scope;
18596
18795
  if (primary) {
18597
18796
  scope = "node";
18598
- const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types61.NodeType.DatabaseNode && /\b(?:which|what)\s+services?\s+(?:talks?\s+to|connects?\s+to|uses?|hits?|calls?|reads?\s+from|writes?\s+to)\b/i.test(question);
18797
+ const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types62.NodeType.DatabaseNode && /\b(?:which|what)\s+services?\s+(?:talks?\s+to|connects?\s+to|uses?|hits?|calls?|reads?\s+from|writes?\s+to)\b/i.test(question);
18599
18798
  if (callersQuestion) sections.push(buildDatabaseCallersSection(graph, primary));
18600
18799
  for (const kind of SECTION_ORDER[intent]) {
18601
18800
  if (callersQuestion && kind === "blast") continue;
@@ -18613,7 +18812,7 @@ async function askGraph(graph, question, opts = {}) {
18613
18812
  const provSet = /* @__PURE__ */ new Set();
18614
18813
  for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
18615
18814
  const confidence = sections[0]?.facts[0]?.confidence;
18616
- return import_types61.AskResultSchema.parse({
18815
+ return import_types62.AskResultSchema.parse({
18617
18816
  question,
18618
18817
  intent,
18619
18818
  matched,
@@ -18707,7 +18906,7 @@ function canonicalJson(value) {
18707
18906
  init_cjs_shims();
18708
18907
  var import_node_fs38 = require("fs");
18709
18908
  var import_node_path73 = __toESM(require("path"), 1);
18710
- var import_types62 = require("@neat.is/types");
18909
+ var import_types63 = require("@neat.is/types");
18711
18910
  var SCHEMA_VERSION = 7;
18712
18911
  function migrateV1ToV2(payload) {
18713
18912
  const nodes = payload.graph.nodes;
@@ -18731,7 +18930,7 @@ function migrateV5ToV6(payload) {
18731
18930
  if (Array.isArray(nodes)) {
18732
18931
  for (const node of nodes) {
18733
18932
  const attrs = node.attributes;
18734
- if (!attrs || attrs.type !== import_types62.NodeType.InfraNode) continue;
18933
+ if (!attrs || attrs.type !== import_types63.NodeType.InfraNode) continue;
18735
18934
  if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
18736
18935
  if (!Array.isArray(attrs.columns)) attrs.columns = [];
18737
18936
  }
@@ -18747,12 +18946,12 @@ function migrateV2ToV3(payload) {
18747
18946
  for (const edge of edges) {
18748
18947
  const attrs = edge.attributes;
18749
18948
  if (!attrs || attrs.provenance !== "FRONTIER") continue;
18750
- attrs.provenance = import_types62.Provenance.OBSERVED;
18949
+ attrs.provenance = import_types63.Provenance.OBSERVED;
18751
18950
  const type = typeof attrs.type === "string" ? attrs.type : void 0;
18752
18951
  const source = typeof attrs.source === "string" ? attrs.source : void 0;
18753
18952
  const target = typeof attrs.target === "string" ? attrs.target : void 0;
18754
18953
  if (type && source && target) {
18755
- const newId = (0, import_types62.observedEdgeId)(source, target, type);
18954
+ const newId = (0, import_types63.observedEdgeId)(source, target, type);
18756
18955
  attrs.id = newId;
18757
18956
  if (edge.key) edge.key = newId;
18758
18957
  }
@@ -18963,7 +19162,7 @@ init_cjs_shims();
18963
19162
  var import_node_fs39 = require("fs");
18964
19163
  var import_node_os3 = __toESM(require("os"), 1);
18965
19164
  var import_node_path75 = __toESM(require("path"), 1);
18966
- var import_types63 = require("@neat.is/types");
19165
+ var import_types64 = require("@neat.is/types");
18967
19166
  function neatHome() {
18968
19167
  const override = process.env.NEAT_HOME;
18969
19168
  if (override && override.length > 0) return import_node_path75.default.resolve(override);
@@ -19053,7 +19252,7 @@ async function readRegistry() {
19053
19252
  throw err;
19054
19253
  }
19055
19254
  const parsed = JSON.parse(raw);
19056
- return import_types63.RegistryFileSchema.parse(parsed);
19255
+ return import_types64.RegistryFileSchema.parse(parsed);
19057
19256
  }
19058
19257
  async function getProject(name) {
19059
19258
  const reg = await readRegistry();
@@ -19070,11 +19269,11 @@ var DEFAULT_PRUNE_TTL_MS = 7 * DAY_MS2;
19070
19269
  init_cjs_shims();
19071
19270
  var import_node_fs40 = require("fs");
19072
19271
  var import_zod = require("zod");
19073
- var import_types64 = require("@neat.is/types");
19272
+ var import_types65 = require("@neat.is/types");
19074
19273
  var SSE_HEARTBEAT_MS = 3e4;
19075
19274
  var SSE_BACKPRESSURE_CAP = 1e3;
19076
19275
  var INCIDENT_TRIGGER_STREAM_SCOPE = "incident-only-v1";
19077
- var IncidentTriggerSchema = import_types64.IncidentEventPayloadSchema.extend({
19276
+ var IncidentTriggerSchema = import_types65.IncidentEventPayloadSchema.extend({
19078
19277
  incidentId: import_zod.z.string().regex(/^[A-Za-z0-9:_-]{1,100}$/),
19079
19278
  affectedNode: import_zod.z.string().min(1).max(512),
19080
19279
  service: import_zod.z.string().min(1).max(256),
@@ -19102,12 +19301,12 @@ function loadIncidentReplay(errorsPath, cursor) {
19102
19301
  if (!isExtractionFailure(row)) throw new Error("incident replay unavailable");
19103
19302
  continue;
19104
19303
  }
19105
- const event = import_types64.ErrorEventSchema.parse(row);
19304
+ const event = import_types65.ErrorEventSchema.parse(row);
19106
19305
  const trigger = IncidentTriggerSchema.parse({
19107
19306
  incidentId: event.id,
19108
19307
  affectedNode: event.affectedNode,
19109
19308
  service: event.service,
19110
- incidentKind: (0, import_types64.incidentKindOf)(event),
19309
+ incidentKind: (0, import_types65.incidentKindOf)(event),
19111
19310
  at: event.timestamp
19112
19311
  });
19113
19312
  const prior = seen.get(trigger.incidentId), encoded = JSON.stringify(trigger);
@@ -19482,7 +19681,7 @@ function renderVerdict({
19482
19681
  }
19483
19682
 
19484
19683
  // src/pr-verdict.ts
19485
- var import_types65 = require("@neat.is/types");
19684
+ var import_types66 = require("@neat.is/types");
19486
19685
 
19487
19686
  // src/connectors/hosted-repos.ts
19488
19687
  init_cjs_shims();
@@ -19555,7 +19754,7 @@ var PrVerdictError = class extends Error {
19555
19754
  details;
19556
19755
  };
19557
19756
  function parsePrVerdictRequest(body) {
19558
- const parsed = import_types65.PrVerdictBodySchema.safeParse(body);
19757
+ const parsed = import_types66.PrVerdictBodySchema.safeParse(body);
19559
19758
  if (!parsed.success) {
19560
19759
  throw new PrVerdictError("invalid pr-verdict body", 400, void 0, parsed.error.issues);
19561
19760
  }
@@ -19904,15 +20103,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
19904
20103
 
19905
20104
  // src/connectors/index.ts
19906
20105
  init_cjs_shims();
19907
- var import_types66 = require("@neat.is/types");
20106
+ var import_types67 = require("@neat.is/types");
19908
20107
  var NO_ENV = "unknown";
19909
20108
  function staticCallSiteFor(graph, serviceName, targetNodeId) {
19910
20109
  if (!graph.hasNode(targetNodeId)) return void 0;
19911
20110
  const sites = [];
19912
20111
  for (const edgeId of graph.inboundEdges(targetNodeId)) {
19913
20112
  const edge = graph.getEdgeAttributes(edgeId);
19914
- if (edge.provenance !== import_types66.Provenance.EXTRACTED) continue;
19915
- const parsed = (0, import_types66.parseFileId)(edge.source);
20113
+ if (edge.provenance !== import_types67.Provenance.EXTRACTED) continue;
20114
+ const parsed = (0, import_types67.parseFileId)(edge.source);
19916
20115
  if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
19917
20116
  const site = { relPath: edge.evidence.file };
19918
20117
  if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
@@ -19923,7 +20122,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
19923
20122
  function routeCallSiteFor(graph, targetNodeId) {
19924
20123
  if (!graph.hasNode(targetNodeId)) return void 0;
19925
20124
  const attrs = graph.getNodeAttributes(targetNodeId);
19926
- if (attrs.type !== import_types66.NodeType.RouteNode || !attrs.path) return void 0;
20125
+ if (attrs.type !== import_types67.NodeType.RouteNode || !attrs.path) return void 0;
19927
20126
  const site = { relPath: attrs.path };
19928
20127
  if (attrs.line !== void 0) site.line = attrs.line;
19929
20128
  return site;
@@ -20605,23 +20804,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
20605
20804
 
20606
20805
  // src/connectors/supabase/resolve.ts
20607
20806
  init_cjs_shims();
20608
- var import_types68 = require("@neat.is/types");
20807
+ var import_types69 = require("@neat.is/types");
20609
20808
  function createSupabaseResolveTarget(graph, config) {
20610
20809
  return (signal, _ctx) => {
20611
20810
  if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
20612
20811
  return null;
20613
20812
  }
20614
- const subResourceId = (0, import_types68.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
20813
+ const subResourceId = (0, import_types69.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
20615
20814
  if (graph.hasNode(subResourceId)) {
20616
- return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
20815
+ return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
20617
20816
  }
20618
- const bareResourceId = (0, import_types68.infraId)(signal.targetKind, signal.targetName);
20817
+ const bareResourceId = (0, import_types69.infraId)(signal.targetKind, signal.targetName);
20619
20818
  if (graph.hasNode(bareResourceId)) {
20620
- return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
20819
+ return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
20621
20820
  }
20622
- const projectLevelId = (0, import_types68.infraId)("supabase", config.nodeRef);
20821
+ const projectLevelId = (0, import_types69.infraId)("supabase", config.nodeRef);
20623
20822
  if (graph.hasNode(projectLevelId)) {
20624
- return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
20823
+ return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
20625
20824
  }
20626
20825
  return null;
20627
20826
  };
@@ -20714,7 +20913,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
20714
20913
 
20715
20914
  // src/connectors/railway/index.ts
20716
20915
  init_cjs_shims();
20717
- var import_types72 = require("@neat.is/types");
20916
+ var import_types73 = require("@neat.is/types");
20718
20917
 
20719
20918
  // src/connectors/railway/client.ts
20720
20919
  init_cjs_shims();
@@ -20865,7 +21064,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
20865
21064
  const out = [];
20866
21065
  graph.forEachNode((_id, attrs) => {
20867
21066
  const node = attrs;
20868
- if (node.type !== import_types72.NodeType.RouteNode) return;
21067
+ if (node.type !== import_types73.NodeType.RouteNode) return;
20869
21068
  const route = attrs;
20870
21069
  if (route.service !== serviceName) return;
20871
21070
  out.push({
@@ -20969,12 +21168,12 @@ function createRailwayResolveTarget(config) {
20969
21168
  const serviceName = config.serviceNameById[config.serviceId];
20970
21169
  if (!serviceName) return null;
20971
21170
  if (signal.targetKind === ROUTE_TARGET_KIND) {
20972
- return { targetNodeId: signal.targetName, serviceName, edgeType: import_types72.EdgeType.CALLS };
21171
+ return { targetNodeId: signal.targetName, serviceName, edgeType: import_types73.EdgeType.CALLS };
20973
21172
  }
20974
21173
  if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
20975
21174
  const peerName = config.serviceNameById[signal.targetName];
20976
21175
  if (!peerName) return null;
20977
- return { targetNodeId: (0, import_types72.serviceId)(peerName), serviceName, edgeType: import_types72.EdgeType.CONNECTS_TO };
21176
+ return { targetNodeId: (0, import_types73.serviceId)(peerName), serviceName, edgeType: import_types73.EdgeType.CONNECTS_TO };
20978
21177
  }
20979
21178
  return null;
20980
21179
  };
@@ -21162,11 +21361,11 @@ function mapLogEntriesToSignals(entries) {
21162
21361
 
21163
21362
  // src/connectors/firebase/resolve.ts
21164
21363
  init_cjs_shims();
21165
- var import_types74 = require("@neat.is/types");
21364
+ var import_types75 = require("@neat.is/types");
21166
21365
 
21167
21366
  // src/connectors/infer-service.ts
21168
21367
  init_cjs_shims();
21169
- var import_types73 = require("@neat.is/types");
21368
+ var import_types74 = require("@neat.is/types");
21170
21369
  function normalizeName(name) {
21171
21370
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
21172
21371
  }
@@ -21177,11 +21376,11 @@ function inferServiceName(graph, resourceName, method, path81) {
21177
21376
  const owners = /* @__PURE__ */ new Set();
21178
21377
  graph.forEachNode((_id, attrs) => {
21179
21378
  const node = attrs;
21180
- if (node.type === import_types73.NodeType.ServiceNode && typeof node.name === "string") {
21379
+ if (node.type === import_types74.NodeType.ServiceNode && typeof node.name === "string") {
21181
21380
  services.push(node.name);
21182
21381
  return;
21183
21382
  }
21184
- if (node.type !== import_types73.NodeType.RouteNode) return;
21383
+ if (node.type !== import_types74.NodeType.RouteNode) return;
21185
21384
  const route = attrs;
21186
21385
  if (!route.pathTemplate || normalizePathTemplate(route.pathTemplate) !== wantedPath) return;
21187
21386
  const routeMethod = route.method.toUpperCase();
@@ -21208,7 +21407,7 @@ function routeEntriesFor(graph, serviceName) {
21208
21407
  const entries = [];
21209
21408
  graph.forEachNode((_id, attrs) => {
21210
21409
  const node = attrs;
21211
- if (node.type !== import_types74.NodeType.RouteNode) return;
21410
+ if (node.type !== import_types75.NodeType.RouteNode) return;
21212
21411
  const route = attrs;
21213
21412
  if (route.service !== serviceName) return;
21214
21413
  entries.push({
@@ -21240,7 +21439,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
21240
21439
  return {
21241
21440
  targetNodeId: match.routeNodeId,
21242
21441
  serviceName,
21243
- edgeType: import_types74.EdgeType.CALLS
21442
+ edgeType: import_types75.EdgeType.CALLS
21244
21443
  };
21245
21444
  };
21246
21445
  }
@@ -21273,7 +21472,7 @@ init_cjs_shims();
21273
21472
 
21274
21473
  // src/connectors/cloudflare/connector.ts
21275
21474
  init_cjs_shims();
21276
- var import_types76 = require("@neat.is/types");
21475
+ var import_types77 = require("@neat.is/types");
21277
21476
 
21278
21477
  // src/connectors/cloudflare/client.ts
21279
21478
  init_cjs_shims();
@@ -21437,7 +21636,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
21437
21636
  graph.forEachNode((id, attrs) => {
21438
21637
  if (found) return;
21439
21638
  const a = attrs;
21440
- if (a.type === import_types76.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
21639
+ if (a.type === import_types77.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
21441
21640
  found = id;
21442
21641
  }
21443
21642
  });
@@ -21449,7 +21648,7 @@ function findMatchingRouteNode(graph, serviceName, method, path81) {
21449
21648
  graph.forEachNode((id, attrs) => {
21450
21649
  if (found) return;
21451
21650
  const a = attrs;
21452
- if (a.type !== import_types76.NodeType.RouteNode || a.service !== serviceName) return;
21651
+ if (a.type !== import_types77.NodeType.RouteNode || a.service !== serviceName) return;
21453
21652
  if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
21454
21653
  const routeMethod = (a.method ?? "").toUpperCase();
21455
21654
  if (routeMethod !== "ALL" && routeMethod !== method) return;
@@ -21468,11 +21667,11 @@ function createCloudflareResolveTarget(config, graph) {
21468
21667
  };
21469
21668
  const mapping = config.workers?.[scriptName];
21470
21669
  if (mapping) {
21471
- const wholeFileId = (0, import_types76.fileId)(mapping.service, mapping.entryFile);
21670
+ const wholeFileId = (0, import_types77.fileId)(mapping.service, mapping.entryFile);
21472
21671
  return {
21473
21672
  targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
21474
21673
  serviceName: mapping.service,
21475
- edgeType: import_types76.EdgeType.CALLS
21674
+ edgeType: import_types77.EdgeType.CALLS
21476
21675
  };
21477
21676
  }
21478
21677
  const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
@@ -21481,13 +21680,13 @@ function createCloudflareResolveTarget(config, graph) {
21481
21680
  return {
21482
21681
  targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
21483
21682
  serviceName: fileNode.service,
21484
- edgeType: import_types76.EdgeType.CALLS
21683
+ edgeType: import_types77.EdgeType.CALLS
21485
21684
  };
21486
21685
  }
21487
21686
  return {
21488
- targetNodeId: (0, import_types76.infraId)("cloudflare-worker", scriptName),
21687
+ targetNodeId: (0, import_types77.infraId)("cloudflare-worker", scriptName),
21489
21688
  serviceName: scriptName,
21490
- edgeType: import_types76.EdgeType.CALLS,
21689
+ edgeType: import_types77.EdgeType.CALLS,
21491
21690
  ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
21492
21691
  };
21493
21692
  };
@@ -21683,14 +21882,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
21683
21882
 
21684
21883
  // src/connectors/neon/resolve.ts
21685
21884
  init_cjs_shims();
21686
- var import_types80 = require("@neat.is/types");
21885
+ var import_types81 = require("@neat.is/types");
21687
21886
  function createNeonResolveTarget(config) {
21688
21887
  return (signal) => {
21689
21888
  if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
21690
21889
  return {
21691
- targetNodeId: (0, import_types80.infraId)("sql-table", signal.targetName),
21890
+ targetNodeId: (0, import_types81.infraId)("sql-table", signal.targetName),
21692
21891
  serviceName: config.serviceName,
21693
- edgeType: import_types80.EdgeType.CALLS,
21892
+ edgeType: import_types81.EdgeType.CALLS,
21694
21893
  ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
21695
21894
  };
21696
21895
  };
@@ -21871,14 +22070,14 @@ function mapLogEntriesToSignals2(entries) {
21871
22070
 
21872
22071
  // src/connectors/cloud-run/resolve.ts
21873
22072
  init_cjs_shims();
21874
- var import_types84 = require("@neat.is/types");
22073
+ var import_types85 = require("@neat.is/types");
21875
22074
  var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
21876
22075
  function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
21877
22076
  let found = null;
21878
22077
  graph.forEachNode((_id, attrs) => {
21879
22078
  if (found) return;
21880
22079
  const node = attrs;
21881
- if (node.type !== import_types84.NodeType.RouteNode) return;
22080
+ if (node.type !== import_types85.NodeType.RouteNode) return;
21882
22081
  const route = attrs;
21883
22082
  if (route.service !== serviceName || !route.pathTemplate) return;
21884
22083
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -21903,13 +22102,13 @@ function createCloudRunResolveTarget(graph, config) {
21903
22102
  normalizePathTemplate(path81)
21904
22103
  );
21905
22104
  if (routeNodeId) {
21906
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types84.EdgeType.CALLS };
22105
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types85.EdgeType.CALLS };
21907
22106
  }
21908
22107
  }
21909
22108
  return {
21910
- targetNodeId: (0, import_types84.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
22109
+ targetNodeId: (0, import_types85.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
21911
22110
  serviceName: mappedService ?? gcpServiceName,
21912
- edgeType: import_types84.EdgeType.CALLS,
22111
+ edgeType: import_types85.EdgeType.CALLS,
21913
22112
  ensureInfraNode: {
21914
22113
  kind: CLOUD_RUN_SERVICE_INFRA_KIND,
21915
22114
  name: gcpServiceName,
@@ -22091,14 +22290,14 @@ function mapLogEntriesToSignals3(entries) {
22091
22290
 
22092
22291
  // src/connectors/gcp-lb/resolve.ts
22093
22292
  init_cjs_shims();
22094
- var import_types88 = require("@neat.is/types");
22293
+ var import_types89 = require("@neat.is/types");
22095
22294
  var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
22096
22295
  function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
22097
22296
  let found = null;
22098
22297
  graph.forEachNode((_id, attrs) => {
22099
22298
  if (found) return;
22100
22299
  const node = attrs;
22101
- if (node.type !== import_types88.NodeType.RouteNode) return;
22300
+ if (node.type !== import_types89.NodeType.RouteNode) return;
22102
22301
  const route = attrs;
22103
22302
  if (route.service !== serviceName || !route.pathTemplate) return;
22104
22303
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -22123,13 +22322,13 @@ function createGcpLbResolveTarget(graph, config) {
22123
22322
  normalizePathTemplate(path81)
22124
22323
  );
22125
22324
  if (routeNodeId) {
22126
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types88.EdgeType.CALLS };
22325
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types89.EdgeType.CALLS };
22127
22326
  }
22128
22327
  }
22129
22328
  return {
22130
- targetNodeId: (0, import_types88.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
22329
+ targetNodeId: (0, import_types89.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
22131
22330
  serviceName: mappedService ?? backendServiceName,
22132
- edgeType: import_types88.EdgeType.CALLS,
22331
+ edgeType: import_types89.EdgeType.CALLS,
22133
22332
  ensureInfraNode: {
22134
22333
  kind: GCP_LB_BACKEND_INFRA_KIND,
22135
22334
  name: backendServiceName,
@@ -22170,7 +22369,7 @@ function createGcpLbConnector(graph, config = {}) {
22170
22369
 
22171
22370
  // src/connectors/render/index.ts
22172
22371
  init_cjs_shims();
22173
- var import_types91 = require("@neat.is/types");
22372
+ var import_types92 = require("@neat.is/types");
22174
22373
 
22175
22374
  // src/connectors/render/types.ts
22176
22375
  init_cjs_shims();
@@ -22248,7 +22447,7 @@ function buildRenderRouteIndex(graph, serviceName) {
22248
22447
  const out = [];
22249
22448
  graph.forEachNode((_id, attrs) => {
22250
22449
  const node = attrs;
22251
- if (node.type !== import_types91.NodeType.RouteNode) return;
22450
+ if (node.type !== import_types92.NodeType.RouteNode) return;
22252
22451
  const route = attrs;
22253
22452
  if (route.service !== serviceName) return;
22254
22453
  out.push({
@@ -22333,7 +22532,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
22333
22532
  function createRenderResolveTarget(config) {
22334
22533
  return (signal) => {
22335
22534
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
22336
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types91.EdgeType.CALLS };
22535
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types92.EdgeType.CALLS };
22337
22536
  }
22338
22537
  return null;
22339
22538
  };
@@ -22471,21 +22670,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
22471
22670
 
22472
22671
  // src/connectors/planetscale/resolve.ts
22473
22672
  init_cjs_shims();
22474
- var import_types95 = require("@neat.is/types");
22673
+ var import_types96 = require("@neat.is/types");
22475
22674
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
22476
22675
  function createPlanetscaleResolveTarget(graph, config) {
22477
22676
  const databaseName = `${config.organization}/${config.database}`;
22478
22677
  return (signal, _ctx) => {
22479
22678
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
22480
- const tableId = (0, import_types95.infraId)("sql-table", signal.targetName);
22679
+ const tableId = (0, import_types96.infraId)("sql-table", signal.targetName);
22481
22680
  if (graph.hasNode(tableId)) {
22482
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types95.EdgeType.CALLS };
22681
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types96.EdgeType.CALLS };
22483
22682
  }
22484
- const providerId = (0, import_types95.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
22683
+ const providerId = (0, import_types96.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
22485
22684
  return {
22486
22685
  targetNodeId: providerId,
22487
22686
  serviceName: config.serviceName,
22488
- edgeType: import_types95.EdgeType.CALLS,
22687
+ edgeType: import_types96.EdgeType.CALLS,
22489
22688
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
22490
22689
  };
22491
22690
  };
@@ -22750,7 +22949,7 @@ function mapBuildsToSignals(builds, serviceName) {
22750
22949
 
22751
22950
  // src/connectors/eas/resolve.ts
22752
22951
  init_cjs_shims();
22753
- var import_types100 = require("@neat.is/types");
22952
+ var import_types101 = require("@neat.is/types");
22754
22953
  var NO_ENV2 = "unknown";
22755
22954
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
22756
22955
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -22766,8 +22965,8 @@ function configBasenamesForPhase(phase) {
22766
22965
  function configNodeService(graph, configNodeId) {
22767
22966
  for (const edgeId of graph.inboundEdges(configNodeId)) {
22768
22967
  const edge = graph.getEdgeAttributes(edgeId);
22769
- if (edge.type !== import_types100.EdgeType.CONFIGURED_BY) continue;
22770
- const parsed = (0, import_types100.parseFileId)(edge.source);
22968
+ if (edge.type !== import_types101.EdgeType.CONFIGURED_BY) continue;
22969
+ const parsed = (0, import_types101.parseFileId)(edge.source);
22771
22970
  if (parsed) return parsed.service;
22772
22971
  }
22773
22972
  return null;
@@ -22778,7 +22977,7 @@ function findConfigNode(graph, basenames, serviceName) {
22778
22977
  graph.forEachNode((id, attrs) => {
22779
22978
  if (scoped) return;
22780
22979
  const node = attrs;
22781
- if (node.type !== import_types100.NodeType.ConfigNode) return;
22980
+ if (node.type !== import_types101.NodeType.ConfigNode) return;
22782
22981
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
22783
22982
  if (anyMatch === null) anyMatch = id;
22784
22983
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -22795,13 +22994,13 @@ function createEasResolveTarget(graph) {
22795
22994
  if (basenames.length > 0) {
22796
22995
  const configNodeId = findConfigNode(graph, basenames, serviceName);
22797
22996
  if (configNodeId) {
22798
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types100.EdgeType.CALLS };
22997
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types101.EdgeType.CALLS };
22799
22998
  }
22800
22999
  }
22801
23000
  return {
22802
23001
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
22803
23002
  serviceName,
22804
- edgeType: import_types100.EdgeType.CALLS
23003
+ edgeType: import_types101.EdgeType.CALLS
22805
23004
  };
22806
23005
  };
22807
23006
  }
@@ -23380,7 +23579,7 @@ function serializeGraph(graph) {
23380
23579
  graph.forEachEdge((_id, attrs) => {
23381
23580
  edges.push(attrs);
23382
23581
  });
23383
- return { nodes, edges };
23582
+ return { nodes, edges, sourceBaselines: readSourceBaselines(graph) };
23384
23583
  }
23385
23584
  function projectFromReq(req, singleProject, registry) {
23386
23585
  const params = req.params;
@@ -23563,11 +23762,11 @@ function registerRoutes(scope, ctx) {
23563
23762
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
23564
23763
  const parsed = [];
23565
23764
  for (const c of candidates) {
23566
- const r = import_types103.DivergenceTypeSchema.safeParse(c);
23765
+ const r = import_types104.DivergenceTypeSchema.safeParse(c);
23567
23766
  if (!r.success) {
23568
23767
  return reply.code(400).send({
23569
23768
  error: `unknown divergence type "${c}"`,
23570
- allowed: import_types103.DivergenceTypeSchema.options
23769
+ allowed: import_types104.DivergenceTypeSchema.options
23571
23770
  });
23572
23771
  }
23573
23772
  parsed.push(r.data);
@@ -24004,7 +24203,7 @@ function registerRoutes(scope, ctx) {
24004
24203
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
24005
24204
  let violations = await log.readAll();
24006
24205
  if (req.query.severity) {
24007
- const sev = import_types103.PolicySeveritySchema.safeParse(req.query.severity);
24206
+ const sev = import_types104.PolicySeveritySchema.safeParse(req.query.severity);
24008
24207
  if (!sev.success) {
24009
24208
  return reply.code(400).send({
24010
24209
  error: "invalid severity",
@@ -24043,7 +24242,7 @@ function registerRoutes(scope, ctx) {
24043
24242
  scope.post("/policies/check", async (req, reply) => {
24044
24243
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
24045
24244
  if (!proj) return;
24046
- const parsed = import_types103.PoliciesCheckBodySchema.safeParse(req.body ?? {});
24245
+ const parsed = import_types104.PoliciesCheckBodySchema.safeParse(req.body ?? {});
24047
24246
  if (!parsed.success) {
24048
24247
  return reply.code(400).send({
24049
24248
  error: "invalid /policies/check body",