@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/cli.cjs CHANGED
@@ -801,6 +801,7 @@ __export(cli_exports, {
801
801
  cwdProjectApplies: () => cwdProjectApplies,
802
802
  isLoopbackEndpoint: () => isLoopbackEndpoint,
803
803
  isNpxInvocation: () => isNpxInvocation,
804
+ loopbackResolutionHint: () => loopbackResolutionHint,
804
805
  main: () => main,
805
806
  parseArgs: () => parseArgs,
806
807
  printBanner: () => printBanner,
@@ -3039,7 +3040,7 @@ var PolicyViolationsLog = class {
3039
3040
  };
3040
3041
 
3041
3042
  // src/ingest.ts
3042
- var import_types9 = require("@neat.is/types");
3043
+ var import_types10 = require("@neat.is/types");
3043
3044
 
3044
3045
  // src/extract/routes.ts
3045
3046
  init_cjs_shims();
@@ -5816,9 +5817,95 @@ async function addRoutes(graph, services) {
5816
5817
  return { nodesAdded, edgesAdded };
5817
5818
  }
5818
5819
 
5819
- // src/columns.ts
5820
+ // src/extract/source-baseline.ts
5820
5821
  init_cjs_shims();
5821
5822
  var import_types8 = require("@neat.is/types");
5823
+ var states = /* @__PURE__ */ new WeakMap();
5824
+ var REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
5825
+ function validCommit(commit, repository) {
5826
+ return !!commit && commit.repository === repository && /^[0-9a-f]{40}$/.test(commit.sha);
5827
+ }
5828
+ function stateOf(graph) {
5829
+ let state = states.get(graph);
5830
+ if (!state) {
5831
+ state = { repos: /* @__PURE__ */ new Map(), active: /* @__PURE__ */ new Set(), conflicted: /* @__PURE__ */ new Set() };
5832
+ states.set(graph, state);
5833
+ }
5834
+ return state;
5835
+ }
5836
+ function setEntry(state, repository, baseline, generation = /* @__PURE__ */ Symbol()) {
5837
+ state.repos.set(repository, {
5838
+ baseline,
5839
+ generation,
5840
+ services: state.repos.get(repository)?.services ?? /* @__PURE__ */ new Set()
5841
+ });
5842
+ }
5843
+ function readSourceBaselines(graph) {
5844
+ const state = states.get(graph);
5845
+ if (!state) return [];
5846
+ return [...state.repos.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, entry2]) => ({ ...entry2.baseline }));
5847
+ }
5848
+ function invalidateSourceBaseline(graph, repository, status2 = "unavailable") {
5849
+ if (repository !== void 0) {
5850
+ if (REPOSITORY.test(repository)) setEntry(stateOf(graph), repository, { status: status2, repository });
5851
+ return;
5852
+ }
5853
+ const state = states.get(graph);
5854
+ if (!state) return;
5855
+ for (const generation of state.active) state.conflicted.add(generation);
5856
+ for (const name of state.repos.keys()) {
5857
+ setEntry(state, name, { status: "unavailable", repository: name });
5858
+ }
5859
+ }
5860
+ function beginSourceExtraction(graph, source, commit) {
5861
+ const generation = /* @__PURE__ */ Symbol();
5862
+ const state = stateOf(graph);
5863
+ if (source === void 0) {
5864
+ invalidateSourceBaseline(graph);
5865
+ state.active.add(generation);
5866
+ return generation;
5867
+ }
5868
+ state.active.add(generation);
5869
+ if (!REPOSITORY.test(source)) return generation;
5870
+ setEntry(
5871
+ state,
5872
+ source,
5873
+ validCommit(commit, source) ? { status: "syncing", repository: source } : { status: "unavailable", repository: source },
5874
+ generation
5875
+ );
5876
+ return generation;
5877
+ }
5878
+ function servicesOf(graph, repository) {
5879
+ const services = /* @__PURE__ */ new Set();
5880
+ graph.forEachNode((_id, attrs) => {
5881
+ const node = attrs;
5882
+ if (node.type === import_types8.NodeType.FileNode && node.source === repository && node.service) {
5883
+ services.add(node.service);
5884
+ }
5885
+ });
5886
+ return services;
5887
+ }
5888
+ function finishSourceExtraction(graph, generation, source, commit, result) {
5889
+ const state = states.get(graph);
5890
+ if (!state) return;
5891
+ state.active.delete(generation);
5892
+ const conflicted = state.conflicted.delete(generation);
5893
+ if (source === void 0 || !REPOSITORY.test(source)) return;
5894
+ const entry2 = state.repos.get(source);
5895
+ if (!entry2 || entry2.generation !== generation) return;
5896
+ entry2.services = servicesOf(graph, source);
5897
+ let shared = false;
5898
+ for (const [name, other] of state.repos) {
5899
+ if (name === source || ![...entry2.services].some((s) => other.services.has(s))) continue;
5900
+ shared = true;
5901
+ setEntry(state, name, { status: "unavailable", repository: name }, other.generation);
5902
+ }
5903
+ entry2.baseline = !conflicted && !shared && validCommit(commit, source) && result.extractionErrors === 0 && result.skippedFiles === 0 ? { status: "ready", repository: source, sha: commit.sha } : { status: "unavailable", repository: source };
5904
+ }
5905
+
5906
+ // src/columns.ts
5907
+ init_cjs_shims();
5908
+ var import_types9 = require("@neat.is/types");
5822
5909
  var OBSERVED_COLUMN_CONFIDENCE = 0.9;
5823
5910
  function normalizeProvenances(provenances) {
5824
5911
  return [...new Set(provenances)].sort();
@@ -5861,10 +5948,10 @@ function foldSdkWrites(existing, writes) {
5861
5948
  return out;
5862
5949
  }
5863
5950
  function columnIsDeclared(col) {
5864
- return col.provenances.includes(import_types8.Provenance.EXTRACTED);
5951
+ return col.provenances.includes(import_types9.Provenance.EXTRACTED);
5865
5952
  }
5866
5953
  function columnIsObserved(col) {
5867
- return col.provenances.includes(import_types8.Provenance.OBSERVED);
5954
+ return col.provenances.includes(import_types9.Provenance.OBSERVED);
5868
5955
  }
5869
5956
 
5870
5957
  // src/latency-digest.ts
@@ -6328,11 +6415,11 @@ function callSiteFromSpan(span, serviceNode, scanPath) {
6328
6415
  };
6329
6416
  }
6330
6417
  function reconcileObservedRelPath(graph, serviceName, relPath) {
6331
- if (graph.hasNode((0, import_types9.fileId)(serviceName, relPath))) return relPath;
6418
+ if (graph.hasNode((0, import_types10.fileId)(serviceName, relPath))) return relPath;
6332
6419
  let best = null;
6333
6420
  graph.forEachNode((_id, attrs) => {
6334
6421
  const a = attrs;
6335
- if (a.type !== import_types9.NodeType.FileNode || a.service !== serviceName) return;
6422
+ if (a.type !== import_types10.NodeType.FileNode || a.service !== serviceName) return;
6336
6423
  if (a.discoveredVia === "otel") return;
6337
6424
  const p = a.path;
6338
6425
  if (!p) return;
@@ -6344,14 +6431,14 @@ function reconcileObservedRelPath(graph, serviceName, relPath) {
6344
6431
  }
6345
6432
  function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
6346
6433
  const svcAttrs = graph.hasNode(serviceNodeId) ? graph.getNodeAttributes(serviceNodeId) : void 0;
6347
- const canonicalService = svcAttrs && svcAttrs.type === import_types9.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
6434
+ const canonicalService = svcAttrs && svcAttrs.type === import_types10.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
6348
6435
  const relPath = reconcileObservedRelPath(graph, canonicalService, callSite.relPath);
6349
- const fileNodeId = (0, import_types9.fileId)(canonicalService, relPath);
6436
+ const fileNodeId = (0, import_types10.fileId)(canonicalService, relPath);
6350
6437
  if (!graph.hasNode(fileNodeId)) {
6351
6438
  const language = languageForExt(relPath);
6352
6439
  const node = {
6353
6440
  id: fileNodeId,
6354
- type: import_types9.NodeType.FileNode,
6441
+ type: import_types10.NodeType.FileNode,
6355
6442
  service: canonicalService,
6356
6443
  path: relPath,
6357
6444
  ...language ? { language } : {},
@@ -6360,14 +6447,14 @@ function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
6360
6447
  };
6361
6448
  graph.addNode(fileNodeId, node);
6362
6449
  }
6363
- const containsId = makeObservedEdgeId(import_types9.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
6450
+ const containsId = makeObservedEdgeId(import_types10.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
6364
6451
  if (!graph.hasEdge(containsId)) {
6365
6452
  const edge = {
6366
6453
  id: containsId,
6367
6454
  source: serviceNodeId,
6368
6455
  target: fileNodeId,
6369
- type: import_types9.EdgeType.CONTAINS,
6370
- provenance: import_types9.Provenance.OBSERVED
6456
+ type: import_types10.EdgeType.CONTAINS,
6457
+ provenance: import_types10.Provenance.OBSERVED
6371
6458
  };
6372
6459
  graph.addEdgeWithKey(containsId, serviceNodeId, fileNodeId, edge);
6373
6460
  }
@@ -6391,11 +6478,11 @@ function pickContainingSymbol(candidates, fn) {
6391
6478
  return [...candidates].sort(bySpan)[0].id;
6392
6479
  }
6393
6480
  function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line) {
6394
- const sid = (0, import_types9.symbolId)(service, relPath, fn);
6481
+ const sid = (0, import_types10.symbolId)(service, relPath, fn);
6395
6482
  if (!graph.hasNode(sid)) {
6396
6483
  const node = {
6397
6484
  id: sid,
6398
- type: import_types9.NodeType.SymbolNode,
6485
+ type: import_types10.NodeType.SymbolNode,
6399
6486
  kind: "function",
6400
6487
  qualname: fn,
6401
6488
  span: { startLine: line, endLine: line },
@@ -6405,14 +6492,14 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
6405
6492
  };
6406
6493
  graph.addNode(sid, node);
6407
6494
  }
6408
- const containsId = makeObservedEdgeId(import_types9.EdgeType.CONTAINS, fileNodeId, sid);
6495
+ const containsId = makeObservedEdgeId(import_types10.EdgeType.CONTAINS, fileNodeId, sid);
6409
6496
  if (!graph.hasEdge(containsId)) {
6410
6497
  const edge = {
6411
6498
  id: containsId,
6412
6499
  source: fileNodeId,
6413
6500
  target: sid,
6414
- type: import_types9.EdgeType.CONTAINS,
6415
- provenance: import_types9.Provenance.OBSERVED
6501
+ type: import_types10.EdgeType.CONTAINS,
6502
+ provenance: import_types10.Provenance.OBSERVED
6416
6503
  };
6417
6504
  graph.addEdgeWithKey(containsId, fileNodeId, sid, edge);
6418
6505
  }
@@ -6424,9 +6511,9 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
6424
6511
  let sawSymbol = false;
6425
6512
  const candidates = [];
6426
6513
  graph.forEachOutboundEdge(fileNodeId, (_edge, edgeAttrs, _source, target) => {
6427
- if (edgeAttrs.type !== import_types9.EdgeType.CONTAINS) return;
6514
+ if (edgeAttrs.type !== import_types10.EdgeType.CONTAINS) return;
6428
6515
  const t = graph.getNodeAttributes(target);
6429
- if (t.type !== import_types9.NodeType.SymbolNode) return;
6516
+ if (t.type !== import_types10.NodeType.SymbolNode) return;
6430
6517
  sawSymbol = true;
6431
6518
  if (line >= t.span.startLine && line <= t.span.endLine) {
6432
6519
  candidates.push({ id: target, symbol: t });
@@ -6439,17 +6526,17 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
6439
6526
  return fileNodeId;
6440
6527
  }
6441
6528
  function makeObservedEdgeId(type, source, target) {
6442
- return (0, import_types9.observedEdgeId)(source, target, type);
6529
+ return (0, import_types10.observedEdgeId)(source, target, type);
6443
6530
  }
6444
6531
  function makeInferredEdgeId(type, source, target) {
6445
- return (0, import_types9.inferredEdgeId)(source, target, type);
6532
+ return (0, import_types10.inferredEdgeId)(source, target, type);
6446
6533
  }
6447
6534
  var INFERRED_CONFIDENCE = 0.6;
6448
6535
  var STITCH_MAX_DEPTH = 2;
6449
6536
  var STITCH_EDGE_TYPES = /* @__PURE__ */ new Set([
6450
- import_types9.EdgeType.CALLS,
6451
- import_types9.EdgeType.CONNECTS_TO,
6452
- import_types9.EdgeType.DEPENDS_ON
6537
+ import_types10.EdgeType.CALLS,
6538
+ import_types10.EdgeType.CONNECTS_TO,
6539
+ import_types10.EdgeType.DEPENDS_ON
6453
6540
  ]);
6454
6541
  var WIRE_SPAN_KIND_CLIENT = 3;
6455
6542
  var WIRE_SPAN_KIND_PRODUCER = 4;
@@ -6465,11 +6552,11 @@ function spanServesGraphqlOperation(kind) {
6465
6552
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6466
6553
  }
6467
6554
  function ensureGraphqlOperationNode(graph, serviceName, operationType, operationName) {
6468
- const id = (0, import_types9.graphqlOperationId)(serviceName, operationType, operationName);
6555
+ const id = (0, import_types10.graphqlOperationId)(serviceName, operationType, operationName);
6469
6556
  if (graph.hasNode(id)) return id;
6470
6557
  const node = {
6471
6558
  id,
6472
- type: import_types9.NodeType.GraphQLOperationNode,
6559
+ type: import_types10.NodeType.GraphQLOperationNode,
6473
6560
  name: operationName,
6474
6561
  service: serviceName,
6475
6562
  operationType: operationType.toLowerCase(),
@@ -6483,11 +6570,11 @@ function spanServesGrpcMethod(kind) {
6483
6570
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6484
6571
  }
6485
6572
  function ensureGrpcMethodNode(graph, rpcService, rpcMethod) {
6486
- const id = (0, import_types9.grpcMethodId)(rpcService, rpcMethod);
6573
+ const id = (0, import_types10.grpcMethodId)(rpcService, rpcMethod);
6487
6574
  if (graph.hasNode(id)) return id;
6488
6575
  const node = {
6489
6576
  id,
6490
- type: import_types9.NodeType.GrpcMethodNode,
6577
+ type: import_types10.NodeType.GrpcMethodNode,
6491
6578
  name: `${rpcService}/${rpcMethod}`,
6492
6579
  rpcService,
6493
6580
  rpcMethod,
@@ -6500,11 +6587,11 @@ function spanServesWebsocketChannel(kind) {
6500
6587
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6501
6588
  }
6502
6589
  function ensureWebsocketChannelNode(graph, serviceName, channel) {
6503
- const id = (0, import_types9.websocketChannelId)(serviceName, channel);
6590
+ const id = (0, import_types10.websocketChannelId)(serviceName, channel);
6504
6591
  if (graph.hasNode(id)) return id;
6505
6592
  const node = {
6506
6593
  id,
6507
- type: import_types9.NodeType.WebSocketChannelNode,
6594
+ type: import_types10.NodeType.WebSocketChannelNode,
6508
6595
  name: channel,
6509
6596
  service: serviceName,
6510
6597
  channel,
@@ -6517,11 +6604,11 @@ function messagingDestinationKind(system) {
6517
6604
  return `${system}-topic`;
6518
6605
  }
6519
6606
  function ensureMessagingDestinationNode(graph, system, destination) {
6520
- const id = (0, import_types9.infraId)(messagingDestinationKind(system), destination);
6607
+ const id = (0, import_types10.infraId)(messagingDestinationKind(system), destination);
6521
6608
  if (graph.hasNode(id)) return id;
6522
6609
  const node = {
6523
6610
  id,
6524
- type: import_types9.NodeType.InfraNode,
6611
+ type: import_types10.NodeType.InfraNode,
6525
6612
  name: destination,
6526
6613
  provider: "self",
6527
6614
  kind: messagingDestinationKind(system)
@@ -6565,9 +6652,9 @@ function lookupParentSpan(traceId, parentSpanId, now) {
6565
6652
  };
6566
6653
  }
6567
6654
  function resolveServiceId(graph, host, env) {
6568
- const envTagged = (0, import_types9.serviceId)(host, env);
6655
+ const envTagged = (0, import_types10.serviceId)(host, env);
6569
6656
  if (graph.hasNode(envTagged)) return envTagged;
6570
- const envLess = (0, import_types9.serviceId)(host);
6657
+ const envLess = (0, import_types10.serviceId)(host);
6571
6658
  if (envLess !== envTagged && graph.hasNode(envLess)) return envLess;
6572
6659
  let sameEnv = null;
6573
6660
  let envLessMatch = null;
@@ -6575,7 +6662,7 @@ function resolveServiceId(graph, host, env) {
6575
6662
  graph.forEachNode((id, attrs) => {
6576
6663
  if (sameEnv) return;
6577
6664
  const a = attrs;
6578
- if (a.type !== import_types9.NodeType.ServiceNode) return;
6665
+ if (a.type !== import_types10.NodeType.ServiceNode) return;
6579
6666
  const matchesByName = a.name === host;
6580
6667
  const matchesByAlias = a.aliases ? a.aliases.includes(host) : false;
6581
6668
  if (!matchesByName && !matchesByAlias) return;
@@ -6590,14 +6677,14 @@ function resolveServiceId(graph, host, env) {
6590
6677
  return sameEnv ?? envLessMatch ?? anyMatch;
6591
6678
  }
6592
6679
  function frontierIdFor(host) {
6593
- return (0, import_types9.frontierId)(host);
6680
+ return (0, import_types10.frontierId)(host);
6594
6681
  }
6595
6682
  function resolveFusedServiceId(graph, serviceName, env) {
6596
- const id = (0, import_types9.serviceId)(serviceName, env);
6683
+ const id = (0, import_types10.serviceId)(serviceName, env);
6597
6684
  if (graph.hasNode(id)) return id;
6598
6685
  const wanted = serviceName.toLowerCase();
6599
6686
  const extractedId = graph.findNode((_nid, attrs) => {
6600
- if (attrs.type !== import_types9.NodeType.ServiceNode) return false;
6687
+ if (attrs.type !== import_types10.NodeType.ServiceNode) return false;
6601
6688
  const svc = attrs;
6602
6689
  if (svc.discoveredVia === "otel") return false;
6603
6690
  return typeof svc.name === "string" && svc.name.toLowerCase() === wanted;
@@ -6609,7 +6696,7 @@ function ensureServiceNode(graph, serviceName, env) {
6609
6696
  if (graph.hasNode(resolved)) return resolved;
6610
6697
  const node = {
6611
6698
  id: resolved,
6612
- type: import_types9.NodeType.ServiceNode,
6699
+ type: import_types10.NodeType.ServiceNode,
6613
6700
  name: serviceName,
6614
6701
  language: "unknown",
6615
6702
  discoveredVia: "otel",
@@ -6619,11 +6706,11 @@ function ensureServiceNode(graph, serviceName, env) {
6619
6706
  return resolved;
6620
6707
  }
6621
6708
  function ensureInfraNode(graph, kind, name, provider) {
6622
- const id = (0, import_types9.infraId)(kind, name);
6709
+ const id = (0, import_types10.infraId)(kind, name);
6623
6710
  if (graph.hasNode(id)) return id;
6624
6711
  const node = {
6625
6712
  id,
6626
- type: import_types9.NodeType.InfraNode,
6713
+ type: import_types10.NodeType.InfraNode,
6627
6714
  name,
6628
6715
  provider,
6629
6716
  kind
@@ -6635,7 +6722,7 @@ var COLUMN_BEARING_INFRA_KINDS = /* @__PURE__ */ new Set(["sql-table", "supabase
6635
6722
  function mergeColumnsAt(graph, tableNodeId, columns, provenance2, confidence) {
6636
6723
  if (!columns || columns.length === 0 || !graph.hasNode(tableNodeId)) return;
6637
6724
  const node = graph.getNodeAttributes(tableNodeId);
6638
- if (node.type !== import_types9.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
6725
+ if (node.type !== import_types10.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
6639
6726
  return;
6640
6727
  }
6641
6728
  graph.replaceNodeAttributes(tableNodeId, {
@@ -6644,7 +6731,7 @@ function mergeColumnsAt(graph, tableNodeId, columns, provenance2, confidence) {
6644
6731
  });
6645
6732
  }
6646
6733
  function mergeObservedColumns(graph, tableNodeId, columns) {
6647
- mergeColumnsAt(graph, tableNodeId, columns, import_types9.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
6734
+ mergeColumnsAt(graph, tableNodeId, columns, import_types10.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
6648
6735
  }
6649
6736
  function mergeObservedDeployState(graph, serviceNodeId, state) {
6650
6737
  if (!graph.hasNode(serviceNodeId)) return;
@@ -6655,11 +6742,11 @@ function mergeObservedDeployState(graph, serviceNodeId, state) {
6655
6742
  graph.mergeNodeAttributes(serviceNodeId, attrs);
6656
6743
  }
6657
6744
  function ensureDatabaseNode(graph, host, engine) {
6658
- const id = (0, import_types9.databaseId)(host);
6745
+ const id = (0, import_types10.databaseId)(host);
6659
6746
  if (graph.hasNode(id)) return id;
6660
6747
  const node = {
6661
6748
  id,
6662
- type: import_types9.NodeType.DatabaseNode,
6749
+ type: import_types10.NodeType.DatabaseNode,
6663
6750
  name: host,
6664
6751
  engine,
6665
6752
  engineVersion: "unknown",
@@ -6671,11 +6758,11 @@ function ensureDatabaseNode(graph, host, engine) {
6671
6758
  return id;
6672
6759
  }
6673
6760
  function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
6674
- const id = (0, import_types9.localDatabaseId)(serviceName, name);
6761
+ const id = (0, import_types10.localDatabaseId)(serviceName, name);
6675
6762
  if (graph.hasNode(id)) return id;
6676
6763
  const node = {
6677
6764
  id,
6678
- type: import_types9.NodeType.DatabaseNode,
6765
+ type: import_types10.NodeType.DatabaseNode,
6679
6766
  name,
6680
6767
  engine,
6681
6768
  engineVersion: "unknown",
@@ -6690,17 +6777,17 @@ function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
6690
6777
  const sources = [serviceNodeId];
6691
6778
  for (const edgeId of graph.outboundEdges(serviceNodeId)) {
6692
6779
  const e = graph.getEdgeAttributes(edgeId);
6693
- if (e.type === import_types9.EdgeType.CONTAINS) sources.push(e.target);
6780
+ if (e.type === import_types10.EdgeType.CONTAINS) sources.push(e.target);
6694
6781
  }
6695
6782
  const matches = /* @__PURE__ */ new Set();
6696
6783
  for (const src of sources) {
6697
6784
  if (!graph.hasNode(src)) continue;
6698
6785
  for (const edgeId of graph.outboundEdges(src)) {
6699
6786
  const edge = graph.getEdgeAttributes(edgeId);
6700
- if (edge.type !== import_types9.EdgeType.CONNECTS_TO || edge.provenance !== import_types9.Provenance.EXTRACTED) continue;
6787
+ if (edge.type !== import_types10.EdgeType.CONNECTS_TO || edge.provenance !== import_types10.Provenance.EXTRACTED) continue;
6701
6788
  if (!graph.hasNode(edge.target)) continue;
6702
6789
  const target = graph.getNodeAttributes(edge.target);
6703
- if (target.type !== import_types9.NodeType.DatabaseNode || target.engine !== engine) continue;
6790
+ if (target.type !== import_types10.NodeType.DatabaseNode || target.engine !== engine) continue;
6704
6791
  matches.add(edge.target);
6705
6792
  }
6706
6793
  }
@@ -6715,7 +6802,7 @@ function ensureFrontierNode(graph, host, ts) {
6715
6802
  }
6716
6803
  const node = {
6717
6804
  id,
6718
- type: import_types9.NodeType.FrontierNode,
6805
+ type: import_types10.NodeType.FrontierNode,
6719
6806
  name: host,
6720
6807
  host,
6721
6808
  firstObserved: ts,
@@ -6768,11 +6855,11 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
6768
6855
  };
6769
6856
  const updated = {
6770
6857
  ...existing,
6771
- provenance: import_types9.Provenance.OBSERVED,
6858
+ provenance: import_types10.Provenance.OBSERVED,
6772
6859
  lastObserved: ts,
6773
6860
  callCount: newSpanCount,
6774
6861
  signal: newSignal,
6775
- confidence: (0, import_types9.confidenceForObservedSignal)(newSignal),
6862
+ confidence: (0, import_types10.confidenceForObservedSignal)(newSignal),
6776
6863
  grain
6777
6864
  // backfills legacy edges that predate ADR-142
6778
6865
  };
@@ -6795,8 +6882,8 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
6795
6882
  source,
6796
6883
  target,
6797
6884
  type,
6798
- provenance: import_types9.Provenance.OBSERVED,
6799
- confidence: (0, import_types9.confidenceForObservedSignal)(signal),
6885
+ provenance: import_types10.Provenance.OBSERVED,
6886
+ confidence: (0, import_types10.confidenceForObservedSignal)(signal),
6800
6887
  lastObserved: ts,
6801
6888
  callCount: 1,
6802
6889
  signal,
@@ -6818,9 +6905,9 @@ function stitchTrace(graph, sourceServiceId, ts) {
6818
6905
  const outbound = graph.outboundEdges(nodeId);
6819
6906
  for (const edgeId of outbound) {
6820
6907
  const edge = graph.getEdgeAttributes(edgeId);
6821
- if (edge.provenance !== import_types9.Provenance.EXTRACTED) continue;
6908
+ if (edge.provenance !== import_types10.Provenance.EXTRACTED) continue;
6822
6909
  if (!STITCH_EDGE_TYPES.has(edge.type)) continue;
6823
- if (graph.hasEdge((0, import_types9.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
6910
+ if (graph.hasEdge((0, import_types10.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
6824
6911
  upsertInferredEdge(graph, edge.type, edge.source, edge.target, ts);
6825
6912
  if (!visited.has(edge.target)) {
6826
6913
  visited.add(edge.target);
@@ -6842,7 +6929,7 @@ function upsertInferredEdge(graph, type, source, target, ts) {
6842
6929
  source,
6843
6930
  target,
6844
6931
  type,
6845
- provenance: import_types9.Provenance.INFERRED,
6932
+ provenance: import_types10.Provenance.INFERRED,
6846
6933
  confidence: INFERRED_CONFIDENCE,
6847
6934
  lastObserved: ts
6848
6935
  };
@@ -6856,7 +6943,7 @@ function emitIncidentEvent(project, ev) {
6856
6943
  incidentId: ev.id,
6857
6944
  affectedNode: ev.affectedNode,
6858
6945
  service: ev.service,
6859
- incidentKind: (0, import_types9.incidentKindOf)(ev),
6946
+ incidentKind: (0, import_types10.incidentKindOf)(ev),
6860
6947
  at: ev.timestamp
6861
6948
  }
6862
6949
  });
@@ -6885,7 +6972,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
6885
6972
  const canonicalService = serviceNodeName(graph, span) ?? span.service;
6886
6973
  const recovered = !trusted;
6887
6974
  if (graph) {
6888
- const fusedFileId = (0, import_types9.fileId)(canonicalService, relPath);
6975
+ const fusedFileId = (0, import_types10.fileId)(canonicalService, relPath);
6889
6976
  if (graph.hasNode(fusedFileId)) {
6890
6977
  const node = landObservedSymbol(
6891
6978
  graph,
@@ -6905,7 +6992,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
6905
6992
  }
6906
6993
  if (recovered) return null;
6907
6994
  }
6908
- return { affectedNode: (0, import_types9.fileId)(span.service, relPath) };
6995
+ return { affectedNode: (0, import_types10.fileId)(span.service, relPath) };
6909
6996
  }
6910
6997
  function serviceNodeName(graph, span) {
6911
6998
  if (!graph) return void 0;
@@ -6922,7 +7009,7 @@ function stacktraceCallSite(span, serviceNode, scanPath) {
6922
7009
  return { relPath, line: frame.line, ...frame.fn ? { fn: frame.fn } : {} };
6923
7010
  }
6924
7011
  function incidentLocus(span, graph, scanPath) {
6925
- const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types9.serviceId)(span.service, span.env);
7012
+ const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types10.serviceId)(span.service, span.env);
6926
7013
  const serviceNode = graph && graph.hasNode(sid) ? graph.getNodeAttributes(sid) : void 0;
6927
7014
  const callSite = callSiteFromSpan(span, serviceNode, scanPath);
6928
7015
  if (callSite) {
@@ -7113,7 +7200,7 @@ function findRouteNodeByHttpRoute(graph, serviceName, method, httpRoute) {
7113
7200
  graph.forEachNode((id, attrs) => {
7114
7201
  if (found) return;
7115
7202
  const a = attrs;
7116
- if (a.type !== import_types9.NodeType.RouteNode || a.service !== serviceName) return;
7203
+ if (a.type !== import_types10.NodeType.RouteNode || a.service !== serviceName) return;
7117
7204
  if (m && a.method !== "ALL" && a.method !== m) return;
7118
7205
  if (normalizePathTemplate(a.pathTemplate) === target) found = id;
7119
7206
  });
@@ -7146,7 +7233,7 @@ async function handleSpan(ctx, span) {
7146
7233
  let targetId;
7147
7234
  if (host) {
7148
7235
  ensureDatabaseNode(ctx.graph, host, span.dbSystem);
7149
- targetId = (0, import_types9.databaseId)(host);
7236
+ targetId = (0, import_types10.databaseId)(host);
7150
7237
  } else {
7151
7238
  const declared = findDeclaredDatabaseForService(ctx.graph, sourceId, span.dbSystem);
7152
7239
  if (declared) {
@@ -7163,7 +7250,7 @@ async function handleSpan(ctx, span) {
7163
7250
  }
7164
7251
  const result = upsertObservedEdge(
7165
7252
  ctx.graph,
7166
- import_types9.EdgeType.CONNECTS_TO,
7253
+ import_types10.EdgeType.CONNECTS_TO,
7167
7254
  observedSource(),
7168
7255
  targetId,
7169
7256
  ts,
@@ -7177,7 +7264,7 @@ async function handleSpan(ctx, span) {
7177
7264
  const collectionId = ensureInfraNode(ctx.graph, "mongodb-collection", span.dbCollection, "self");
7178
7265
  upsertObservedEdge(
7179
7266
  ctx.graph,
7180
- import_types9.EdgeType.CALLS,
7267
+ import_types10.EdgeType.CALLS,
7181
7268
  observedSource(),
7182
7269
  collectionId,
7183
7270
  ts,
@@ -7191,7 +7278,7 @@ async function handleSpan(ctx, span) {
7191
7278
  const tableId = ensureInfraNode(ctx.graph, "sql-table", span.dbTable, "self");
7192
7279
  upsertObservedEdge(
7193
7280
  ctx.graph,
7194
- import_types9.EdgeType.CALLS,
7281
+ import_types10.EdgeType.CALLS,
7195
7282
  observedSource(),
7196
7283
  tableId,
7197
7284
  ts,
@@ -7209,7 +7296,7 @@ async function handleSpan(ctx, span) {
7209
7296
  span.messagingSystem,
7210
7297
  span.messagingDestination
7211
7298
  );
7212
- const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types9.EdgeType.CONSUMES_FROM : import_types9.EdgeType.PUBLISHES_TO;
7299
+ const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types10.EdgeType.CONSUMES_FROM : import_types10.EdgeType.PUBLISHES_TO;
7213
7300
  const result = upsertObservedEdge(
7214
7301
  ctx.graph,
7215
7302
  edgeType,
@@ -7231,7 +7318,7 @@ async function handleSpan(ctx, span) {
7231
7318
  );
7232
7319
  const result = upsertObservedEdge(
7233
7320
  ctx.graph,
7234
- import_types9.EdgeType.CONTAINS,
7321
+ import_types10.EdgeType.CONTAINS,
7235
7322
  observedSource(),
7236
7323
  targetId,
7237
7324
  ts,
@@ -7245,7 +7332,7 @@ async function handleSpan(ctx, span) {
7245
7332
  const targetId = ensureGrpcMethodNode(ctx.graph, span.rpcService, span.rpcMethod);
7246
7333
  const result = upsertObservedEdge(
7247
7334
  ctx.graph,
7248
- import_types9.EdgeType.CONTAINS,
7335
+ import_types10.EdgeType.CONTAINS,
7249
7336
  observedSource(),
7250
7337
  targetId,
7251
7338
  ts,
@@ -7263,7 +7350,7 @@ async function handleSpan(ctx, span) {
7263
7350
  );
7264
7351
  const result = upsertObservedEdge(
7265
7352
  ctx.graph,
7266
- import_types9.EdgeType.CONNECTS_TO,
7353
+ import_types10.EdgeType.CONNECTS_TO,
7267
7354
  observedSource(),
7268
7355
  targetId,
7269
7356
  ts,
@@ -7281,7 +7368,7 @@ async function handleSpan(ctx, span) {
7281
7368
  if (targetId && targetId !== sourceId) {
7282
7369
  upsertObservedEdge(
7283
7370
  ctx.graph,
7284
- import_types9.EdgeType.CALLS,
7371
+ import_types10.EdgeType.CALLS,
7285
7372
  observedSource(),
7286
7373
  targetId,
7287
7374
  ts,
@@ -7296,7 +7383,7 @@ async function handleSpan(ctx, span) {
7296
7383
  const frontierNodeId = ensureFrontierNode(ctx.graph, host, ts);
7297
7384
  upsertObservedEdge(
7298
7385
  ctx.graph,
7299
- import_types9.EdgeType.CALLS,
7386
+ import_types10.EdgeType.CALLS,
7300
7387
  observedSource(),
7301
7388
  frontierNodeId,
7302
7389
  ts,
@@ -7324,7 +7411,7 @@ async function handleSpan(ctx, span) {
7324
7411
  } : void 0;
7325
7412
  upsertObservedEdge(
7326
7413
  ctx.graph,
7327
- import_types9.EdgeType.CALLS,
7414
+ import_types10.EdgeType.CALLS,
7328
7415
  fallbackSource,
7329
7416
  sourceId,
7330
7417
  ts,
@@ -7346,7 +7433,7 @@ async function handleSpan(ctx, span) {
7346
7433
  );
7347
7434
  if (routeNodeId) {
7348
7435
  const routeSvc = ctx.graph.getNodeAttributes(routeNodeId).service;
7349
- upsertObservedEdge(ctx.graph, import_types9.EdgeType.CONTAINS, (0, import_types9.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
7436
+ upsertObservedEdge(ctx.graph, import_types10.EdgeType.CONTAINS, (0, import_types10.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
7350
7437
  }
7351
7438
  }
7352
7439
  if (span.statusCode === 2) {
@@ -7376,7 +7463,7 @@ function promoteFrontierNodes(graph, opts = {}) {
7376
7463
  const aliasIndex = /* @__PURE__ */ new Map();
7377
7464
  graph.forEachNode((id, attrs) => {
7378
7465
  const a = attrs;
7379
- if (a.type !== import_types9.NodeType.ServiceNode) return;
7466
+ if (a.type !== import_types10.NodeType.ServiceNode) return;
7380
7467
  aliasIndex.set(a.name, id);
7381
7468
  if (a.aliases) {
7382
7469
  for (const alias of a.aliases) aliasIndex.set(alias, id);
@@ -7385,7 +7472,7 @@ function promoteFrontierNodes(graph, opts = {}) {
7385
7472
  const toPromote = [];
7386
7473
  graph.forEachNode((id, attrs) => {
7387
7474
  const a = attrs;
7388
- if (a.type !== import_types9.NodeType.FrontierNode) return;
7475
+ if (a.type !== import_types10.NodeType.FrontierNode) return;
7389
7476
  const target = aliasIndex.get(a.host);
7390
7477
  if (!target) return;
7391
7478
  if (target === id) return;
@@ -7407,15 +7494,15 @@ function promoteFrontierNodes(graph, opts = {}) {
7407
7494
  }
7408
7495
  function stageFrontierEdge(graph, source, target, type) {
7409
7496
  if (!graph.hasNode(source) || !graph.hasNode(target)) return false;
7410
- if (graph.hasEdge((0, import_types9.observedEdgeId)(source, target, type))) return false;
7411
- const key = (0, import_types9.frontierEdgeId)(source, target, type);
7497
+ if (graph.hasEdge((0, import_types10.observedEdgeId)(source, target, type))) return false;
7498
+ const key = (0, import_types10.frontierEdgeId)(source, target, type);
7412
7499
  if (graph.hasEdge(key)) return false;
7413
7500
  graph.addEdgeWithKey(key, source, target, {
7414
7501
  id: key,
7415
7502
  source,
7416
7503
  target,
7417
7504
  type,
7418
- provenance: import_types9.Provenance.FRONTIER
7505
+ provenance: import_types10.Provenance.FRONTIER
7419
7506
  });
7420
7507
  return true;
7421
7508
  }
@@ -7423,8 +7510,8 @@ function promoteFrontierEdges(graph) {
7423
7510
  const graduated = [];
7424
7511
  graph.forEachEdge((edgeId, attrs) => {
7425
7512
  const e = attrs;
7426
- if (e.provenance !== import_types9.Provenance.FRONTIER) return;
7427
- if (graph.hasEdge((0, import_types9.observedEdgeId)(e.source, e.target, e.type))) {
7513
+ if (e.provenance !== import_types10.Provenance.FRONTIER) return;
7514
+ if (graph.hasEdge((0, import_types10.observedEdgeId)(e.source, e.target, e.type))) {
7428
7515
  graduated.push(edgeId);
7429
7516
  }
7430
7517
  });
@@ -7445,7 +7532,7 @@ function rewireFrontierEdges(graph, frontierId2, serviceId17) {
7445
7532
  }
7446
7533
  function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
7447
7534
  graph.dropEdge(oldEdgeId);
7448
- const newId = edge.provenance === import_types9.Provenance.OBSERVED ? (0, import_types9.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types9.Provenance.INFERRED ? (0, import_types9.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types9.extractedEdgeId)(newSource, newTarget, edge.type);
7535
+ const newId = edge.provenance === import_types10.Provenance.OBSERVED ? (0, import_types10.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types10.Provenance.INFERRED ? (0, import_types10.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types10.extractedEdgeId)(newSource, newTarget, edge.type);
7449
7536
  if (graph.hasEdge(newId)) {
7450
7537
  const existing = graph.getEdgeAttributes(newId);
7451
7538
  const merged = {
@@ -7479,12 +7566,12 @@ async function markStaleEdges(graph, options = {}) {
7479
7566
  const project = options.project ?? DEFAULT_PROJECT;
7480
7567
  graph.forEachEdge((id, attrs) => {
7481
7568
  const e = attrs;
7482
- if (e.provenance !== import_types9.Provenance.OBSERVED) return;
7569
+ if (e.provenance !== import_types10.Provenance.OBSERVED) return;
7483
7570
  if (!e.lastObserved) return;
7484
7571
  const threshold = thresholdForEdgeType(e.type, thresholds);
7485
7572
  const age = now - new Date(e.lastObserved).getTime();
7486
7573
  if (age > threshold) {
7487
- const updated = { ...e, provenance: import_types9.Provenance.STALE, confidence: 0.3 };
7574
+ const updated = { ...e, provenance: import_types10.Provenance.STALE, confidence: 0.3 };
7488
7575
  graph.replaceEdgeAttributes(id, updated);
7489
7576
  events.push({
7490
7577
  edgeId: id,
@@ -7501,8 +7588,8 @@ async function markStaleEdges(graph, options = {}) {
7501
7588
  project,
7502
7589
  payload: {
7503
7590
  edgeId: id,
7504
- from: import_types9.Provenance.OBSERVED,
7505
- to: import_types9.Provenance.STALE
7591
+ from: import_types10.Provenance.OBSERVED,
7592
+ to: import_types10.Provenance.STALE
7506
7593
  }
7507
7594
  });
7508
7595
  }
@@ -7650,6 +7737,7 @@ function describeZodIssues(error2) {
7650
7737
  return error2.issues.map((issue) => issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message).join("; ");
7651
7738
  }
7652
7739
  function mergeSnapshot(graph, snapshot) {
7740
+ invalidateSourceBaseline(graph);
7653
7741
  const exported = snapshot.graph;
7654
7742
  const incomingNodes = Array.isArray(exported.nodes) ? exported.nodes : [];
7655
7743
  const incomingEdges = Array.isArray(exported.edges) ? exported.edges : [];
@@ -7658,7 +7746,7 @@ function mergeSnapshot(graph, snapshot) {
7658
7746
  const validEdges = [];
7659
7747
  for (const node of incomingNodes) {
7660
7748
  if (node.attributes === void 0) continue;
7661
- const parsed = import_types9.GraphNodeSchema.safeParse(node.attributes);
7749
+ const parsed = import_types10.GraphNodeSchema.safeParse(node.attributes);
7662
7750
  if (!parsed.success) {
7663
7751
  issues.push(`node "${node.key}": ${describeZodIssues(parsed.error)}`);
7664
7752
  continue;
@@ -7667,7 +7755,7 @@ function mergeSnapshot(graph, snapshot) {
7667
7755
  }
7668
7756
  for (const edge of incomingEdges) {
7669
7757
  if (edge.attributes === void 0) continue;
7670
- const parsed = import_types9.GraphEdgeSchema.safeParse(edge.attributes);
7758
+ const parsed = import_types10.GraphEdgeSchema.safeParse(edge.attributes);
7671
7759
  if (!parsed.success) {
7672
7760
  const label = edge.key ?? `${edge.source}->${edge.target}`;
7673
7761
  issues.push(`edge "${label}": ${describeZodIssues(parsed.error)}`);
@@ -7701,7 +7789,7 @@ var import_node_fs21 = require("fs");
7701
7789
  var import_node_path23 = __toESM(require("path"), 1);
7702
7790
  var import_ignore2 = __toESM(require("ignore"), 1);
7703
7791
  var import_minimatch2 = require("minimatch");
7704
- var import_types19 = require("@neat.is/types");
7792
+ var import_types20 = require("@neat.is/types");
7705
7793
 
7706
7794
  // src/extract/python.ts
7707
7795
  init_cjs_shims();
@@ -7774,7 +7862,7 @@ function pythonToPackage(service) {
7774
7862
  init_cjs_shims();
7775
7863
  var import_node_fs12 = require("fs");
7776
7864
  var import_node_path13 = __toESM(require("path"), 1);
7777
- var import_types10 = require("@neat.is/types");
7865
+ var import_types11 = require("@neat.is/types");
7778
7866
  function parseGoMod(source) {
7779
7867
  const module2 = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
7780
7868
  if (!module2) return null;
@@ -7810,8 +7898,8 @@ async function discoverGoService(scanPath, dir) {
7810
7898
  const pkg = { name, dependencies: mod.dependencies };
7811
7899
  const framework = goFramework(mod.dependencies);
7812
7900
  const node = {
7813
- id: (0, import_types10.serviceId)(name),
7814
- type: import_types10.NodeType.ServiceNode,
7901
+ id: (0, import_types11.serviceId)(name),
7902
+ type: import_types11.NodeType.ServiceNode,
7815
7903
  name,
7816
7904
  language: "go",
7817
7905
  dependencies: mod.dependencies,
@@ -7825,7 +7913,7 @@ async function discoverGoService(scanPath, dir) {
7825
7913
  init_cjs_shims();
7826
7914
  var import_node_fs13 = require("fs");
7827
7915
  var import_node_path14 = __toESM(require("path"), 1);
7828
- var import_types11 = require("@neat.is/types");
7916
+ var import_types12 = require("@neat.is/types");
7829
7917
  function parseGemfile(source) {
7830
7918
  const dependencies = {};
7831
7919
  for (const raw of source.split(/\r?\n/)) {
@@ -7849,8 +7937,8 @@ async function discoverRubyService(scanPath, dir) {
7849
7937
  const name = import_node_path14.default.basename(dir);
7850
7938
  const pkg = { name, dependencies: gemfile.dependencies };
7851
7939
  const node = {
7852
- id: (0, import_types11.serviceId)(name),
7853
- type: import_types11.NodeType.ServiceNode,
7940
+ id: (0, import_types12.serviceId)(name),
7941
+ type: import_types12.NodeType.ServiceNode,
7854
7942
  name,
7855
7943
  language: "ruby",
7856
7944
  dependencies: gemfile.dependencies,
@@ -7863,7 +7951,7 @@ async function discoverRubyService(scanPath, dir) {
7863
7951
  // src/extract/php.ts
7864
7952
  init_cjs_shims();
7865
7953
  var import_node_path15 = __toESM(require("path"), 1);
7866
- var import_types12 = require("@neat.is/types");
7954
+ var import_types13 = require("@neat.is/types");
7867
7955
  function parseComposerJson(composer) {
7868
7956
  return {
7869
7957
  dependencies: {
@@ -7883,8 +7971,8 @@ async function discoverPhpService(scanPath, dir) {
7883
7971
  const name = import_node_path15.default.basename(dir);
7884
7972
  const pkg = { name, dependencies };
7885
7973
  const node = {
7886
- id: (0, import_types12.serviceId)(name),
7887
- type: import_types12.NodeType.ServiceNode,
7974
+ id: (0, import_types13.serviceId)(name),
7975
+ type: import_types13.NodeType.ServiceNode,
7888
7976
  name,
7889
7977
  language: "php",
7890
7978
  dependencies,
@@ -7898,7 +7986,7 @@ async function discoverPhpService(scanPath, dir) {
7898
7986
  init_cjs_shims();
7899
7987
  var import_node_fs14 = require("fs");
7900
7988
  var import_node_path16 = __toESM(require("path"), 1);
7901
- var import_types13 = require("@neat.is/types");
7989
+ var import_types14 = require("@neat.is/types");
7902
7990
  var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
7903
7991
  async function projectFiles(dir) {
7904
7992
  const entries = await import_node_fs14.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
@@ -7945,8 +8033,8 @@ async function discoverCsharpService(scanPath, dir) {
7945
8033
  }
7946
8034
  const pkg = { name, dependencies };
7947
8035
  const node = {
7948
- id: (0, import_types13.serviceId)(name),
7949
- type: import_types13.NodeType.ServiceNode,
8036
+ id: (0, import_types14.serviceId)(name),
8037
+ type: import_types14.NodeType.ServiceNode,
7950
8038
  name,
7951
8039
  language: "csharp",
7952
8040
  dependencies,
@@ -7961,7 +8049,7 @@ async function discoverCsharpService(scanPath, dir) {
7961
8049
  init_cjs_shims();
7962
8050
  var import_node_fs15 = require("fs");
7963
8051
  var import_node_path17 = __toESM(require("path"), 1);
7964
- var import_types14 = require("@neat.is/types");
8052
+ var import_types15 = require("@neat.is/types");
7965
8053
  var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
7966
8054
  async function hasJavaManifest(dir) {
7967
8055
  for (const manifest of JAVA_MANIFESTS) {
@@ -8016,8 +8104,8 @@ async function discoverJavaService(scanPath, dir) {
8016
8104
  const dependencies = manifest.dependencies;
8017
8105
  const pkg = { name, dependencies };
8018
8106
  const node = {
8019
- id: (0, import_types14.serviceId)(name),
8020
- type: import_types14.NodeType.ServiceNode,
8107
+ id: (0, import_types15.serviceId)(name),
8108
+ type: import_types15.NodeType.ServiceNode,
8021
8109
  name,
8022
8110
  language: "java",
8023
8111
  dependencies,
@@ -8030,7 +8118,7 @@ async function discoverJavaService(scanPath, dir) {
8030
8118
  init_cjs_shims();
8031
8119
  var import_node_fs16 = require("fs");
8032
8120
  var import_node_path18 = __toESM(require("path"), 1);
8033
- var import_types15 = require("@neat.is/types");
8121
+ var import_types16 = require("@neat.is/types");
8034
8122
  var KOTLIN_SOURCE_EXT = ".kt";
8035
8123
  var JAVA_SOURCE_EXT = ".java";
8036
8124
  var SOURCE_PROBE_MAX_DEPTH = 8;
@@ -8081,8 +8169,8 @@ async function discoverKotlinService(scanPath, dir) {
8081
8169
  const dependencies = manifest.dependencies;
8082
8170
  const pkg = { name, dependencies };
8083
8171
  const node = {
8084
- id: (0, import_types15.serviceId)(name),
8085
- type: import_types15.NodeType.ServiceNode,
8172
+ id: (0, import_types16.serviceId)(name),
8173
+ type: import_types16.NodeType.ServiceNode,
8086
8174
  name,
8087
8175
  language: "kotlin",
8088
8176
  dependencies,
@@ -8096,7 +8184,7 @@ init_cjs_shims();
8096
8184
  var import_node_fs17 = require("fs");
8097
8185
  var import_node_path19 = __toESM(require("path"), 1);
8098
8186
  var import_smol_toml2 = require("smol-toml");
8099
- var import_types16 = require("@neat.is/types");
8187
+ var import_types17 = require("@neat.is/types");
8100
8188
  var CARGO_MANIFEST = "Cargo.toml";
8101
8189
  async function hasRustManifest(dir) {
8102
8190
  return exists(import_node_path19.default.join(dir, CARGO_MANIFEST));
@@ -8131,8 +8219,8 @@ async function discoverRustService(scanPath, dir) {
8131
8219
  const dependencies = manifest.dependencies;
8132
8220
  const pkg = { name, dependencies };
8133
8221
  const node = {
8134
- id: (0, import_types16.serviceId)(name),
8135
- type: import_types16.NodeType.ServiceNode,
8222
+ id: (0, import_types17.serviceId)(name),
8223
+ type: import_types17.NodeType.ServiceNode,
8136
8224
  name,
8137
8225
  language: "rust",
8138
8226
  dependencies,
@@ -8145,7 +8233,7 @@ async function discoverRustService(scanPath, dir) {
8145
8233
  init_cjs_shims();
8146
8234
  var import_node_fs18 = require("fs");
8147
8235
  var import_node_path20 = __toESM(require("path"), 1);
8148
- var import_types17 = require("@neat.is/types");
8236
+ var import_types18 = require("@neat.is/types");
8149
8237
  var CMAKE_MANIFEST = "CMakeLists.txt";
8150
8238
  async function hasCppManifest(dir) {
8151
8239
  return exists(import_node_path20.default.join(dir, CMAKE_MANIFEST));
@@ -8163,8 +8251,8 @@ async function discoverCppService(scanPath, dir) {
8163
8251
  const dependencies = {};
8164
8252
  const pkg = { name, dependencies };
8165
8253
  const node = {
8166
- id: (0, import_types17.serviceId)(name),
8167
- type: import_types17.NodeType.ServiceNode,
8254
+ id: (0, import_types18.serviceId)(name),
8255
+ type: import_types18.NodeType.ServiceNode,
8168
8256
  name,
8169
8257
  language: "cpp",
8170
8258
  dependencies,
@@ -8177,7 +8265,7 @@ async function discoverCppService(scanPath, dir) {
8177
8265
  init_cjs_shims();
8178
8266
  var import_node_fs19 = require("fs");
8179
8267
  var import_node_path21 = __toESM(require("path"), 1);
8180
- var import_types18 = require("@neat.is/types");
8268
+ var import_types19 = require("@neat.is/types");
8181
8269
  function languageForSourceExt(ext) {
8182
8270
  switch (ext) {
8183
8271
  case ".py":
@@ -8263,8 +8351,8 @@ async function discoverDockerfileService(scanPath, dir) {
8263
8351
  const name = import_node_path21.default.basename(dir);
8264
8352
  const pkg = { name, dependencies: {} };
8265
8353
  const node = {
8266
- id: (0, import_types18.serviceId)(name),
8267
- type: import_types18.NodeType.ServiceNode,
8354
+ id: (0, import_types19.serviceId)(name),
8355
+ type: import_types19.NodeType.ServiceNode,
8268
8356
  name,
8269
8357
  language,
8270
8358
  dependencies: {},
@@ -8458,8 +8546,8 @@ async function discoverNodeService(scanPath, dir) {
8458
8546
  const framework = detectJsFramework(pkg);
8459
8547
  const language = await detectJsServiceLanguage(dir, pkg);
8460
8548
  const node = {
8461
- id: (0, import_types19.serviceId)(pkg.name),
8462
- type: import_types19.NodeType.ServiceNode,
8549
+ id: (0, import_types20.serviceId)(pkg.name),
8550
+ type: import_types20.NodeType.ServiceNode,
8463
8551
  name: pkg.name,
8464
8552
  language,
8465
8553
  version: pkg.version,
@@ -8475,8 +8563,8 @@ async function discoverPyService(scanPath, dir) {
8475
8563
  if (!py) return null;
8476
8564
  const pkg = pythonToPackage(py);
8477
8565
  const node = {
8478
- id: (0, import_types19.serviceId)(py.name),
8479
- type: import_types19.NodeType.ServiceNode,
8566
+ id: (0, import_types20.serviceId)(py.name),
8567
+ type: import_types20.NodeType.ServiceNode,
8480
8568
  name: py.name,
8481
8569
  language: "python",
8482
8570
  version: py.version,
@@ -8595,7 +8683,7 @@ init_cjs_shims();
8595
8683
  var import_node_path24 = __toESM(require("path"), 1);
8596
8684
  var import_node_fs22 = require("fs");
8597
8685
  var import_yaml2 = require("yaml");
8598
- var import_types20 = require("@neat.is/types");
8686
+ var import_types21 = require("@neat.is/types");
8599
8687
  var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
8600
8688
  "Service",
8601
8689
  "Deployment",
@@ -8605,7 +8693,7 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
8605
8693
  function addAliases(graph, serviceId17, candidates) {
8606
8694
  if (!graph.hasNode(serviceId17)) return;
8607
8695
  const node = graph.getNodeAttributes(serviceId17);
8608
- if (node.type !== import_types20.NodeType.ServiceNode) return;
8696
+ if (node.type !== import_types21.NodeType.ServiceNode) return;
8609
8697
  const set = new Set(node.aliases ?? []);
8610
8698
  for (const c of candidates) {
8611
8699
  if (!c) continue;
@@ -8795,7 +8883,7 @@ var import_tree_sitter_java = __toESM(require("tree-sitter-java"), 1);
8795
8883
  var import_tree_sitter_kotlin = __toESM(require("tree-sitter-kotlin"), 1);
8796
8884
  var import_tree_sitter_rust2 = __toESM(require("tree-sitter-rust"), 1);
8797
8885
  var import_tree_sitter_cpp = __toESM(require("tree-sitter-cpp"), 1);
8798
- var import_types21 = require("@neat.is/types");
8886
+ var import_types22 = require("@neat.is/types");
8799
8887
  var PARSE_CHUNK3 = 16384;
8800
8888
  var GRAMMAR_BY_EXT = {
8801
8889
  ".ts": import_tree_sitter_typescript.default.typescript,
@@ -8848,7 +8936,9 @@ function collectSymbolDefs(root) {
8848
8936
  kind,
8849
8937
  qualname,
8850
8938
  startLine: node.startPosition.row + 1,
8851
- endLine: node.endPosition.row + 1
8939
+ endLine: node.endPosition.row + 1,
8940
+ startIndex: node.startIndex,
8941
+ endIndex: node.endIndex
8852
8942
  });
8853
8943
  };
8854
8944
  const visit = (node, classCtx) => {
@@ -8907,7 +8997,9 @@ function collectPythonSymbolDefs(root) {
8907
8997
  kind,
8908
8998
  qualname,
8909
8999
  startLine: node.startPosition.row + 1,
8910
- endLine: node.endPosition.row + 1
9000
+ endLine: node.endPosition.row + 1,
9001
+ startIndex: node.startIndex,
9002
+ endIndex: node.endIndex
8911
9003
  });
8912
9004
  };
8913
9005
  const visit = (node, classCtx) => {
@@ -8980,7 +9072,9 @@ function collectGoSymbolDefs(root) {
8980
9072
  kind,
8981
9073
  qualname,
8982
9074
  startLine: node.startPosition.row + 1,
8983
- endLine: node.endPosition.row + 1
9075
+ endLine: node.endPosition.row + 1,
9076
+ startIndex: node.startIndex,
9077
+ endIndex: node.endIndex
8984
9078
  });
8985
9079
  };
8986
9080
  const visit = (node) => {
@@ -9014,7 +9108,9 @@ function collectRubySymbolDefs(root) {
9014
9108
  kind,
9015
9109
  qualname,
9016
9110
  startLine: node.startPosition.row + 1,
9017
- endLine: node.endPosition.row + 1
9111
+ endLine: node.endPosition.row + 1,
9112
+ startIndex: node.startIndex,
9113
+ endIndex: node.endIndex
9018
9114
  });
9019
9115
  };
9020
9116
  const nameText = (node) => node.childForFieldName("name")?.text.replace(/::/g, ".");
@@ -9065,7 +9161,9 @@ function collectPhpSymbolDefs(root) {
9065
9161
  kind,
9066
9162
  qualname,
9067
9163
  startLine: node.startPosition.row + 1,
9068
- endLine: node.endPosition.row + 1
9164
+ endLine: node.endPosition.row + 1,
9165
+ startIndex: node.startIndex,
9166
+ endIndex: node.endIndex
9069
9167
  });
9070
9168
  };
9071
9169
  const dot = (s) => s.replace(/\\/g, ".").replace(/::/g, ".").replace(/^\.+/, "");
@@ -9131,7 +9229,9 @@ function collectCsharpSymbolDefs(root) {
9131
9229
  kind,
9132
9230
  qualname,
9133
9231
  startLine: node.startPosition.row + 1,
9134
- endLine: node.endPosition.row + 1
9232
+ endLine: node.endPosition.row + 1,
9233
+ startIndex: node.startIndex,
9234
+ endIndex: node.endIndex
9135
9235
  });
9136
9236
  };
9137
9237
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9193,7 +9293,9 @@ function collectJavaSymbolDefs(root) {
9193
9293
  kind,
9194
9294
  qualname,
9195
9295
  startLine: node.startPosition.row + 1,
9196
- endLine: node.endPosition.row + 1
9296
+ endLine: node.endPosition.row + 1,
9297
+ startIndex: node.startIndex,
9298
+ endIndex: node.endIndex
9197
9299
  });
9198
9300
  };
9199
9301
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9250,7 +9352,9 @@ function collectKotlinSymbolDefs(root) {
9250
9352
  kind,
9251
9353
  qualname,
9252
9354
  startLine: node.startPosition.row + 1,
9253
- endLine: node.endPosition.row + 1
9355
+ endLine: node.endPosition.row + 1,
9356
+ startIndex: node.startIndex,
9357
+ endIndex: node.endIndex
9254
9358
  });
9255
9359
  };
9256
9360
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9320,7 +9424,9 @@ function collectRustSymbolDefs(root) {
9320
9424
  kind,
9321
9425
  qualname,
9322
9426
  startLine: node.startPosition.row + 1,
9323
- endLine: node.endPosition.row + 1
9427
+ endLine: node.endPosition.row + 1,
9428
+ startIndex: node.startIndex,
9429
+ endIndex: node.endIndex
9324
9430
  });
9325
9431
  };
9326
9432
  const join2 = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -9388,7 +9494,9 @@ function collectCppSymbolDefs(root) {
9388
9494
  kind,
9389
9495
  qualname,
9390
9496
  startLine: node.startPosition.row + 1,
9391
- endLine: node.endPosition.row + 1
9497
+ endLine: node.endPosition.row + 1,
9498
+ startIndex: node.startIndex,
9499
+ endIndex: node.endIndex
9392
9500
  });
9393
9501
  };
9394
9502
  const join2 = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -9516,6 +9624,22 @@ function disambiguate(defs) {
9516
9624
  return { def, disambiguator: ordinal };
9517
9625
  });
9518
9626
  }
9627
+ function utf8Offsets(content, defs) {
9628
+ if (content.includes("\uFFFD")) return /* @__PURE__ */ new Map();
9629
+ const indices = [...new Set(defs.flatMap(({ startIndex, endIndex }) => [startIndex, endIndex]))].sort(
9630
+ (a, b) => a - b
9631
+ );
9632
+ const offsets = /* @__PURE__ */ new Map();
9633
+ let cursor = 0;
9634
+ let bytes = 0;
9635
+ for (const index of indices) {
9636
+ if (index < cursor || index > content.length) return /* @__PURE__ */ new Map();
9637
+ bytes += Buffer.byteLength(content.slice(cursor, index), "utf8");
9638
+ offsets.set(index, bytes);
9639
+ cursor = index;
9640
+ }
9641
+ return offsets;
9642
+ }
9519
9643
  async function addSymbols(graph, services) {
9520
9644
  const parsers = /* @__PURE__ */ new Map();
9521
9645
  const parserForExt5 = (ext) => {
@@ -9539,47 +9663,59 @@ async function addSymbols(graph, services) {
9539
9663
  if (!parser) continue;
9540
9664
  const relPath = toPosix(import_node_path26.default.relative(service.dir, file.path));
9541
9665
  let defs;
9666
+ let completeParse;
9542
9667
  try {
9543
9668
  const tree = parseSource3(parser, file.content);
9544
9669
  defs = collectSymbolDefsForExt(ext, tree.rootNode);
9670
+ completeParse = !tree.rootNode.hasError;
9545
9671
  } catch (err) {
9546
9672
  recordExtractionError("symbol extraction", file.path, err);
9547
9673
  continue;
9548
9674
  }
9549
9675
  if (defs.length === 0) continue;
9550
- const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
9551
- graph,
9552
- service.pkg.name,
9553
- service.node.id,
9554
- relPath
9555
- );
9676
+ const offsets = completeParse ? utf8Offsets(file.content, defs) : /* @__PURE__ */ new Map();
9677
+ const {
9678
+ fileNodeId,
9679
+ nodesAdded: fn,
9680
+ edgesAdded: fe
9681
+ } = ensureFileNode(graph, service.pkg.name, service.node.id, relPath);
9556
9682
  nodesAdded += fn;
9557
9683
  edgesAdded += fe;
9558
9684
  for (const { def, disambiguator } of disambiguate(defs)) {
9559
- const sid = (0, import_types21.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
9685
+ const sid = (0, import_types22.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
9686
+ const startByte = offsets.get(def.startIndex);
9687
+ const endByte = offsets.get(def.endIndex);
9688
+ const precise = startByte !== void 0 && endByte !== void 0 && endByte > startByte ? { startByte, endByte } : {};
9689
+ const node = {
9690
+ id: sid,
9691
+ type: import_types22.NodeType.SymbolNode,
9692
+ kind: def.kind,
9693
+ qualname: def.qualname,
9694
+ span: { startLine: def.startLine, endLine: def.endLine, ...precise },
9695
+ service: service.pkg.name,
9696
+ relPath,
9697
+ discoveredVia: "static"
9698
+ };
9560
9699
  if (!graph.hasNode(sid)) {
9561
- const node = {
9562
- id: sid,
9563
- type: import_types21.NodeType.SymbolNode,
9564
- kind: def.kind,
9565
- qualname: def.qualname,
9566
- span: { startLine: def.startLine, endLine: def.endLine },
9567
- service: service.pkg.name,
9568
- relPath,
9569
- discoveredVia: "static"
9570
- };
9571
9700
  graph.addNode(sid, node);
9572
9701
  nodesAdded++;
9702
+ } else {
9703
+ const previous = graph.getNodeAttributes(sid);
9704
+ const discoveredVia = previous.discoveredVia === "otel" || previous.discoveredVia === "merged" ? "merged" : "static";
9705
+ 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;
9706
+ if (moved || previous.kind !== node.kind || previous.qualname !== node.qualname || previous.discoveredVia !== discoveredVia || previous.service !== node.service || previous.relPath !== node.relPath) {
9707
+ graph.replaceNodeAttributes(sid, { ...previous, ...node, discoveredVia });
9708
+ }
9573
9709
  }
9574
- const containsId = (0, import_types21.extractedEdgeId)(fileNodeId, sid, import_types21.EdgeType.CONTAINS);
9710
+ const containsId = (0, import_types22.extractedEdgeId)(fileNodeId, sid, import_types22.EdgeType.CONTAINS);
9575
9711
  if (!graph.hasEdge(containsId)) {
9576
9712
  const edge = {
9577
9713
  id: containsId,
9578
9714
  source: fileNodeId,
9579
9715
  target: sid,
9580
- type: import_types21.EdgeType.CONTAINS,
9581
- provenance: import_types21.Provenance.EXTRACTED,
9582
- confidence: (0, import_types21.confidenceForExtracted)("structural"),
9716
+ type: import_types22.EdgeType.CONTAINS,
9717
+ provenance: import_types22.Provenance.EXTRACTED,
9718
+ confidence: (0, import_types22.confidenceForExtracted)("structural"),
9583
9719
  evidence: {
9584
9720
  file: relPath,
9585
9721
  line: def.startLine,
@@ -9599,7 +9735,7 @@ async function addSymbols(graph, services) {
9599
9735
  init_cjs_shims();
9600
9736
  var import_node_path27 = __toESM(require("path"), 1);
9601
9737
  var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
9602
- var import_types22 = require("@neat.is/types");
9738
+ var import_types23 = require("@neat.is/types");
9603
9739
  function extendsInfo(classHeritage) {
9604
9740
  for (let i = 0; i < classHeritage.namedChildCount; i++) {
9605
9741
  const child = classHeritage.namedChild(i);
@@ -9717,7 +9853,7 @@ async function addSymbolEdges(graph, services) {
9717
9853
  }
9718
9854
  const disambiguated = disambiguate(collectSymbolDefs(root));
9719
9855
  const locals = disambiguated.map(({ def, disambiguator }) => ({
9720
- sid: (0, import_types22.symbolId)(serviceName, relPath, def.qualname, disambiguator),
9856
+ sid: (0, import_types23.symbolId)(serviceName, relPath, def.qualname, disambiguator),
9721
9857
  qualname: def.qualname,
9722
9858
  kind: def.kind,
9723
9859
  startLine: def.startLine,
@@ -9746,10 +9882,10 @@ async function addSymbolEdges(graph, services) {
9746
9882
  if (local) return local.kind === wantKind ? local.sid : null;
9747
9883
  const imp = resolvedImports.get(name);
9748
9884
  if (imp) {
9749
- const candidate = (0, import_types22.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
9885
+ const candidate = (0, import_types23.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
9750
9886
  if (graph.hasNode(candidate)) {
9751
9887
  const node = graph.getNodeAttributes(candidate);
9752
- if (node.type === import_types22.NodeType.SymbolNode && node.kind === wantKind) return candidate;
9888
+ if (node.type === import_types23.NodeType.SymbolNode && node.kind === wantKind) return candidate;
9753
9889
  }
9754
9890
  }
9755
9891
  return null;
@@ -9776,7 +9912,7 @@ async function addSymbolEdges(graph, services) {
9776
9912
  sourceSid: self.sid,
9777
9913
  targetName: ext.name,
9778
9914
  wantKind: "class",
9779
- edgeType: import_types22.EdgeType.INHERITS,
9915
+ edgeType: import_types23.EdgeType.INHERITS,
9780
9916
  line: ext.line
9781
9917
  });
9782
9918
  }
@@ -9785,7 +9921,7 @@ async function addSymbolEdges(graph, services) {
9785
9921
  sourceSid: self.sid,
9786
9922
  targetName: impl.name,
9787
9923
  wantKind: "class",
9788
- edgeType: import_types22.EdgeType.IMPLEMENTS,
9924
+ edgeType: import_types23.EdgeType.IMPLEMENTS,
9789
9925
  line: impl.line
9790
9926
  });
9791
9927
  }
@@ -9801,7 +9937,7 @@ async function addSymbolEdges(graph, services) {
9801
9937
  sourceSid: caller.sid,
9802
9938
  targetName: fn.text,
9803
9939
  wantKind: "function",
9804
- edgeType: import_types22.EdgeType.CALLS,
9940
+ edgeType: import_types23.EdgeType.CALLS,
9805
9941
  line
9806
9942
  });
9807
9943
  }
@@ -9817,15 +9953,15 @@ async function addSymbolEdges(graph, services) {
9817
9953
  const targetSid = resolveTarget(req.targetName, req.wantKind);
9818
9954
  if (!targetSid) continue;
9819
9955
  if (targetSid === req.sourceSid) continue;
9820
- const edgeId = (0, import_types22.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
9956
+ const edgeId = (0, import_types23.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
9821
9957
  if (graph.hasEdge(edgeId)) continue;
9822
9958
  const edge = {
9823
9959
  id: edgeId,
9824
9960
  source: req.sourceSid,
9825
9961
  target: targetSid,
9826
9962
  type: req.edgeType,
9827
- provenance: import_types22.Provenance.EXTRACTED,
9828
- confidence: (0, import_types22.confidenceForExtracted)("structural"),
9963
+ provenance: import_types23.Provenance.EXTRACTED,
9964
+ confidence: (0, import_types23.confidenceForExtracted)("structural"),
9829
9965
  evidence: {
9830
9966
  file: relPath,
9831
9967
  line: req.line,
@@ -9844,7 +9980,7 @@ async function addSymbolEdges(graph, services) {
9844
9980
  init_cjs_shims();
9845
9981
  var import_node_path28 = __toESM(require("path"), 1);
9846
9982
  var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
9847
- var import_types23 = require("@neat.is/types");
9983
+ var import_types24 = require("@neat.is/types");
9848
9984
  function stringLiteralText2(node) {
9849
9985
  for (let i = 0; i < node.childCount; i++) {
9850
9986
  const child = node.child(i);
@@ -10014,11 +10150,11 @@ async function addServerActions(graph, services) {
10014
10150
  nodesAdded += fn;
10015
10151
  edgesAdded += fe;
10016
10152
  for (const action of actions) {
10017
- const aid = (0, import_types23.serverActionId)(service.pkg.name, relPath, action.exportName);
10153
+ const aid = (0, import_types24.serverActionId)(service.pkg.name, relPath, action.exportName);
10018
10154
  if (!graph.hasNode(aid)) {
10019
10155
  const node = {
10020
10156
  id: aid,
10021
- type: import_types23.NodeType.ServerActionNode,
10157
+ type: import_types24.NodeType.ServerActionNode,
10022
10158
  name: action.exportName,
10023
10159
  service: service.pkg.name,
10024
10160
  module: relPath,
@@ -10030,15 +10166,15 @@ async function addServerActions(graph, services) {
10030
10166
  graph.addNode(aid, node);
10031
10167
  nodesAdded++;
10032
10168
  }
10033
- const containsId = (0, import_types23.extractedEdgeId)(fileNodeId, aid, import_types23.EdgeType.CONTAINS);
10169
+ const containsId = (0, import_types24.extractedEdgeId)(fileNodeId, aid, import_types24.EdgeType.CONTAINS);
10034
10170
  if (!graph.hasEdge(containsId)) {
10035
10171
  const edge = {
10036
10172
  id: containsId,
10037
10173
  source: fileNodeId,
10038
10174
  target: aid,
10039
- type: import_types23.EdgeType.CONTAINS,
10040
- provenance: import_types23.Provenance.EXTRACTED,
10041
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
10175
+ type: import_types24.EdgeType.CONTAINS,
10176
+ provenance: import_types24.Provenance.EXTRACTED,
10177
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10042
10178
  evidence: {
10043
10179
  file: relPath,
10044
10180
  line: action.line,
@@ -10068,7 +10204,7 @@ async function addServerActions(graph, services) {
10068
10204
  for (const [local, binding] of bindings) {
10069
10205
  const target = await resolveJsImport(binding.specifier, fileDir, service.dir, tsPaths);
10070
10206
  if (!target) continue;
10071
- const aid = (0, import_types23.serverActionId)(service.pkg.name, target, binding.importedName);
10207
+ const aid = (0, import_types24.serverActionId)(service.pkg.name, target, binding.importedName);
10072
10208
  if (graph.hasNode(aid)) actionBindings.set(local, aid);
10073
10209
  }
10074
10210
  if (actionBindings.size === 0) continue;
@@ -10083,15 +10219,15 @@ async function addServerActions(graph, services) {
10083
10219
  nodesAdded += ensured.nodesAdded;
10084
10220
  edgesAdded += ensured.edgesAdded;
10085
10221
  }
10086
- const callsId = (0, import_types23.extractedEdgeId)(clientFileId, aid, import_types23.EdgeType.CALLS);
10222
+ const callsId = (0, import_types24.extractedEdgeId)(clientFileId, aid, import_types24.EdgeType.CALLS);
10087
10223
  if (graph.hasEdge(callsId)) continue;
10088
10224
  const edge = {
10089
10225
  id: callsId,
10090
10226
  source: clientFileId,
10091
10227
  target: aid,
10092
- type: import_types23.EdgeType.CALLS,
10093
- provenance: import_types23.Provenance.EXTRACTED,
10094
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
10228
+ type: import_types24.EdgeType.CALLS,
10229
+ provenance: import_types24.Provenance.EXTRACTED,
10230
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10095
10231
  evidence: {
10096
10232
  file: relPath,
10097
10233
  line,
@@ -10109,7 +10245,7 @@ async function addServerActions(graph, services) {
10109
10245
  // src/extract/databases/index.ts
10110
10246
  init_cjs_shims();
10111
10247
  var import_node_path37 = __toESM(require("path"), 1);
10112
- var import_types24 = require("@neat.is/types");
10248
+ var import_types25 = require("@neat.is/types");
10113
10249
 
10114
10250
  // src/extract/databases/db-config-yaml.ts
10115
10251
  init_cjs_shims();
@@ -10768,8 +10904,8 @@ function compatibleDriversFor(engine) {
10768
10904
  }
10769
10905
  function toDatabaseNode(config) {
10770
10906
  return {
10771
- id: (0, import_types24.databaseId)(config.host),
10772
- type: import_types24.NodeType.DatabaseNode,
10907
+ id: (0, import_types25.databaseId)(config.host),
10908
+ type: import_types25.NodeType.DatabaseNode,
10773
10909
  name: config.database || config.host,
10774
10910
  engine: config.engine,
10775
10911
  engineVersion: config.engineVersion,
@@ -10910,12 +11046,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10910
11046
  edgesAdded += fe;
10911
11047
  const evidenceFile = toPosix(import_node_path37.default.relative(scanPath, config.sourceFile));
10912
11048
  const edge = {
10913
- id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id, import_types24.EdgeType.CONNECTS_TO),
11049
+ id: (0, import_types4.extractedEdgeId)(fileNodeId, dbNode.id, import_types25.EdgeType.CONNECTS_TO),
10914
11050
  source: fileNodeId,
10915
11051
  target: dbNode.id,
10916
- type: import_types24.EdgeType.CONNECTS_TO,
10917
- provenance: import_types24.Provenance.EXTRACTED,
10918
- confidence: (0, import_types24.confidenceForExtracted)("structural"),
11052
+ type: import_types25.EdgeType.CONNECTS_TO,
11053
+ provenance: import_types25.Provenance.EXTRACTED,
11054
+ confidence: (0, import_types25.confidenceForExtracted)("structural"),
10919
11055
  // Carry how the host was recovered (ADR-213) so the divergence ranker
10920
11056
  // can tell a real declared store from a hardcoded fault-injection /
10921
11057
  // flag-gated probe. Only set when the parser distinguished the two.
@@ -10930,11 +11066,11 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10930
11066
  const primary = allConfigs[0];
10931
11067
  service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
10932
11068
  const relPath = import_node_path37.default.relative(scanPath, primary.sourceFile);
10933
- const cfgId = (0, import_types24.configId)(relPath);
11069
+ const cfgId = (0, import_types25.configId)(relPath);
10934
11070
  if (!graph.hasNode(cfgId)) {
10935
11071
  const cfgNode = {
10936
11072
  id: cfgId,
10937
- type: import_types24.NodeType.ConfigNode,
11073
+ type: import_types25.NodeType.ConfigNode,
10938
11074
  name: import_node_path37.default.basename(primary.sourceFile),
10939
11075
  path: relPath,
10940
11076
  fileType: isConfigFile(import_node_path37.default.basename(primary.sourceFile)).fileType || "config"
@@ -10943,12 +11079,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10943
11079
  nodesAdded++;
10944
11080
  }
10945
11081
  const cfgEdge = {
10946
- id: (0, import_types4.extractedEdgeId)(service.node.id, cfgId, import_types24.EdgeType.CONFIGURED_BY),
11082
+ id: (0, import_types4.extractedEdgeId)(service.node.id, cfgId, import_types25.EdgeType.CONFIGURED_BY),
10947
11083
  source: service.node.id,
10948
11084
  target: cfgId,
10949
- type: import_types24.EdgeType.CONFIGURED_BY,
10950
- provenance: import_types24.Provenance.EXTRACTED,
10951
- confidence: (0, import_types24.confidenceForExtracted)("structural"),
11085
+ type: import_types25.EdgeType.CONFIGURED_BY,
11086
+ provenance: import_types25.Provenance.EXTRACTED,
11087
+ confidence: (0, import_types25.confidenceForExtracted)("structural"),
10952
11088
  evidence: { file: toPosix(relPath) }
10953
11089
  };
10954
11090
  if (!graph.hasEdge(cfgEdge.id)) {
@@ -10980,7 +11116,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10980
11116
  init_cjs_shims();
10981
11117
  var import_node_fs26 = require("fs");
10982
11118
  var import_node_path38 = __toESM(require("path"), 1);
10983
- var import_types25 = require("@neat.is/types");
11119
+ var import_types26 = require("@neat.is/types");
10984
11120
  async function walkConfigFiles(dir, excludeDirs = []) {
10985
11121
  const excluded = new Set(excludeDirs.map((d) => import_node_path38.default.resolve(d)));
10986
11122
  const out = [];
@@ -11009,8 +11145,8 @@ async function addConfigNodes(graph, services, scanPath) {
11009
11145
  for (const file of configFiles) {
11010
11146
  const relPath = import_node_path38.default.relative(scanPath, file);
11011
11147
  const node = {
11012
- id: (0, import_types25.configId)(relPath),
11013
- type: import_types25.NodeType.ConfigNode,
11148
+ id: (0, import_types26.configId)(relPath),
11149
+ type: import_types26.NodeType.ConfigNode,
11014
11150
  name: import_node_path38.default.basename(file),
11015
11151
  path: relPath,
11016
11152
  fileType: isConfigFile(import_node_path38.default.basename(file)).fileType
@@ -11029,12 +11165,12 @@ async function addConfigNodes(graph, services, scanPath) {
11029
11165
  nodesAdded += fn;
11030
11166
  edgesAdded += fe;
11031
11167
  const edge = {
11032
- id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types25.EdgeType.CONFIGURED_BY),
11168
+ id: (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types26.EdgeType.CONFIGURED_BY),
11033
11169
  source: fileNodeId,
11034
11170
  target: node.id,
11035
- type: import_types25.EdgeType.CONFIGURED_BY,
11036
- provenance: import_types25.Provenance.EXTRACTED,
11037
- confidence: (0, import_types25.confidenceForExtracted)("structural"),
11171
+ type: import_types26.EdgeType.CONFIGURED_BY,
11172
+ provenance: import_types26.Provenance.EXTRACTED,
11173
+ confidence: (0, import_types26.confidenceForExtracted)("structural"),
11038
11174
  evidence: { file: relPath.split(import_node_path38.default.sep).join("/") }
11039
11175
  };
11040
11176
  if (!graph.hasEdge(edge.id)) {
@@ -11050,7 +11186,7 @@ async function addConfigNodes(graph, services, scanPath) {
11050
11186
  init_cjs_shims();
11051
11187
  var import_node_fs27 = require("fs");
11052
11188
  var import_node_path39 = __toESM(require("path"), 1);
11053
- var import_types26 = require("@neat.is/types");
11189
+ var import_types27 = require("@neat.is/types");
11054
11190
  var PROTO_EXTENSION = ".proto";
11055
11191
  function packageOf(content) {
11056
11192
  const m = content.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_.]*)\s*;/m);
@@ -11130,11 +11266,11 @@ async function addGrpcMethods(graph, services) {
11130
11266
  }
11131
11267
  if (methods.length === 0) continue;
11132
11268
  for (const method of methods) {
11133
- const mid = (0, import_types26.grpcMethodId)(method.rpcService, method.rpcMethod);
11269
+ const mid = (0, import_types27.grpcMethodId)(method.rpcService, method.rpcMethod);
11134
11270
  if (!graph.hasNode(mid)) {
11135
11271
  const node = {
11136
11272
  id: mid,
11137
- type: import_types26.NodeType.GrpcMethodNode,
11273
+ type: import_types27.NodeType.GrpcMethodNode,
11138
11274
  name: `${method.rpcService}/${method.rpcMethod}`,
11139
11275
  rpcService: method.rpcService,
11140
11276
  rpcMethod: method.rpcMethod,
@@ -11145,15 +11281,15 @@ async function addGrpcMethods(graph, services) {
11145
11281
  graph.addNode(mid, node);
11146
11282
  nodesAdded++;
11147
11283
  }
11148
- const containsId = (0, import_types26.extractedEdgeId)(service.node.id, mid, import_types26.EdgeType.CONTAINS);
11284
+ const containsId = (0, import_types27.extractedEdgeId)(service.node.id, mid, import_types27.EdgeType.CONTAINS);
11149
11285
  if (!graph.hasEdge(containsId)) {
11150
11286
  const edge = {
11151
11287
  id: containsId,
11152
11288
  source: service.node.id,
11153
11289
  target: mid,
11154
- type: import_types26.EdgeType.CONTAINS,
11155
- provenance: import_types26.Provenance.EXTRACTED,
11156
- confidence: (0, import_types26.confidenceForExtracted)("structural"),
11290
+ type: import_types27.EdgeType.CONTAINS,
11291
+ provenance: import_types27.Provenance.EXTRACTED,
11292
+ confidence: (0, import_types27.confidenceForExtracted)("structural"),
11157
11293
  evidence: {
11158
11294
  file: relFile,
11159
11295
  line: method.line,
@@ -11171,7 +11307,7 @@ async function addGrpcMethods(graph, services) {
11171
11307
 
11172
11308
  // src/extract/calls/index.ts
11173
11309
  init_cjs_shims();
11174
- var import_types46 = require("@neat.is/types");
11310
+ var import_types47 = require("@neat.is/types");
11175
11311
 
11176
11312
  // src/extract/calls/http.ts
11177
11313
  init_cjs_shims();
@@ -11180,7 +11316,7 @@ var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
11180
11316
  var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
11181
11317
  var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
11182
11318
  var import_tree_sitter_python4 = __toESM(require("tree-sitter-python"), 1);
11183
- var import_types27 = require("@neat.is/types");
11319
+ var import_types28 = require("@neat.is/types");
11184
11320
  var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
11185
11321
  var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
11186
11322
  function isInsideJsxExternalLink(node) {
@@ -11274,7 +11410,7 @@ async function addHttpCallEdges(graph, services) {
11274
11410
  const dedupKey = `${relFile}|${targetId}`;
11275
11411
  if (seen.has(dedupKey)) continue;
11276
11412
  seen.add(dedupKey);
11277
- const confidence = (0, import_types27.confidenceForExtracted)("url-literal-service-target");
11413
+ const confidence = (0, import_types28.confidenceForExtracted)("url-literal-service-target");
11278
11414
  const ev = {
11279
11415
  file: relFile,
11280
11416
  line: site.line,
@@ -11288,25 +11424,25 @@ async function addHttpCallEdges(graph, services) {
11288
11424
  );
11289
11425
  nodesAdded += n;
11290
11426
  edgesAdded += e;
11291
- if (!(0, import_types27.passesExtractedFloor)(confidence)) {
11427
+ if (!(0, import_types28.passesExtractedFloor)(confidence)) {
11292
11428
  noteExtractedDropped({
11293
11429
  source: fileNodeId,
11294
11430
  target: targetId,
11295
- type: import_types27.EdgeType.CALLS,
11431
+ type: import_types28.EdgeType.CALLS,
11296
11432
  confidence,
11297
11433
  confidenceKind: "url-literal-service-target",
11298
11434
  evidence: ev
11299
11435
  });
11300
11436
  continue;
11301
11437
  }
11302
- const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId, import_types27.EdgeType.CALLS);
11438
+ const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, targetId, import_types28.EdgeType.CALLS);
11303
11439
  if (!graph.hasEdge(edgeId)) {
11304
11440
  const edge = {
11305
11441
  id: edgeId,
11306
11442
  source: fileNodeId,
11307
11443
  target: targetId,
11308
- type: import_types27.EdgeType.CALLS,
11309
- provenance: import_types27.Provenance.EXTRACTED,
11444
+ type: import_types28.EdgeType.CALLS,
11445
+ provenance: import_types28.Provenance.EXTRACTED,
11310
11446
  confidence,
11311
11447
  evidence: ev
11312
11448
  };
@@ -11324,7 +11460,7 @@ init_cjs_shims();
11324
11460
  var import_node_path41 = __toESM(require("path"), 1);
11325
11461
  var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
11326
11462
  var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
11327
- var import_types28 = require("@neat.is/types");
11463
+ var import_types29 = require("@neat.is/types");
11328
11464
  var PARSE_CHUNK5 = 16384;
11329
11465
  function parseSource5(parser, source) {
11330
11466
  return parser.parse(
@@ -11568,9 +11704,9 @@ function buildRouteIndex(graph) {
11568
11704
  const index = /* @__PURE__ */ new Map();
11569
11705
  graph.forEachNode((_id, attrs) => {
11570
11706
  const node = attrs;
11571
- if (node.type !== import_types28.NodeType.RouteNode) return;
11707
+ if (node.type !== import_types29.NodeType.RouteNode) return;
11572
11708
  const route = attrs;
11573
- const owner = (0, import_types28.serviceId)(route.service);
11709
+ const owner = (0, import_types29.serviceId)(route.service);
11574
11710
  const entry2 = {
11575
11711
  method: route.method.toUpperCase(),
11576
11712
  normalizedPath: normalizePathTemplate(route.pathTemplate),
@@ -11625,8 +11761,8 @@ async function addRouteCallEdges(graph, services) {
11625
11761
  noteExtractedDropped({
11626
11762
  source: fileNodeId2,
11627
11763
  target: "route:unresolved",
11628
- type: import_types28.EdgeType.CALLS,
11629
- confidence: (0, import_types28.confidenceForExtracted)("reconstructed-approximate"),
11764
+ type: import_types29.EdgeType.CALLS,
11765
+ confidence: (0, import_types29.confidenceForExtracted)("reconstructed-approximate"),
11630
11766
  confidenceKind: "reconstructed-approximate",
11631
11767
  evidence: {
11632
11768
  file: relFile,
@@ -11659,7 +11795,7 @@ async function addRouteCallEdges(graph, services) {
11659
11795
  edgesAdded += e;
11660
11796
  const anchored = pathHasLiteralAnchor(site.pathTemplate);
11661
11797
  const confidenceKind = site.approximate && !anchored ? "reconstructed-approximate" : "verified-call-site";
11662
- const confidence = (0, import_types28.confidenceForExtracted)(confidenceKind);
11798
+ const confidence = (0, import_types29.confidenceForExtracted)(confidenceKind);
11663
11799
  const ev = {
11664
11800
  file: relFile,
11665
11801
  line: site.line,
@@ -11668,25 +11804,25 @@ async function addRouteCallEdges(graph, services) {
11668
11804
  pathTemplate: site.pathTemplate,
11669
11805
  ...confidenceKind === "reconstructed-approximate" ? { approximate: true, reason: site.reason } : {}
11670
11806
  };
11671
- if (!(0, import_types28.passesExtractedFloor)(confidence)) {
11807
+ if (!(0, import_types29.passesExtractedFloor)(confidence)) {
11672
11808
  noteExtractedDropped({
11673
11809
  source: fileNodeId,
11674
11810
  target: match.routeNodeId,
11675
- type: import_types28.EdgeType.CALLS,
11811
+ type: import_types29.EdgeType.CALLS,
11676
11812
  confidence,
11677
11813
  confidenceKind,
11678
11814
  evidence: ev
11679
11815
  });
11680
11816
  continue;
11681
11817
  }
11682
- const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types28.EdgeType.CALLS);
11818
+ const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types29.EdgeType.CALLS);
11683
11819
  if (!graph.hasEdge(edgeId)) {
11684
11820
  const edge = {
11685
11821
  id: edgeId,
11686
11822
  source: fileNodeId,
11687
11823
  target: match.routeNodeId,
11688
- type: import_types28.EdgeType.CALLS,
11689
- provenance: import_types28.Provenance.EXTRACTED,
11824
+ type: import_types29.EdgeType.CALLS,
11825
+ provenance: import_types29.Provenance.EXTRACTED,
11690
11826
  confidence,
11691
11827
  evidence: ev
11692
11828
  };
@@ -11702,7 +11838,7 @@ async function addRouteCallEdges(graph, services) {
11702
11838
  // src/extract/calls/kafka.ts
11703
11839
  init_cjs_shims();
11704
11840
  var import_node_path42 = __toESM(require("path"), 1);
11705
- var import_types29 = require("@neat.is/types");
11841
+ var import_types30 = require("@neat.is/types");
11706
11842
  var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
11707
11843
  var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
11708
11844
  var SARAMA_IMPORT_RE = /"[^"]*\/sarama"/;
@@ -11779,7 +11915,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
11779
11915
  seen.add(key);
11780
11916
  const line = anchor !== void 0 ? file.content.slice(0, anchor).split("\n").length : lineOf(file.content, topic);
11781
11917
  out.push({
11782
- infraId: (0, import_types29.infraId)("kafka-topic", topic),
11918
+ infraId: (0, import_types30.infraId)("kafka-topic", topic),
11783
11919
  name: topic,
11784
11920
  kind: "kafka-topic",
11785
11921
  edgeType,
@@ -11807,7 +11943,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
11807
11943
  // src/extract/calls/redis.ts
11808
11944
  init_cjs_shims();
11809
11945
  var import_node_path43 = __toESM(require("path"), 1);
11810
- var import_types30 = require("@neat.is/types");
11946
+ var import_types31 = require("@neat.is/types");
11811
11947
  var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
11812
11948
  function redisEndpointsFromFile(file, serviceDir) {
11813
11949
  const out = [];
@@ -11820,7 +11956,7 @@ function redisEndpointsFromFile(file, serviceDir) {
11820
11956
  seen.add(host);
11821
11957
  const line = lineOf(file.content, host);
11822
11958
  out.push({
11823
- infraId: (0, import_types30.infraId)("redis", host),
11959
+ infraId: (0, import_types31.infraId)("redis", host),
11824
11960
  name: host,
11825
11961
  kind: "redis",
11826
11962
  edgeType: "CALLS",
@@ -11841,7 +11977,7 @@ function redisEndpointsFromFile(file, serviceDir) {
11841
11977
  // src/extract/calls/aws.ts
11842
11978
  init_cjs_shims();
11843
11979
  var import_node_path44 = __toESM(require("path"), 1);
11844
- var import_types31 = require("@neat.is/types");
11980
+ var import_types32 = require("@neat.is/types");
11845
11981
  var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
11846
11982
  var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
11847
11983
  function hasMarker(text, markers) {
@@ -11865,7 +12001,7 @@ function awsEndpointsFromFile(file, serviceDir) {
11865
12001
  seen.add(key);
11866
12002
  const line = lineOf(file.content, name);
11867
12003
  out.push({
11868
- infraId: (0, import_types31.infraId)(kind, name),
12004
+ infraId: (0, import_types32.infraId)(kind, name),
11869
12005
  name,
11870
12006
  kind,
11871
12007
  edgeType: "CALLS",
@@ -11900,7 +12036,7 @@ function awsEndpointsFromFile(file, serviceDir) {
11900
12036
  // src/extract/calls/grpc.ts
11901
12037
  init_cjs_shims();
11902
12038
  var import_node_path45 = __toESM(require("path"), 1);
11903
- var import_types32 = require("@neat.is/types");
12039
+ var import_types33 = require("@neat.is/types");
11904
12040
  var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
11905
12041
  var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
11906
12042
  var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
@@ -11949,7 +12085,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
11949
12085
  const { kind } = classified;
11950
12086
  const line = lineOf(file.content, m[0]);
11951
12087
  out.push({
11952
- infraId: (0, import_types32.infraId)(kind, name),
12088
+ infraId: (0, import_types33.infraId)(kind, name),
11953
12089
  name,
11954
12090
  kind,
11955
12091
  edgeType: "CALLS",
@@ -11970,7 +12106,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
11970
12106
  // src/extract/calls/supabase.ts
11971
12107
  init_cjs_shims();
11972
12108
  var import_node_path46 = __toESM(require("path"), 1);
11973
- var import_types33 = require("@neat.is/types");
12109
+ var import_types34 = require("@neat.is/types");
11974
12110
  var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
11975
12111
  var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
11976
12112
  var SUPABASE_CLIENT_RE = /\b(createClient|createServerClient|createBrowserClient)\s*\(\s*(?:['"`]([^'"`]*)['"`])?/g;
@@ -12018,7 +12154,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
12018
12154
  seen.add(name);
12019
12155
  const line = lineOf(file.content, m[0]);
12020
12156
  out.push({
12021
- infraId: (0, import_types33.infraId)("supabase", name),
12157
+ infraId: (0, import_types34.infraId)("supabase", name),
12022
12158
  name,
12023
12159
  kind: "supabase",
12024
12160
  edgeType: "CALLS",
@@ -12049,7 +12185,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
12049
12185
  seen.add(key);
12050
12186
  const line = lineOf(file.content, am[0]);
12051
12187
  out.push({
12052
- infraId: (0, import_types33.infraId)(kind, resource),
12188
+ infraId: (0, import_types34.infraId)(kind, resource),
12053
12189
  name: resource,
12054
12190
  kind,
12055
12191
  edgeType: "CALLS",
@@ -12070,7 +12206,7 @@ init_cjs_shims();
12070
12206
  var import_node_path47 = __toESM(require("path"), 1);
12071
12207
  var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
12072
12208
  var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
12073
- var import_types34 = require("@neat.is/types");
12209
+ var import_types35 = require("@neat.is/types");
12074
12210
  var FIRESTORE_CLIENT_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase\/firestore['"`]/;
12075
12211
  var FIRESTORE_ADMIN_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase-admin(?:\/firestore)?['"`]/;
12076
12212
  function parserForExt2(ext) {
@@ -12334,7 +12470,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
12334
12470
  }
12335
12471
  }
12336
12472
  out.push({
12337
- infraId: (0, import_types34.infraId)("firestore-collection", collPath),
12473
+ infraId: (0, import_types35.infraId)("firestore-collection", collPath),
12338
12474
  name: collPath,
12339
12475
  kind: "firestore-collection",
12340
12476
  edgeType: "CALLS",
@@ -12450,7 +12586,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
12450
12586
  // src/extract/calls/mongoose.ts
12451
12587
  init_cjs_shims();
12452
12588
  var import_node_path48 = __toESM(require("path"), 1);
12453
- var import_types35 = require("@neat.is/types");
12589
+ var import_types36 = require("@neat.is/types");
12454
12590
  var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
12455
12591
  var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
12456
12592
  var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
@@ -12595,7 +12731,7 @@ function collectModelDefs(content, pluralizeOn) {
12595
12731
  function endpoint(r, file, serviceDir, matchText) {
12596
12732
  const line = lineOf(file.content, matchText);
12597
12733
  return {
12598
- infraId: (0, import_types35.infraId)(r.kind, r.name),
12734
+ infraId: (0, import_types36.infraId)(r.kind, r.name),
12599
12735
  name: r.name,
12600
12736
  kind: r.kind,
12601
12737
  edgeType: "CALLS",
@@ -12748,7 +12884,7 @@ init_cjs_shims();
12748
12884
  var import_node_path49 = __toESM(require("path"), 1);
12749
12885
  var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
12750
12886
  var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
12751
- var import_types36 = require("@neat.is/types");
12887
+ var import_types37 = require("@neat.is/types");
12752
12888
  var SQLALCHEMY_IMPORT_RE = /(?:from|import)\s+(?:flask_sqlalchemy|sqlalchemy)\b/;
12753
12889
  var PARSE_CHUNK6 = 16384;
12754
12890
  function makePyParser3() {
@@ -12902,7 +13038,7 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
12902
13038
  if (seen.has(name)) return;
12903
13039
  seen.add(name);
12904
13040
  out.push({
12905
- infraId: (0, import_types36.infraId)("sql-table", name),
13041
+ infraId: (0, import_types37.infraId)("sql-table", name),
12906
13042
  name,
12907
13043
  kind: "sql-table",
12908
13044
  edgeType: "CALLS",
@@ -13010,7 +13146,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
13010
13146
  if (seen.has(key)) continue;
13011
13147
  seen.add(key);
13012
13148
  out.push({
13013
- infraId: (0, import_types36.infraId)("sql-table", t),
13149
+ infraId: (0, import_types37.infraId)("sql-table", t),
13014
13150
  name: t,
13015
13151
  kind: "sql-table",
13016
13152
  edgeType: "CALLS",
@@ -13031,7 +13167,7 @@ init_cjs_shims();
13031
13167
  var import_node_path50 = __toESM(require("path"), 1);
13032
13168
  var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
13033
13169
  var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
13034
- var import_types37 = require("@neat.is/types");
13170
+ var import_types38 = require("@neat.is/types");
13035
13171
  var SOCKET_IMPORT_RE = /(?:^|\n)\s*(?:import\s+socket\b|from\s+socket\s+import\b)/;
13036
13172
  var PARSE_CHUNK7 = 16384;
13037
13173
  function makePyParser4() {
@@ -13097,7 +13233,7 @@ function socketEndpointsFromFile(file, serviceDir) {
13097
13233
  seen.add(name);
13098
13234
  const line = node.startPosition.row + 1;
13099
13235
  out.push({
13100
- infraId: (0, import_types37.infraId)("socket", name),
13236
+ infraId: (0, import_types38.infraId)("socket", name),
13101
13237
  name,
13102
13238
  kind: "socket",
13103
13239
  edgeType: "CALLS",
@@ -13118,7 +13254,7 @@ init_cjs_shims();
13118
13254
  var import_node_path51 = __toESM(require("path"), 1);
13119
13255
  var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
13120
13256
  var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
13121
- var import_types38 = require("@neat.is/types");
13257
+ var import_types39 = require("@neat.is/types");
13122
13258
  var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
13123
13259
  var PARSE_CHUNK8 = 16384;
13124
13260
  function makePyParser5() {
@@ -13198,7 +13334,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
13198
13334
  seen.add(table2);
13199
13335
  const line = node.startPosition.row + 1;
13200
13336
  out.push({
13201
- infraId: (0, import_types38.infraId)("sql-table", table2),
13337
+ infraId: (0, import_types39.infraId)("sql-table", table2),
13202
13338
  name: table2,
13203
13339
  kind: "sql-table",
13204
13340
  edgeType: "CALLS",
@@ -13214,7 +13350,7 @@ init_cjs_shims();
13214
13350
  var import_node_path52 = __toESM(require("path"), 1);
13215
13351
  var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
13216
13352
  var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
13217
- var import_types39 = require("@neat.is/types");
13353
+ var import_types40 = require("@neat.is/types");
13218
13354
  var DRIZZLE_IMPORT_RE = /drizzle-orm/;
13219
13355
  var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
13220
13356
  function parserForExt3(ext) {
@@ -13305,7 +13441,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
13305
13441
  const columns = columnsFromObject(obj);
13306
13442
  const line = node.startPosition.row + 1;
13307
13443
  out.push({
13308
- infraId: (0, import_types39.infraId)("sql-table", tableName2),
13444
+ infraId: (0, import_types40.infraId)("sql-table", tableName2),
13309
13445
  name: tableName2,
13310
13446
  kind: "sql-table",
13311
13447
  edgeType: "CALLS",
@@ -13415,7 +13551,7 @@ function drizzleForeignKeys(file, serviceDir) {
13415
13551
  // src/extract/calls/prisma.ts
13416
13552
  init_cjs_shims();
13417
13553
  var import_node_path53 = __toESM(require("path"), 1);
13418
- var import_types40 = require("@neat.is/types");
13554
+ var import_types41 = require("@neat.is/types");
13419
13555
  var SCALAR_TYPES = /* @__PURE__ */ new Set([
13420
13556
  "Int",
13421
13557
  "String",
@@ -13463,7 +13599,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
13463
13599
  if (seenTable.has(b.tableName)) return;
13464
13600
  seenTable.add(b.tableName);
13465
13601
  out.push({
13466
- infraId: (0, import_types40.infraId)("sql-table", b.tableName),
13602
+ infraId: (0, import_types41.infraId)("sql-table", b.tableName),
13467
13603
  name: b.tableName,
13468
13604
  kind: "sql-table",
13469
13605
  edgeType: "CALLS",
@@ -13635,7 +13771,7 @@ init_cjs_shims();
13635
13771
  var import_node_path54 = __toESM(require("path"), 1);
13636
13772
  var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
13637
13773
  var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
13638
- var import_types41 = require("@neat.is/types");
13774
+ var import_types42 = require("@neat.is/types");
13639
13775
  var AR_SCHEMA_RE = /ActiveRecord::Schema/;
13640
13776
  var PARSE_CHUNK9 = 16384;
13641
13777
  function makeRubyParser2() {
@@ -13833,7 +13969,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
13833
13969
  if (!table2 || seen.has(table2.name)) return;
13834
13970
  seen.add(table2.name);
13835
13971
  out.push({
13836
- infraId: (0, import_types41.infraId)("sql-table", table2.name),
13972
+ infraId: (0, import_types42.infraId)("sql-table", table2.name),
13837
13973
  name: table2.name,
13838
13974
  kind: "sql-table",
13839
13975
  edgeType: "CALLS",
@@ -13939,7 +14075,7 @@ function railsModelEndpointsFromFile(file, serviceDir) {
13939
14075
  seen.add(table2);
13940
14076
  const line = node.startPosition.row + 1;
13941
14077
  out.push({
13942
- infraId: (0, import_types41.infraId)("sql-table", table2),
14078
+ infraId: (0, import_types42.infraId)("sql-table", table2),
13943
14079
  name: table2,
13944
14080
  kind: "sql-table",
13945
14081
  edgeType: "CALLS",
@@ -13997,7 +14133,7 @@ init_cjs_shims();
13997
14133
  var import_node_path55 = __toESM(require("path"), 1);
13998
14134
  var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
13999
14135
  var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
14000
- var import_types42 = require("@neat.is/types");
14136
+ var import_types43 = require("@neat.is/types");
14001
14137
  var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
14002
14138
  var PARSE_CHUNK10 = 16384;
14003
14139
  function makePhpParser2() {
@@ -14244,7 +14380,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
14244
14380
  }
14245
14381
  }
14246
14382
  out.push({
14247
- infraId: (0, import_types42.infraId)("sql-table", bp.table),
14383
+ infraId: (0, import_types43.infraId)("sql-table", bp.table),
14248
14384
  name: bp.table,
14249
14385
  kind: "sql-table",
14250
14386
  edgeType: "CALLS",
@@ -14387,7 +14523,7 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
14387
14523
  seen.add(table2);
14388
14524
  const line = node.startPosition.row + 1;
14389
14525
  out.push({
14390
- infraId: (0, import_types42.infraId)("sql-table", table2),
14526
+ infraId: (0, import_types43.infraId)("sql-table", table2),
14391
14527
  name: table2,
14392
14528
  kind: "sql-table",
14393
14529
  edgeType: "CALLS",
@@ -14444,7 +14580,7 @@ init_cjs_shims();
14444
14580
  var import_node_path58 = __toESM(require("path"), 1);
14445
14581
  var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
14446
14582
  var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
14447
- var import_types43 = require("@neat.is/types");
14583
+ var import_types44 = require("@neat.is/types");
14448
14584
  init_otel();
14449
14585
  var PARSE_CHUNK11 = 16384;
14450
14586
  var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
@@ -14538,7 +14674,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
14538
14674
  const columns = columnsFromSqlStatement(sql);
14539
14675
  const line = node.startPosition.row + 1;
14540
14676
  out.push({
14541
- infraId: (0, import_types43.infraId)("sql-table", table2),
14677
+ infraId: (0, import_types44.infraId)("sql-table", table2),
14542
14678
  name: table2,
14543
14679
  kind: "sql-table",
14544
14680
  edgeType: "CALLS",
@@ -14559,7 +14695,7 @@ init_cjs_shims();
14559
14695
  var import_node_path59 = __toESM(require("path"), 1);
14560
14696
  var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
14561
14697
  var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
14562
- var import_types44 = require("@neat.is/types");
14698
+ var import_types45 = require("@neat.is/types");
14563
14699
  var GORM_IMPORT_RE = /gorm\.io\/gorm/;
14564
14700
  var PARSE_CHUNK12 = 16384;
14565
14701
  function makeGoParser4() {
@@ -15004,7 +15140,7 @@ function gormEndpointsFromFile(file, serviceDir) {
15004
15140
  const columns = [];
15005
15141
  collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
15006
15142
  out.push({
15007
- infraId: (0, import_types44.infraId)("sql-table", table2),
15143
+ infraId: (0, import_types45.infraId)("sql-table", table2),
15008
15144
  name: table2,
15009
15145
  kind: "sql-table",
15010
15146
  edgeType: "CALLS",
@@ -15075,7 +15211,7 @@ init_cjs_shims();
15075
15211
  var import_node_path60 = __toESM(require("path"), 1);
15076
15212
  var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
15077
15213
  var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
15078
- var import_types45 = require("@neat.is/types");
15214
+ var import_types46 = require("@neat.is/types");
15079
15215
  var EFCORE_GATE = /Microsoft\.EntityFrameworkCore|DataAnnotations\.Schema|\bDbContext\b|\bDbSet\s*</;
15080
15216
  var PARSE_CHUNK13 = 16384;
15081
15217
  function makeCsParser() {
@@ -15160,7 +15296,7 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15160
15296
  if (!name || seen.has(name)) return;
15161
15297
  seen.add(name);
15162
15298
  out.push({
15163
- infraId: (0, import_types45.infraId)("sql-table", name),
15299
+ infraId: (0, import_types46.infraId)("sql-table", name),
15164
15300
  name,
15165
15301
  kind: "sql-table",
15166
15302
  edgeType: "CALLS",
@@ -15190,11 +15326,11 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15190
15326
  function edgeTypeFromEndpoint(ep) {
15191
15327
  switch (ep.edgeType) {
15192
15328
  case "PUBLISHES_TO":
15193
- return import_types46.EdgeType.PUBLISHES_TO;
15329
+ return import_types47.EdgeType.PUBLISHES_TO;
15194
15330
  case "CONSUMES_FROM":
15195
- return import_types46.EdgeType.CONSUMES_FROM;
15331
+ return import_types47.EdgeType.CONSUMES_FROM;
15196
15332
  default:
15197
- return import_types46.EdgeType.CALLS;
15333
+ return import_types47.EdgeType.CALLS;
15198
15334
  }
15199
15335
  }
15200
15336
  function isAwsKind(kind) {
@@ -15265,7 +15401,7 @@ async function addExternalEndpointEdges(graph, services) {
15265
15401
  if (!graph.hasNode(ep.infraId)) {
15266
15402
  const node = {
15267
15403
  id: ep.infraId,
15268
- type: import_types46.NodeType.InfraNode,
15404
+ type: import_types47.NodeType.InfraNode,
15269
15405
  name: ep.name,
15270
15406
  // #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
15271
15407
  // aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
@@ -15278,21 +15414,21 @@ async function addExternalEndpointEdges(graph, services) {
15278
15414
  }
15279
15415
  if (ep.columns && ep.columns.length > 0) {
15280
15416
  const node = graph.getNodeAttributes(ep.infraId);
15281
- if (node.type === import_types46.NodeType.InfraNode) {
15417
+ if (node.type === import_types47.NodeType.InfraNode) {
15282
15418
  graph.replaceNodeAttributes(ep.infraId, {
15283
15419
  ...node,
15284
15420
  columns: foldColumns(
15285
15421
  node.columns,
15286
15422
  ep.columns,
15287
- import_types46.Provenance.EXTRACTED,
15288
- (0, import_types46.confidenceForExtracted)(ep.confidenceKind)
15423
+ import_types47.Provenance.EXTRACTED,
15424
+ (0, import_types47.confidenceForExtracted)(ep.confidenceKind)
15289
15425
  )
15290
15426
  });
15291
15427
  }
15292
15428
  }
15293
15429
  if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
15294
15430
  const node = graph.getNodeAttributes(ep.infraId);
15295
- if (node.type === import_types46.NodeType.InfraNode) {
15431
+ if (node.type === import_types47.NodeType.InfraNode) {
15296
15432
  graph.replaceNodeAttributes(ep.infraId, {
15297
15433
  ...node,
15298
15434
  columns: foldSdkWrites(node.columns, ep.sdkWrites)
@@ -15300,7 +15436,7 @@ async function addExternalEndpointEdges(graph, services) {
15300
15436
  }
15301
15437
  }
15302
15438
  const edgeType = edgeTypeFromEndpoint(ep);
15303
- const confidence = (0, import_types46.confidenceForExtracted)(ep.confidenceKind);
15439
+ const confidence = (0, import_types47.confidenceForExtracted)(ep.confidenceKind);
15304
15440
  const relFile = toPosix(ep.evidence.file);
15305
15441
  const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
15306
15442
  graph,
@@ -15310,7 +15446,7 @@ async function addExternalEndpointEdges(graph, services) {
15310
15446
  );
15311
15447
  nodesAdded += n;
15312
15448
  edgesAdded += e;
15313
- if (!(0, import_types46.passesExtractedFloor)(confidence)) {
15449
+ if (!(0, import_types47.passesExtractedFloor)(confidence)) {
15314
15450
  noteExtractedDropped({
15315
15451
  source: fileNodeId,
15316
15452
  target: ep.infraId,
@@ -15330,7 +15466,7 @@ async function addExternalEndpointEdges(graph, services) {
15330
15466
  source: fileNodeId,
15331
15467
  target: ep.infraId,
15332
15468
  type: edgeType,
15333
- provenance: import_types46.Provenance.EXTRACTED,
15469
+ provenance: import_types47.Provenance.EXTRACTED,
15334
15470
  confidence,
15335
15471
  evidence: ep.evidence
15336
15472
  };
@@ -15353,7 +15489,7 @@ async function addCallEdges(graph, services) {
15353
15489
 
15354
15490
  // src/extract/table-edges.ts
15355
15491
  init_cjs_shims();
15356
- var import_types47 = require("@neat.is/types");
15492
+ var import_types48 = require("@neat.is/types");
15357
15493
  async function addTableEdges(graph, services) {
15358
15494
  let nodesAdded = 0;
15359
15495
  let edgesAdded = 0;
@@ -15381,20 +15517,20 @@ async function addTableEdges(graph, services) {
15381
15517
  }
15382
15518
  refs.push(...modelRefs);
15383
15519
  for (const ref of refs) {
15384
- const childId = (0, import_types47.infraId)("sql-table", ref.childTable);
15385
- const parentId = (0, import_types47.infraId)("sql-table", ref.parentTable);
15520
+ const childId = (0, import_types48.infraId)("sql-table", ref.childTable);
15521
+ const parentId = (0, import_types48.infraId)("sql-table", ref.parentTable);
15386
15522
  if (childId === parentId) continue;
15387
15523
  nodesAdded += ensureTableNode(graph, childId, ref.childTable);
15388
15524
  nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
15389
- const edgeId = (0, import_types47.extractedEdgeId)(childId, parentId, import_types47.EdgeType.REFERENCES);
15525
+ const edgeId = (0, import_types48.extractedEdgeId)(childId, parentId, import_types48.EdgeType.REFERENCES);
15390
15526
  if (graph.hasEdge(edgeId)) continue;
15391
15527
  const edge = {
15392
15528
  id: edgeId,
15393
15529
  source: childId,
15394
15530
  target: parentId,
15395
- type: import_types47.EdgeType.REFERENCES,
15396
- provenance: import_types47.Provenance.EXTRACTED,
15397
- confidence: (0, import_types47.confidenceForExtracted)("structural"),
15531
+ type: import_types48.EdgeType.REFERENCES,
15532
+ provenance: import_types48.Provenance.EXTRACTED,
15533
+ confidence: (0, import_types48.confidenceForExtracted)("structural"),
15398
15534
  evidence: ref.evidence
15399
15535
  };
15400
15536
  graph.addEdgeWithKey(edgeId, childId, parentId, edge);
@@ -15407,7 +15543,7 @@ function ensureTableNode(graph, id, name) {
15407
15543
  if (graph.hasNode(id)) return 0;
15408
15544
  const node = {
15409
15545
  id,
15410
- type: import_types47.NodeType.InfraNode,
15546
+ type: import_types48.NodeType.InfraNode,
15411
15547
  name,
15412
15548
  provider: "self",
15413
15549
  kind: "sql-table"
@@ -15422,15 +15558,15 @@ init_cjs_shims();
15422
15558
  // src/extract/infra/docker-compose.ts
15423
15559
  init_cjs_shims();
15424
15560
  var import_node_path61 = __toESM(require("path"), 1);
15425
- var import_types49 = require("@neat.is/types");
15561
+ var import_types50 = require("@neat.is/types");
15426
15562
 
15427
15563
  // src/extract/infra/shared.ts
15428
15564
  init_cjs_shims();
15429
- var import_types48 = require("@neat.is/types");
15565
+ var import_types49 = require("@neat.is/types");
15430
15566
  function makeInfraNode(kind, name, provider = "self", extras) {
15431
15567
  return {
15432
- id: (0, import_types48.infraId)(kind, name),
15433
- type: import_types48.NodeType.InfraNode,
15568
+ id: (0, import_types49.infraId)(kind, name),
15569
+ type: import_types49.NodeType.InfraNode,
15434
15570
  name,
15435
15571
  provider,
15436
15572
  kind,
@@ -15474,8 +15610,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
15474
15610
  source: anchorId,
15475
15611
  target: node.id,
15476
15612
  type: edgeType,
15477
- provenance: import_types48.Provenance.EXTRACTED,
15478
- confidence: (0, import_types48.confidenceForExtracted)("structural"),
15613
+ provenance: import_types49.Provenance.EXTRACTED,
15614
+ confidence: (0, import_types49.confidenceForExtracted)("structural"),
15479
15615
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
15480
15616
  };
15481
15617
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15542,15 +15678,15 @@ async function addComposeInfra(graph, scanPath, services) {
15542
15678
  for (const dep of dependsOnList(svc.depends_on)) {
15543
15679
  const targetId = composeNameToNodeId.get(dep);
15544
15680
  if (!targetId) continue;
15545
- const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId, import_types49.EdgeType.DEPENDS_ON);
15681
+ const edgeId = (0, import_types4.extractedEdgeId)(sourceId, targetId, import_types50.EdgeType.DEPENDS_ON);
15546
15682
  if (graph.hasEdge(edgeId)) continue;
15547
15683
  const edge = {
15548
15684
  id: edgeId,
15549
15685
  source: sourceId,
15550
15686
  target: targetId,
15551
- type: import_types49.EdgeType.DEPENDS_ON,
15552
- provenance: import_types49.Provenance.EXTRACTED,
15553
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
15687
+ type: import_types50.EdgeType.DEPENDS_ON,
15688
+ provenance: import_types50.Provenance.EXTRACTED,
15689
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
15554
15690
  evidence: { file: evidenceFile }
15555
15691
  };
15556
15692
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15564,7 +15700,7 @@ async function addComposeInfra(graph, scanPath, services) {
15564
15700
  init_cjs_shims();
15565
15701
  var import_node_path62 = __toESM(require("path"), 1);
15566
15702
  var import_node_fs28 = require("fs");
15567
- var import_types50 = require("@neat.is/types");
15703
+ var import_types51 = require("@neat.is/types");
15568
15704
  function readDockerfile(content) {
15569
15705
  let image = null;
15570
15706
  const ports = [];
@@ -15623,15 +15759,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15623
15759
  );
15624
15760
  nodesAdded += fn;
15625
15761
  edgesAdded += fe;
15626
- const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types50.EdgeType.RUNS_ON);
15762
+ const edgeId = (0, import_types4.extractedEdgeId)(fileNodeId, node.id, import_types51.EdgeType.RUNS_ON);
15627
15763
  if (!graph.hasEdge(edgeId)) {
15628
15764
  const edge = {
15629
15765
  id: edgeId,
15630
15766
  source: fileNodeId,
15631
15767
  target: node.id,
15632
- type: import_types50.EdgeType.RUNS_ON,
15633
- provenance: import_types50.Provenance.EXTRACTED,
15634
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
15768
+ type: import_types51.EdgeType.RUNS_ON,
15769
+ provenance: import_types51.Provenance.EXTRACTED,
15770
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
15635
15771
  evidence: {
15636
15772
  file: evidenceFile,
15637
15773
  ...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
@@ -15646,15 +15782,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15646
15782
  graph.addNode(portNode.id, portNode);
15647
15783
  nodesAdded++;
15648
15784
  }
15649
- const portEdgeId = (0, import_types4.extractedEdgeId)(fileNodeId, portNode.id, import_types50.EdgeType.CONNECTS_TO);
15785
+ const portEdgeId = (0, import_types4.extractedEdgeId)(fileNodeId, portNode.id, import_types51.EdgeType.CONNECTS_TO);
15650
15786
  if (graph.hasEdge(portEdgeId)) continue;
15651
15787
  const portEdge = {
15652
15788
  id: portEdgeId,
15653
15789
  source: fileNodeId,
15654
15790
  target: portNode.id,
15655
- type: import_types50.EdgeType.CONNECTS_TO,
15656
- provenance: import_types50.Provenance.EXTRACTED,
15657
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
15791
+ type: import_types51.EdgeType.CONNECTS_TO,
15792
+ provenance: import_types51.Provenance.EXTRACTED,
15793
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
15658
15794
  evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
15659
15795
  };
15660
15796
  graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
@@ -15668,7 +15804,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15668
15804
  init_cjs_shims();
15669
15805
  var import_node_fs29 = require("fs");
15670
15806
  var import_node_path63 = __toESM(require("path"), 1);
15671
- var import_types51 = require("@neat.is/types");
15807
+ var import_types52 = require("@neat.is/types");
15672
15808
  var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
15673
15809
  var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
15674
15810
  async function walkTfFiles(start, depth = 0, max = 5) {
@@ -15749,16 +15885,16 @@ async function addTerraformResources(graph, scanPath) {
15749
15885
  if (!target) continue;
15750
15886
  if (seen.has(target.nodeId)) continue;
15751
15887
  seen.add(target.nodeId);
15752
- const edgeId = (0, import_types4.extractedEdgeId)(resource.nodeId, target.nodeId, import_types51.EdgeType.DEPENDS_ON);
15888
+ const edgeId = (0, import_types4.extractedEdgeId)(resource.nodeId, target.nodeId, import_types52.EdgeType.DEPENDS_ON);
15753
15889
  if (graph.hasEdge(edgeId)) continue;
15754
15890
  const line = lineAt2(content, resource.bodyOffset + ref.index);
15755
15891
  const edge = {
15756
15892
  id: edgeId,
15757
15893
  source: resource.nodeId,
15758
15894
  target: target.nodeId,
15759
- type: import_types51.EdgeType.DEPENDS_ON,
15760
- provenance: import_types51.Provenance.EXTRACTED,
15761
- confidence: (0, import_types51.confidenceForExtracted)("structural"),
15895
+ type: import_types52.EdgeType.DEPENDS_ON,
15896
+ provenance: import_types52.Provenance.EXTRACTED,
15897
+ confidence: (0, import_types52.confidenceForExtracted)("structural"),
15762
15898
  evidence: { file: evidenceFile, line, snippet: key }
15763
15899
  };
15764
15900
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15774,7 +15910,7 @@ init_cjs_shims();
15774
15910
  var import_node_fs30 = require("fs");
15775
15911
  var import_node_path64 = __toESM(require("path"), 1);
15776
15912
  var import_yaml3 = require("yaml");
15777
- var import_types52 = require("@neat.is/types");
15913
+ var import_types53 = require("@neat.is/types");
15778
15914
  var K8S_KIND_TO_INFRA_KIND = {
15779
15915
  Service: "k8s-service",
15780
15916
  Deployment: "k8s-deployment",
@@ -15834,7 +15970,7 @@ async function addK8sResources(graph, scanPath) {
15834
15970
  nodesAdded++;
15835
15971
  }
15836
15972
  if (isWorkload) {
15837
- const svcId = (0, import_types52.serviceId)(name);
15973
+ const svcId = (0, import_types53.serviceId)(name);
15838
15974
  if (graph.hasNode(svcId)) {
15839
15975
  const svc = graph.getNodeAttributes(svcId);
15840
15976
  graph.replaceNodeAttributes(svcId, {
@@ -15846,7 +15982,7 @@ async function addK8sResources(graph, scanPath) {
15846
15982
  edgesAdded += emitPlatformResourceEdge(
15847
15983
  graph,
15848
15984
  svcId,
15849
- import_types52.EdgeType.RUNS_ON,
15985
+ import_types53.EdgeType.RUNS_ON,
15850
15986
  infraKind,
15851
15987
  name,
15852
15988
  "kubernetes",
@@ -15865,7 +16001,7 @@ init_cjs_shims();
15865
16001
  var import_node_fs31 = require("fs");
15866
16002
  var import_node_path65 = __toESM(require("path"), 1);
15867
16003
  var import_smol_toml3 = require("smol-toml");
15868
- var import_types53 = require("@neat.is/types");
16004
+ var import_types54 = require("@neat.is/types");
15869
16005
  var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
15870
16006
  async function readWranglerConfig(dir) {
15871
16007
  for (const filename of WRANGLER_FILENAMES) {
@@ -15913,8 +16049,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
15913
16049
  source: anchorId,
15914
16050
  target: node.id,
15915
16051
  type: edgeType,
15916
- provenance: import_types53.Provenance.EXTRACTED,
15917
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16052
+ provenance: import_types54.Provenance.EXTRACTED,
16053
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
15918
16054
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
15919
16055
  };
15920
16056
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15975,15 +16111,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15975
16111
  nodesAdded++;
15976
16112
  }
15977
16113
  if (runtimeNode.id !== anchorId) {
15978
- const runsOnId = (0, import_types4.extractedEdgeId)(anchorId, runtimeNode.id, import_types53.EdgeType.RUNS_ON);
16114
+ const runsOnId = (0, import_types4.extractedEdgeId)(anchorId, runtimeNode.id, import_types54.EdgeType.RUNS_ON);
15979
16115
  if (!graph.hasEdge(runsOnId)) {
15980
16116
  const edge = {
15981
16117
  id: runsOnId,
15982
16118
  source: anchorId,
15983
16119
  target: runtimeNode.id,
15984
- type: import_types53.EdgeType.RUNS_ON,
15985
- provenance: import_types53.Provenance.EXTRACTED,
15986
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16120
+ type: import_types54.EdgeType.RUNS_ON,
16121
+ provenance: import_types54.Provenance.EXTRACTED,
16122
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
15987
16123
  evidence: {
15988
16124
  file: evidenceFile,
15989
16125
  ...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
@@ -15997,7 +16133,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15997
16133
  const result = addResourceEdge(
15998
16134
  graph,
15999
16135
  anchorId,
16000
- import_types53.EdgeType.CONNECTS_TO,
16136
+ import_types54.EdgeType.CONNECTS_TO,
16001
16137
  "cloudflare-route",
16002
16138
  route,
16003
16139
  evidenceFile,
@@ -16021,7 +16157,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16021
16157
  const result = addResourceEdge(
16022
16158
  graph,
16023
16159
  anchorId,
16024
- import_types53.EdgeType.DEPENDS_ON,
16160
+ import_types54.EdgeType.DEPENDS_ON,
16025
16161
  group.kind,
16026
16162
  name,
16027
16163
  evidenceFile,
@@ -16035,7 +16171,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16035
16171
  const result = addResourceEdge(
16036
16172
  graph,
16037
16173
  anchorId,
16038
- import_types53.EdgeType.DEPENDS_ON,
16174
+ import_types54.EdgeType.DEPENDS_ON,
16039
16175
  "cloudflare-cron",
16040
16176
  cron,
16041
16177
  evidenceFile,
@@ -16048,7 +16184,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16048
16184
  const result = addResourceEdge(
16049
16185
  graph,
16050
16186
  anchorId,
16051
- import_types53.EdgeType.DEPENDS_ON,
16187
+ import_types54.EdgeType.DEPENDS_ON,
16052
16188
  "cloudflare-env-var",
16053
16189
  varName,
16054
16190
  evidenceFile,
@@ -16061,15 +16197,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16061
16197
  if (!svc.service) continue;
16062
16198
  const target = workerIndex.get(svc.service);
16063
16199
  if (target && target.anchorId !== anchorId) {
16064
- const edgeId = (0, import_types4.extractedEdgeId)(anchorId, target.anchorId, import_types53.EdgeType.CALLS);
16200
+ const edgeId = (0, import_types4.extractedEdgeId)(anchorId, target.anchorId, import_types54.EdgeType.CALLS);
16065
16201
  if (!graph.hasEdge(edgeId)) {
16066
16202
  const edge = {
16067
16203
  id: edgeId,
16068
16204
  source: anchorId,
16069
16205
  target: target.anchorId,
16070
- type: import_types53.EdgeType.CALLS,
16071
- provenance: import_types53.Provenance.EXTRACTED,
16072
- confidence: (0, import_types53.confidenceForExtracted)("structural"),
16206
+ type: import_types54.EdgeType.CALLS,
16207
+ provenance: import_types54.Provenance.EXTRACTED,
16208
+ confidence: (0, import_types54.confidenceForExtracted)("structural"),
16073
16209
  evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
16074
16210
  };
16075
16211
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16080,7 +16216,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16080
16216
  const result = addResourceEdge(
16081
16217
  graph,
16082
16218
  anchorId,
16083
- import_types53.EdgeType.DEPENDS_ON,
16219
+ import_types54.EdgeType.DEPENDS_ON,
16084
16220
  "cloudflare-service-binding",
16085
16221
  svc.service,
16086
16222
  evidenceFile,
@@ -16097,7 +16233,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16097
16233
  init_cjs_shims();
16098
16234
  var import_node_fs32 = require("fs");
16099
16235
  var import_node_path66 = __toESM(require("path"), 1);
16100
- var import_types54 = require("@neat.is/types");
16236
+ var import_types55 = require("@neat.is/types");
16101
16237
  var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
16102
16238
  async function readVercelConfig(dir) {
16103
16239
  for (const filename of VERCEL_CONFIG_FILENAMES) {
@@ -16160,12 +16296,12 @@ async function addVercelServices(graph, services, scanPath) {
16160
16296
  nodesAdded += result.nodesAdded;
16161
16297
  edgesAdded += result.edgesAdded;
16162
16298
  };
16163
- add(import_types54.EdgeType.RUNS_ON, "vercel", "vercel");
16164
- for (const cron of config.crons ?? []) add(import_types54.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16165
- for (const varName of Object.keys(config.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16166
- for (const varName of Object.keys(config.build?.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16299
+ add(import_types55.EdgeType.RUNS_ON, "vercel", "vercel");
16300
+ for (const cron of config.crons ?? []) add(import_types55.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16301
+ for (const varName of Object.keys(config.env ?? {})) add(import_types55.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16302
+ for (const varName of Object.keys(config.build?.env ?? {})) add(import_types55.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16167
16303
  for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
16168
- add(import_types54.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16304
+ add(import_types55.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16169
16305
  }
16170
16306
  }
16171
16307
  return { nodesAdded, edgesAdded };
@@ -16176,7 +16312,7 @@ init_cjs_shims();
16176
16312
  var import_node_fs33 = require("fs");
16177
16313
  var import_node_path67 = __toESM(require("path"), 1);
16178
16314
  var import_smol_toml4 = require("smol-toml");
16179
- var import_types55 = require("@neat.is/types");
16315
+ var import_types56 = require("@neat.is/types");
16180
16316
  var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
16181
16317
  async function readRailwayConfig(dir) {
16182
16318
  for (const filename of RAILWAY_FILENAMES) {
@@ -16222,9 +16358,9 @@ async function addRailwayServices(graph, services, scanPath) {
16222
16358
  nodesAdded += result.nodesAdded;
16223
16359
  edgesAdded += result.edgesAdded;
16224
16360
  };
16225
- add(import_types55.EdgeType.RUNS_ON, "railway", "railway");
16226
- add(import_types55.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16227
- add(import_types55.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16361
+ add(import_types56.EdgeType.RUNS_ON, "railway", "railway");
16362
+ add(import_types56.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16363
+ add(import_types56.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16228
16364
  }
16229
16365
  return { nodesAdded, edgesAdded };
16230
16366
  }
@@ -16234,7 +16370,7 @@ init_cjs_shims();
16234
16370
  var import_node_fs34 = require("fs");
16235
16371
  var import_node_path68 = __toESM(require("path"), 1);
16236
16372
  var import_smol_toml5 = require("smol-toml");
16237
- var import_types56 = require("@neat.is/types");
16373
+ var import_types57 = require("@neat.is/types");
16238
16374
  async function readSupabaseConfig(dir) {
16239
16375
  const relFile = import_node_path68.default.join("supabase", "config.toml");
16240
16376
  const abs = import_node_path68.default.join(dir, relFile);
@@ -16282,10 +16418,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
16282
16418
  nodesAdded += result.nodesAdded;
16283
16419
  edgesAdded += result.edgesAdded;
16284
16420
  };
16285
- add(import_types56.EdgeType.RUNS_ON, "supabase", "supabase");
16286
- for (const fn of Object.keys(config.functions ?? {})) add(import_types56.EdgeType.DEPENDS_ON, "supabase-function", fn);
16287
- if (config.storage) add(import_types56.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16288
- if (config.auth) add(import_types56.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16421
+ add(import_types57.EdgeType.RUNS_ON, "supabase", "supabase");
16422
+ for (const fn of Object.keys(config.functions ?? {})) add(import_types57.EdgeType.DEPENDS_ON, "supabase-function", fn);
16423
+ if (config.storage) add(import_types57.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16424
+ if (config.auth) add(import_types57.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16289
16425
  }
16290
16426
  return { nodesAdded, edgesAdded };
16291
16427
  }
@@ -16311,7 +16447,7 @@ init_cjs_shims();
16311
16447
  var import_node_path69 = __toESM(require("path"), 1);
16312
16448
  var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
16313
16449
  var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
16314
- var import_types57 = require("@neat.is/types");
16450
+ var import_types58 = require("@neat.is/types");
16315
16451
  var ZOD_IMPORT_RE = /\bzod\b/;
16316
16452
  var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
16317
16453
  function parserForExt4(ext) {
@@ -16417,7 +16553,7 @@ function zodShapesFromFile(file, serviceDir) {
16417
16553
  seen.add(name);
16418
16554
  const line = call.startPosition.row + 1;
16419
16555
  out.push({
16420
- infraId: (0, import_types57.infraId)("zod-schema", name),
16556
+ infraId: (0, import_types58.infraId)("zod-schema", name),
16421
16557
  name,
16422
16558
  fields,
16423
16559
  evidence: {
@@ -16452,7 +16588,7 @@ async function addZodShapes(graph, services) {
16452
16588
  if (!graph.hasNode(shape.infraId)) {
16453
16589
  const node = {
16454
16590
  id: shape.infraId,
16455
- type: import_types57.NodeType.InfraNode,
16591
+ type: import_types58.NodeType.InfraNode,
16456
16592
  name: shape.name,
16457
16593
  provider: "self",
16458
16594
  kind: "zod-schema"
@@ -16462,14 +16598,14 @@ async function addZodShapes(graph, services) {
16462
16598
  }
16463
16599
  if (shape.fields.length > 0) {
16464
16600
  const node = graph.getNodeAttributes(shape.infraId);
16465
- if (node.type === import_types57.NodeType.InfraNode) {
16601
+ if (node.type === import_types58.NodeType.InfraNode) {
16466
16602
  graph.replaceNodeAttributes(shape.infraId, {
16467
16603
  ...node,
16468
16604
  columns: foldColumns(
16469
16605
  node.columns,
16470
16606
  shape.fields,
16471
- import_types57.Provenance.EXTRACTED,
16472
- (0, import_types57.confidenceForExtracted)("structural")
16607
+ import_types58.Provenance.EXTRACTED,
16608
+ (0, import_types58.confidenceForExtracted)("structural")
16473
16609
  )
16474
16610
  });
16475
16611
  }
@@ -16483,15 +16619,15 @@ async function addZodShapes(graph, services) {
16483
16619
  );
16484
16620
  nodesAdded += n;
16485
16621
  edgesAdded += e;
16486
- const edgeId = (0, import_types57.extractedEdgeId)(fileNodeId, shape.infraId, import_types57.EdgeType.CONTAINS);
16622
+ const edgeId = (0, import_types58.extractedEdgeId)(fileNodeId, shape.infraId, import_types58.EdgeType.CONTAINS);
16487
16623
  if (!graph.hasEdge(edgeId)) {
16488
16624
  const edge = {
16489
16625
  id: edgeId,
16490
16626
  source: fileNodeId,
16491
16627
  target: shape.infraId,
16492
- type: import_types57.EdgeType.CONTAINS,
16493
- provenance: import_types57.Provenance.EXTRACTED,
16494
- confidence: (0, import_types57.confidenceForExtracted)("structural"),
16628
+ type: import_types58.EdgeType.CONTAINS,
16629
+ provenance: import_types58.Provenance.EXTRACTED,
16630
+ confidence: (0, import_types58.confidenceForExtracted)("structural"),
16495
16631
  evidence: shape.evidence
16496
16632
  };
16497
16633
  graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
@@ -16505,7 +16641,7 @@ async function addZodShapes(graph, services) {
16505
16641
 
16506
16642
  // src/extract/firestore-rules.ts
16507
16643
  init_cjs_shims();
16508
- var import_types58 = require("@neat.is/types");
16644
+ var import_types59 = require("@neat.is/types");
16509
16645
  var FIRESTORE_COLLECTION_KIND = "firestore-collection";
16510
16646
  var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
16511
16647
  function stripComments(src) {
@@ -16676,7 +16812,7 @@ async function addFirestoreRules(graph, services) {
16676
16812
  if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
16677
16813
  graph.forEachNode((id, attrs) => {
16678
16814
  const node = attrs;
16679
- if (node.type !== import_types58.NodeType.InfraNode) return;
16815
+ if (node.type !== import_types59.NodeType.InfraNode) return;
16680
16816
  if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
16681
16817
  const fields = guards.get(collectionKeyFromName(node.name));
16682
16818
  if (!fields || fields.size === 0) return;
@@ -16695,12 +16831,12 @@ var import_node_path71 = __toESM(require("path"), 1);
16695
16831
  init_cjs_shims();
16696
16832
  var import_node_fs35 = require("fs");
16697
16833
  var import_node_path70 = __toESM(require("path"), 1);
16698
- var import_types59 = require("@neat.is/types");
16834
+ var import_types60 = require("@neat.is/types");
16699
16835
  function dropOrphanedFileNodes(graph, source) {
16700
16836
  const orphans = [];
16701
16837
  graph.forEachNode((id, attrs) => {
16702
16838
  const node = attrs;
16703
- if (node.type !== import_types59.NodeType.FileNode) return;
16839
+ if (node.type !== import_types60.NodeType.FileNode) return;
16704
16840
  if (source && node.source !== source) return;
16705
16841
  if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
16706
16842
  orphans.push(id);
@@ -16714,7 +16850,7 @@ function retireEdgesByFile(graph, file) {
16714
16850
  const toDrop = [];
16715
16851
  graph.forEachEdge((id, attrs) => {
16716
16852
  const edge = attrs;
16717
- if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
16853
+ if (edge.provenance !== import_types60.Provenance.EXTRACTED) return;
16718
16854
  if (!edge.evidence?.file) return;
16719
16855
  if (edge.evidence.file === normalized) toDrop.push(id);
16720
16856
  });
@@ -16727,7 +16863,7 @@ function outOfScope(graph, edge, source) {
16727
16863
  for (const endpoint2 of [edge.source, edge.target]) {
16728
16864
  if (!graph.hasNode(endpoint2)) continue;
16729
16865
  const node = graph.getNodeAttributes(endpoint2);
16730
- if (node.type !== import_types59.NodeType.FileNode) continue;
16866
+ if (node.type !== import_types60.NodeType.FileNode) continue;
16731
16867
  return node.source !== source;
16732
16868
  }
16733
16869
  return false;
@@ -16737,7 +16873,7 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
16737
16873
  const bases = [scanPath, ...serviceDirs];
16738
16874
  graph.forEachEdge((id, attrs) => {
16739
16875
  const edge = attrs;
16740
- if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
16876
+ if (edge.provenance !== import_types60.Provenance.EXTRACTED) return;
16741
16877
  if (outOfScope(graph, edge, source)) return;
16742
16878
  const evidenceFile = edge.evidence?.file;
16743
16879
  if (!evidenceFile) return;
@@ -16756,7 +16892,23 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
16756
16892
  // src/extract/index.ts
16757
16893
  var passQueue = Promise.resolve();
16758
16894
  function extractFromDirectory(graph, scanPath, opts = {}) {
16759
- const pass = passQueue.then(() => runExtractionPass(graph, scanPath, opts));
16895
+ invalidateSourceBaseline(graph, opts.source, "syncing");
16896
+ const pass = passQueue.then(async () => {
16897
+ const sourceGeneration = beginSourceExtraction(graph, opts.source, opts.sourceCommit);
16898
+ let result;
16899
+ try {
16900
+ result = await runExtractionPass(graph, scanPath, opts);
16901
+ return result;
16902
+ } finally {
16903
+ finishSourceExtraction(
16904
+ graph,
16905
+ sourceGeneration,
16906
+ opts.source,
16907
+ opts.sourceCommit,
16908
+ result ?? { extractionErrors: 1, skippedFiles: 0 }
16909
+ );
16910
+ }
16911
+ });
16760
16912
  passQueue = pass.catch(() => {
16761
16913
  });
16762
16914
  return pass;
@@ -16850,39 +17002,39 @@ async function runExtractionPass(graph, scanPath, opts) {
16850
17002
 
16851
17003
  // src/divergences.ts
16852
17004
  init_cjs_shims();
16853
- var import_types60 = require("@neat.is/types");
17005
+ var import_types61 = require("@neat.is/types");
16854
17006
  function bucketKey(source, target, type) {
16855
17007
  return `${type}|${source}|${target}`;
16856
17008
  }
16857
17009
  function bucketSourceFor(graph, edge) {
16858
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) return edge.source;
16859
- const parsed = (0, import_types60.parseFileId)(edge.source);
17010
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) return edge.source;
17011
+ const parsed = (0, import_types61.parseFileId)(edge.source);
16860
17012
  if (!parsed || !graph.hasNode(edge.target)) return edge.source;
16861
17013
  const target = graph.getNodeAttributes(edge.target);
16862
- if (target.type !== import_types60.NodeType.DatabaseNode) return edge.source;
16863
- return (0, import_types60.serviceId)(parsed.service);
17014
+ if (target.type !== import_types61.NodeType.DatabaseNode) return edge.source;
17015
+ return (0, import_types61.serviceId)(parsed.service);
16864
17016
  }
16865
17017
  function bucketEdges(graph) {
16866
17018
  const buckets2 = /* @__PURE__ */ new Map();
16867
17019
  graph.forEachEdge((id, attrs) => {
16868
17020
  const e = attrs;
16869
- const parsed = (0, import_types60.parseEdgeId)(id);
17021
+ const parsed = (0, import_types61.parseEdgeId)(id);
16870
17022
  const provenance2 = parsed?.provenance ?? e.provenance;
16871
17023
  const source = bucketSourceFor(graph, e);
16872
17024
  const key = bucketKey(source, e.target, e.type);
16873
17025
  const cur = buckets2.get(key) ?? { source, target: e.target, type: e.type };
16874
17026
  switch (provenance2) {
16875
- case import_types60.Provenance.EXTRACTED:
17027
+ case import_types61.Provenance.EXTRACTED:
16876
17028
  cur.extracted = e;
16877
17029
  break;
16878
- case import_types60.Provenance.OBSERVED:
17030
+ case import_types61.Provenance.OBSERVED:
16879
17031
  cur.observed = e;
16880
17032
  break;
16881
- case import_types60.Provenance.INFERRED:
17033
+ case import_types61.Provenance.INFERRED:
16882
17034
  cur.inferred = e;
16883
17035
  break;
16884
17036
  default:
16885
- if (e.provenance === import_types60.Provenance.STALE) cur.stale = e;
17037
+ if (e.provenance === import_types61.Provenance.STALE) cur.stale = e;
16886
17038
  }
16887
17039
  buckets2.set(key, cur);
16888
17040
  });
@@ -16891,22 +17043,22 @@ function bucketEdges(graph) {
16891
17043
  function nodeIsFrontier(graph, nodeId) {
16892
17044
  if (!graph.hasNode(nodeId)) return false;
16893
17045
  const attrs = graph.getNodeAttributes(nodeId);
16894
- return attrs.type === import_types60.NodeType.FrontierNode;
17046
+ return attrs.type === import_types61.NodeType.FrontierNode;
16895
17047
  }
16896
17048
  function nodeIsWebsocketChannel(graph, nodeId) {
16897
17049
  if (!graph.hasNode(nodeId)) return false;
16898
17050
  const attrs = graph.getNodeAttributes(nodeId);
16899
- return attrs.type === import_types60.NodeType.WebSocketChannelNode;
17051
+ return attrs.type === import_types61.NodeType.WebSocketChannelNode;
16900
17052
  }
16901
17053
  function nodeIsServerAction(graph, nodeId) {
16902
17054
  if (!graph.hasNode(nodeId)) return false;
16903
17055
  const attrs = graph.getNodeAttributes(nodeId);
16904
- return attrs.type === import_types60.NodeType.ServerActionNode;
17056
+ return attrs.type === import_types61.NodeType.ServerActionNode;
16905
17057
  }
16906
17058
  function nodeIsSymbol(graph, nodeId) {
16907
17059
  if (!graph.hasNode(nodeId)) return false;
16908
17060
  const attrs = graph.getNodeAttributes(nodeId);
16909
- return attrs.type === import_types60.NodeType.SymbolNode;
17061
+ return attrs.type === import_types61.NodeType.SymbolNode;
16910
17062
  }
16911
17063
  function clampConfidence(n) {
16912
17064
  if (!Number.isFinite(n)) return 0;
@@ -16926,14 +17078,14 @@ function gradedConfidence(edge) {
16926
17078
  return clampConfidence(confidenceForEdge(edge));
16927
17079
  }
16928
17080
  var OBSERVABLE_EDGE_TYPES = /* @__PURE__ */ new Set([
16929
- import_types60.EdgeType.CALLS,
16930
- import_types60.EdgeType.CONNECTS_TO,
16931
- import_types60.EdgeType.PUBLISHES_TO,
16932
- import_types60.EdgeType.CONSUMES_FROM
17081
+ import_types61.EdgeType.CALLS,
17082
+ import_types61.EdgeType.CONNECTS_TO,
17083
+ import_types61.EdgeType.PUBLISHES_TO,
17084
+ import_types61.EdgeType.CONSUMES_FROM
16933
17085
  ]);
16934
17086
  function detectMissingDivergences(graph, bucket) {
16935
17087
  const out = [];
16936
- if (bucket.type === import_types60.EdgeType.CONTAINS) return out;
17088
+ if (bucket.type === import_types61.EdgeType.CONTAINS) return out;
16937
17089
  if (nodeIsSymbol(graph, bucket.source) || nodeIsSymbol(graph, bucket.target)) return out;
16938
17090
  if (bucket.extracted && !bucket.observed && OBSERVABLE_EDGE_TYPES.has(bucket.type)) {
16939
17091
  if (!nodeIsFrontier(graph, bucket.target) && !nodeIsServerAction(graph, bucket.target)) {
@@ -16975,7 +17127,7 @@ function declaredHostFor(svc) {
16975
17127
  function hasExtractedConfiguredBy(graph, svcId) {
16976
17128
  for (const edgeId of graph.outboundEdges(svcId)) {
16977
17129
  const e = graph.getEdgeAttributes(edgeId);
16978
- if (e.type === import_types60.EdgeType.CONFIGURED_BY && e.provenance === import_types60.Provenance.EXTRACTED) {
17130
+ if (e.type === import_types61.EdgeType.CONFIGURED_BY && e.provenance === import_types61.Provenance.EXTRACTED) {
16979
17131
  return true;
16980
17132
  }
16981
17133
  }
@@ -16988,10 +17140,10 @@ function detectHostMismatch(graph, svcId, svc) {
16988
17140
  const out = [];
16989
17141
  for (const edgeId of graph.outboundEdges(svcId)) {
16990
17142
  const edge = graph.getEdgeAttributes(edgeId);
16991
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) continue;
16992
- if (edge.provenance !== import_types60.Provenance.OBSERVED) continue;
17143
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17144
+ if (edge.provenance !== import_types61.Provenance.OBSERVED) continue;
16993
17145
  const target = graph.getNodeAttributes(edge.target);
16994
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17146
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
16995
17147
  const observedHost = target.host?.trim();
16996
17148
  if (!observedHost) continue;
16997
17149
  if (observedHost === declaredHost) continue;
@@ -17013,10 +17165,10 @@ function detectCompatDivergences(graph, svcId, svc) {
17013
17165
  const deps = svc.dependencies ?? {};
17014
17166
  for (const edgeId of graph.outboundEdges(svcId)) {
17015
17167
  const edge = graph.getEdgeAttributes(edgeId);
17016
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) continue;
17017
- if (edge.provenance !== import_types60.Provenance.OBSERVED) continue;
17168
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17169
+ if (edge.provenance !== import_types61.Provenance.OBSERVED) continue;
17018
17170
  const target = graph.getNodeAttributes(edge.target);
17019
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17171
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
17020
17172
  for (const pair of compatPairs()) {
17021
17173
  if (pair.engine !== target.engine) continue;
17022
17174
  const declared = deps[pair.driver];
@@ -17179,11 +17331,11 @@ function symbolLocus(graph, ev) {
17179
17331
  const location = filepath ? `${filepath}${lineno !== void 0 ? `:${lineno}` : ""}` : void 0;
17180
17332
  const affected = ev.affectedNode;
17181
17333
  const affectedInGraph = affected.length > 0 && graph.hasNode(affected);
17182
- const affectedIsCode = affectedInGraph && ((0, import_types60.parseSymbolId)(affected) !== null || (0, import_types60.parseFileId)(affected) !== null);
17334
+ const affectedIsCode = affectedInGraph && ((0, import_types61.parseSymbolId)(affected) !== null || (0, import_types61.parseFileId)(affected) !== null);
17183
17335
  if (affectedIsCode) return { node: affected, ...location ? { location } : {} };
17184
17336
  if (!location) return null;
17185
17337
  if (affectedInGraph) return { node: affected, location };
17186
- const svc = (0, import_types60.serviceId)(ev.service);
17338
+ const svc = (0, import_types61.serviceId)(ev.service);
17187
17339
  if (graph.hasNode(svc)) return { node: svc, location };
17188
17340
  return null;
17189
17341
  }
@@ -17226,7 +17378,7 @@ function detectSymbolMismatches(graph, incidents) {
17226
17378
  mismatchKind: g.kind,
17227
17379
  ...g.symbol ? { symbol: g.symbol } : {},
17228
17380
  ...g.location ? { location: g.location } : {},
17229
- provenance: import_types60.Provenance.INFERRED,
17381
+ provenance: import_types61.Provenance.INFERRED,
17230
17382
  incidentId: g.latest.id,
17231
17383
  errorMessage: g.latest.errorMessage,
17232
17384
  incidentCount: g.count,
@@ -17243,7 +17395,7 @@ var OBSERVED_FAILING_CONFIDENCE = 0.6;
17243
17395
  function detectObservedFailingEdge(graph, bucket) {
17244
17396
  if (!bucket.extracted || !bucket.observed) return [];
17245
17397
  if (!OBSERVABLE_EDGE_TYPES.has(bucket.type)) return [];
17246
- if (bucket.observed.provenance !== import_types60.Provenance.OBSERVED) return [];
17398
+ if (bucket.observed.provenance !== import_types61.Provenance.OBSERVED) return [];
17247
17399
  const signal = bucket.observed.signal;
17248
17400
  if (!signal) return [];
17249
17401
  const { spanCount, errorCount } = signal;
@@ -17257,7 +17409,7 @@ function detectObservedFailingEdge(graph, bucket) {
17257
17409
  source: bucket.source,
17258
17410
  target: bucket.target,
17259
17411
  failureKind: "error-rate",
17260
- provenance: import_types60.Provenance.INFERRED,
17412
+ provenance: import_types61.Provenance.INFERRED,
17261
17413
  edgeType: bucket.type,
17262
17414
  observed: bucket.observed,
17263
17415
  spanCount,
@@ -17362,7 +17514,7 @@ function detectObservedFailingIncidents(graph, incidents) {
17362
17514
  source: g.node,
17363
17515
  target: g.node,
17364
17516
  failureKind: g.kind,
17365
- provenance: import_types60.Provenance.INFERRED,
17517
+ provenance: import_types61.Provenance.INFERRED,
17366
17518
  ...g.location ? { location: g.location } : {},
17367
17519
  incidentId: g.latest.id,
17368
17520
  errorMessage: g.latest.errorMessage,
@@ -17381,24 +17533,24 @@ function involvesNode(d, nodeId) {
17381
17533
  function datastoreEverObserved(graph, nodeId) {
17382
17534
  if (!graph.hasNode(nodeId)) return false;
17383
17535
  const n = graph.getNodeAttributes(nodeId);
17384
- if (n.type === import_types60.NodeType.DatabaseNode) {
17536
+ if (n.type === import_types61.NodeType.DatabaseNode) {
17385
17537
  const via = n.discoveredVia;
17386
17538
  if (via === "otel" || via === "merged") return true;
17387
17539
  }
17388
17540
  for (const edgeId of graph.inboundEdges(nodeId)) {
17389
17541
  const e = graph.getEdgeAttributes(edgeId);
17390
- if (e.provenance === import_types60.Provenance.OBSERVED || e.provenance === import_types60.Provenance.STALE) return true;
17542
+ if (e.provenance === import_types61.Provenance.OBSERVED || e.provenance === import_types61.Provenance.STALE) return true;
17391
17543
  }
17392
17544
  return false;
17393
17545
  }
17394
17546
  function serviceHasObservedSameEngineStore(graph, buckets2, serviceId17, engine, excludeTarget) {
17395
17547
  for (const bucket of buckets2.values()) {
17396
- if (bucket.type !== import_types60.EdgeType.CONNECTS_TO) continue;
17548
+ if (bucket.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17397
17549
  if (bucket.source !== serviceId17) continue;
17398
17550
  if (bucket.target === excludeTarget) continue;
17399
17551
  if (!graph.hasNode(bucket.target)) continue;
17400
17552
  const target = graph.getNodeAttributes(bucket.target);
17401
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17553
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
17402
17554
  if (target.engine !== engine) continue;
17403
17555
  if (bucket.observed || datastoreEverObserved(graph, bucket.target)) return true;
17404
17556
  }
@@ -17408,10 +17560,10 @@ var DEAD_CODE_PROBE_CONFIDENCE = 0.1;
17408
17560
  function dampenDeadCodeProbes(graph, buckets2, all) {
17409
17561
  return all.map((d) => {
17410
17562
  if (d.type !== "missing-observed") return d;
17411
- if (!d.extracted || d.edgeType !== import_types60.EdgeType.CONNECTS_TO) return d;
17563
+ if (!d.extracted || d.edgeType !== import_types61.EdgeType.CONNECTS_TO) return d;
17412
17564
  if (!graph.hasNode(d.target)) return d;
17413
17565
  const target = graph.getNodeAttributes(d.target);
17414
- if (target.type !== import_types60.NodeType.DatabaseNode) return d;
17566
+ if (target.type !== import_types61.NodeType.DatabaseNode) return d;
17415
17567
  if (d.extracted.evidence?.hostSource !== "literal") return d;
17416
17568
  if (datastoreEverObserved(graph, d.target)) return d;
17417
17569
  const engine = target.engine;
@@ -17431,7 +17583,7 @@ function suppressHostMismatchHalves(all) {
17431
17583
  for (const d of all) {
17432
17584
  if (d.type !== "host-mismatch") continue;
17433
17585
  observedHalf.add(`${d.source}->${d.target}`);
17434
- declaredHalf.add((0, import_types60.databaseId)(d.extractedHost));
17586
+ declaredHalf.add((0, import_types61.databaseId)(d.extractedHost));
17435
17587
  }
17436
17588
  if (observedHalf.size === 0) return all;
17437
17589
  return all.filter((d) => {
@@ -17451,14 +17603,14 @@ function computeDivergences(graph, opts = {}) {
17451
17603
  }
17452
17604
  graph.forEachNode((nodeId, attrs) => {
17453
17605
  const n = attrs;
17454
- if (n.type === import_types60.NodeType.ServiceNode) {
17606
+ if (n.type === import_types61.NodeType.ServiceNode) {
17455
17607
  const svc = n;
17456
17608
  for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
17457
17609
  for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
17458
17610
  for (const d of detectDeployDivergence(svc)) all.push(d);
17459
17611
  return;
17460
17612
  }
17461
- if (n.type === import_types60.NodeType.InfraNode && n.kind === "sql-table") {
17613
+ if (n.type === import_types61.NodeType.InfraNode && n.kind === "sql-table") {
17462
17614
  for (const d of detectColumnDrift(n)) all.push(d);
17463
17615
  }
17464
17616
  });
@@ -17523,7 +17675,7 @@ function computeDivergences(graph, opts = {}) {
17523
17675
  const bloc = "location" in b && b.location ? b.location : "";
17524
17676
  return aloc.localeCompare(bloc);
17525
17677
  });
17526
- return import_types60.DivergenceResultSchema.parse({
17678
+ return import_types61.DivergenceResultSchema.parse({
17527
17679
  divergences: filtered,
17528
17680
  totalAffected: filtered.length,
17529
17681
  computedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -17534,7 +17686,7 @@ function computeDivergences(graph, opts = {}) {
17534
17686
  init_cjs_shims();
17535
17687
  var import_node_fs36 = require("fs");
17536
17688
  var import_node_path72 = __toESM(require("path"), 1);
17537
- var import_types61 = require("@neat.is/types");
17689
+ var import_types62 = require("@neat.is/types");
17538
17690
  var SCHEMA_VERSION = 7;
17539
17691
  function migrateV1ToV2(payload) {
17540
17692
  const nodes = payload.graph.nodes;
@@ -17558,7 +17710,7 @@ function migrateV5ToV6(payload) {
17558
17710
  if (Array.isArray(nodes)) {
17559
17711
  for (const node of nodes) {
17560
17712
  const attrs = node.attributes;
17561
- if (!attrs || attrs.type !== import_types61.NodeType.InfraNode) continue;
17713
+ if (!attrs || attrs.type !== import_types62.NodeType.InfraNode) continue;
17562
17714
  if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
17563
17715
  if (!Array.isArray(attrs.columns)) attrs.columns = [];
17564
17716
  }
@@ -17574,12 +17726,12 @@ function migrateV2ToV3(payload) {
17574
17726
  for (const edge of edges) {
17575
17727
  const attrs = edge.attributes;
17576
17728
  if (!attrs || attrs.provenance !== "FRONTIER") continue;
17577
- attrs.provenance = import_types61.Provenance.OBSERVED;
17729
+ attrs.provenance = import_types62.Provenance.OBSERVED;
17578
17730
  const type = typeof attrs.type === "string" ? attrs.type : void 0;
17579
17731
  const source = typeof attrs.source === "string" ? attrs.source : void 0;
17580
17732
  const target = typeof attrs.target === "string" ? attrs.target : void 0;
17581
17733
  if (type && source && target) {
17582
- const newId = (0, import_types61.observedEdgeId)(source, target, type);
17734
+ const newId = (0, import_types62.observedEdgeId)(source, target, type);
17583
17735
  attrs.id = newId;
17584
17736
  if (edge.key) edge.key = newId;
17585
17737
  }
@@ -17767,7 +17919,7 @@ ${NEAT_OUT_LINE}
17767
17919
 
17768
17920
  // src/summary.ts
17769
17921
  init_cjs_shims();
17770
- var import_types62 = require("@neat.is/types");
17922
+ var import_types63 = require("@neat.is/types");
17771
17923
 
17772
17924
  // src/otlp-headers.ts
17773
17925
  init_cjs_shims();
@@ -17786,19 +17938,19 @@ function renderOtelEnvBlock() {
17786
17938
  }
17787
17939
  function findIncompatServices(nodes) {
17788
17940
  return nodes.filter(
17789
- (n) => n.type === import_types62.NodeType.ServiceNode && Array.isArray(n.incompatibilities) && (n.incompatibilities ?? []).length > 0
17941
+ (n) => n.type === import_types63.NodeType.ServiceNode && Array.isArray(n.incompatibilities) && (n.incompatibilities ?? []).length > 0
17790
17942
  );
17791
17943
  }
17792
17944
  function servicesWithoutObserved(nodes, edges) {
17793
17945
  const seen = /* @__PURE__ */ new Set();
17794
17946
  for (const e of edges) {
17795
- if (e.provenance === import_types62.Provenance.OBSERVED) {
17947
+ if (e.provenance === import_types63.Provenance.OBSERVED) {
17796
17948
  seen.add(e.source);
17797
17949
  seen.add(e.target);
17798
17950
  }
17799
17951
  }
17800
17952
  return nodes.filter(
17801
- (n) => n.type === import_types62.NodeType.ServiceNode && !seen.has(n.id)
17953
+ (n) => n.type === import_types63.NodeType.ServiceNode && !seen.has(n.id)
17802
17954
  );
17803
17955
  }
17804
17956
  function formatDivergence(d) {
@@ -17821,8 +17973,8 @@ function computeLanguageCoverage(nodes, edges) {
17821
17973
  const nodeById = /* @__PURE__ */ new Map();
17822
17974
  for (const n of nodes) {
17823
17975
  nodeById.set(n.id, n);
17824
- if (n.type === import_types62.NodeType.ServiceNode) serviceLang.set(n.name, n.language);
17825
- else if (n.type === import_types62.NodeType.FileNode) fileService.set(n.id, n.service);
17976
+ if (n.type === import_types63.NodeType.ServiceNode) serviceLang.set(n.name, n.language);
17977
+ else if (n.type === import_types63.NodeType.FileNode) fileService.set(n.id, n.service);
17826
17978
  }
17827
17979
  const cov = /* @__PURE__ */ new Map();
17828
17980
  const ensure = (lang) => {
@@ -17835,25 +17987,25 @@ function computeLanguageCoverage(nodes, edges) {
17835
17987
  };
17836
17988
  for (const lang of serviceLang.values()) ensure(lang);
17837
17989
  for (const n of nodes) {
17838
- if (n.type === import_types62.NodeType.SymbolNode) {
17990
+ if (n.type === import_types63.NodeType.SymbolNode) {
17839
17991
  if (n.discoveredVia === "otel") continue;
17840
17992
  const lang = serviceLang.get(n.service);
17841
17993
  if (lang) ensure(lang).symbols = true;
17842
- } else if (n.type === import_types62.NodeType.RouteNode) {
17994
+ } else if (n.type === import_types63.NodeType.RouteNode) {
17843
17995
  if (n.discoveredVia === "otel") continue;
17844
17996
  const lang = serviceLang.get(n.service);
17845
17997
  if (lang) ensure(lang).routes = true;
17846
17998
  }
17847
17999
  }
17848
18000
  for (const e of edges) {
17849
- if (e.type !== import_types62.EdgeType.CALLS || e.provenance !== import_types62.Provenance.EXTRACTED) continue;
18001
+ if (e.type !== import_types63.EdgeType.CALLS || e.provenance !== import_types63.Provenance.EXTRACTED) continue;
17850
18002
  const svc = fileService.get(e.source);
17851
18003
  const lang = svc ? serviceLang.get(svc) : void 0;
17852
18004
  if (!lang) continue;
17853
18005
  const target = nodeById.get(e.target);
17854
18006
  if (!target) continue;
17855
- if (target.type === import_types62.NodeType.RouteNode) ensure(lang).crossServiceCalls = true;
17856
- else if (target.type === import_types62.NodeType.InfraNode && isTableInfra(target.kind)) ensure(lang).data = true;
18007
+ if (target.type === import_types63.NodeType.RouteNode) ensure(lang).crossServiceCalls = true;
18008
+ else if (target.type === import_types63.NodeType.InfraNode && isTableInfra(target.kind)) ensure(lang).data = true;
17857
18009
  }
17858
18010
  return cov;
17859
18011
  }
@@ -17953,7 +18105,7 @@ init_cjs_shims();
17953
18105
  var import_fastify2 = __toESM(require("fastify"), 1);
17954
18106
  var import_node_crypto6 = require("crypto");
17955
18107
  var import_cors = __toESM(require("@fastify/cors"), 1);
17956
- var import_types105 = require("@neat.is/types");
18108
+ var import_types106 = require("@neat.is/types");
17957
18109
 
17958
18110
  // src/extend/index.ts
17959
18111
  init_cjs_shims();
@@ -18345,10 +18497,40 @@ function queryLogEntries(opts) {
18345
18497
 
18346
18498
  // src/goodybag.ts
18347
18499
  init_cjs_shims();
18348
- var import_types63 = require("@neat.is/types");
18500
+ var import_types64 = require("@neat.is/types");
18349
18501
  var CODE_FILEPATH_ATTR2 = "code.filepath";
18350
18502
  var CODE_LINENO_ATTR2 = "code.lineno";
18351
18503
  var BLAST_NEAREST_LIMIT = 5;
18504
+ function deployContextOf(ev) {
18505
+ const a = ev.attributes;
18506
+ if (!a) return void 0;
18507
+ const str = (k) => typeof a[k] === "string" ? a[k] : void 0;
18508
+ const int = (k) => typeof a[k] === "number" && Number.isFinite(a[k]) ? Math.trunc(a[k]) : void 0;
18509
+ const strs = (k) => {
18510
+ const v = a[k];
18511
+ return Array.isArray(v) && v.every((x) => typeof x === "string") && v.length > 0 ? v : void 0;
18512
+ };
18513
+ const ctx = {};
18514
+ const fault = str("k8s.fault");
18515
+ if (fault) ctx.fault = fault;
18516
+ const waiting = str("k8s.waitingReason");
18517
+ if (waiting) ctx.waitingReason = waiting;
18518
+ const image = str("k8s.image");
18519
+ if (image) ctx.image = image;
18520
+ const restarts = int("k8s.restartCount");
18521
+ if (restarts !== void 0) ctx.restartCount = restarts;
18522
+ const termReason = str("k8s.terminatedReason");
18523
+ if (termReason) ctx.terminatedReason = termReason;
18524
+ const exitCode = int("k8s.exitCode");
18525
+ if (exitCode !== void 0) ctx.exitCode = exitCode;
18526
+ const env = strs("k8s.containerEnv");
18527
+ if (env) ctx.containerEnv = env;
18528
+ const args = strs("k8s.containerArgs");
18529
+ if (args) ctx.containerArgs = args;
18530
+ const log = str("k8s.processLog");
18531
+ if (log) ctx.processLog = log;
18532
+ return Object.keys(ctx).length > 0 ? ctx : void 0;
18533
+ }
18352
18534
  function grainOf2(graph, nodeId) {
18353
18535
  if (graph.hasNode(nodeId)) {
18354
18536
  const t = graph.getNodeAttributes(nodeId).type;
@@ -18371,7 +18553,7 @@ function locusOf(graph, ev) {
18371
18553
  ...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
18372
18554
  ...symbol ? { symbol } : {},
18373
18555
  service: node?.service ?? ev.service,
18374
- provenance: import_types63.Provenance.OBSERVED
18556
+ provenance: import_types64.Provenance.OBSERVED
18375
18557
  };
18376
18558
  }
18377
18559
  function locusFromNode(graph, nodeId) {
@@ -18387,7 +18569,7 @@ function locusFromNode(graph, nodeId) {
18387
18569
  ...typeof end === "number" ? { lineEnd: end } : {},
18388
18570
  ...n.qualname ? { symbol: shortLabel(graph, nodeId) } : {},
18389
18571
  ...n.service ? { service: n.service } : {},
18390
- provenance: import_types63.Provenance.INFERRED
18572
+ provenance: import_types64.Provenance.INFERRED
18391
18573
  };
18392
18574
  }
18393
18575
  function promoteCauseLocus(graph, causeNode, incidents) {
@@ -18396,11 +18578,16 @@ function promoteCauseLocus(graph, causeNode, incidents) {
18396
18578
  );
18397
18579
  if (native) {
18398
18580
  const l = locusOf(graph, native);
18399
- if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types63.Provenance.INFERRED };
18581
+ if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types64.Provenance.INFERRED };
18400
18582
  }
18401
18583
  return locusFromNode(graph, causeNode);
18402
18584
  }
18403
18585
  function divergenceSummary(d) {
18586
+ if (d.type === "observed-symbol-mismatch" || d.source === d.target) {
18587
+ const symbol = "symbol" in d && d.symbol ? d.symbol : d.source;
18588
+ const at = "location" in d && d.location ? ` at ${d.location}` : "";
18589
+ return `${symbol}${at}`;
18590
+ }
18404
18591
  const column = "column" in d && d.column ? `.${d.column}` : "";
18405
18592
  const label = "table" in d && d.table ? `${d.table}${column}` : `${d.source} \u2192 ${d.target}`;
18406
18593
  return label;
@@ -18445,7 +18632,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18445
18632
  const chain = (rc.traversalPath ?? []).map((node, i) => ({
18446
18633
  node,
18447
18634
  grain: grainOf2(graph, node),
18448
- provenance: provs[i] ?? provs[provs.length - 1] ?? import_types63.Provenance.INFERRED
18635
+ provenance: provs[i] ?? provs[provs.length - 1] ?? import_types64.Provenance.INFERRED
18449
18636
  }));
18450
18637
  rootCause = {
18451
18638
  node: rc.rootCauseNode,
@@ -18476,7 +18663,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18476
18663
  kind: "incident",
18477
18664
  id: errorEvent.id,
18478
18665
  at: errorEvent.timestamp,
18479
- incidentKind: (0, import_types63.incidentKindOf)(errorEvent),
18666
+ incidentKind: (0, import_types64.incidentKindOf)(errorEvent),
18480
18667
  service: errorEvent.service,
18481
18668
  affectedNode: affected,
18482
18669
  message: errorEvent.errorMessage,
@@ -18491,10 +18678,14 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18491
18678
  ...nearest.length > 0 ? { blastRadius: { totalAffected: blast.totalAffected, nearest } } : {},
18492
18679
  ...policyCards.length > 0 ? { policies: policyCards } : {},
18493
18680
  ...divergences.length > 0 ? { divergence: divergences } : {},
18681
+ ...(() => {
18682
+ const dc = deployContextOf(errorEvent);
18683
+ return dc ? { deployContext: dc } : {};
18684
+ })(),
18494
18685
  headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
18495
18686
  };
18496
18687
  card.grade = gradeIncidentCard(card);
18497
- return import_types63.IncidentCardSchema.parse(card);
18688
+ return import_types64.IncidentCardSchema.parse(card);
18498
18689
  }
18499
18690
  var GRADE_PRIORS_VERSION = "sniper-architecture-priors-2026-10-08";
18500
18691
  var GRADE_WEIGHTS = {
@@ -18601,7 +18792,7 @@ function gradeIncidentCard(card) {
18601
18792
 
18602
18793
  // src/ask.ts
18603
18794
  init_cjs_shims();
18604
- var import_types64 = require("@neat.is/types");
18795
+ var import_types65 = require("@neat.is/types");
18605
18796
  var DEFAULT_MAX_NODES = 3;
18606
18797
  var MAX_FACTS_PER_SECTION = 6;
18607
18798
  var INTENT_RULES = [
@@ -18837,14 +19028,23 @@ function idBody(id) {
18837
19028
  return colon >= 0 ? id.slice(colon + 1) : id;
18838
19029
  }
18839
19030
  var TYPE_NOUNS = [
18840
- { nouns: ["database", "db", "table"], type: import_types64.NodeType.DatabaseNode },
18841
- { nouns: ["service", "api", "backend"], type: import_types64.NodeType.ServiceNode },
18842
- { nouns: ["route", "endpoint"], type: import_types64.NodeType.RouteNode },
18843
- { nouns: ["file"], type: import_types64.NodeType.FileNode },
18844
- { nouns: ["config"], type: import_types64.NodeType.ConfigNode }
19031
+ { nouns: ["database", "db", "table"], type: import_types65.NodeType.DatabaseNode },
19032
+ { nouns: ["service", "api", "backend"], type: import_types65.NodeType.ServiceNode },
19033
+ { nouns: ["route", "endpoint"], type: import_types65.NodeType.RouteNode },
19034
+ { nouns: ["file"], type: import_types65.NodeType.FileNode },
19035
+ { nouns: ["config"], type: import_types65.NodeType.ConfigNode }
18845
19036
  ];
18846
19037
  var EMBED_MIN_SCORE = 0.35;
18847
19038
  async function resolveEntities(graph, question, searchIndex, maxNodes) {
19039
+ const verbatim = [];
19040
+ for (const word of question.split(/\s+/)) {
19041
+ const id = word.replace(/^["'`(<]+|["'`)>?!.,;]+$/g, "");
19042
+ if (!id || !graph.hasNode(id) || verbatim.some((m) => m.nodeId === id)) continue;
19043
+ const node = graph.getNodeAttributes(id);
19044
+ if (node.type === import_types65.NodeType.FrontierNode) continue;
19045
+ verbatim.push({ nodeId: id, label: nodeName(node), via: "id", score: 1 });
19046
+ }
19047
+ if (verbatim.length > 0) return { matched: verbatim.slice(0, maxNodes) };
18848
19048
  const qTokens = queryTokens(question);
18849
19049
  const normalized = question.toLowerCase();
18850
19050
  const best = /* @__PURE__ */ new Map();
@@ -18855,7 +19055,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18855
19055
  };
18856
19056
  graph.forEachNode((id, attrs) => {
18857
19057
  const node = attrs;
18858
- if (node.type === import_types64.NodeType.FrontierNode) return;
19058
+ if (node.type === import_types65.NodeType.FrontierNode) return;
18859
19059
  const name = nodeName(node);
18860
19060
  const body = idBody(id);
18861
19061
  const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
@@ -18874,7 +19074,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18874
19074
  const res = await searchIndex.search(question, 10);
18875
19075
  if (res.provider !== "substring") {
18876
19076
  for (const m of res.matches) {
18877
- if (m.node.type === import_types64.NodeType.FrontierNode) continue;
19077
+ if (m.node.type === import_types65.NodeType.FrontierNode) continue;
18878
19078
  if (!graph.hasNode(m.node.id)) continue;
18879
19079
  const already = best.get(m.node.id);
18880
19080
  if (!already && m.score < EMBED_MIN_SCORE) continue;
@@ -18934,7 +19134,7 @@ function edgeSignalNote(e) {
18934
19134
  function buildRootCauseSection(graph, node, incidents, now) {
18935
19135
  const result = getRootCause(graph, node, void 0, incidents, { now });
18936
19136
  if (!result) return null;
18937
- const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types64.Provenance.OBSERVED;
19137
+ const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types65.Provenance.OBSERVED;
18938
19138
  const facts = [
18939
19139
  {
18940
19140
  text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
@@ -18984,7 +19184,7 @@ function buildObservedSection(graph, node) {
18984
19184
  if (result.observed && result.inboundObservedCount > 0) {
18985
19185
  facts.push({
18986
19186
  text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
18987
- provenance: import_types64.Provenance.OBSERVED
19187
+ provenance: import_types65.Provenance.OBSERVED
18988
19188
  });
18989
19189
  } else {
18990
19190
  return null;
@@ -19007,10 +19207,10 @@ function buildBlastSection(graph, node) {
19007
19207
  }
19008
19208
  function buildDatabaseCallersSection(graph, node) {
19009
19209
  const callers = getBlastRadius(graph, node).affectedNodes.filter((item) => {
19010
- if (graph.getNodeAttributes(item.nodeId).type !== import_types64.NodeType.ServiceNode) return false;
19210
+ if (graph.getNodeAttributes(item.nodeId).type !== import_types65.NodeType.ServiceNode) return false;
19011
19211
  return item.path.slice(1, -1).every((id) => {
19012
19212
  const type = graph.getNodeAttributes(id).type;
19013
- return type === import_types64.NodeType.FileNode || type === import_types64.NodeType.SymbolNode;
19213
+ return type === import_types65.NodeType.FileNode || type === import_types65.NodeType.SymbolNode;
19014
19214
  });
19015
19215
  });
19016
19216
  return {
@@ -19029,7 +19229,7 @@ function buildIncidentsSection(node, incidents) {
19029
19229
  const facts = ordered.map((ev) => ({
19030
19230
  text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
19031
19231
  // ErrorEvents are observation records — OBSERVED by definition.
19032
- provenance: import_types64.Provenance.OBSERVED
19232
+ provenance: import_types65.Provenance.OBSERVED
19033
19233
  }));
19034
19234
  return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
19035
19235
  }
@@ -19052,8 +19252,8 @@ function runtimeEdgeState(graph) {
19052
19252
  let observed = false;
19053
19253
  let stale = false;
19054
19254
  graph.forEachEdge((_id, attrs) => {
19055
- if (attrs.provenance === import_types64.Provenance.OBSERVED) observed = true;
19056
- if (attrs.provenance === import_types64.Provenance.STALE) stale = true;
19255
+ if (attrs.provenance === import_types65.Provenance.OBSERVED) observed = true;
19256
+ if (attrs.provenance === import_types65.Provenance.STALE) stale = true;
19057
19257
  });
19058
19258
  return { observed, stale };
19059
19259
  }
@@ -19121,7 +19321,7 @@ function buildGlobalIncidentsSection(incidents) {
19121
19321
  }
19122
19322
  const byKey = /* @__PURE__ */ new Map();
19123
19323
  for (const ev of incidents) {
19124
- const key = ev.affectedNode || (0, import_types64.serviceId)(ev.service);
19324
+ const key = ev.affectedNode || (0, import_types65.serviceId)(ev.service);
19125
19325
  const cur = byKey.get(key);
19126
19326
  if (!cur) {
19127
19327
  byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
@@ -19136,7 +19336,7 @@ function buildGlobalIncidentsSection(incidents) {
19136
19336
  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);
19137
19337
  const facts = rows.map((r) => ({
19138
19338
  text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
19139
- provenance: import_types64.Provenance.OBSERVED
19339
+ provenance: import_types65.Provenance.OBSERVED
19140
19340
  }));
19141
19341
  return {
19142
19342
  heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
@@ -19149,7 +19349,7 @@ function buildOverviewSections(graph, incidents) {
19149
19349
  graph.forEachNode((_id, attrs) => {
19150
19350
  const node = attrs;
19151
19351
  nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
19152
- if (node.type === import_types64.NodeType.ServiceNode) services.push(node.id);
19352
+ if (node.type === import_types65.NodeType.ServiceNode) services.push(node.id);
19153
19353
  });
19154
19354
  const edgeByProv = /* @__PURE__ */ new Map();
19155
19355
  graph.forEachEdge((_id, attrs) => {
@@ -19161,10 +19361,10 @@ function buildOverviewSections(graph, incidents) {
19161
19361
  const shapeFacts = [
19162
19362
  { text: `${graph.order} nodes, ${graph.size} edges` },
19163
19363
  {
19164
- text: `${count(import_types64.NodeType.ServiceNode)} services, ${count(import_types64.NodeType.FileNode)} files, ${count(import_types64.NodeType.SymbolNode)} symbols, ${count(import_types64.NodeType.DatabaseNode)} databases`
19364
+ text: `${count(import_types65.NodeType.ServiceNode)} services, ${count(import_types65.NodeType.FileNode)} files, ${count(import_types65.NodeType.SymbolNode)} symbols, ${count(import_types65.NodeType.DatabaseNode)} databases`
19165
19365
  }
19166
19366
  ];
19167
- for (const p of [import_types64.Provenance.EXTRACTED, import_types64.Provenance.OBSERVED, import_types64.Provenance.INFERRED, import_types64.Provenance.STALE]) {
19367
+ for (const p of [import_types65.Provenance.EXTRACTED, import_types65.Provenance.OBSERVED, import_types65.Provenance.INFERRED, import_types65.Provenance.STALE]) {
19168
19368
  const n = edgeByProv.get(p) ?? 0;
19169
19369
  if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
19170
19370
  }
@@ -19181,7 +19381,7 @@ function buildOverviewSections(graph, incidents) {
19181
19381
  if (incidents && incidents.length > 0) {
19182
19382
  const incCount = /* @__PURE__ */ new Map();
19183
19383
  for (const ev of incidents) {
19184
- const key = ev.affectedNode || (0, import_types64.serviceId)(ev.service);
19384
+ const key = ev.affectedNode || (0, import_types65.serviceId)(ev.service);
19185
19385
  incCount.set(key, (incCount.get(key) ?? 0) + 1);
19186
19386
  }
19187
19387
  const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
@@ -19189,7 +19389,7 @@ function buildOverviewSections(graph, incidents) {
19189
19389
  heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
19190
19390
  facts: top.map(([k, n]) => ({
19191
19391
  text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
19192
- provenance: import_types64.Provenance.OBSERVED
19392
+ provenance: import_types65.Provenance.OBSERVED
19193
19393
  }))
19194
19394
  });
19195
19395
  }
@@ -19320,7 +19520,7 @@ async function askGraph(graph, question, opts = {}) {
19320
19520
  let scope;
19321
19521
  if (primary) {
19322
19522
  scope = "node";
19323
- const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types64.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);
19523
+ const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types65.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);
19324
19524
  if (callersQuestion) sections.push(buildDatabaseCallersSection(graph, primary));
19325
19525
  for (const kind of SECTION_ORDER[intent]) {
19326
19526
  if (callersQuestion && kind === "blast") continue;
@@ -19338,7 +19538,7 @@ async function askGraph(graph, question, opts = {}) {
19338
19538
  const provSet = /* @__PURE__ */ new Set();
19339
19539
  for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
19340
19540
  const confidence = sections[0]?.facts[0]?.confidence;
19341
- return import_types64.AskResultSchema.parse({
19541
+ return import_types65.AskResultSchema.parse({
19342
19542
  question,
19343
19543
  intent,
19344
19544
  matched,
@@ -19485,7 +19685,7 @@ init_cjs_shims();
19485
19685
  var import_node_fs41 = require("fs");
19486
19686
  var import_node_os3 = __toESM(require("os"), 1);
19487
19687
  var import_node_path77 = __toESM(require("path"), 1);
19488
- var import_types65 = require("@neat.is/types");
19688
+ var import_types66 = require("@neat.is/types");
19489
19689
  var LOCK_TIMEOUT_MS = 5e3;
19490
19690
  var LOCK_RETRY_MS = 50;
19491
19691
  function neatHome() {
@@ -19755,10 +19955,10 @@ async function readRegistry() {
19755
19955
  throw err;
19756
19956
  }
19757
19957
  const parsed = JSON.parse(raw);
19758
- return import_types65.RegistryFileSchema.parse(parsed);
19958
+ return import_types66.RegistryFileSchema.parse(parsed);
19759
19959
  }
19760
19960
  async function writeRegistry(reg) {
19761
- const validated = import_types65.RegistryFileSchema.parse(reg);
19961
+ const validated = import_types66.RegistryFileSchema.parse(reg);
19762
19962
  await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
19763
19963
  }
19764
19964
  var RegistryError = class extends Error {
@@ -19908,11 +20108,11 @@ async function pruneRegistry(opts = {}) {
19908
20108
  init_cjs_shims();
19909
20109
  var import_node_fs42 = require("fs");
19910
20110
  var import_zod = require("zod");
19911
- var import_types66 = require("@neat.is/types");
20111
+ var import_types67 = require("@neat.is/types");
19912
20112
  var SSE_HEARTBEAT_MS = 3e4;
19913
20113
  var SSE_BACKPRESSURE_CAP = 1e3;
19914
20114
  var INCIDENT_TRIGGER_STREAM_SCOPE = "incident-only-v1";
19915
- var IncidentTriggerSchema = import_types66.IncidentEventPayloadSchema.extend({
20115
+ var IncidentTriggerSchema = import_types67.IncidentEventPayloadSchema.extend({
19916
20116
  incidentId: import_zod.z.string().regex(/^[A-Za-z0-9:_-]{1,100}$/),
19917
20117
  affectedNode: import_zod.z.string().min(1).max(512),
19918
20118
  service: import_zod.z.string().min(1).max(256),
@@ -19940,12 +20140,12 @@ function loadIncidentReplay(errorsPath, cursor) {
19940
20140
  if (!isExtractionFailure(row)) throw new Error("incident replay unavailable");
19941
20141
  continue;
19942
20142
  }
19943
- const event = import_types66.ErrorEventSchema.parse(row);
20143
+ const event = import_types67.ErrorEventSchema.parse(row);
19944
20144
  const trigger = IncidentTriggerSchema.parse({
19945
20145
  incidentId: event.id,
19946
20146
  affectedNode: event.affectedNode,
19947
20147
  service: event.service,
19948
- incidentKind: (0, import_types66.incidentKindOf)(event),
20148
+ incidentKind: (0, import_types67.incidentKindOf)(event),
19949
20149
  at: event.timestamp
19950
20150
  });
19951
20151
  const prior = seen.get(trigger.incidentId), encoded = JSON.stringify(trigger);
@@ -20320,7 +20520,7 @@ function renderVerdict({
20320
20520
  }
20321
20521
 
20322
20522
  // src/pr-verdict.ts
20323
- var import_types67 = require("@neat.is/types");
20523
+ var import_types68 = require("@neat.is/types");
20324
20524
 
20325
20525
  // src/connectors/hosted-repos.ts
20326
20526
  init_cjs_shims();
@@ -20393,7 +20593,7 @@ var PrVerdictError = class extends Error {
20393
20593
  details;
20394
20594
  };
20395
20595
  function parsePrVerdictRequest(body) {
20396
- const parsed = import_types67.PrVerdictBodySchema.safeParse(body);
20596
+ const parsed = import_types68.PrVerdictBodySchema.safeParse(body);
20397
20597
  if (!parsed.success) {
20398
20598
  throw new PrVerdictError("invalid pr-verdict body", 400, void 0, parsed.error.issues);
20399
20599
  }
@@ -20863,15 +21063,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
20863
21063
 
20864
21064
  // src/connectors/index.ts
20865
21065
  init_cjs_shims();
20866
- var import_types68 = require("@neat.is/types");
21066
+ var import_types69 = require("@neat.is/types");
20867
21067
  var NO_ENV = "unknown";
20868
21068
  function staticCallSiteFor(graph, serviceName, targetNodeId) {
20869
21069
  if (!graph.hasNode(targetNodeId)) return void 0;
20870
21070
  const sites = [];
20871
21071
  for (const edgeId of graph.inboundEdges(targetNodeId)) {
20872
21072
  const edge = graph.getEdgeAttributes(edgeId);
20873
- if (edge.provenance !== import_types68.Provenance.EXTRACTED) continue;
20874
- const parsed = (0, import_types68.parseFileId)(edge.source);
21073
+ if (edge.provenance !== import_types69.Provenance.EXTRACTED) continue;
21074
+ const parsed = (0, import_types69.parseFileId)(edge.source);
20875
21075
  if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
20876
21076
  const site = { relPath: edge.evidence.file };
20877
21077
  if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
@@ -20882,7 +21082,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
20882
21082
  function routeCallSiteFor(graph, targetNodeId) {
20883
21083
  if (!graph.hasNode(targetNodeId)) return void 0;
20884
21084
  const attrs = graph.getNodeAttributes(targetNodeId);
20885
- if (attrs.type !== import_types68.NodeType.RouteNode || !attrs.path) return void 0;
21085
+ if (attrs.type !== import_types69.NodeType.RouteNode || !attrs.path) return void 0;
20886
21086
  const site = { relPath: attrs.path };
20887
21087
  if (attrs.line !== void 0) site.line = attrs.line;
20888
21088
  return site;
@@ -21606,23 +21806,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
21606
21806
 
21607
21807
  // src/connectors/supabase/resolve.ts
21608
21808
  init_cjs_shims();
21609
- var import_types70 = require("@neat.is/types");
21809
+ var import_types71 = require("@neat.is/types");
21610
21810
  function createSupabaseResolveTarget(graph, config) {
21611
21811
  return (signal, _ctx) => {
21612
21812
  if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
21613
21813
  return null;
21614
21814
  }
21615
- const subResourceId = (0, import_types70.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
21815
+ const subResourceId = (0, import_types71.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
21616
21816
  if (graph.hasNode(subResourceId)) {
21617
- return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types70.EdgeType.CALLS };
21817
+ return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types71.EdgeType.CALLS };
21618
21818
  }
21619
- const bareResourceId = (0, import_types70.infraId)(signal.targetKind, signal.targetName);
21819
+ const bareResourceId = (0, import_types71.infraId)(signal.targetKind, signal.targetName);
21620
21820
  if (graph.hasNode(bareResourceId)) {
21621
- return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types70.EdgeType.CALLS };
21821
+ return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types71.EdgeType.CALLS };
21622
21822
  }
21623
- const projectLevelId = (0, import_types70.infraId)("supabase", config.nodeRef);
21823
+ const projectLevelId = (0, import_types71.infraId)("supabase", config.nodeRef);
21624
21824
  if (graph.hasNode(projectLevelId)) {
21625
- return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types70.EdgeType.CALLS };
21825
+ return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types71.EdgeType.CALLS };
21626
21826
  }
21627
21827
  return null;
21628
21828
  };
@@ -21715,7 +21915,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
21715
21915
 
21716
21916
  // src/connectors/railway/index.ts
21717
21917
  init_cjs_shims();
21718
- var import_types74 = require("@neat.is/types");
21918
+ var import_types75 = require("@neat.is/types");
21719
21919
 
21720
21920
  // src/connectors/railway/client.ts
21721
21921
  init_cjs_shims();
@@ -21866,7 +22066,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
21866
22066
  const out = [];
21867
22067
  graph.forEachNode((_id, attrs) => {
21868
22068
  const node = attrs;
21869
- if (node.type !== import_types74.NodeType.RouteNode) return;
22069
+ if (node.type !== import_types75.NodeType.RouteNode) return;
21870
22070
  const route = attrs;
21871
22071
  if (route.service !== serviceName) return;
21872
22072
  out.push({
@@ -21970,12 +22170,12 @@ function createRailwayResolveTarget(config) {
21970
22170
  const serviceName = config.serviceNameById[config.serviceId];
21971
22171
  if (!serviceName) return null;
21972
22172
  if (signal.targetKind === ROUTE_TARGET_KIND) {
21973
- return { targetNodeId: signal.targetName, serviceName, edgeType: import_types74.EdgeType.CALLS };
22173
+ return { targetNodeId: signal.targetName, serviceName, edgeType: import_types75.EdgeType.CALLS };
21974
22174
  }
21975
22175
  if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
21976
22176
  const peerName = config.serviceNameById[signal.targetName];
21977
22177
  if (!peerName) return null;
21978
- return { targetNodeId: (0, import_types74.serviceId)(peerName), serviceName, edgeType: import_types74.EdgeType.CONNECTS_TO };
22178
+ return { targetNodeId: (0, import_types75.serviceId)(peerName), serviceName, edgeType: import_types75.EdgeType.CONNECTS_TO };
21979
22179
  }
21980
22180
  return null;
21981
22181
  };
@@ -22163,11 +22363,11 @@ function mapLogEntriesToSignals(entries) {
22163
22363
 
22164
22364
  // src/connectors/firebase/resolve.ts
22165
22365
  init_cjs_shims();
22166
- var import_types76 = require("@neat.is/types");
22366
+ var import_types77 = require("@neat.is/types");
22167
22367
 
22168
22368
  // src/connectors/infer-service.ts
22169
22369
  init_cjs_shims();
22170
- var import_types75 = require("@neat.is/types");
22370
+ var import_types76 = require("@neat.is/types");
22171
22371
  function normalizeName(name) {
22172
22372
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
22173
22373
  }
@@ -22178,11 +22378,11 @@ function inferServiceName(graph, resourceName, method, path104) {
22178
22378
  const owners = /* @__PURE__ */ new Set();
22179
22379
  graph.forEachNode((_id, attrs) => {
22180
22380
  const node = attrs;
22181
- if (node.type === import_types75.NodeType.ServiceNode && typeof node.name === "string") {
22381
+ if (node.type === import_types76.NodeType.ServiceNode && typeof node.name === "string") {
22182
22382
  services.push(node.name);
22183
22383
  return;
22184
22384
  }
22185
- if (node.type !== import_types75.NodeType.RouteNode) return;
22385
+ if (node.type !== import_types76.NodeType.RouteNode) return;
22186
22386
  const route = attrs;
22187
22387
  if (!route.pathTemplate || normalizePathTemplate(route.pathTemplate) !== wantedPath) return;
22188
22388
  const routeMethod = route.method.toUpperCase();
@@ -22209,7 +22409,7 @@ function routeEntriesFor(graph, serviceName) {
22209
22409
  const entries = [];
22210
22410
  graph.forEachNode((_id, attrs) => {
22211
22411
  const node = attrs;
22212
- if (node.type !== import_types76.NodeType.RouteNode) return;
22412
+ if (node.type !== import_types77.NodeType.RouteNode) return;
22213
22413
  const route = attrs;
22214
22414
  if (route.service !== serviceName) return;
22215
22415
  entries.push({
@@ -22241,7 +22441,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
22241
22441
  return {
22242
22442
  targetNodeId: match.routeNodeId,
22243
22443
  serviceName,
22244
- edgeType: import_types76.EdgeType.CALLS
22444
+ edgeType: import_types77.EdgeType.CALLS
22245
22445
  };
22246
22446
  };
22247
22447
  }
@@ -22274,7 +22474,7 @@ init_cjs_shims();
22274
22474
 
22275
22475
  // src/connectors/cloudflare/connector.ts
22276
22476
  init_cjs_shims();
22277
- var import_types78 = require("@neat.is/types");
22477
+ var import_types79 = require("@neat.is/types");
22278
22478
 
22279
22479
  // src/connectors/cloudflare/client.ts
22280
22480
  init_cjs_shims();
@@ -22438,7 +22638,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
22438
22638
  graph.forEachNode((id, attrs) => {
22439
22639
  if (found) return;
22440
22640
  const a = attrs;
22441
- if (a.type === import_types78.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
22641
+ if (a.type === import_types79.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
22442
22642
  found = id;
22443
22643
  }
22444
22644
  });
@@ -22450,7 +22650,7 @@ function findMatchingRouteNode(graph, serviceName, method, path104) {
22450
22650
  graph.forEachNode((id, attrs) => {
22451
22651
  if (found) return;
22452
22652
  const a = attrs;
22453
- if (a.type !== import_types78.NodeType.RouteNode || a.service !== serviceName) return;
22653
+ if (a.type !== import_types79.NodeType.RouteNode || a.service !== serviceName) return;
22454
22654
  if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
22455
22655
  const routeMethod = (a.method ?? "").toUpperCase();
22456
22656
  if (routeMethod !== "ALL" && routeMethod !== method) return;
@@ -22469,11 +22669,11 @@ function createCloudflareResolveTarget(config, graph) {
22469
22669
  };
22470
22670
  const mapping = config.workers?.[scriptName];
22471
22671
  if (mapping) {
22472
- const wholeFileId = (0, import_types78.fileId)(mapping.service, mapping.entryFile);
22672
+ const wholeFileId = (0, import_types79.fileId)(mapping.service, mapping.entryFile);
22473
22673
  return {
22474
22674
  targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
22475
22675
  serviceName: mapping.service,
22476
- edgeType: import_types78.EdgeType.CALLS
22676
+ edgeType: import_types79.EdgeType.CALLS
22477
22677
  };
22478
22678
  }
22479
22679
  const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
@@ -22482,13 +22682,13 @@ function createCloudflareResolveTarget(config, graph) {
22482
22682
  return {
22483
22683
  targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
22484
22684
  serviceName: fileNode.service,
22485
- edgeType: import_types78.EdgeType.CALLS
22685
+ edgeType: import_types79.EdgeType.CALLS
22486
22686
  };
22487
22687
  }
22488
22688
  return {
22489
- targetNodeId: (0, import_types78.infraId)("cloudflare-worker", scriptName),
22689
+ targetNodeId: (0, import_types79.infraId)("cloudflare-worker", scriptName),
22490
22690
  serviceName: scriptName,
22491
- edgeType: import_types78.EdgeType.CALLS,
22691
+ edgeType: import_types79.EdgeType.CALLS,
22492
22692
  ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
22493
22693
  };
22494
22694
  };
@@ -22684,14 +22884,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
22684
22884
 
22685
22885
  // src/connectors/neon/resolve.ts
22686
22886
  init_cjs_shims();
22687
- var import_types82 = require("@neat.is/types");
22887
+ var import_types83 = require("@neat.is/types");
22688
22888
  function createNeonResolveTarget(config) {
22689
22889
  return (signal) => {
22690
22890
  if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
22691
22891
  return {
22692
- targetNodeId: (0, import_types82.infraId)("sql-table", signal.targetName),
22892
+ targetNodeId: (0, import_types83.infraId)("sql-table", signal.targetName),
22693
22893
  serviceName: config.serviceName,
22694
- edgeType: import_types82.EdgeType.CALLS,
22894
+ edgeType: import_types83.EdgeType.CALLS,
22695
22895
  ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
22696
22896
  };
22697
22897
  };
@@ -22872,14 +23072,14 @@ function mapLogEntriesToSignals2(entries) {
22872
23072
 
22873
23073
  // src/connectors/cloud-run/resolve.ts
22874
23074
  init_cjs_shims();
22875
- var import_types86 = require("@neat.is/types");
23075
+ var import_types87 = require("@neat.is/types");
22876
23076
  var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
22877
23077
  function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
22878
23078
  let found = null;
22879
23079
  graph.forEachNode((_id, attrs) => {
22880
23080
  if (found) return;
22881
23081
  const node = attrs;
22882
- if (node.type !== import_types86.NodeType.RouteNode) return;
23082
+ if (node.type !== import_types87.NodeType.RouteNode) return;
22883
23083
  const route = attrs;
22884
23084
  if (route.service !== serviceName || !route.pathTemplate) return;
22885
23085
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -22904,13 +23104,13 @@ function createCloudRunResolveTarget(graph, config) {
22904
23104
  normalizePathTemplate(path104)
22905
23105
  );
22906
23106
  if (routeNodeId) {
22907
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types86.EdgeType.CALLS };
23107
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types87.EdgeType.CALLS };
22908
23108
  }
22909
23109
  }
22910
23110
  return {
22911
- targetNodeId: (0, import_types86.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
23111
+ targetNodeId: (0, import_types87.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
22912
23112
  serviceName: mappedService ?? gcpServiceName,
22913
- edgeType: import_types86.EdgeType.CALLS,
23113
+ edgeType: import_types87.EdgeType.CALLS,
22914
23114
  ensureInfraNode: {
22915
23115
  kind: CLOUD_RUN_SERVICE_INFRA_KIND,
22916
23116
  name: gcpServiceName,
@@ -23092,14 +23292,14 @@ function mapLogEntriesToSignals3(entries) {
23092
23292
 
23093
23293
  // src/connectors/gcp-lb/resolve.ts
23094
23294
  init_cjs_shims();
23095
- var import_types90 = require("@neat.is/types");
23295
+ var import_types91 = require("@neat.is/types");
23096
23296
  var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
23097
23297
  function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
23098
23298
  let found = null;
23099
23299
  graph.forEachNode((_id, attrs) => {
23100
23300
  if (found) return;
23101
23301
  const node = attrs;
23102
- if (node.type !== import_types90.NodeType.RouteNode) return;
23302
+ if (node.type !== import_types91.NodeType.RouteNode) return;
23103
23303
  const route = attrs;
23104
23304
  if (route.service !== serviceName || !route.pathTemplate) return;
23105
23305
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -23124,13 +23324,13 @@ function createGcpLbResolveTarget(graph, config) {
23124
23324
  normalizePathTemplate(path104)
23125
23325
  );
23126
23326
  if (routeNodeId) {
23127
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types90.EdgeType.CALLS };
23327
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types91.EdgeType.CALLS };
23128
23328
  }
23129
23329
  }
23130
23330
  return {
23131
- targetNodeId: (0, import_types90.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
23331
+ targetNodeId: (0, import_types91.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
23132
23332
  serviceName: mappedService ?? backendServiceName,
23133
- edgeType: import_types90.EdgeType.CALLS,
23333
+ edgeType: import_types91.EdgeType.CALLS,
23134
23334
  ensureInfraNode: {
23135
23335
  kind: GCP_LB_BACKEND_INFRA_KIND,
23136
23336
  name: backendServiceName,
@@ -23171,7 +23371,7 @@ function createGcpLbConnector(graph, config = {}) {
23171
23371
 
23172
23372
  // src/connectors/render/index.ts
23173
23373
  init_cjs_shims();
23174
- var import_types93 = require("@neat.is/types");
23374
+ var import_types94 = require("@neat.is/types");
23175
23375
 
23176
23376
  // src/connectors/render/types.ts
23177
23377
  init_cjs_shims();
@@ -23249,7 +23449,7 @@ function buildRenderRouteIndex(graph, serviceName) {
23249
23449
  const out = [];
23250
23450
  graph.forEachNode((_id, attrs) => {
23251
23451
  const node = attrs;
23252
- if (node.type !== import_types93.NodeType.RouteNode) return;
23452
+ if (node.type !== import_types94.NodeType.RouteNode) return;
23253
23453
  const route = attrs;
23254
23454
  if (route.service !== serviceName) return;
23255
23455
  out.push({
@@ -23334,7 +23534,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
23334
23534
  function createRenderResolveTarget(config) {
23335
23535
  return (signal) => {
23336
23536
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
23337
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types93.EdgeType.CALLS };
23537
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types94.EdgeType.CALLS };
23338
23538
  }
23339
23539
  return null;
23340
23540
  };
@@ -23472,21 +23672,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
23472
23672
 
23473
23673
  // src/connectors/planetscale/resolve.ts
23474
23674
  init_cjs_shims();
23475
- var import_types97 = require("@neat.is/types");
23675
+ var import_types98 = require("@neat.is/types");
23476
23676
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
23477
23677
  function createPlanetscaleResolveTarget(graph, config) {
23478
23678
  const databaseName = `${config.organization}/${config.database}`;
23479
23679
  return (signal, _ctx) => {
23480
23680
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
23481
- const tableId = (0, import_types97.infraId)("sql-table", signal.targetName);
23681
+ const tableId = (0, import_types98.infraId)("sql-table", signal.targetName);
23482
23682
  if (graph.hasNode(tableId)) {
23483
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types97.EdgeType.CALLS };
23683
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types98.EdgeType.CALLS };
23484
23684
  }
23485
- const providerId = (0, import_types97.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
23685
+ const providerId = (0, import_types98.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
23486
23686
  return {
23487
23687
  targetNodeId: providerId,
23488
23688
  serviceName: config.serviceName,
23489
- edgeType: import_types97.EdgeType.CALLS,
23689
+ edgeType: import_types98.EdgeType.CALLS,
23490
23690
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
23491
23691
  };
23492
23692
  };
@@ -23751,7 +23951,7 @@ function mapBuildsToSignals(builds, serviceName) {
23751
23951
 
23752
23952
  // src/connectors/eas/resolve.ts
23753
23953
  init_cjs_shims();
23754
- var import_types102 = require("@neat.is/types");
23954
+ var import_types103 = require("@neat.is/types");
23755
23955
  var NO_ENV2 = "unknown";
23756
23956
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
23757
23957
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -23767,8 +23967,8 @@ function configBasenamesForPhase(phase) {
23767
23967
  function configNodeService(graph, configNodeId) {
23768
23968
  for (const edgeId of graph.inboundEdges(configNodeId)) {
23769
23969
  const edge = graph.getEdgeAttributes(edgeId);
23770
- if (edge.type !== import_types102.EdgeType.CONFIGURED_BY) continue;
23771
- const parsed = (0, import_types102.parseFileId)(edge.source);
23970
+ if (edge.type !== import_types103.EdgeType.CONFIGURED_BY) continue;
23971
+ const parsed = (0, import_types103.parseFileId)(edge.source);
23772
23972
  if (parsed) return parsed.service;
23773
23973
  }
23774
23974
  return null;
@@ -23779,7 +23979,7 @@ function findConfigNode(graph, basenames, serviceName) {
23779
23979
  graph.forEachNode((id, attrs) => {
23780
23980
  if (scoped) return;
23781
23981
  const node = attrs;
23782
- if (node.type !== import_types102.NodeType.ConfigNode) return;
23982
+ if (node.type !== import_types103.NodeType.ConfigNode) return;
23783
23983
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
23784
23984
  if (anyMatch === null) anyMatch = id;
23785
23985
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -23796,13 +23996,13 @@ function createEasResolveTarget(graph) {
23796
23996
  if (basenames.length > 0) {
23797
23997
  const configNodeId = findConfigNode(graph, basenames, serviceName);
23798
23998
  if (configNodeId) {
23799
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types102.EdgeType.CALLS };
23999
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types103.EdgeType.CALLS };
23800
24000
  }
23801
24001
  }
23802
24002
  return {
23803
24003
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
23804
24004
  serviceName,
23805
- edgeType: import_types102.EdgeType.CALLS
24005
+ edgeType: import_types103.EdgeType.CALLS
23806
24006
  };
23807
24007
  };
23808
24008
  }
@@ -24521,7 +24721,7 @@ function serializeGraph(graph) {
24521
24721
  graph.forEachEdge((_id, attrs) => {
24522
24722
  edges.push(attrs);
24523
24723
  });
24524
- return { nodes, edges };
24724
+ return { nodes, edges, sourceBaselines: readSourceBaselines(graph) };
24525
24725
  }
24526
24726
  function projectFromReq(req, singleProject, registry) {
24527
24727
  const params = req.params;
@@ -24704,11 +24904,11 @@ function registerRoutes(scope, ctx) {
24704
24904
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
24705
24905
  const parsed = [];
24706
24906
  for (const c of candidates) {
24707
- const r = import_types105.DivergenceTypeSchema.safeParse(c);
24907
+ const r = import_types106.DivergenceTypeSchema.safeParse(c);
24708
24908
  if (!r.success) {
24709
24909
  return reply.code(400).send({
24710
24910
  error: `unknown divergence type "${c}"`,
24711
- allowed: import_types105.DivergenceTypeSchema.options
24911
+ allowed: import_types106.DivergenceTypeSchema.options
24712
24912
  });
24713
24913
  }
24714
24914
  parsed.push(r.data);
@@ -25145,7 +25345,7 @@ function registerRoutes(scope, ctx) {
25145
25345
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
25146
25346
  let violations = await log.readAll();
25147
25347
  if (req.query.severity) {
25148
- const sev = import_types105.PolicySeveritySchema.safeParse(req.query.severity);
25348
+ const sev = import_types106.PolicySeveritySchema.safeParse(req.query.severity);
25149
25349
  if (!sev.success) {
25150
25350
  return reply.code(400).send({
25151
25351
  error: "invalid severity",
@@ -25184,7 +25384,7 @@ function registerRoutes(scope, ctx) {
25184
25384
  scope.post("/policies/check", async (req, reply) => {
25185
25385
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
25186
25386
  if (!proj) return;
25187
- const parsed = import_types105.PoliciesCheckBodySchema.safeParse(req.body ?? {});
25387
+ const parsed = import_types106.PoliciesCheckBodySchema.safeParse(req.body ?? {});
25188
25388
  if (!parsed.success) {
25189
25389
  return reply.code(400).send({
25190
25390
  error: "invalid /policies/check body",
@@ -25545,7 +25745,7 @@ init_auth();
25545
25745
 
25546
25746
  // src/hang-sensor.ts
25547
25747
  init_cjs_shims();
25548
- var import_types106 = require("@neat.is/types");
25748
+ var import_types107 = require("@neat.is/types");
25549
25749
  var RECONCILE_INCIDENT_LIMIT = 500;
25550
25750
  function stageHangSurfaces(graph, incidents) {
25551
25751
  const boundaries = /* @__PURE__ */ new Set();
@@ -25558,7 +25758,7 @@ function stageHangSurfaces(graph, incidents) {
25558
25758
  if (!isBoundaryTimeoutSymptom(ctx)) continue;
25559
25759
  const hop = resolveHangHop(graph, boundary, incidents);
25560
25760
  if (!hop) continue;
25561
- if (stageFrontierEdge(graph, hop.source, hop.target, import_types106.EdgeType.CALLS)) staged++;
25761
+ if (stageFrontierEdge(graph, hop.source, hop.target, import_types107.EdgeType.CALLS)) staged++;
25562
25762
  }
25563
25763
  return staged;
25564
25764
  }
@@ -25691,6 +25891,15 @@ async function fetchPodLog(transport, namespace, podName, opts = {}) {
25691
25891
  return void 0;
25692
25892
  }
25693
25893
  }
25894
+ function hasLogContent(text) {
25895
+ return typeof text === "string" && text.trim().length > 0;
25896
+ }
25897
+ async function fetchPodProcessLog(transport, namespace, podName, opts = {}) {
25898
+ const previous = await fetchPodLog(transport, namespace, podName, { ...opts, previous: true });
25899
+ if (hasLogContent(previous)) return previous;
25900
+ const current = await fetchPodLog(transport, namespace, podName, { ...opts, previous: false });
25901
+ return hasLogContent(current) ? current : void 0;
25902
+ }
25694
25903
 
25695
25904
  // src/connectors/kubernetes/kubeconfig.ts
25696
25905
  init_cjs_shims();
@@ -26116,7 +26325,7 @@ function mapWorkloadsToSignals(deployments, pods, config, logs) {
26116
26325
 
26117
26326
  // src/connectors/kubernetes/resolve.ts
26118
26327
  init_cjs_shims();
26119
- var import_types108 = require("@neat.is/types");
26328
+ var import_types109 = require("@neat.is/types");
26120
26329
  var NO_ENV3 = "unknown";
26121
26330
  function createK8sResolveTarget(graph) {
26122
26331
  return (signal) => {
@@ -26127,7 +26336,7 @@ function createK8sResolveTarget(graph) {
26127
26336
  return {
26128
26337
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV3),
26129
26338
  serviceName,
26130
- edgeType: import_types108.EdgeType.CALLS
26339
+ edgeType: import_types109.EdgeType.CALLS
26131
26340
  };
26132
26341
  };
26133
26342
  }
@@ -26237,11 +26446,10 @@ var KubernetesConnector = class {
26237
26446
  const targets = faultedPods(deployments, pods, this.config);
26238
26447
  await Promise.all(
26239
26448
  targets.map(async (t) => {
26240
- const text = await fetchPodLog(transport, namespace, t.podName, {
26449
+ const text = await fetchPodProcessLog(transport, namespace, t.podName, {
26241
26450
  ...t.container ? { container: t.container } : {},
26242
26451
  tailLines: PROCESS_LOG_TAIL_LINES,
26243
26452
  limitBytes: PROCESS_LOG_LIMIT_BYTES,
26244
- previous: true,
26245
26453
  ...opts
26246
26454
  });
26247
26455
  if (typeof text === "string" && text.length > 0) logs.set(podLogKey(t.podName, t.container), text);
@@ -26281,7 +26489,7 @@ var import_node_fs47 = require("fs");
26281
26489
  var import_node_path83 = __toESM(require("path"), 1);
26282
26490
 
26283
26491
  // src/daemon.ts
26284
- var import_types111 = require("@neat.is/types");
26492
+ var import_types112 = require("@neat.is/types");
26285
26493
  function daemonJsonPath(scanPath) {
26286
26494
  return import_node_path84.default.join(scanPath, "neat-out", "daemon.json");
26287
26495
  }
@@ -31344,7 +31552,7 @@ async function connectorAdd(args, deps) {
31344
31552
  }
31345
31553
  const { replaced } = await upsertConnectorEntry(entry2, deps.home);
31346
31554
  const verb = replaced ? "updated" : "added";
31347
- const where = project ? `project "${project}"` : "the bootstrapping project";
31555
+ const where = project ? `project "${project}"` : "every project (no --project set)";
31348
31556
  deps.out(`${verb} connector "${id}" (${provider}) for ${where}.`);
31349
31557
  if (push) {
31350
31558
  deps.out("The drain is live \u2014 traces arrive at the daemon's OTLP receiver. No poll or restart needed.");
@@ -31407,7 +31615,7 @@ async function connectorList(deps, filterProject, json = false) {
31407
31615
  }
31408
31616
  deps.out("id provider project credential");
31409
31617
  for (const e of entries) {
31410
- const project = e.project ?? "(bootstrapping project)";
31618
+ const project = e.project ?? "(every project)";
31411
31619
  const credential = describeCredential(e.credential, deps.env).map((c) => {
31412
31620
  const status2 = c.status ? ` (${c.status})` : c.kind === "plaintext" ? " (plaintext)" : "";
31413
31621
  return c.field ? `${c.field}=${c.display}${status2}` : `${c.display}${status2}`;
@@ -32420,7 +32628,48 @@ var import_node_path96 = __toESM(require("path"), 1);
32420
32628
 
32421
32629
  // src/cli-client.ts
32422
32630
  init_cjs_shims();
32423
- var import_types112 = require("@neat.is/types");
32631
+ var import_types113 = require("@neat.is/types");
32632
+
32633
+ // src/incidents-render.ts
32634
+ init_cjs_shims();
32635
+ function deployHintLines(ev) {
32636
+ const a = ev.attributes;
32637
+ if (!a) return [];
32638
+ const s = (k) => typeof a[k] === "string" ? a[k] : void 0;
32639
+ const n = (k) => typeof a[k] === "number" ? a[k] : void 0;
32640
+ const arr = (k) => Array.isArray(a[k]) ? a[k].filter((x) => typeof x === "string") : [];
32641
+ const fault = s("k8s.fault");
32642
+ const env = arr("k8s.containerEnv");
32643
+ const args = arr("k8s.containerArgs");
32644
+ const log = s("k8s.processLog");
32645
+ if (!fault && env.length === 0 && args.length === 0 && !log) return [];
32646
+ const out = [];
32647
+ if (fault) {
32648
+ const bits = [fault];
32649
+ const wr = s("k8s.waitingReason");
32650
+ if (wr) bits.push(wr);
32651
+ const rc = n("k8s.restartCount");
32652
+ if (rc !== void 0) bits.push(`restarts=${rc}`);
32653
+ const ec = n("k8s.exitCode");
32654
+ if (ec !== void 0) bits.push(`exit=${ec}`);
32655
+ const tr = s("k8s.terminatedReason");
32656
+ if (tr) bits.push(tr);
32657
+ out.push(`deploy: ${bits.join(" ")}`);
32658
+ }
32659
+ const cap = (xs, max) => {
32660
+ const joined = xs.join(" ");
32661
+ return joined.length > max ? `${joined.slice(0, max)}\u2026(+${xs.length} entries)` : joined;
32662
+ };
32663
+ if (env.length > 0) out.push(`env: ${cap(env, 700)}`);
32664
+ if (args.length > 0) out.push(`args: ${cap(args, 300)}`);
32665
+ if (log) {
32666
+ const tail = log.split("\n").filter((l) => l.trim().length > 0).slice(-4);
32667
+ if (tail.length > 0) out.push(`log: ${tail.join(" \u23CE ")}`);
32668
+ }
32669
+ return out;
32670
+ }
32671
+
32672
+ // src/cli-client.ts
32424
32673
  var HttpError = class extends Error {
32425
32674
  constructor(status2, message, responseBody = "") {
32426
32675
  super(message);
@@ -32562,7 +32811,7 @@ async function runBlastRadius(client, input) {
32562
32811
  }
32563
32812
  }
32564
32813
  function formatBlastEntry(n) {
32565
- const tag = n.edgeProvenance === import_types112.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
32814
+ const tag = n.edgeProvenance === import_types113.Provenance.STALE ? " [STALE \u2014 last seen too long ago]" : "";
32566
32815
  return ` \u2022 ${n.nodeId} (distance ${n.distance}, ${n.edgeProvenance})${tag}`;
32567
32816
  }
32568
32817
  async function runDependencies(client, input) {
@@ -32619,7 +32868,7 @@ async function runObservedDependencies(client, input) {
32619
32868
  if (result.observed) {
32620
32869
  return {
32621
32870
  summary: `${input.nodeId} makes no outbound runtime calls, but OTel has observed it receiving traffic on ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 it's a pure receiver.`,
32622
- provenance: import_types112.Provenance.OBSERVED
32871
+ provenance: import_types113.Provenance.OBSERVED
32623
32872
  };
32624
32873
  }
32625
32874
  const note = result.hasExtractedOutbound ? " Static (EXTRACTED) dependencies exist but no runtime traffic has been seen \u2014 is OTel running?" : "";
@@ -32629,7 +32878,7 @@ async function runObservedDependencies(client, input) {
32629
32878
  return {
32630
32879
  summary: `${input.nodeId} has ${result.dependencies.length} runtime dependenc${result.dependencies.length === 1 ? "y" : "ies"} confirmed by OTel.`,
32631
32880
  block: blockLines.join("\n"),
32632
- provenance: import_types112.Provenance.OBSERVED
32881
+ provenance: import_types113.Provenance.OBSERVED
32633
32882
  };
32634
32883
  } catch (err) {
32635
32884
  if (err instanceof HttpError && err.status === 404) {
@@ -32677,13 +32926,15 @@ async function runIncidents(client, input) {
32677
32926
  const blockLines = [];
32678
32927
  for (const ev of ordered) {
32679
32928
  blockLines.push(` ${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`);
32929
+ if (ev.exceptionType) blockLines.push(` exception: ${ev.exceptionType}`);
32930
+ for (const l of deployHintLines(ev)) blockLines.push(` ${l}`);
32680
32931
  blockLines.push(` trace=${ev.traceId} span=${ev.spanId}`);
32681
32932
  }
32682
32933
  const target = input.nodeId ?? "the project";
32683
32934
  return {
32684
32935
  summary: `${target} has ${body.total} recorded incident${body.total === 1 ? "" : "s"}; showing the ${ordered.length} most recent.`,
32685
32936
  block: blockLines.join("\n"),
32686
- provenance: import_types112.Provenance.OBSERVED
32937
+ provenance: import_types113.Provenance.OBSERVED
32687
32938
  };
32688
32939
  } catch (err) {
32689
32940
  if (err instanceof HttpError && err.status === 404) {
@@ -32792,7 +33043,7 @@ async function runStaleEdges(client, input) {
32792
33043
  return {
32793
33044
  summary: `${events.length} stale-edge transition${events.length === 1 ? "" : "s"} recorded${input.edgeType ? ` for ${input.edgeType}` : ""}.`,
32794
33045
  block: blockLines.join("\n"),
32795
- provenance: import_types112.Provenance.STALE
33046
+ provenance: import_types113.Provenance.STALE
32796
33047
  };
32797
33048
  }
32798
33049
  async function runPolicies(client, input) {
@@ -33532,7 +33783,7 @@ var import_promises5 = __toESM(require("readline/promises"), 1);
33532
33783
 
33533
33784
  // src/agent-directive.generated.ts
33534
33785
  init_cjs_shims();
33535
- var AGENT_DIRECTIVE = '## Query NEAT before searching files\n\nThis project has a live NEAT graph: code, data and infrastructure declarations\nfused with runtime traffic, incidents and supported provider telemetry. It can\nshow what exists, what actually ran, where a failure began, and what may break\nwhen a node changes. The graph is deterministic: the agent supplies the model;\nNEAT resolves named nodes and traverses recorded evidence rather than asking an\nLLM to infer architecture from file names.\n\nEvery claim carries provenance and confidence. `EXTRACTED` comes from recognized\nsource or configuration, `OBSERVED` from spans or supported provider signals,\n`INFERRED` from a bridged relationship, and `STALE` marks an observed edge that\nwent quiet. Missing runtime evidence does not prove a path never runs.\n\n**For questions about this system\'s behavior, structure, data dependencies,\nfailures, or change impact, call the MCP `ask` tool (`mcp__neat__ask`) before\nRead/Grep/Glob/Bash.** You do not need an exact node id. `ask` resolves names\nand routes to the relevant graph traversal, returning provenance-tagged facts.\nWhen MCP is unavailable, use the same door through the CLI:\n\n```\nnpx neat.is ask "why is checkout failing?"\nnpx neat.is ask "what breaks if I change the orders table?"\nnpx neat.is ask "what does the payments service depend on at runtime?"\n```\n\nFor a failure, ask first, then call `get_incident_card` on the named service,\nfile or symbol. The card combines the incident, likely cause, blast radius,\npolicies and divergence into a work order. Use `expand` one hop at a time and\n`relate` to test whether the suspected cause and symptom share a signal. Check\nprovenance and confidence before acting.\n\nBefore a change, use `get_blast_radius` and `check_policies` to see dependents\nand advisory architectural rules. Use `get_divergences` to compare declared\nintent with observed behavior, `get_graph_diff` to compare a saved snapshot\nwith the live graph, and `get_recent_stale_edges` when traffic goes quiet.\n`get_dependencies` maps a node\'s outgoing graph; `get_observed_dependencies`\nshows only seen runtime/provider calls. `semantic_search` finds node labels,\nnot arbitrary source text.\n\nRead source when the graph does not model what you need: comments, arbitrary\nstring literals, config details, unsupported syntax, or a repository that has\nnot been extracted or connected. If a graph answer is empty, check the daemon\nwith `npx neat.is list` or restart it with `npx neat.is up`; wire MCP with\n`npx neat.is skill --apply`.\n';
33786
+ var AGENT_DIRECTIVE = '## Let NEAT investigate before you search files\n\nThis project has NEAT. It does the investigation for this system so you can\nspend your effort on the code: what exists, what actually ran, where a failure\nbegan, and what a change will reach. It answers from a live graph that fuses\ncode, data and infrastructure declarations with runtime traffic, incidents and\nsupported provider telemetry. The graph is deterministic: you supply the\nreasoning about the fix; NEAT resolves named nodes and traverses recorded\nevidence rather than asking an LLM to infer architecture from file names.\n\nEvery claim carries provenance and confidence. `EXTRACTED` comes from recognized\nsource or configuration, `OBSERVED` from spans or supported provider signals,\n`INFERRED` from a bridged relationship, and `STALE` marks an observed edge that\nwent quiet. Missing runtime evidence does not prove a path never runs.\n\n**For questions about this system\'s behavior, structure, data dependencies,\nfailures, or change impact, call the MCP `ask` tool (`mcp__neat__ask`) before\nRead/Grep/Glob/Bash.** You do not need an exact node id. `ask` resolves names\nand routes to the relevant graph traversal, returning provenance-tagged facts.\nWhen MCP is unavailable, use the same door through the CLI:\n\n```\nnpx neat.is ask "why is checkout failing?"\nnpx neat.is ask "what breaks if I change the orders table?"\nnpx neat.is ask "what does the payments service depend on at runtime?"\n```\n\nFor a failure, call `get_incident_card` on the failing service, file or symbol\n(if you don\'t know which, `ask` what is failing first). The card is the\ninvestigation already done: the incident, its likely cause chain, blast radius,\nthe governing policies and divergence, in one work order. Use `expand` one hop\nat a time and `relate` to test whether the suspected cause and symptom share a\nsignal. Check provenance and confidence before acting.\n\nBefore a change, use `get_blast_radius` and `check_policies` to see dependents\nand advisory architectural rules. Use `get_divergences` to compare declared\nintent with observed behavior, `get_graph_diff` to compare a saved snapshot\nwith the live graph, and `get_recent_stale_edges` when traffic goes quiet.\n`get_dependencies` maps a node\'s outgoing graph; `get_observed_dependencies`\nshows only seen runtime/provider calls. `semantic_search` finds node labels,\nnot arbitrary source text.\n\nRead source when the graph does not model what you need: comments, arbitrary\nstring literals, config details, unsupported syntax, or a repository that has\nnot been extracted or connected. If a graph answer is empty, check the daemon\nwith `npx neat.is list` or restart it with `npx neat.is up`; wire MCP with\n`npx neat.is skill --apply`.\n';
33536
33787
 
33537
33788
  // src/welcome.ts
33538
33789
  var WORDMARK = [
@@ -33547,10 +33798,13 @@ function renderAgentSetupPrompt(project, restPort) {
33547
33798
  const endpoint2 = restPort === void 0 ? "The daemon endpoint is unavailable; run `npx neat.is up` to start it." : `The local daemon is serving it at http://127.0.0.1:${restPort}.`;
33548
33799
  return `NEAT is set up for project "${project}". ${endpoint2}
33549
33800
 
33550
- NEAT models this software system as one graph: code, data, infrastructure,
33551
- runtime traffic, incidents, and supported provider telemetry fused where evidence
33552
- permits. Use it to see what exists, what actually ran, where a failure began, and
33553
- what a change could affect. Missing observations do not prove a path never runs.
33801
+ NEAT does the investigation for this system, so you can spend your effort on the
33802
+ code. When something fails, call get_incident_card on the failing service, file
33803
+ or symbol: one work order with where the failure is, the cause chain (provenance
33804
+ on every hop), what a fix reaches, the policies that govern the code, and where
33805
+ code and runtime disagree. For anything else about how the system works, ask.
33806
+ NEAT answers from a live graph that fuses the code with what actually ran; a
33807
+ path it hasn't seen run is not proof the path never runs.
33554
33808
 
33555
33809
  1. Wire NEAT's MCP server into this agent session:
33556
33810
  npx neat.is skill --apply
@@ -33561,8 +33815,10 @@ what a change could affect. Missing observations do not prove a path never runs.
33561
33815
  If the daemon is unreachable, run \`npx neat.is up\`.
33562
33816
 
33563
33817
  ${AGENT_DIRECTIVE}
33564
- As the app or tests run, traces fill the OBSERVED layer. Daemon log:
33565
- neat-out/daemon.log. Reopen this door with \`npx neat.is welcome\`.`;
33818
+ Runtime evidence arrives once the app runs with NEAT attached: for Node, load
33819
+ .env.neat first (\`set -a; . ./.env.neat; set +a\`); for Python, start under
33820
+ \`opentelemetry-instrument\`. Daemon log: neat-out/daemon.log. Reopen this
33821
+ door with \`npx neat.is welcome\`.`;
33566
33822
  }
33567
33823
  function printHeader(out) {
33568
33824
  for (const line of WORDMARK) out(line);
@@ -34802,12 +35058,12 @@ async function runEditorCommand(clientId, args, projectDir = process.cwd()) {
34802
35058
 
34803
35059
  // src/monitor.ts
34804
35060
  init_cjs_shims();
34805
- var import_types113 = require("@neat.is/types");
35061
+ var import_types114 = require("@neat.is/types");
34806
35062
  var OBSERVED_DEP_EDGE_TYPES = /* @__PURE__ */ new Set([
34807
- import_types113.EdgeType.CALLS,
34808
- import_types113.EdgeType.CONNECTS_TO,
34809
- import_types113.EdgeType.PUBLISHES_TO,
34810
- import_types113.EdgeType.CONSUMES_FROM
35063
+ import_types114.EdgeType.CALLS,
35064
+ import_types114.EdgeType.CONNECTS_TO,
35065
+ import_types114.EdgeType.PUBLISHES_TO,
35066
+ import_types114.EdgeType.CONSUMES_FROM
34811
35067
  ]);
34812
35068
  function divergenceKey(d) {
34813
35069
  const column = "column" in d && d.column ? d.column : "";
@@ -34877,7 +35133,7 @@ function formatDivergenceLine2(d) {
34877
35133
  }
34878
35134
  }
34879
35135
  function formatStaleLine(edgeId) {
34880
- const parsed = (0, import_types113.parseEdgeId)(edgeId);
35136
+ const parsed = (0, import_types114.parseEdgeId)(edgeId);
34881
35137
  if (parsed) {
34882
35138
  return `\u22EF stale ${parsed.source} \u2192 ${parsed.target} (observed edge went quiet)`;
34883
35139
  }
@@ -34890,7 +35146,7 @@ function divergenceJson(d) {
34890
35146
  return JSON.stringify({ kind: "divergence", ...d });
34891
35147
  }
34892
35148
  function staleJson(edgeId) {
34893
- const parsed = (0, import_types113.parseEdgeId)(edgeId);
35149
+ const parsed = (0, import_types114.parseEdgeId)(edgeId);
34894
35150
  return JSON.stringify({
34895
35151
  kind: "stale",
34896
35152
  edgeId,
@@ -34974,7 +35230,7 @@ var MonitorEmitter = class {
34974
35230
  // ignores non-OBSERVED edges and non-dependency edge types (structural
34975
35231
  // ownership), so only real runtime dependencies reach stdout.
34976
35232
  emitObservedEdge(edge) {
34977
- if (edge.provenance !== import_types113.Provenance.OBSERVED) return false;
35233
+ if (edge.provenance !== import_types114.Provenance.OBSERVED) return false;
34978
35234
  if (!OBSERVED_DEP_EDGE_TYPES.has(edge.type)) return false;
34979
35235
  const key = `edge|${edge.id}`;
34980
35236
  if (this.seen.has(key)) return false;
@@ -35155,7 +35411,7 @@ async function runMonitor(opts) {
35155
35411
  case "edge-added": {
35156
35412
  const payload = safeParse(frame.data);
35157
35413
  const edge = payload?.edge;
35158
- if (edge && edge.provenance === import_types113.Provenance.OBSERVED) {
35414
+ if (edge && edge.provenance === import_types114.Provenance.OBSERVED) {
35159
35415
  emitter.emitObservedEdge(edge);
35160
35416
  divergences.schedule();
35161
35417
  }
@@ -35426,7 +35682,7 @@ async function runSync(opts) {
35426
35682
  }
35427
35683
 
35428
35684
  // src/cli.ts
35429
- var import_types114 = require("@neat.is/types");
35685
+ var import_types115 = require("@neat.is/types");
35430
35686
  init_auth();
35431
35687
  function usage5() {
35432
35688
  const neat = commandPrefix();
@@ -36338,10 +36594,15 @@ async function main() {
36338
36594
  return;
36339
36595
  }
36340
36596
  if (cmd === "sync") {
36597
+ const syncTarget = await resolveClientTarget({
36598
+ ...parsed.project ? { project: parsed.project } : {},
36599
+ ...parsed.profile ? { profile: parsed.profile } : {}
36600
+ });
36341
36601
  const result = await runSync({
36342
36602
  ...parsed.project ? { project: parsed.project } : {},
36343
36603
  ...parsed.to ? { to: parsed.to } : {},
36344
36604
  ...parsed.token ? { token: parsed.token } : {},
36605
+ daemonUrl: syncTarget.endpoint,
36345
36606
  dryRun: parsed.dryRun,
36346
36607
  noInstrument: parsed.noInstrument,
36347
36608
  sourceEdit: parsed.sourceEdit,
@@ -36500,9 +36761,28 @@ async function resolveClientTarget(opts = {}) {
36500
36761
  if (daemon) {
36501
36762
  return { endpoint: `http://localhost:${daemon.record.ports.rest}`, source: "daemon-record" };
36502
36763
  }
36764
+ } else {
36765
+ const live = (await discoverDaemons()).filter((d) => d.live);
36766
+ if (live.length === 1) {
36767
+ return {
36768
+ endpoint: `http://localhost:${live[0].record.ports.rest}`,
36769
+ source: "sole-daemon"
36770
+ };
36771
+ }
36503
36772
  }
36504
36773
  return { endpoint: "http://localhost:8080", source: "default" };
36505
36774
  }
36775
+ async function loopbackResolutionHint() {
36776
+ const live = (await discoverDaemons()).filter((d) => d.live);
36777
+ if (live.length === 0) {
36778
+ return "No NEAT daemon is running. Start one with `npx neat.is` in your project (or `neat up`), then re-run \u2014 or set NEAT_API_URL to a daemon.";
36779
+ }
36780
+ if (live.length > 1) {
36781
+ const list = live.map((d) => ` ${d.record.project} \u2192 http://localhost:${d.record.ports.rest}`).join("\n");
36782
+ return "This directory is not a registered NEAT project and several daemons are running, so NEAT cannot pick one. Run from the project directory, pass --project <name>, or set NEAT_API_URL:\n" + list;
36783
+ }
36784
+ return void 0;
36785
+ }
36506
36786
  async function projectForCwd(cwd = process.cwd()) {
36507
36787
  try {
36508
36788
  return (await findProjectByPath(cwd))?.name;
@@ -36511,7 +36791,7 @@ async function projectForCwd(cwd = process.cwd()) {
36511
36791
  }
36512
36792
  }
36513
36793
  function cwdProjectApplies(source) {
36514
- return source === "daemon-record" || source === "default";
36794
+ return source === "daemon-record" || source === "sole-daemon" || source === "default";
36515
36795
  }
36516
36796
  async function resolveDaemonUrl(project, profile) {
36517
36797
  return (await resolveClientTarget({ project, profile })).endpoint;
@@ -36533,6 +36813,11 @@ async function runQueryVerb(cmd, parsed) {
36533
36813
  }
36534
36814
  throw err;
36535
36815
  }
36816
+ if (target.source === "default" && !requestedProject && !cwdProject) {
36817
+ const hint = await loopbackResolutionHint();
36818
+ if (hint) process.stderr.write(`${hint}
36819
+ `);
36820
+ }
36536
36821
  const client = createHttpClient(target.endpoint, target.authToken);
36537
36822
  const positional = parsed.positional;
36538
36823
  let makeWork;
@@ -36659,10 +36944,10 @@ async function runQueryVerb(cmd, parsed) {
36659
36944
  const parts = parsed.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
36660
36945
  const out = [];
36661
36946
  for (const p of parts) {
36662
- const r = import_types114.DivergenceTypeSchema.safeParse(p);
36947
+ const r = import_types115.DivergenceTypeSchema.safeParse(p);
36663
36948
  if (!r.success) {
36664
36949
  console.error(
36665
- `neat divergences: unknown --type "${p}". allowed: ${import_types114.DivergenceTypeSchema.options.join(", ")}`
36950
+ `neat divergences: unknown --type "${p}". allowed: ${import_types115.DivergenceTypeSchema.options.join(", ")}`
36666
36951
  );
36667
36952
  return 2;
36668
36953
  }
@@ -36780,6 +37065,7 @@ if (/[\\/](?:cli\.(?:cjs|js)|cli|neat|neat\.is)$/.test(entry)) {
36780
37065
  cwdProjectApplies,
36781
37066
  isLoopbackEndpoint,
36782
37067
  isNpxInvocation,
37068
+ loopbackResolutionHint,
36783
37069
  main,
36784
37070
  parseArgs,
36785
37071
  printBanner,