@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/index.cjs CHANGED
@@ -2919,7 +2919,7 @@ var PolicyViolationsLog = class {
2919
2919
  };
2920
2920
 
2921
2921
  // src/ingest.ts
2922
- var import_types8 = require("@neat.is/types");
2922
+ var import_types9 = require("@neat.is/types");
2923
2923
 
2924
2924
  // src/extract/routes.ts
2925
2925
  init_cjs_shims();
@@ -5679,9 +5679,101 @@ async function addRoutes(graph, services) {
5679
5679
  return { nodesAdded, edgesAdded };
5680
5680
  }
5681
5681
 
5682
- // src/columns.ts
5682
+ // src/extract/source-baseline.ts
5683
5683
  init_cjs_shims();
5684
5684
  var import_types7 = require("@neat.is/types");
5685
+ var states = /* @__PURE__ */ new WeakMap();
5686
+ var REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
5687
+ function validCommit(commit, repository) {
5688
+ return !!commit && commit.repository === repository && /^[0-9a-f]{40}$/.test(commit.sha);
5689
+ }
5690
+ function stateOf(graph) {
5691
+ let state = states.get(graph);
5692
+ if (!state) {
5693
+ state = { repos: /* @__PURE__ */ new Map(), active: /* @__PURE__ */ new Set(), conflicted: /* @__PURE__ */ new Set() };
5694
+ states.set(graph, state);
5695
+ }
5696
+ return state;
5697
+ }
5698
+ function setEntry(state, repository, baseline, generation = /* @__PURE__ */ Symbol()) {
5699
+ state.repos.set(repository, {
5700
+ baseline,
5701
+ generation,
5702
+ services: state.repos.get(repository)?.services ?? /* @__PURE__ */ new Set()
5703
+ });
5704
+ }
5705
+ function readSourceBaselines(graph) {
5706
+ const state = states.get(graph);
5707
+ if (!state) return [];
5708
+ return [...state.repos.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, entry]) => ({ ...entry.baseline }));
5709
+ }
5710
+ function invalidateSourceBaseline(graph, repository, status2 = "unavailable") {
5711
+ if (repository !== void 0) {
5712
+ if (REPOSITORY.test(repository)) setEntry(stateOf(graph), repository, { status: status2, repository });
5713
+ return;
5714
+ }
5715
+ const state = states.get(graph);
5716
+ if (!state) return;
5717
+ for (const generation of state.active) state.conflicted.add(generation);
5718
+ for (const name of state.repos.keys()) {
5719
+ setEntry(state, name, { status: "unavailable", repository: name });
5720
+ }
5721
+ }
5722
+ function retainSourceBaselines(graph, repositories) {
5723
+ const state = states.get(graph);
5724
+ if (!state) return;
5725
+ const keep = new Set(repositories);
5726
+ for (const name of [...state.repos.keys()]) if (!keep.has(name)) state.repos.delete(name);
5727
+ }
5728
+ function beginSourceExtraction(graph, source, commit) {
5729
+ const generation = /* @__PURE__ */ Symbol();
5730
+ const state = stateOf(graph);
5731
+ if (source === void 0) {
5732
+ invalidateSourceBaseline(graph);
5733
+ state.active.add(generation);
5734
+ return generation;
5735
+ }
5736
+ state.active.add(generation);
5737
+ if (!REPOSITORY.test(source)) return generation;
5738
+ setEntry(
5739
+ state,
5740
+ source,
5741
+ validCommit(commit, source) ? { status: "syncing", repository: source } : { status: "unavailable", repository: source },
5742
+ generation
5743
+ );
5744
+ return generation;
5745
+ }
5746
+ function servicesOf(graph, repository) {
5747
+ const services = /* @__PURE__ */ new Set();
5748
+ graph.forEachNode((_id, attrs) => {
5749
+ const node = attrs;
5750
+ if (node.type === import_types7.NodeType.FileNode && node.source === repository && node.service) {
5751
+ services.add(node.service);
5752
+ }
5753
+ });
5754
+ return services;
5755
+ }
5756
+ function finishSourceExtraction(graph, generation, source, commit, result) {
5757
+ const state = states.get(graph);
5758
+ if (!state) return;
5759
+ state.active.delete(generation);
5760
+ const conflicted = state.conflicted.delete(generation);
5761
+ if (source === void 0 || !REPOSITORY.test(source)) return;
5762
+ const entry = state.repos.get(source);
5763
+ if (!entry || entry.generation !== generation) return;
5764
+ entry.services = servicesOf(graph, source);
5765
+ let shared = false;
5766
+ for (const [name, other] of state.repos) {
5767
+ if (name === source || ![...entry.services].some((s) => other.services.has(s))) continue;
5768
+ shared = true;
5769
+ setEntry(state, name, { status: "unavailable", repository: name }, other.generation);
5770
+ }
5771
+ entry.baseline = !conflicted && !shared && validCommit(commit, source) && result.extractionErrors === 0 && result.skippedFiles === 0 ? { status: "ready", repository: source, sha: commit.sha } : { status: "unavailable", repository: source };
5772
+ }
5773
+
5774
+ // src/columns.ts
5775
+ init_cjs_shims();
5776
+ var import_types8 = require("@neat.is/types");
5685
5777
  var OBSERVED_COLUMN_CONFIDENCE = 0.9;
5686
5778
  function normalizeProvenances(provenances) {
5687
5779
  return [...new Set(provenances)].sort();
@@ -5724,10 +5816,10 @@ function foldSdkWrites(existing, writes) {
5724
5816
  return out;
5725
5817
  }
5726
5818
  function columnIsDeclared(col) {
5727
- return col.provenances.includes(import_types7.Provenance.EXTRACTED);
5819
+ return col.provenances.includes(import_types8.Provenance.EXTRACTED);
5728
5820
  }
5729
5821
  function columnIsObserved(col) {
5730
- return col.provenances.includes(import_types7.Provenance.OBSERVED);
5822
+ return col.provenances.includes(import_types8.Provenance.OBSERVED);
5731
5823
  }
5732
5824
 
5733
5825
  // src/latency-digest.ts
@@ -6191,11 +6283,11 @@ function callSiteFromSpan(span, serviceNode, scanPath) {
6191
6283
  };
6192
6284
  }
6193
6285
  function reconcileObservedRelPath(graph, serviceName, relPath) {
6194
- if (graph.hasNode((0, import_types8.fileId)(serviceName, relPath))) return relPath;
6286
+ if (graph.hasNode((0, import_types9.fileId)(serviceName, relPath))) return relPath;
6195
6287
  let best = null;
6196
6288
  graph.forEachNode((_id, attrs) => {
6197
6289
  const a = attrs;
6198
- if (a.type !== import_types8.NodeType.FileNode || a.service !== serviceName) return;
6290
+ if (a.type !== import_types9.NodeType.FileNode || a.service !== serviceName) return;
6199
6291
  if (a.discoveredVia === "otel") return;
6200
6292
  const p = a.path;
6201
6293
  if (!p) return;
@@ -6207,14 +6299,14 @@ function reconcileObservedRelPath(graph, serviceName, relPath) {
6207
6299
  }
6208
6300
  function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
6209
6301
  const svcAttrs = graph.hasNode(serviceNodeId) ? graph.getNodeAttributes(serviceNodeId) : void 0;
6210
- const canonicalService = svcAttrs && svcAttrs.type === import_types8.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
6302
+ const canonicalService = svcAttrs && svcAttrs.type === import_types9.NodeType.ServiceNode && typeof svcAttrs.name === "string" ? svcAttrs.name : serviceName;
6211
6303
  const relPath = reconcileObservedRelPath(graph, canonicalService, callSite.relPath);
6212
- const fileNodeId = (0, import_types8.fileId)(canonicalService, relPath);
6304
+ const fileNodeId = (0, import_types9.fileId)(canonicalService, relPath);
6213
6305
  if (!graph.hasNode(fileNodeId)) {
6214
6306
  const language = languageForExt(relPath);
6215
6307
  const node = {
6216
6308
  id: fileNodeId,
6217
- type: import_types8.NodeType.FileNode,
6309
+ type: import_types9.NodeType.FileNode,
6218
6310
  service: canonicalService,
6219
6311
  path: relPath,
6220
6312
  ...language ? { language } : {},
@@ -6223,14 +6315,14 @@ function ensureObservedFileNode(graph, serviceName, serviceNodeId, callSite) {
6223
6315
  };
6224
6316
  graph.addNode(fileNodeId, node);
6225
6317
  }
6226
- const containsId = makeObservedEdgeId(import_types8.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
6318
+ const containsId = makeObservedEdgeId(import_types9.EdgeType.CONTAINS, serviceNodeId, fileNodeId);
6227
6319
  if (!graph.hasEdge(containsId)) {
6228
6320
  const edge = {
6229
6321
  id: containsId,
6230
6322
  source: serviceNodeId,
6231
6323
  target: fileNodeId,
6232
- type: import_types8.EdgeType.CONTAINS,
6233
- provenance: import_types8.Provenance.OBSERVED
6324
+ type: import_types9.EdgeType.CONTAINS,
6325
+ provenance: import_types9.Provenance.OBSERVED
6234
6326
  };
6235
6327
  graph.addEdgeWithKey(containsId, serviceNodeId, fileNodeId, edge);
6236
6328
  }
@@ -6254,11 +6346,11 @@ function pickContainingSymbol(candidates, fn) {
6254
6346
  return [...candidates].sort(bySpan)[0].id;
6255
6347
  }
6256
6348
  function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line) {
6257
- const sid = (0, import_types8.symbolId)(service, relPath, fn);
6349
+ const sid = (0, import_types9.symbolId)(service, relPath, fn);
6258
6350
  if (!graph.hasNode(sid)) {
6259
6351
  const node = {
6260
6352
  id: sid,
6261
- type: import_types8.NodeType.SymbolNode,
6353
+ type: import_types9.NodeType.SymbolNode,
6262
6354
  kind: "function",
6263
6355
  qualname: fn,
6264
6356
  span: { startLine: line, endLine: line },
@@ -6268,14 +6360,14 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
6268
6360
  };
6269
6361
  graph.addNode(sid, node);
6270
6362
  }
6271
- const containsId = makeObservedEdgeId(import_types8.EdgeType.CONTAINS, fileNodeId, sid);
6363
+ const containsId = makeObservedEdgeId(import_types9.EdgeType.CONTAINS, fileNodeId, sid);
6272
6364
  if (!graph.hasEdge(containsId)) {
6273
6365
  const edge = {
6274
6366
  id: containsId,
6275
6367
  source: fileNodeId,
6276
6368
  target: sid,
6277
- type: import_types8.EdgeType.CONTAINS,
6278
- provenance: import_types8.Provenance.OBSERVED
6369
+ type: import_types9.EdgeType.CONTAINS,
6370
+ provenance: import_types9.Provenance.OBSERVED
6279
6371
  };
6280
6372
  graph.addEdgeWithKey(containsId, fileNodeId, sid, edge);
6281
6373
  }
@@ -6287,9 +6379,9 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
6287
6379
  let sawSymbol = false;
6288
6380
  const candidates = [];
6289
6381
  graph.forEachOutboundEdge(fileNodeId, (_edge, edgeAttrs, _source, target) => {
6290
- if (edgeAttrs.type !== import_types8.EdgeType.CONTAINS) return;
6382
+ if (edgeAttrs.type !== import_types9.EdgeType.CONTAINS) return;
6291
6383
  const t = graph.getNodeAttributes(target);
6292
- if (t.type !== import_types8.NodeType.SymbolNode) return;
6384
+ if (t.type !== import_types9.NodeType.SymbolNode) return;
6293
6385
  sawSymbol = true;
6294
6386
  if (line >= t.span.startLine && line <= t.span.endLine) {
6295
6387
  candidates.push({ id: target, symbol: t });
@@ -6302,17 +6394,17 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint
6302
6394
  return fileNodeId;
6303
6395
  }
6304
6396
  function makeObservedEdgeId(type, source, target) {
6305
- return (0, import_types8.observedEdgeId)(source, target, type);
6397
+ return (0, import_types9.observedEdgeId)(source, target, type);
6306
6398
  }
6307
6399
  function makeInferredEdgeId(type, source, target) {
6308
- return (0, import_types8.inferredEdgeId)(source, target, type);
6400
+ return (0, import_types9.inferredEdgeId)(source, target, type);
6309
6401
  }
6310
6402
  var INFERRED_CONFIDENCE = 0.6;
6311
6403
  var STITCH_MAX_DEPTH = 2;
6312
6404
  var STITCH_EDGE_TYPES = /* @__PURE__ */ new Set([
6313
- import_types8.EdgeType.CALLS,
6314
- import_types8.EdgeType.CONNECTS_TO,
6315
- import_types8.EdgeType.DEPENDS_ON
6405
+ import_types9.EdgeType.CALLS,
6406
+ import_types9.EdgeType.CONNECTS_TO,
6407
+ import_types9.EdgeType.DEPENDS_ON
6316
6408
  ]);
6317
6409
  var WIRE_SPAN_KIND_CLIENT = 3;
6318
6410
  var WIRE_SPAN_KIND_PRODUCER = 4;
@@ -6328,11 +6420,11 @@ function spanServesGraphqlOperation(kind) {
6328
6420
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6329
6421
  }
6330
6422
  function ensureGraphqlOperationNode(graph, serviceName, operationType, operationName) {
6331
- const id = (0, import_types8.graphqlOperationId)(serviceName, operationType, operationName);
6423
+ const id = (0, import_types9.graphqlOperationId)(serviceName, operationType, operationName);
6332
6424
  if (graph.hasNode(id)) return id;
6333
6425
  const node = {
6334
6426
  id,
6335
- type: import_types8.NodeType.GraphQLOperationNode,
6427
+ type: import_types9.NodeType.GraphQLOperationNode,
6336
6428
  name: operationName,
6337
6429
  service: serviceName,
6338
6430
  operationType: operationType.toLowerCase(),
@@ -6346,11 +6438,11 @@ function spanServesGrpcMethod(kind) {
6346
6438
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6347
6439
  }
6348
6440
  function ensureGrpcMethodNode(graph, rpcService, rpcMethod) {
6349
- const id = (0, import_types8.grpcMethodId)(rpcService, rpcMethod);
6441
+ const id = (0, import_types9.grpcMethodId)(rpcService, rpcMethod);
6350
6442
  if (graph.hasNode(id)) return id;
6351
6443
  const node = {
6352
6444
  id,
6353
- type: import_types8.NodeType.GrpcMethodNode,
6445
+ type: import_types9.NodeType.GrpcMethodNode,
6354
6446
  name: `${rpcService}/${rpcMethod}`,
6355
6447
  rpcService,
6356
6448
  rpcMethod,
@@ -6363,11 +6455,11 @@ function spanServesWebsocketChannel(kind) {
6363
6455
  return kind !== WIRE_SPAN_KIND_CLIENT && kind !== WIRE_SPAN_KIND_PRODUCER && kind !== WIRE_SPAN_KIND_CONSUMER;
6364
6456
  }
6365
6457
  function ensureWebsocketChannelNode(graph, serviceName, channel) {
6366
- const id = (0, import_types8.websocketChannelId)(serviceName, channel);
6458
+ const id = (0, import_types9.websocketChannelId)(serviceName, channel);
6367
6459
  if (graph.hasNode(id)) return id;
6368
6460
  const node = {
6369
6461
  id,
6370
- type: import_types8.NodeType.WebSocketChannelNode,
6462
+ type: import_types9.NodeType.WebSocketChannelNode,
6371
6463
  name: channel,
6372
6464
  service: serviceName,
6373
6465
  channel,
@@ -6380,11 +6472,11 @@ function messagingDestinationKind(system) {
6380
6472
  return `${system}-topic`;
6381
6473
  }
6382
6474
  function ensureMessagingDestinationNode(graph, system, destination) {
6383
- const id = (0, import_types8.infraId)(messagingDestinationKind(system), destination);
6475
+ const id = (0, import_types9.infraId)(messagingDestinationKind(system), destination);
6384
6476
  if (graph.hasNode(id)) return id;
6385
6477
  const node = {
6386
6478
  id,
6387
- type: import_types8.NodeType.InfraNode,
6479
+ type: import_types9.NodeType.InfraNode,
6388
6480
  name: destination,
6389
6481
  provider: "self",
6390
6482
  kind: messagingDestinationKind(system)
@@ -6428,9 +6520,9 @@ function lookupParentSpan(traceId, parentSpanId, now) {
6428
6520
  };
6429
6521
  }
6430
6522
  function resolveServiceId(graph, host, env) {
6431
- const envTagged = (0, import_types8.serviceId)(host, env);
6523
+ const envTagged = (0, import_types9.serviceId)(host, env);
6432
6524
  if (graph.hasNode(envTagged)) return envTagged;
6433
- const envLess = (0, import_types8.serviceId)(host);
6525
+ const envLess = (0, import_types9.serviceId)(host);
6434
6526
  if (envLess !== envTagged && graph.hasNode(envLess)) return envLess;
6435
6527
  let sameEnv = null;
6436
6528
  let envLessMatch = null;
@@ -6438,7 +6530,7 @@ function resolveServiceId(graph, host, env) {
6438
6530
  graph.forEachNode((id, attrs) => {
6439
6531
  if (sameEnv) return;
6440
6532
  const a = attrs;
6441
- if (a.type !== import_types8.NodeType.ServiceNode) return;
6533
+ if (a.type !== import_types9.NodeType.ServiceNode) return;
6442
6534
  const matchesByName = a.name === host;
6443
6535
  const matchesByAlias = a.aliases ? a.aliases.includes(host) : false;
6444
6536
  if (!matchesByName && !matchesByAlias) return;
@@ -6453,14 +6545,14 @@ function resolveServiceId(graph, host, env) {
6453
6545
  return sameEnv ?? envLessMatch ?? anyMatch;
6454
6546
  }
6455
6547
  function frontierIdFor(host) {
6456
- return (0, import_types8.frontierId)(host);
6548
+ return (0, import_types9.frontierId)(host);
6457
6549
  }
6458
6550
  function resolveFusedServiceId(graph, serviceName, env) {
6459
- const id = (0, import_types8.serviceId)(serviceName, env);
6551
+ const id = (0, import_types9.serviceId)(serviceName, env);
6460
6552
  if (graph.hasNode(id)) return id;
6461
6553
  const wanted = serviceName.toLowerCase();
6462
6554
  const extractedId = graph.findNode((_nid, attrs) => {
6463
- if (attrs.type !== import_types8.NodeType.ServiceNode) return false;
6555
+ if (attrs.type !== import_types9.NodeType.ServiceNode) return false;
6464
6556
  const svc = attrs;
6465
6557
  if (svc.discoveredVia === "otel") return false;
6466
6558
  return typeof svc.name === "string" && svc.name.toLowerCase() === wanted;
@@ -6472,7 +6564,7 @@ function ensureServiceNode(graph, serviceName, env) {
6472
6564
  if (graph.hasNode(resolved)) return resolved;
6473
6565
  const node = {
6474
6566
  id: resolved,
6475
- type: import_types8.NodeType.ServiceNode,
6567
+ type: import_types9.NodeType.ServiceNode,
6476
6568
  name: serviceName,
6477
6569
  language: "unknown",
6478
6570
  discoveredVia: "otel",
@@ -6482,11 +6574,11 @@ function ensureServiceNode(graph, serviceName, env) {
6482
6574
  return resolved;
6483
6575
  }
6484
6576
  function ensureInfraNode(graph, kind, name, provider) {
6485
- const id = (0, import_types8.infraId)(kind, name);
6577
+ const id = (0, import_types9.infraId)(kind, name);
6486
6578
  if (graph.hasNode(id)) return id;
6487
6579
  const node = {
6488
6580
  id,
6489
- type: import_types8.NodeType.InfraNode,
6581
+ type: import_types9.NodeType.InfraNode,
6490
6582
  name,
6491
6583
  provider,
6492
6584
  kind
@@ -6498,7 +6590,7 @@ var COLUMN_BEARING_INFRA_KINDS = /* @__PURE__ */ new Set(["sql-table", "supabase
6498
6590
  function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
6499
6591
  if (!columns || columns.length === 0 || !graph.hasNode(tableNodeId)) return;
6500
6592
  const node = graph.getNodeAttributes(tableNodeId);
6501
- if (node.type !== import_types8.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
6593
+ if (node.type !== import_types9.NodeType.InfraNode || !node.kind || !COLUMN_BEARING_INFRA_KINDS.has(node.kind)) {
6502
6594
  return;
6503
6595
  }
6504
6596
  graph.replaceNodeAttributes(tableNodeId, {
@@ -6507,7 +6599,7 @@ function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
6507
6599
  });
6508
6600
  }
6509
6601
  function mergeObservedColumns(graph, tableNodeId, columns) {
6510
- mergeColumnsAt(graph, tableNodeId, columns, import_types8.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
6602
+ mergeColumnsAt(graph, tableNodeId, columns, import_types9.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
6511
6603
  }
6512
6604
  function mergeObservedDeployState(graph, serviceNodeId, state) {
6513
6605
  if (!graph.hasNode(serviceNodeId)) return;
@@ -6518,11 +6610,11 @@ function mergeObservedDeployState(graph, serviceNodeId, state) {
6518
6610
  graph.mergeNodeAttributes(serviceNodeId, attrs);
6519
6611
  }
6520
6612
  function ensureDatabaseNode(graph, host, engine) {
6521
- const id = (0, import_types8.databaseId)(host);
6613
+ const id = (0, import_types9.databaseId)(host);
6522
6614
  if (graph.hasNode(id)) return id;
6523
6615
  const node = {
6524
6616
  id,
6525
- type: import_types8.NodeType.DatabaseNode,
6617
+ type: import_types9.NodeType.DatabaseNode,
6526
6618
  name: host,
6527
6619
  engine,
6528
6620
  engineVersion: "unknown",
@@ -6534,11 +6626,11 @@ function ensureDatabaseNode(graph, host, engine) {
6534
6626
  return id;
6535
6627
  }
6536
6628
  function ensureLocalDatabaseNode(graph, serviceName, name, engine) {
6537
- const id = (0, import_types8.localDatabaseId)(serviceName, name);
6629
+ const id = (0, import_types9.localDatabaseId)(serviceName, name);
6538
6630
  if (graph.hasNode(id)) return id;
6539
6631
  const node = {
6540
6632
  id,
6541
- type: import_types8.NodeType.DatabaseNode,
6633
+ type: import_types9.NodeType.DatabaseNode,
6542
6634
  name,
6543
6635
  engine,
6544
6636
  engineVersion: "unknown",
@@ -6553,17 +6645,17 @@ function findDeclaredDatabaseForService(graph, serviceNodeId, engine) {
6553
6645
  const sources = [serviceNodeId];
6554
6646
  for (const edgeId of graph.outboundEdges(serviceNodeId)) {
6555
6647
  const e = graph.getEdgeAttributes(edgeId);
6556
- if (e.type === import_types8.EdgeType.CONTAINS) sources.push(e.target);
6648
+ if (e.type === import_types9.EdgeType.CONTAINS) sources.push(e.target);
6557
6649
  }
6558
6650
  const matches = /* @__PURE__ */ new Set();
6559
6651
  for (const src of sources) {
6560
6652
  if (!graph.hasNode(src)) continue;
6561
6653
  for (const edgeId of graph.outboundEdges(src)) {
6562
6654
  const edge = graph.getEdgeAttributes(edgeId);
6563
- if (edge.type !== import_types8.EdgeType.CONNECTS_TO || edge.provenance !== import_types8.Provenance.EXTRACTED) continue;
6655
+ if (edge.type !== import_types9.EdgeType.CONNECTS_TO || edge.provenance !== import_types9.Provenance.EXTRACTED) continue;
6564
6656
  if (!graph.hasNode(edge.target)) continue;
6565
6657
  const target = graph.getNodeAttributes(edge.target);
6566
- if (target.type !== import_types8.NodeType.DatabaseNode || target.engine !== engine) continue;
6658
+ if (target.type !== import_types9.NodeType.DatabaseNode || target.engine !== engine) continue;
6567
6659
  matches.add(edge.target);
6568
6660
  }
6569
6661
  }
@@ -6578,7 +6670,7 @@ function ensureFrontierNode(graph, host, ts) {
6578
6670
  }
6579
6671
  const node = {
6580
6672
  id,
6581
- type: import_types8.NodeType.FrontierNode,
6673
+ type: import_types9.NodeType.FrontierNode,
6582
6674
  name: host,
6583
6675
  host,
6584
6676
  firstObserved: ts,
@@ -6631,11 +6723,11 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
6631
6723
  };
6632
6724
  const updated = {
6633
6725
  ...existing,
6634
- provenance: import_types8.Provenance.OBSERVED,
6726
+ provenance: import_types9.Provenance.OBSERVED,
6635
6727
  lastObserved: ts,
6636
6728
  callCount: newSpanCount,
6637
6729
  signal: newSignal,
6638
- confidence: (0, import_types8.confidenceForObservedSignal)(newSignal),
6730
+ confidence: (0, import_types9.confidenceForObservedSignal)(newSignal),
6639
6731
  grain
6640
6732
  // backfills legacy edges that predate ADR-142
6641
6733
  };
@@ -6658,8 +6750,8 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
6658
6750
  source,
6659
6751
  target,
6660
6752
  type,
6661
- provenance: import_types8.Provenance.OBSERVED,
6662
- confidence: (0, import_types8.confidenceForObservedSignal)(signal),
6753
+ provenance: import_types9.Provenance.OBSERVED,
6754
+ confidence: (0, import_types9.confidenceForObservedSignal)(signal),
6663
6755
  lastObserved: ts,
6664
6756
  callCount: 1,
6665
6757
  signal,
@@ -6681,9 +6773,9 @@ function stitchTrace(graph, sourceServiceId, ts) {
6681
6773
  const outbound = graph.outboundEdges(nodeId);
6682
6774
  for (const edgeId of outbound) {
6683
6775
  const edge = graph.getEdgeAttributes(edgeId);
6684
- if (edge.provenance !== import_types8.Provenance.EXTRACTED) continue;
6776
+ if (edge.provenance !== import_types9.Provenance.EXTRACTED) continue;
6685
6777
  if (!STITCH_EDGE_TYPES.has(edge.type)) continue;
6686
- if (graph.hasEdge((0, import_types8.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
6778
+ if (graph.hasEdge((0, import_types9.observedEdgeId)(edge.source, edge.target, edge.type))) continue;
6687
6779
  upsertInferredEdge(graph, edge.type, edge.source, edge.target, ts);
6688
6780
  if (!visited.has(edge.target)) {
6689
6781
  visited.add(edge.target);
@@ -6705,7 +6797,7 @@ function upsertInferredEdge(graph, type, source, target, ts) {
6705
6797
  source,
6706
6798
  target,
6707
6799
  type,
6708
- provenance: import_types8.Provenance.INFERRED,
6800
+ provenance: import_types9.Provenance.INFERRED,
6709
6801
  confidence: INFERRED_CONFIDENCE,
6710
6802
  lastObserved: ts
6711
6803
  };
@@ -6719,7 +6811,7 @@ function emitIncidentEvent(project, ev) {
6719
6811
  incidentId: ev.id,
6720
6812
  affectedNode: ev.affectedNode,
6721
6813
  service: ev.service,
6722
- incidentKind: (0, import_types8.incidentKindOf)(ev),
6814
+ incidentKind: (0, import_types9.incidentKindOf)(ev),
6723
6815
  at: ev.timestamp
6724
6816
  }
6725
6817
  });
@@ -6748,7 +6840,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
6748
6840
  const canonicalService = serviceNodeName(graph, span) ?? span.service;
6749
6841
  const recovered = !trusted;
6750
6842
  if (graph) {
6751
- const fusedFileId = (0, import_types8.fileId)(canonicalService, relPath);
6843
+ const fusedFileId = (0, import_types9.fileId)(canonicalService, relPath);
6752
6844
  if (graph.hasNode(fusedFileId)) {
6753
6845
  const node = landObservedSymbol(
6754
6846
  graph,
@@ -6768,7 +6860,7 @@ function landIncidentCallSite(span, callSite, trusted, graph) {
6768
6860
  }
6769
6861
  if (recovered) return null;
6770
6862
  }
6771
- return { affectedNode: (0, import_types8.fileId)(span.service, relPath) };
6863
+ return { affectedNode: (0, import_types9.fileId)(span.service, relPath) };
6772
6864
  }
6773
6865
  function serviceNodeName(graph, span) {
6774
6866
  if (!graph) return void 0;
@@ -6785,7 +6877,7 @@ function stacktraceCallSite(span, serviceNode, scanPath) {
6785
6877
  return { relPath, line: frame.line, ...frame.fn ? { fn: frame.fn } : {} };
6786
6878
  }
6787
6879
  function incidentLocus(span, graph, scanPath) {
6788
- const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types8.serviceId)(span.service, span.env);
6880
+ const sid = graph ? resolveFusedServiceId(graph, span.service, span.env) : (0, import_types9.serviceId)(span.service, span.env);
6789
6881
  const serviceNode = graph && graph.hasNode(sid) ? graph.getNodeAttributes(sid) : void 0;
6790
6882
  const callSite = callSiteFromSpan(span, serviceNode, scanPath);
6791
6883
  if (callSite) {
@@ -6976,7 +7068,7 @@ function findRouteNodeByHttpRoute(graph, serviceName, method, httpRoute) {
6976
7068
  graph.forEachNode((id, attrs) => {
6977
7069
  if (found) return;
6978
7070
  const a = attrs;
6979
- if (a.type !== import_types8.NodeType.RouteNode || a.service !== serviceName) return;
7071
+ if (a.type !== import_types9.NodeType.RouteNode || a.service !== serviceName) return;
6980
7072
  if (m && a.method !== "ALL" && a.method !== m) return;
6981
7073
  if (normalizePathTemplate(a.pathTemplate) === target) found = id;
6982
7074
  });
@@ -7009,7 +7101,7 @@ async function handleSpan(ctx, span) {
7009
7101
  let targetId;
7010
7102
  if (host) {
7011
7103
  ensureDatabaseNode(ctx.graph, host, span.dbSystem);
7012
- targetId = (0, import_types8.databaseId)(host);
7104
+ targetId = (0, import_types9.databaseId)(host);
7013
7105
  } else {
7014
7106
  const declared = findDeclaredDatabaseForService(ctx.graph, sourceId, span.dbSystem);
7015
7107
  if (declared) {
@@ -7026,7 +7118,7 @@ async function handleSpan(ctx, span) {
7026
7118
  }
7027
7119
  const result = upsertObservedEdge(
7028
7120
  ctx.graph,
7029
- import_types8.EdgeType.CONNECTS_TO,
7121
+ import_types9.EdgeType.CONNECTS_TO,
7030
7122
  observedSource(),
7031
7123
  targetId,
7032
7124
  ts,
@@ -7040,7 +7132,7 @@ async function handleSpan(ctx, span) {
7040
7132
  const collectionId = ensureInfraNode(ctx.graph, "mongodb-collection", span.dbCollection, "self");
7041
7133
  upsertObservedEdge(
7042
7134
  ctx.graph,
7043
- import_types8.EdgeType.CALLS,
7135
+ import_types9.EdgeType.CALLS,
7044
7136
  observedSource(),
7045
7137
  collectionId,
7046
7138
  ts,
@@ -7054,7 +7146,7 @@ async function handleSpan(ctx, span) {
7054
7146
  const tableId = ensureInfraNode(ctx.graph, "sql-table", span.dbTable, "self");
7055
7147
  upsertObservedEdge(
7056
7148
  ctx.graph,
7057
- import_types8.EdgeType.CALLS,
7149
+ import_types9.EdgeType.CALLS,
7058
7150
  observedSource(),
7059
7151
  tableId,
7060
7152
  ts,
@@ -7072,7 +7164,7 @@ async function handleSpan(ctx, span) {
7072
7164
  span.messagingSystem,
7073
7165
  span.messagingDestination
7074
7166
  );
7075
- const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types8.EdgeType.CONSUMES_FROM : import_types8.EdgeType.PUBLISHES_TO;
7167
+ const edgeType = span.kind === WIRE_SPAN_KIND_CONSUMER ? import_types9.EdgeType.CONSUMES_FROM : import_types9.EdgeType.PUBLISHES_TO;
7076
7168
  const result = upsertObservedEdge(
7077
7169
  ctx.graph,
7078
7170
  edgeType,
@@ -7094,7 +7186,7 @@ async function handleSpan(ctx, span) {
7094
7186
  );
7095
7187
  const result = upsertObservedEdge(
7096
7188
  ctx.graph,
7097
- import_types8.EdgeType.CONTAINS,
7189
+ import_types9.EdgeType.CONTAINS,
7098
7190
  observedSource(),
7099
7191
  targetId,
7100
7192
  ts,
@@ -7108,7 +7200,7 @@ async function handleSpan(ctx, span) {
7108
7200
  const targetId = ensureGrpcMethodNode(ctx.graph, span.rpcService, span.rpcMethod);
7109
7201
  const result = upsertObservedEdge(
7110
7202
  ctx.graph,
7111
- import_types8.EdgeType.CONTAINS,
7203
+ import_types9.EdgeType.CONTAINS,
7112
7204
  observedSource(),
7113
7205
  targetId,
7114
7206
  ts,
@@ -7126,7 +7218,7 @@ async function handleSpan(ctx, span) {
7126
7218
  );
7127
7219
  const result = upsertObservedEdge(
7128
7220
  ctx.graph,
7129
- import_types8.EdgeType.CONNECTS_TO,
7221
+ import_types9.EdgeType.CONNECTS_TO,
7130
7222
  observedSource(),
7131
7223
  targetId,
7132
7224
  ts,
@@ -7144,7 +7236,7 @@ async function handleSpan(ctx, span) {
7144
7236
  if (targetId && targetId !== sourceId) {
7145
7237
  upsertObservedEdge(
7146
7238
  ctx.graph,
7147
- import_types8.EdgeType.CALLS,
7239
+ import_types9.EdgeType.CALLS,
7148
7240
  observedSource(),
7149
7241
  targetId,
7150
7242
  ts,
@@ -7159,7 +7251,7 @@ async function handleSpan(ctx, span) {
7159
7251
  const frontierNodeId = ensureFrontierNode(ctx.graph, host, ts);
7160
7252
  upsertObservedEdge(
7161
7253
  ctx.graph,
7162
- import_types8.EdgeType.CALLS,
7254
+ import_types9.EdgeType.CALLS,
7163
7255
  observedSource(),
7164
7256
  frontierNodeId,
7165
7257
  ts,
@@ -7187,7 +7279,7 @@ async function handleSpan(ctx, span) {
7187
7279
  } : void 0;
7188
7280
  upsertObservedEdge(
7189
7281
  ctx.graph,
7190
- import_types8.EdgeType.CALLS,
7282
+ import_types9.EdgeType.CALLS,
7191
7283
  fallbackSource,
7192
7284
  sourceId,
7193
7285
  ts,
@@ -7209,7 +7301,7 @@ async function handleSpan(ctx, span) {
7209
7301
  );
7210
7302
  if (routeNodeId) {
7211
7303
  const routeSvc = ctx.graph.getNodeAttributes(routeNodeId).service;
7212
- upsertObservedEdge(ctx.graph, import_types8.EdgeType.CONTAINS, (0, import_types8.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
7304
+ upsertObservedEdge(ctx.graph, import_types9.EdgeType.CONTAINS, (0, import_types9.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
7213
7305
  }
7214
7306
  }
7215
7307
  if (span.statusCode === 2) {
@@ -7239,7 +7331,7 @@ function promoteFrontierNodes(graph, opts = {}) {
7239
7331
  const aliasIndex = /* @__PURE__ */ new Map();
7240
7332
  graph.forEachNode((id, attrs) => {
7241
7333
  const a = attrs;
7242
- if (a.type !== import_types8.NodeType.ServiceNode) return;
7334
+ if (a.type !== import_types9.NodeType.ServiceNode) return;
7243
7335
  aliasIndex.set(a.name, id);
7244
7336
  if (a.aliases) {
7245
7337
  for (const alias of a.aliases) aliasIndex.set(alias, id);
@@ -7248,7 +7340,7 @@ function promoteFrontierNodes(graph, opts = {}) {
7248
7340
  const toPromote = [];
7249
7341
  graph.forEachNode((id, attrs) => {
7250
7342
  const a = attrs;
7251
- if (a.type !== import_types8.NodeType.FrontierNode) return;
7343
+ if (a.type !== import_types9.NodeType.FrontierNode) return;
7252
7344
  const target = aliasIndex.get(a.host);
7253
7345
  if (!target) return;
7254
7346
  if (target === id) return;
@@ -7270,15 +7362,15 @@ function promoteFrontierNodes(graph, opts = {}) {
7270
7362
  }
7271
7363
  function stageFrontierEdge(graph, source, target, type) {
7272
7364
  if (!graph.hasNode(source) || !graph.hasNode(target)) return false;
7273
- if (graph.hasEdge((0, import_types8.observedEdgeId)(source, target, type))) return false;
7274
- const key = (0, import_types8.frontierEdgeId)(source, target, type);
7365
+ if (graph.hasEdge((0, import_types9.observedEdgeId)(source, target, type))) return false;
7366
+ const key = (0, import_types9.frontierEdgeId)(source, target, type);
7275
7367
  if (graph.hasEdge(key)) return false;
7276
7368
  graph.addEdgeWithKey(key, source, target, {
7277
7369
  id: key,
7278
7370
  source,
7279
7371
  target,
7280
7372
  type,
7281
- provenance: import_types8.Provenance.FRONTIER
7373
+ provenance: import_types9.Provenance.FRONTIER
7282
7374
  });
7283
7375
  return true;
7284
7376
  }
@@ -7286,8 +7378,8 @@ function promoteFrontierEdges(graph) {
7286
7378
  const graduated = [];
7287
7379
  graph.forEachEdge((edgeId, attrs) => {
7288
7380
  const e = attrs;
7289
- if (e.provenance !== import_types8.Provenance.FRONTIER) return;
7290
- if (graph.hasEdge((0, import_types8.observedEdgeId)(e.source, e.target, e.type))) {
7381
+ if (e.provenance !== import_types9.Provenance.FRONTIER) return;
7382
+ if (graph.hasEdge((0, import_types9.observedEdgeId)(e.source, e.target, e.type))) {
7291
7383
  graduated.push(edgeId);
7292
7384
  }
7293
7385
  });
@@ -7308,7 +7400,7 @@ function rewireFrontierEdges(graph, frontierId2, serviceId17) {
7308
7400
  }
7309
7401
  function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
7310
7402
  graph.dropEdge(oldEdgeId);
7311
- const newId = edge.provenance === import_types8.Provenance.OBSERVED ? (0, import_types8.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types8.Provenance.INFERRED ? (0, import_types8.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types8.extractedEdgeId)(newSource, newTarget, edge.type);
7403
+ 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);
7312
7404
  if (graph.hasEdge(newId)) {
7313
7405
  const existing = graph.getEdgeAttributes(newId);
7314
7406
  const merged = {
@@ -7342,12 +7434,12 @@ async function markStaleEdges(graph, options = {}) {
7342
7434
  const project = options.project ?? DEFAULT_PROJECT;
7343
7435
  graph.forEachEdge((id, attrs) => {
7344
7436
  const e = attrs;
7345
- if (e.provenance !== import_types8.Provenance.OBSERVED) return;
7437
+ if (e.provenance !== import_types9.Provenance.OBSERVED) return;
7346
7438
  if (!e.lastObserved) return;
7347
7439
  const threshold = thresholdForEdgeType(e.type, thresholds);
7348
7440
  const age = now - new Date(e.lastObserved).getTime();
7349
7441
  if (age > threshold) {
7350
- const updated = { ...e, provenance: import_types8.Provenance.STALE, confidence: 0.3 };
7442
+ const updated = { ...e, provenance: import_types9.Provenance.STALE, confidence: 0.3 };
7351
7443
  graph.replaceEdgeAttributes(id, updated);
7352
7444
  events.push({
7353
7445
  edgeId: id,
@@ -7364,8 +7456,8 @@ async function markStaleEdges(graph, options = {}) {
7364
7456
  project,
7365
7457
  payload: {
7366
7458
  edgeId: id,
7367
- from: import_types8.Provenance.OBSERVED,
7368
- to: import_types8.Provenance.STALE
7459
+ from: import_types9.Provenance.OBSERVED,
7460
+ to: import_types9.Provenance.STALE
7369
7461
  }
7370
7462
  });
7371
7463
  }
@@ -7513,6 +7605,7 @@ function describeZodIssues(error) {
7513
7605
  return error.issues.map((issue) => issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message).join("; ");
7514
7606
  }
7515
7607
  function mergeSnapshot(graph, snapshot) {
7608
+ invalidateSourceBaseline(graph);
7516
7609
  const exported = snapshot.graph;
7517
7610
  const incomingNodes = Array.isArray(exported.nodes) ? exported.nodes : [];
7518
7611
  const incomingEdges = Array.isArray(exported.edges) ? exported.edges : [];
@@ -7521,7 +7614,7 @@ function mergeSnapshot(graph, snapshot) {
7521
7614
  const validEdges = [];
7522
7615
  for (const node of incomingNodes) {
7523
7616
  if (node.attributes === void 0) continue;
7524
- const parsed = import_types8.GraphNodeSchema.safeParse(node.attributes);
7617
+ const parsed = import_types9.GraphNodeSchema.safeParse(node.attributes);
7525
7618
  if (!parsed.success) {
7526
7619
  issues.push(`node "${node.key}": ${describeZodIssues(parsed.error)}`);
7527
7620
  continue;
@@ -7530,7 +7623,7 @@ function mergeSnapshot(graph, snapshot) {
7530
7623
  }
7531
7624
  for (const edge of incomingEdges) {
7532
7625
  if (edge.attributes === void 0) continue;
7533
- const parsed = import_types8.GraphEdgeSchema.safeParse(edge.attributes);
7626
+ const parsed = import_types9.GraphEdgeSchema.safeParse(edge.attributes);
7534
7627
  if (!parsed.success) {
7535
7628
  const label = edge.key ?? `${edge.source}->${edge.target}`;
7536
7629
  issues.push(`edge "${label}": ${describeZodIssues(parsed.error)}`);
@@ -7564,7 +7657,7 @@ var import_node_fs20 = require("fs");
7564
7657
  var import_node_path22 = __toESM(require("path"), 1);
7565
7658
  var import_ignore2 = __toESM(require("ignore"), 1);
7566
7659
  var import_minimatch2 = require("minimatch");
7567
- var import_types18 = require("@neat.is/types");
7660
+ var import_types19 = require("@neat.is/types");
7568
7661
 
7569
7662
  // src/extract/python.ts
7570
7663
  init_cjs_shims();
@@ -7637,7 +7730,7 @@ function pythonToPackage(service) {
7637
7730
  init_cjs_shims();
7638
7731
  var import_node_fs11 = require("fs");
7639
7732
  var import_node_path12 = __toESM(require("path"), 1);
7640
- var import_types9 = require("@neat.is/types");
7733
+ var import_types10 = require("@neat.is/types");
7641
7734
  function parseGoMod(source) {
7642
7735
  const module2 = source.match(/^\s*module\s+(\S+)\s*$/m)?.[1];
7643
7736
  if (!module2) return null;
@@ -7673,8 +7766,8 @@ async function discoverGoService(scanPath, dir) {
7673
7766
  const pkg = { name, dependencies: mod.dependencies };
7674
7767
  const framework = goFramework(mod.dependencies);
7675
7768
  const node = {
7676
- id: (0, import_types9.serviceId)(name),
7677
- type: import_types9.NodeType.ServiceNode,
7769
+ id: (0, import_types10.serviceId)(name),
7770
+ type: import_types10.NodeType.ServiceNode,
7678
7771
  name,
7679
7772
  language: "go",
7680
7773
  dependencies: mod.dependencies,
@@ -7688,7 +7781,7 @@ async function discoverGoService(scanPath, dir) {
7688
7781
  init_cjs_shims();
7689
7782
  var import_node_fs12 = require("fs");
7690
7783
  var import_node_path13 = __toESM(require("path"), 1);
7691
- var import_types10 = require("@neat.is/types");
7784
+ var import_types11 = require("@neat.is/types");
7692
7785
  function parseGemfile(source) {
7693
7786
  const dependencies = {};
7694
7787
  for (const raw of source.split(/\r?\n/)) {
@@ -7712,8 +7805,8 @@ async function discoverRubyService(scanPath, dir) {
7712
7805
  const name = import_node_path13.default.basename(dir);
7713
7806
  const pkg = { name, dependencies: gemfile.dependencies };
7714
7807
  const node = {
7715
- id: (0, import_types10.serviceId)(name),
7716
- type: import_types10.NodeType.ServiceNode,
7808
+ id: (0, import_types11.serviceId)(name),
7809
+ type: import_types11.NodeType.ServiceNode,
7717
7810
  name,
7718
7811
  language: "ruby",
7719
7812
  dependencies: gemfile.dependencies,
@@ -7726,7 +7819,7 @@ async function discoverRubyService(scanPath, dir) {
7726
7819
  // src/extract/php.ts
7727
7820
  init_cjs_shims();
7728
7821
  var import_node_path14 = __toESM(require("path"), 1);
7729
- var import_types11 = require("@neat.is/types");
7822
+ var import_types12 = require("@neat.is/types");
7730
7823
  function parseComposerJson(composer) {
7731
7824
  return {
7732
7825
  dependencies: {
@@ -7746,8 +7839,8 @@ async function discoverPhpService(scanPath, dir) {
7746
7839
  const name = import_node_path14.default.basename(dir);
7747
7840
  const pkg = { name, dependencies };
7748
7841
  const node = {
7749
- id: (0, import_types11.serviceId)(name),
7750
- type: import_types11.NodeType.ServiceNode,
7842
+ id: (0, import_types12.serviceId)(name),
7843
+ type: import_types12.NodeType.ServiceNode,
7751
7844
  name,
7752
7845
  language: "php",
7753
7846
  dependencies,
@@ -7761,7 +7854,7 @@ async function discoverPhpService(scanPath, dir) {
7761
7854
  init_cjs_shims();
7762
7855
  var import_node_fs13 = require("fs");
7763
7856
  var import_node_path15 = __toESM(require("path"), 1);
7764
- var import_types12 = require("@neat.is/types");
7857
+ var import_types13 = require("@neat.is/types");
7765
7858
  var CSHARP_PROJECT_EXTS = /* @__PURE__ */ new Set([".csproj", ".sln"]);
7766
7859
  async function projectFiles(dir) {
7767
7860
  const entries = await import_node_fs13.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
@@ -7808,8 +7901,8 @@ async function discoverCsharpService(scanPath, dir) {
7808
7901
  }
7809
7902
  const pkg = { name, dependencies };
7810
7903
  const node = {
7811
- id: (0, import_types12.serviceId)(name),
7812
- type: import_types12.NodeType.ServiceNode,
7904
+ id: (0, import_types13.serviceId)(name),
7905
+ type: import_types13.NodeType.ServiceNode,
7813
7906
  name,
7814
7907
  language: "csharp",
7815
7908
  dependencies,
@@ -7824,7 +7917,7 @@ async function discoverCsharpService(scanPath, dir) {
7824
7917
  init_cjs_shims();
7825
7918
  var import_node_fs14 = require("fs");
7826
7919
  var import_node_path16 = __toESM(require("path"), 1);
7827
- var import_types13 = require("@neat.is/types");
7920
+ var import_types14 = require("@neat.is/types");
7828
7921
  var JAVA_MANIFESTS = ["pom.xml", "build.gradle", "build.gradle.kts"];
7829
7922
  async function hasJavaManifest(dir) {
7830
7923
  for (const manifest of JAVA_MANIFESTS) {
@@ -7879,8 +7972,8 @@ async function discoverJavaService(scanPath, dir) {
7879
7972
  const dependencies = manifest.dependencies;
7880
7973
  const pkg = { name, dependencies };
7881
7974
  const node = {
7882
- id: (0, import_types13.serviceId)(name),
7883
- type: import_types13.NodeType.ServiceNode,
7975
+ id: (0, import_types14.serviceId)(name),
7976
+ type: import_types14.NodeType.ServiceNode,
7884
7977
  name,
7885
7978
  language: "java",
7886
7979
  dependencies,
@@ -7893,7 +7986,7 @@ async function discoverJavaService(scanPath, dir) {
7893
7986
  init_cjs_shims();
7894
7987
  var import_node_fs15 = require("fs");
7895
7988
  var import_node_path17 = __toESM(require("path"), 1);
7896
- var import_types14 = require("@neat.is/types");
7989
+ var import_types15 = require("@neat.is/types");
7897
7990
  var KOTLIN_SOURCE_EXT = ".kt";
7898
7991
  var JAVA_SOURCE_EXT = ".java";
7899
7992
  var SOURCE_PROBE_MAX_DEPTH = 8;
@@ -7944,8 +8037,8 @@ async function discoverKotlinService(scanPath, dir) {
7944
8037
  const dependencies = manifest.dependencies;
7945
8038
  const pkg = { name, dependencies };
7946
8039
  const node = {
7947
- id: (0, import_types14.serviceId)(name),
7948
- type: import_types14.NodeType.ServiceNode,
8040
+ id: (0, import_types15.serviceId)(name),
8041
+ type: import_types15.NodeType.ServiceNode,
7949
8042
  name,
7950
8043
  language: "kotlin",
7951
8044
  dependencies,
@@ -7959,7 +8052,7 @@ init_cjs_shims();
7959
8052
  var import_node_fs16 = require("fs");
7960
8053
  var import_node_path18 = __toESM(require("path"), 1);
7961
8054
  var import_smol_toml2 = require("smol-toml");
7962
- var import_types15 = require("@neat.is/types");
8055
+ var import_types16 = require("@neat.is/types");
7963
8056
  var CARGO_MANIFEST = "Cargo.toml";
7964
8057
  async function hasRustManifest(dir) {
7965
8058
  return exists(import_node_path18.default.join(dir, CARGO_MANIFEST));
@@ -7994,8 +8087,8 @@ async function discoverRustService(scanPath, dir) {
7994
8087
  const dependencies = manifest.dependencies;
7995
8088
  const pkg = { name, dependencies };
7996
8089
  const node = {
7997
- id: (0, import_types15.serviceId)(name),
7998
- type: import_types15.NodeType.ServiceNode,
8090
+ id: (0, import_types16.serviceId)(name),
8091
+ type: import_types16.NodeType.ServiceNode,
7999
8092
  name,
8000
8093
  language: "rust",
8001
8094
  dependencies,
@@ -8008,7 +8101,7 @@ async function discoverRustService(scanPath, dir) {
8008
8101
  init_cjs_shims();
8009
8102
  var import_node_fs17 = require("fs");
8010
8103
  var import_node_path19 = __toESM(require("path"), 1);
8011
- var import_types16 = require("@neat.is/types");
8104
+ var import_types17 = require("@neat.is/types");
8012
8105
  var CMAKE_MANIFEST = "CMakeLists.txt";
8013
8106
  async function hasCppManifest(dir) {
8014
8107
  return exists(import_node_path19.default.join(dir, CMAKE_MANIFEST));
@@ -8026,8 +8119,8 @@ async function discoverCppService(scanPath, dir) {
8026
8119
  const dependencies = {};
8027
8120
  const pkg = { name, dependencies };
8028
8121
  const node = {
8029
- id: (0, import_types16.serviceId)(name),
8030
- type: import_types16.NodeType.ServiceNode,
8122
+ id: (0, import_types17.serviceId)(name),
8123
+ type: import_types17.NodeType.ServiceNode,
8031
8124
  name,
8032
8125
  language: "cpp",
8033
8126
  dependencies,
@@ -8040,7 +8133,7 @@ async function discoverCppService(scanPath, dir) {
8040
8133
  init_cjs_shims();
8041
8134
  var import_node_fs18 = require("fs");
8042
8135
  var import_node_path20 = __toESM(require("path"), 1);
8043
- var import_types17 = require("@neat.is/types");
8136
+ var import_types18 = require("@neat.is/types");
8044
8137
  function languageForSourceExt(ext) {
8045
8138
  switch (ext) {
8046
8139
  case ".py":
@@ -8126,8 +8219,8 @@ async function discoverDockerfileService(scanPath, dir) {
8126
8219
  const name = import_node_path20.default.basename(dir);
8127
8220
  const pkg = { name, dependencies: {} };
8128
8221
  const node = {
8129
- id: (0, import_types17.serviceId)(name),
8130
- type: import_types17.NodeType.ServiceNode,
8222
+ id: (0, import_types18.serviceId)(name),
8223
+ type: import_types18.NodeType.ServiceNode,
8131
8224
  name,
8132
8225
  language,
8133
8226
  dependencies: {},
@@ -8321,8 +8414,8 @@ async function discoverNodeService(scanPath, dir) {
8321
8414
  const framework = detectJsFramework(pkg);
8322
8415
  const language = await detectJsServiceLanguage(dir, pkg);
8323
8416
  const node = {
8324
- id: (0, import_types18.serviceId)(pkg.name),
8325
- type: import_types18.NodeType.ServiceNode,
8417
+ id: (0, import_types19.serviceId)(pkg.name),
8418
+ type: import_types19.NodeType.ServiceNode,
8326
8419
  name: pkg.name,
8327
8420
  language,
8328
8421
  version: pkg.version,
@@ -8338,8 +8431,8 @@ async function discoverPyService(scanPath, dir) {
8338
8431
  if (!py) return null;
8339
8432
  const pkg = pythonToPackage(py);
8340
8433
  const node = {
8341
- id: (0, import_types18.serviceId)(py.name),
8342
- type: import_types18.NodeType.ServiceNode,
8434
+ id: (0, import_types19.serviceId)(py.name),
8435
+ type: import_types19.NodeType.ServiceNode,
8343
8436
  name: py.name,
8344
8437
  language: "python",
8345
8438
  version: py.version,
@@ -8458,7 +8551,7 @@ init_cjs_shims();
8458
8551
  var import_node_path23 = __toESM(require("path"), 1);
8459
8552
  var import_node_fs21 = require("fs");
8460
8553
  var import_yaml2 = require("yaml");
8461
- var import_types19 = require("@neat.is/types");
8554
+ var import_types20 = require("@neat.is/types");
8462
8555
  var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
8463
8556
  "Service",
8464
8557
  "Deployment",
@@ -8468,7 +8561,7 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
8468
8561
  function addAliases(graph, serviceId17, candidates) {
8469
8562
  if (!graph.hasNode(serviceId17)) return;
8470
8563
  const node = graph.getNodeAttributes(serviceId17);
8471
- if (node.type !== import_types19.NodeType.ServiceNode) return;
8564
+ if (node.type !== import_types20.NodeType.ServiceNode) return;
8472
8565
  const set = new Set(node.aliases ?? []);
8473
8566
  for (const c of candidates) {
8474
8567
  if (!c) continue;
@@ -8658,7 +8751,7 @@ var import_tree_sitter_java = __toESM(require("tree-sitter-java"), 1);
8658
8751
  var import_tree_sitter_kotlin = __toESM(require("tree-sitter-kotlin"), 1);
8659
8752
  var import_tree_sitter_rust2 = __toESM(require("tree-sitter-rust"), 1);
8660
8753
  var import_tree_sitter_cpp = __toESM(require("tree-sitter-cpp"), 1);
8661
- var import_types20 = require("@neat.is/types");
8754
+ var import_types21 = require("@neat.is/types");
8662
8755
  var PARSE_CHUNK3 = 16384;
8663
8756
  var GRAMMAR_BY_EXT = {
8664
8757
  ".ts": import_tree_sitter_typescript.default.typescript,
@@ -8711,7 +8804,9 @@ function collectSymbolDefs(root) {
8711
8804
  kind,
8712
8805
  qualname,
8713
8806
  startLine: node.startPosition.row + 1,
8714
- endLine: node.endPosition.row + 1
8807
+ endLine: node.endPosition.row + 1,
8808
+ startIndex: node.startIndex,
8809
+ endIndex: node.endIndex
8715
8810
  });
8716
8811
  };
8717
8812
  const visit = (node, classCtx) => {
@@ -8770,7 +8865,9 @@ function collectPythonSymbolDefs(root) {
8770
8865
  kind,
8771
8866
  qualname,
8772
8867
  startLine: node.startPosition.row + 1,
8773
- endLine: node.endPosition.row + 1
8868
+ endLine: node.endPosition.row + 1,
8869
+ startIndex: node.startIndex,
8870
+ endIndex: node.endIndex
8774
8871
  });
8775
8872
  };
8776
8873
  const visit = (node, classCtx) => {
@@ -8843,7 +8940,9 @@ function collectGoSymbolDefs(root) {
8843
8940
  kind,
8844
8941
  qualname,
8845
8942
  startLine: node.startPosition.row + 1,
8846
- endLine: node.endPosition.row + 1
8943
+ endLine: node.endPosition.row + 1,
8944
+ startIndex: node.startIndex,
8945
+ endIndex: node.endIndex
8847
8946
  });
8848
8947
  };
8849
8948
  const visit = (node) => {
@@ -8877,7 +8976,9 @@ function collectRubySymbolDefs(root) {
8877
8976
  kind,
8878
8977
  qualname,
8879
8978
  startLine: node.startPosition.row + 1,
8880
- endLine: node.endPosition.row + 1
8979
+ endLine: node.endPosition.row + 1,
8980
+ startIndex: node.startIndex,
8981
+ endIndex: node.endIndex
8881
8982
  });
8882
8983
  };
8883
8984
  const nameText = (node) => node.childForFieldName("name")?.text.replace(/::/g, ".");
@@ -8928,7 +9029,9 @@ function collectPhpSymbolDefs(root) {
8928
9029
  kind,
8929
9030
  qualname,
8930
9031
  startLine: node.startPosition.row + 1,
8931
- endLine: node.endPosition.row + 1
9032
+ endLine: node.endPosition.row + 1,
9033
+ startIndex: node.startIndex,
9034
+ endIndex: node.endIndex
8932
9035
  });
8933
9036
  };
8934
9037
  const dot = (s) => s.replace(/\\/g, ".").replace(/::/g, ".").replace(/^\.+/, "");
@@ -8994,7 +9097,9 @@ function collectCsharpSymbolDefs(root) {
8994
9097
  kind,
8995
9098
  qualname,
8996
9099
  startLine: node.startPosition.row + 1,
8997
- endLine: node.endPosition.row + 1
9100
+ endLine: node.endPosition.row + 1,
9101
+ startIndex: node.startIndex,
9102
+ endIndex: node.endIndex
8998
9103
  });
8999
9104
  };
9000
9105
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9056,7 +9161,9 @@ function collectJavaSymbolDefs(root) {
9056
9161
  kind,
9057
9162
  qualname,
9058
9163
  startLine: node.startPosition.row + 1,
9059
- endLine: node.endPosition.row + 1
9164
+ endLine: node.endPosition.row + 1,
9165
+ startIndex: node.startIndex,
9166
+ endIndex: node.endIndex
9060
9167
  });
9061
9168
  };
9062
9169
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9113,7 +9220,9 @@ function collectKotlinSymbolDefs(root) {
9113
9220
  kind,
9114
9221
  qualname,
9115
9222
  startLine: node.startPosition.row + 1,
9116
- endLine: node.endPosition.row + 1
9223
+ endLine: node.endPosition.row + 1,
9224
+ startIndex: node.startIndex,
9225
+ endIndex: node.endIndex
9117
9226
  });
9118
9227
  };
9119
9228
  const join2 = (prefix, name) => prefix ? `${prefix}.${name}` : name;
@@ -9183,7 +9292,9 @@ function collectRustSymbolDefs(root) {
9183
9292
  kind,
9184
9293
  qualname,
9185
9294
  startLine: node.startPosition.row + 1,
9186
- endLine: node.endPosition.row + 1
9295
+ endLine: node.endPosition.row + 1,
9296
+ startIndex: node.startIndex,
9297
+ endIndex: node.endIndex
9187
9298
  });
9188
9299
  };
9189
9300
  const join2 = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -9251,7 +9362,9 @@ function collectCppSymbolDefs(root) {
9251
9362
  kind,
9252
9363
  qualname,
9253
9364
  startLine: node.startPosition.row + 1,
9254
- endLine: node.endPosition.row + 1
9365
+ endLine: node.endPosition.row + 1,
9366
+ startIndex: node.startIndex,
9367
+ endIndex: node.endIndex
9255
9368
  });
9256
9369
  };
9257
9370
  const join2 = (prefix, name) => prefix ? `${prefix}::${name}` : name;
@@ -9379,6 +9492,22 @@ function disambiguate(defs) {
9379
9492
  return { def, disambiguator: ordinal };
9380
9493
  });
9381
9494
  }
9495
+ function utf8Offsets(content, defs) {
9496
+ if (content.includes("\uFFFD")) return /* @__PURE__ */ new Map();
9497
+ const indices = [...new Set(defs.flatMap(({ startIndex, endIndex }) => [startIndex, endIndex]))].sort(
9498
+ (a, b) => a - b
9499
+ );
9500
+ const offsets = /* @__PURE__ */ new Map();
9501
+ let cursor = 0;
9502
+ let bytes = 0;
9503
+ for (const index of indices) {
9504
+ if (index < cursor || index > content.length) return /* @__PURE__ */ new Map();
9505
+ bytes += Buffer.byteLength(content.slice(cursor, index), "utf8");
9506
+ offsets.set(index, bytes);
9507
+ cursor = index;
9508
+ }
9509
+ return offsets;
9510
+ }
9382
9511
  async function addSymbols(graph, services) {
9383
9512
  const parsers = /* @__PURE__ */ new Map();
9384
9513
  const parserForExt5 = (ext) => {
@@ -9402,47 +9531,59 @@ async function addSymbols(graph, services) {
9402
9531
  if (!parser) continue;
9403
9532
  const relPath = toPosix(import_node_path25.default.relative(service.dir, file.path));
9404
9533
  let defs;
9534
+ let completeParse;
9405
9535
  try {
9406
9536
  const tree = parseSource3(parser, file.content);
9407
9537
  defs = collectSymbolDefsForExt(ext, tree.rootNode);
9538
+ completeParse = !tree.rootNode.hasError;
9408
9539
  } catch (err) {
9409
9540
  recordExtractionError("symbol extraction", file.path, err);
9410
9541
  continue;
9411
9542
  }
9412
9543
  if (defs.length === 0) continue;
9413
- const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
9414
- graph,
9415
- service.pkg.name,
9416
- service.node.id,
9417
- relPath
9418
- );
9544
+ const offsets = completeParse ? utf8Offsets(file.content, defs) : /* @__PURE__ */ new Map();
9545
+ const {
9546
+ fileNodeId,
9547
+ nodesAdded: fn,
9548
+ edgesAdded: fe
9549
+ } = ensureFileNode(graph, service.pkg.name, service.node.id, relPath);
9419
9550
  nodesAdded += fn;
9420
9551
  edgesAdded += fe;
9421
9552
  for (const { def, disambiguator } of disambiguate(defs)) {
9422
- const sid = (0, import_types20.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
9553
+ const sid = (0, import_types21.symbolId)(service.pkg.name, relPath, def.qualname, disambiguator);
9554
+ const startByte = offsets.get(def.startIndex);
9555
+ const endByte = offsets.get(def.endIndex);
9556
+ const precise = startByte !== void 0 && endByte !== void 0 && endByte > startByte ? { startByte, endByte } : {};
9557
+ const node = {
9558
+ id: sid,
9559
+ type: import_types21.NodeType.SymbolNode,
9560
+ kind: def.kind,
9561
+ qualname: def.qualname,
9562
+ span: { startLine: def.startLine, endLine: def.endLine, ...precise },
9563
+ service: service.pkg.name,
9564
+ relPath,
9565
+ discoveredVia: "static"
9566
+ };
9423
9567
  if (!graph.hasNode(sid)) {
9424
- const node = {
9425
- id: sid,
9426
- type: import_types20.NodeType.SymbolNode,
9427
- kind: def.kind,
9428
- qualname: def.qualname,
9429
- span: { startLine: def.startLine, endLine: def.endLine },
9430
- service: service.pkg.name,
9431
- relPath,
9432
- discoveredVia: "static"
9433
- };
9434
9568
  graph.addNode(sid, node);
9435
9569
  nodesAdded++;
9570
+ } else {
9571
+ const previous = graph.getNodeAttributes(sid);
9572
+ const discoveredVia = previous.discoveredVia === "otel" || previous.discoveredVia === "merged" ? "merged" : "static";
9573
+ 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;
9574
+ if (moved || previous.kind !== node.kind || previous.qualname !== node.qualname || previous.discoveredVia !== discoveredVia || previous.service !== node.service || previous.relPath !== node.relPath) {
9575
+ graph.replaceNodeAttributes(sid, { ...previous, ...node, discoveredVia });
9576
+ }
9436
9577
  }
9437
- const containsId = (0, import_types20.extractedEdgeId)(fileNodeId, sid, import_types20.EdgeType.CONTAINS);
9578
+ const containsId = (0, import_types21.extractedEdgeId)(fileNodeId, sid, import_types21.EdgeType.CONTAINS);
9438
9579
  if (!graph.hasEdge(containsId)) {
9439
9580
  const edge = {
9440
9581
  id: containsId,
9441
9582
  source: fileNodeId,
9442
9583
  target: sid,
9443
- type: import_types20.EdgeType.CONTAINS,
9444
- provenance: import_types20.Provenance.EXTRACTED,
9445
- confidence: (0, import_types20.confidenceForExtracted)("structural"),
9584
+ type: import_types21.EdgeType.CONTAINS,
9585
+ provenance: import_types21.Provenance.EXTRACTED,
9586
+ confidence: (0, import_types21.confidenceForExtracted)("structural"),
9446
9587
  evidence: {
9447
9588
  file: relPath,
9448
9589
  line: def.startLine,
@@ -9462,7 +9603,7 @@ async function addSymbols(graph, services) {
9462
9603
  init_cjs_shims();
9463
9604
  var import_node_path26 = __toESM(require("path"), 1);
9464
9605
  var import_tree_sitter4 = __toESM(require("tree-sitter"), 1);
9465
- var import_types21 = require("@neat.is/types");
9606
+ var import_types22 = require("@neat.is/types");
9466
9607
  function extendsInfo(classHeritage) {
9467
9608
  for (let i = 0; i < classHeritage.namedChildCount; i++) {
9468
9609
  const child = classHeritage.namedChild(i);
@@ -9580,7 +9721,7 @@ async function addSymbolEdges(graph, services) {
9580
9721
  }
9581
9722
  const disambiguated = disambiguate(collectSymbolDefs(root));
9582
9723
  const locals = disambiguated.map(({ def, disambiguator }) => ({
9583
- sid: (0, import_types21.symbolId)(serviceName, relPath, def.qualname, disambiguator),
9724
+ sid: (0, import_types22.symbolId)(serviceName, relPath, def.qualname, disambiguator),
9584
9725
  qualname: def.qualname,
9585
9726
  kind: def.kind,
9586
9727
  startLine: def.startLine,
@@ -9609,10 +9750,10 @@ async function addSymbolEdges(graph, services) {
9609
9750
  if (local) return local.kind === wantKind ? local.sid : null;
9610
9751
  const imp = resolvedImports.get(name);
9611
9752
  if (imp) {
9612
- const candidate = (0, import_types21.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
9753
+ const candidate = (0, import_types22.symbolId)(serviceName, imp.targetRelPath, imp.importedName);
9613
9754
  if (graph.hasNode(candidate)) {
9614
9755
  const node = graph.getNodeAttributes(candidate);
9615
- if (node.type === import_types21.NodeType.SymbolNode && node.kind === wantKind) return candidate;
9756
+ if (node.type === import_types22.NodeType.SymbolNode && node.kind === wantKind) return candidate;
9616
9757
  }
9617
9758
  }
9618
9759
  return null;
@@ -9639,7 +9780,7 @@ async function addSymbolEdges(graph, services) {
9639
9780
  sourceSid: self.sid,
9640
9781
  targetName: ext.name,
9641
9782
  wantKind: "class",
9642
- edgeType: import_types21.EdgeType.INHERITS,
9783
+ edgeType: import_types22.EdgeType.INHERITS,
9643
9784
  line: ext.line
9644
9785
  });
9645
9786
  }
@@ -9648,7 +9789,7 @@ async function addSymbolEdges(graph, services) {
9648
9789
  sourceSid: self.sid,
9649
9790
  targetName: impl.name,
9650
9791
  wantKind: "class",
9651
- edgeType: import_types21.EdgeType.IMPLEMENTS,
9792
+ edgeType: import_types22.EdgeType.IMPLEMENTS,
9652
9793
  line: impl.line
9653
9794
  });
9654
9795
  }
@@ -9664,7 +9805,7 @@ async function addSymbolEdges(graph, services) {
9664
9805
  sourceSid: caller.sid,
9665
9806
  targetName: fn.text,
9666
9807
  wantKind: "function",
9667
- edgeType: import_types21.EdgeType.CALLS,
9808
+ edgeType: import_types22.EdgeType.CALLS,
9668
9809
  line
9669
9810
  });
9670
9811
  }
@@ -9680,15 +9821,15 @@ async function addSymbolEdges(graph, services) {
9680
9821
  const targetSid = resolveTarget(req.targetName, req.wantKind);
9681
9822
  if (!targetSid) continue;
9682
9823
  if (targetSid === req.sourceSid) continue;
9683
- const edgeId = (0, import_types21.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
9824
+ const edgeId = (0, import_types22.extractedEdgeId)(req.sourceSid, targetSid, req.edgeType);
9684
9825
  if (graph.hasEdge(edgeId)) continue;
9685
9826
  const edge = {
9686
9827
  id: edgeId,
9687
9828
  source: req.sourceSid,
9688
9829
  target: targetSid,
9689
9830
  type: req.edgeType,
9690
- provenance: import_types21.Provenance.EXTRACTED,
9691
- confidence: (0, import_types21.confidenceForExtracted)("structural"),
9831
+ provenance: import_types22.Provenance.EXTRACTED,
9832
+ confidence: (0, import_types22.confidenceForExtracted)("structural"),
9692
9833
  evidence: {
9693
9834
  file: relPath,
9694
9835
  line: req.line,
@@ -9707,7 +9848,7 @@ async function addSymbolEdges(graph, services) {
9707
9848
  init_cjs_shims();
9708
9849
  var import_node_path27 = __toESM(require("path"), 1);
9709
9850
  var import_tree_sitter5 = __toESM(require("tree-sitter"), 1);
9710
- var import_types22 = require("@neat.is/types");
9851
+ var import_types23 = require("@neat.is/types");
9711
9852
  function stringLiteralText2(node) {
9712
9853
  for (let i = 0; i < node.childCount; i++) {
9713
9854
  const child = node.child(i);
@@ -9877,11 +10018,11 @@ async function addServerActions(graph, services) {
9877
10018
  nodesAdded += fn;
9878
10019
  edgesAdded += fe;
9879
10020
  for (const action of actions) {
9880
- const aid = (0, import_types22.serverActionId)(service.pkg.name, relPath, action.exportName);
10021
+ const aid = (0, import_types23.serverActionId)(service.pkg.name, relPath, action.exportName);
9881
10022
  if (!graph.hasNode(aid)) {
9882
10023
  const node = {
9883
10024
  id: aid,
9884
- type: import_types22.NodeType.ServerActionNode,
10025
+ type: import_types23.NodeType.ServerActionNode,
9885
10026
  name: action.exportName,
9886
10027
  service: service.pkg.name,
9887
10028
  module: relPath,
@@ -9893,15 +10034,15 @@ async function addServerActions(graph, services) {
9893
10034
  graph.addNode(aid, node);
9894
10035
  nodesAdded++;
9895
10036
  }
9896
- const containsId = (0, import_types22.extractedEdgeId)(fileNodeId, aid, import_types22.EdgeType.CONTAINS);
10037
+ const containsId = (0, import_types23.extractedEdgeId)(fileNodeId, aid, import_types23.EdgeType.CONTAINS);
9897
10038
  if (!graph.hasEdge(containsId)) {
9898
10039
  const edge = {
9899
10040
  id: containsId,
9900
10041
  source: fileNodeId,
9901
10042
  target: aid,
9902
- type: import_types22.EdgeType.CONTAINS,
9903
- provenance: import_types22.Provenance.EXTRACTED,
9904
- confidence: (0, import_types22.confidenceForExtracted)("structural"),
10043
+ type: import_types23.EdgeType.CONTAINS,
10044
+ provenance: import_types23.Provenance.EXTRACTED,
10045
+ confidence: (0, import_types23.confidenceForExtracted)("structural"),
9905
10046
  evidence: {
9906
10047
  file: relPath,
9907
10048
  line: action.line,
@@ -9931,7 +10072,7 @@ async function addServerActions(graph, services) {
9931
10072
  for (const [local, binding] of bindings) {
9932
10073
  const target = await resolveJsImport(binding.specifier, fileDir, service.dir, tsPaths);
9933
10074
  if (!target) continue;
9934
- const aid = (0, import_types22.serverActionId)(service.pkg.name, target, binding.importedName);
10075
+ const aid = (0, import_types23.serverActionId)(service.pkg.name, target, binding.importedName);
9935
10076
  if (graph.hasNode(aid)) actionBindings.set(local, aid);
9936
10077
  }
9937
10078
  if (actionBindings.size === 0) continue;
@@ -9946,15 +10087,15 @@ async function addServerActions(graph, services) {
9946
10087
  nodesAdded += ensured.nodesAdded;
9947
10088
  edgesAdded += ensured.edgesAdded;
9948
10089
  }
9949
- const callsId = (0, import_types22.extractedEdgeId)(clientFileId, aid, import_types22.EdgeType.CALLS);
10090
+ const callsId = (0, import_types23.extractedEdgeId)(clientFileId, aid, import_types23.EdgeType.CALLS);
9950
10091
  if (graph.hasEdge(callsId)) continue;
9951
10092
  const edge = {
9952
10093
  id: callsId,
9953
10094
  source: clientFileId,
9954
10095
  target: aid,
9955
- type: import_types22.EdgeType.CALLS,
9956
- provenance: import_types22.Provenance.EXTRACTED,
9957
- confidence: (0, import_types22.confidenceForExtracted)("structural"),
10096
+ type: import_types23.EdgeType.CALLS,
10097
+ provenance: import_types23.Provenance.EXTRACTED,
10098
+ confidence: (0, import_types23.confidenceForExtracted)("structural"),
9958
10099
  evidence: {
9959
10100
  file: relPath,
9960
10101
  line,
@@ -9972,7 +10113,7 @@ async function addServerActions(graph, services) {
9972
10113
  // src/extract/databases/index.ts
9973
10114
  init_cjs_shims();
9974
10115
  var import_node_path36 = __toESM(require("path"), 1);
9975
- var import_types23 = require("@neat.is/types");
10116
+ var import_types24 = require("@neat.is/types");
9976
10117
 
9977
10118
  // src/extract/databases/db-config-yaml.ts
9978
10119
  init_cjs_shims();
@@ -10631,8 +10772,8 @@ function compatibleDriversFor(engine) {
10631
10772
  }
10632
10773
  function toDatabaseNode(config) {
10633
10774
  return {
10634
- id: (0, import_types23.databaseId)(config.host),
10635
- type: import_types23.NodeType.DatabaseNode,
10775
+ id: (0, import_types24.databaseId)(config.host),
10776
+ type: import_types24.NodeType.DatabaseNode,
10636
10777
  name: config.database || config.host,
10637
10778
  engine: config.engine,
10638
10779
  engineVersion: config.engineVersion,
@@ -10773,12 +10914,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10773
10914
  edgesAdded += fe;
10774
10915
  const evidenceFile = toPosix(import_node_path36.default.relative(scanPath, config.sourceFile));
10775
10916
  const edge = {
10776
- id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types23.EdgeType.CONNECTS_TO),
10917
+ id: (0, import_types3.extractedEdgeId)(fileNodeId, dbNode.id, import_types24.EdgeType.CONNECTS_TO),
10777
10918
  source: fileNodeId,
10778
10919
  target: dbNode.id,
10779
- type: import_types23.EdgeType.CONNECTS_TO,
10780
- provenance: import_types23.Provenance.EXTRACTED,
10781
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
10920
+ type: import_types24.EdgeType.CONNECTS_TO,
10921
+ provenance: import_types24.Provenance.EXTRACTED,
10922
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10782
10923
  // Carry how the host was recovered (ADR-213) so the divergence ranker
10783
10924
  // can tell a real declared store from a hardcoded fault-injection /
10784
10925
  // flag-gated probe. Only set when the parser distinguished the two.
@@ -10793,11 +10934,11 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10793
10934
  const primary = allConfigs[0];
10794
10935
  service.node.dbConnectionTarget = primary.port ? `${primary.host}:${primary.port}` : primary.host;
10795
10936
  const relPath = import_node_path36.default.relative(scanPath, primary.sourceFile);
10796
- const cfgId = (0, import_types23.configId)(relPath);
10937
+ const cfgId = (0, import_types24.configId)(relPath);
10797
10938
  if (!graph.hasNode(cfgId)) {
10798
10939
  const cfgNode = {
10799
10940
  id: cfgId,
10800
- type: import_types23.NodeType.ConfigNode,
10941
+ type: import_types24.NodeType.ConfigNode,
10801
10942
  name: import_node_path36.default.basename(primary.sourceFile),
10802
10943
  path: relPath,
10803
10944
  fileType: isConfigFile(import_node_path36.default.basename(primary.sourceFile)).fileType || "config"
@@ -10806,12 +10947,12 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10806
10947
  nodesAdded++;
10807
10948
  }
10808
10949
  const cfgEdge = {
10809
- id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types23.EdgeType.CONFIGURED_BY),
10950
+ id: (0, import_types3.extractedEdgeId)(service.node.id, cfgId, import_types24.EdgeType.CONFIGURED_BY),
10810
10951
  source: service.node.id,
10811
10952
  target: cfgId,
10812
- type: import_types23.EdgeType.CONFIGURED_BY,
10813
- provenance: import_types23.Provenance.EXTRACTED,
10814
- confidence: (0, import_types23.confidenceForExtracted)("structural"),
10953
+ type: import_types24.EdgeType.CONFIGURED_BY,
10954
+ provenance: import_types24.Provenance.EXTRACTED,
10955
+ confidence: (0, import_types24.confidenceForExtracted)("structural"),
10815
10956
  evidence: { file: toPosix(relPath) }
10816
10957
  };
10817
10958
  if (!graph.hasEdge(cfgEdge.id)) {
@@ -10843,7 +10984,7 @@ async function addDatabasesAndCompat(graph, services, scanPath) {
10843
10984
  init_cjs_shims();
10844
10985
  var import_node_fs25 = require("fs");
10845
10986
  var import_node_path37 = __toESM(require("path"), 1);
10846
- var import_types24 = require("@neat.is/types");
10987
+ var import_types25 = require("@neat.is/types");
10847
10988
  async function walkConfigFiles(dir, excludeDirs = []) {
10848
10989
  const excluded = new Set(excludeDirs.map((d) => import_node_path37.default.resolve(d)));
10849
10990
  const out = [];
@@ -10872,8 +11013,8 @@ async function addConfigNodes(graph, services, scanPath) {
10872
11013
  for (const file of configFiles) {
10873
11014
  const relPath = import_node_path37.default.relative(scanPath, file);
10874
11015
  const node = {
10875
- id: (0, import_types24.configId)(relPath),
10876
- type: import_types24.NodeType.ConfigNode,
11016
+ id: (0, import_types25.configId)(relPath),
11017
+ type: import_types25.NodeType.ConfigNode,
10877
11018
  name: import_node_path37.default.basename(file),
10878
11019
  path: relPath,
10879
11020
  fileType: isConfigFile(import_node_path37.default.basename(file)).fileType
@@ -10892,12 +11033,12 @@ async function addConfigNodes(graph, services, scanPath) {
10892
11033
  nodesAdded += fn;
10893
11034
  edgesAdded += fe;
10894
11035
  const edge = {
10895
- id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types24.EdgeType.CONFIGURED_BY),
11036
+ id: (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types25.EdgeType.CONFIGURED_BY),
10896
11037
  source: fileNodeId,
10897
11038
  target: node.id,
10898
- type: import_types24.EdgeType.CONFIGURED_BY,
10899
- provenance: import_types24.Provenance.EXTRACTED,
10900
- confidence: (0, import_types24.confidenceForExtracted)("structural"),
11039
+ type: import_types25.EdgeType.CONFIGURED_BY,
11040
+ provenance: import_types25.Provenance.EXTRACTED,
11041
+ confidence: (0, import_types25.confidenceForExtracted)("structural"),
10901
11042
  evidence: { file: relPath.split(import_node_path37.default.sep).join("/") }
10902
11043
  };
10903
11044
  if (!graph.hasEdge(edge.id)) {
@@ -10913,7 +11054,7 @@ async function addConfigNodes(graph, services, scanPath) {
10913
11054
  init_cjs_shims();
10914
11055
  var import_node_fs26 = require("fs");
10915
11056
  var import_node_path38 = __toESM(require("path"), 1);
10916
- var import_types25 = require("@neat.is/types");
11057
+ var import_types26 = require("@neat.is/types");
10917
11058
  var PROTO_EXTENSION = ".proto";
10918
11059
  function packageOf(content) {
10919
11060
  const m = content.match(/^\s*package\s+([A-Za-z_][A-Za-z0-9_.]*)\s*;/m);
@@ -10993,11 +11134,11 @@ async function addGrpcMethods(graph, services) {
10993
11134
  }
10994
11135
  if (methods.length === 0) continue;
10995
11136
  for (const method of methods) {
10996
- const mid = (0, import_types25.grpcMethodId)(method.rpcService, method.rpcMethod);
11137
+ const mid = (0, import_types26.grpcMethodId)(method.rpcService, method.rpcMethod);
10997
11138
  if (!graph.hasNode(mid)) {
10998
11139
  const node = {
10999
11140
  id: mid,
11000
- type: import_types25.NodeType.GrpcMethodNode,
11141
+ type: import_types26.NodeType.GrpcMethodNode,
11001
11142
  name: `${method.rpcService}/${method.rpcMethod}`,
11002
11143
  rpcService: method.rpcService,
11003
11144
  rpcMethod: method.rpcMethod,
@@ -11008,15 +11149,15 @@ async function addGrpcMethods(graph, services) {
11008
11149
  graph.addNode(mid, node);
11009
11150
  nodesAdded++;
11010
11151
  }
11011
- const containsId = (0, import_types25.extractedEdgeId)(service.node.id, mid, import_types25.EdgeType.CONTAINS);
11152
+ const containsId = (0, import_types26.extractedEdgeId)(service.node.id, mid, import_types26.EdgeType.CONTAINS);
11012
11153
  if (!graph.hasEdge(containsId)) {
11013
11154
  const edge = {
11014
11155
  id: containsId,
11015
11156
  source: service.node.id,
11016
11157
  target: mid,
11017
- type: import_types25.EdgeType.CONTAINS,
11018
- provenance: import_types25.Provenance.EXTRACTED,
11019
- confidence: (0, import_types25.confidenceForExtracted)("structural"),
11158
+ type: import_types26.EdgeType.CONTAINS,
11159
+ provenance: import_types26.Provenance.EXTRACTED,
11160
+ confidence: (0, import_types26.confidenceForExtracted)("structural"),
11020
11161
  evidence: {
11021
11162
  file: relFile,
11022
11163
  line: method.line,
@@ -11034,7 +11175,7 @@ async function addGrpcMethods(graph, services) {
11034
11175
 
11035
11176
  // src/extract/calls/index.ts
11036
11177
  init_cjs_shims();
11037
- var import_types45 = require("@neat.is/types");
11178
+ var import_types46 = require("@neat.is/types");
11038
11179
 
11039
11180
  // src/extract/calls/http.ts
11040
11181
  init_cjs_shims();
@@ -11043,7 +11184,7 @@ var import_tree_sitter6 = __toESM(require("tree-sitter"), 1);
11043
11184
  var import_tree_sitter_javascript4 = __toESM(require("tree-sitter-javascript"), 1);
11044
11185
  var import_tree_sitter_typescript2 = __toESM(require("tree-sitter-typescript"), 1);
11045
11186
  var import_tree_sitter_python4 = __toESM(require("tree-sitter-python"), 1);
11046
- var import_types26 = require("@neat.is/types");
11187
+ var import_types27 = require("@neat.is/types");
11047
11188
  var STRING_LITERAL_NODE_TYPES = /* @__PURE__ */ new Set(["string_fragment", "string_content"]);
11048
11189
  var JSX_EXTERNAL_LINK_TAGS = /* @__PURE__ */ new Set(["a", "Link", "NavLink", "ExternalLink", "Anchor"]);
11049
11190
  function isInsideJsxExternalLink(node) {
@@ -11137,7 +11278,7 @@ async function addHttpCallEdges(graph, services) {
11137
11278
  const dedupKey = `${relFile}|${targetId}`;
11138
11279
  if (seen.has(dedupKey)) continue;
11139
11280
  seen.add(dedupKey);
11140
- const confidence = (0, import_types26.confidenceForExtracted)("url-literal-service-target");
11281
+ const confidence = (0, import_types27.confidenceForExtracted)("url-literal-service-target");
11141
11282
  const ev = {
11142
11283
  file: relFile,
11143
11284
  line: site.line,
@@ -11151,25 +11292,25 @@ async function addHttpCallEdges(graph, services) {
11151
11292
  );
11152
11293
  nodesAdded += n;
11153
11294
  edgesAdded += e;
11154
- if (!(0, import_types26.passesExtractedFloor)(confidence)) {
11295
+ if (!(0, import_types27.passesExtractedFloor)(confidence)) {
11155
11296
  noteExtractedDropped({
11156
11297
  source: fileNodeId,
11157
11298
  target: targetId,
11158
- type: import_types26.EdgeType.CALLS,
11299
+ type: import_types27.EdgeType.CALLS,
11159
11300
  confidence,
11160
11301
  confidenceKind: "url-literal-service-target",
11161
11302
  evidence: ev
11162
11303
  });
11163
11304
  continue;
11164
11305
  }
11165
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types26.EdgeType.CALLS);
11306
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, targetId, import_types27.EdgeType.CALLS);
11166
11307
  if (!graph.hasEdge(edgeId)) {
11167
11308
  const edge = {
11168
11309
  id: edgeId,
11169
11310
  source: fileNodeId,
11170
11311
  target: targetId,
11171
- type: import_types26.EdgeType.CALLS,
11172
- provenance: import_types26.Provenance.EXTRACTED,
11312
+ type: import_types27.EdgeType.CALLS,
11313
+ provenance: import_types27.Provenance.EXTRACTED,
11173
11314
  confidence,
11174
11315
  evidence: ev
11175
11316
  };
@@ -11187,7 +11328,7 @@ init_cjs_shims();
11187
11328
  var import_node_path40 = __toESM(require("path"), 1);
11188
11329
  var import_tree_sitter7 = __toESM(require("tree-sitter"), 1);
11189
11330
  var import_tree_sitter_javascript5 = __toESM(require("tree-sitter-javascript"), 1);
11190
- var import_types27 = require("@neat.is/types");
11331
+ var import_types28 = require("@neat.is/types");
11191
11332
  var PARSE_CHUNK5 = 16384;
11192
11333
  function parseSource5(parser, source) {
11193
11334
  return parser.parse(
@@ -11431,9 +11572,9 @@ function buildRouteIndex(graph) {
11431
11572
  const index = /* @__PURE__ */ new Map();
11432
11573
  graph.forEachNode((_id, attrs) => {
11433
11574
  const node = attrs;
11434
- if (node.type !== import_types27.NodeType.RouteNode) return;
11575
+ if (node.type !== import_types28.NodeType.RouteNode) return;
11435
11576
  const route = attrs;
11436
- const owner = (0, import_types27.serviceId)(route.service);
11577
+ const owner = (0, import_types28.serviceId)(route.service);
11437
11578
  const entry = {
11438
11579
  method: route.method.toUpperCase(),
11439
11580
  normalizedPath: normalizePathTemplate(route.pathTemplate),
@@ -11488,8 +11629,8 @@ async function addRouteCallEdges(graph, services) {
11488
11629
  noteExtractedDropped({
11489
11630
  source: fileNodeId2,
11490
11631
  target: "route:unresolved",
11491
- type: import_types27.EdgeType.CALLS,
11492
- confidence: (0, import_types27.confidenceForExtracted)("reconstructed-approximate"),
11632
+ type: import_types28.EdgeType.CALLS,
11633
+ confidence: (0, import_types28.confidenceForExtracted)("reconstructed-approximate"),
11493
11634
  confidenceKind: "reconstructed-approximate",
11494
11635
  evidence: {
11495
11636
  file: relFile,
@@ -11522,7 +11663,7 @@ async function addRouteCallEdges(graph, services) {
11522
11663
  edgesAdded += e;
11523
11664
  const anchored = pathHasLiteralAnchor(site.pathTemplate);
11524
11665
  const confidenceKind = site.approximate && !anchored ? "reconstructed-approximate" : "verified-call-site";
11525
- const confidence = (0, import_types27.confidenceForExtracted)(confidenceKind);
11666
+ const confidence = (0, import_types28.confidenceForExtracted)(confidenceKind);
11526
11667
  const ev = {
11527
11668
  file: relFile,
11528
11669
  line: site.line,
@@ -11531,25 +11672,25 @@ async function addRouteCallEdges(graph, services) {
11531
11672
  pathTemplate: site.pathTemplate,
11532
11673
  ...confidenceKind === "reconstructed-approximate" ? { approximate: true, reason: site.reason } : {}
11533
11674
  };
11534
- if (!(0, import_types27.passesExtractedFloor)(confidence)) {
11675
+ if (!(0, import_types28.passesExtractedFloor)(confidence)) {
11535
11676
  noteExtractedDropped({
11536
11677
  source: fileNodeId,
11537
11678
  target: match.routeNodeId,
11538
- type: import_types27.EdgeType.CALLS,
11679
+ type: import_types28.EdgeType.CALLS,
11539
11680
  confidence,
11540
11681
  confidenceKind,
11541
11682
  evidence: ev
11542
11683
  });
11543
11684
  continue;
11544
11685
  }
11545
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types27.EdgeType.CALLS);
11686
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, match.routeNodeId, import_types28.EdgeType.CALLS);
11546
11687
  if (!graph.hasEdge(edgeId)) {
11547
11688
  const edge = {
11548
11689
  id: edgeId,
11549
11690
  source: fileNodeId,
11550
11691
  target: match.routeNodeId,
11551
- type: import_types27.EdgeType.CALLS,
11552
- provenance: import_types27.Provenance.EXTRACTED,
11692
+ type: import_types28.EdgeType.CALLS,
11693
+ provenance: import_types28.Provenance.EXTRACTED,
11553
11694
  confidence,
11554
11695
  evidence: ev
11555
11696
  };
@@ -11565,7 +11706,7 @@ async function addRouteCallEdges(graph, services) {
11565
11706
  // src/extract/calls/kafka.ts
11566
11707
  init_cjs_shims();
11567
11708
  var import_node_path41 = __toESM(require("path"), 1);
11568
- var import_types28 = require("@neat.is/types");
11709
+ var import_types29 = require("@neat.is/types");
11569
11710
  var PRODUCER_TOPIC_RE = /(?:producer|kafkaProducer)[\s\S]{0,40}?\.send\s*\(\s*\{[\s\S]{0,200}?topic\s*:\s*['"`]([^'"`]+)['"`]/g;
11570
11711
  var CONSUMER_TOPIC_RE = /(?:consumer|kafkaConsumer)[\s\S]{0,40}?\.(?:subscribe|run)\s*\(\s*\{[\s\S]{0,200}?topic[s]?\s*:\s*(?:\[\s*)?['"`]([^'"`]+)['"`]/g;
11571
11712
  var SARAMA_IMPORT_RE = /"[^"]*\/sarama"/;
@@ -11642,7 +11783,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
11642
11783
  seen.add(key);
11643
11784
  const line = anchor !== void 0 ? file.content.slice(0, anchor).split("\n").length : lineOf(file.content, topic);
11644
11785
  out.push({
11645
- infraId: (0, import_types28.infraId)("kafka-topic", topic),
11786
+ infraId: (0, import_types29.infraId)("kafka-topic", topic),
11646
11787
  name: topic,
11647
11788
  kind: "kafka-topic",
11648
11789
  edgeType,
@@ -11670,7 +11811,7 @@ function kafkaEndpointsFromFile(file, serviceDir) {
11670
11811
  // src/extract/calls/redis.ts
11671
11812
  init_cjs_shims();
11672
11813
  var import_node_path42 = __toESM(require("path"), 1);
11673
- var import_types29 = require("@neat.is/types");
11814
+ var import_types30 = require("@neat.is/types");
11674
11815
  var REDIS_URL_RE = /redis(?:s)?:\/\/(?:[^@'"`\s]+@)?([^:/'"`\s]+)(?::(\d+))?/g;
11675
11816
  function redisEndpointsFromFile(file, serviceDir) {
11676
11817
  const out = [];
@@ -11683,7 +11824,7 @@ function redisEndpointsFromFile(file, serviceDir) {
11683
11824
  seen.add(host);
11684
11825
  const line = lineOf(file.content, host);
11685
11826
  out.push({
11686
- infraId: (0, import_types29.infraId)("redis", host),
11827
+ infraId: (0, import_types30.infraId)("redis", host),
11687
11828
  name: host,
11688
11829
  kind: "redis",
11689
11830
  edgeType: "CALLS",
@@ -11704,7 +11845,7 @@ function redisEndpointsFromFile(file, serviceDir) {
11704
11845
  // src/extract/calls/aws.ts
11705
11846
  init_cjs_shims();
11706
11847
  var import_node_path43 = __toESM(require("path"), 1);
11707
- var import_types30 = require("@neat.is/types");
11848
+ var import_types31 = require("@neat.is/types");
11708
11849
  var S3_BUCKET_RE = /Bucket\s*:\s*['"`]([^'"`]+)['"`]/g;
11709
11850
  var DYNAMO_TABLE_RE = /TableName\s*:\s*['"`]([^'"`]+)['"`]/g;
11710
11851
  function hasMarker(text, markers) {
@@ -11728,7 +11869,7 @@ function awsEndpointsFromFile(file, serviceDir) {
11728
11869
  seen.add(key);
11729
11870
  const line = lineOf(file.content, name);
11730
11871
  out.push({
11731
- infraId: (0, import_types30.infraId)(kind, name),
11872
+ infraId: (0, import_types31.infraId)(kind, name),
11732
11873
  name,
11733
11874
  kind,
11734
11875
  edgeType: "CALLS",
@@ -11763,7 +11904,7 @@ function awsEndpointsFromFile(file, serviceDir) {
11763
11904
  // src/extract/calls/grpc.ts
11764
11905
  init_cjs_shims();
11765
11906
  var import_node_path44 = __toESM(require("path"), 1);
11766
- var import_types31 = require("@neat.is/types");
11907
+ var import_types32 = require("@neat.is/types");
11767
11908
  var GRPC_CLIENT_RE = /new\s+([A-Z][A-Za-z0-9_]*)Client\s*\(\s*['"`]?([^,'"`)]+)?/g;
11768
11909
  var AWS_SDK_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@aws-sdk\/client-([a-z0-9-]+)['"`]/g;
11769
11910
  var GRPC_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@grpc\/grpc-js['"`]|_grpc_pb['"`]/;
@@ -11812,7 +11953,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
11812
11953
  const { kind } = classified;
11813
11954
  const line = lineOf(file.content, m[0]);
11814
11955
  out.push({
11815
- infraId: (0, import_types31.infraId)(kind, name),
11956
+ infraId: (0, import_types32.infraId)(kind, name),
11816
11957
  name,
11817
11958
  kind,
11818
11959
  edgeType: "CALLS",
@@ -11833,7 +11974,7 @@ function grpcEndpointsFromFile(file, serviceDir) {
11833
11974
  // src/extract/calls/supabase.ts
11834
11975
  init_cjs_shims();
11835
11976
  var import_node_path45 = __toESM(require("path"), 1);
11836
- var import_types32 = require("@neat.is/types");
11977
+ var import_types33 = require("@neat.is/types");
11837
11978
  var SUPABASE_JS_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/supabase-js['"`]/;
11838
11979
  var SUPABASE_SSR_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])@supabase\/ssr['"`]/;
11839
11980
  var SUPABASE_CLIENT_RE = /\b(createClient|createServerClient|createBrowserClient)\s*\(\s*(?:['"`]([^'"`]*)['"`])?/g;
@@ -11881,7 +12022,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
11881
12022
  seen.add(name);
11882
12023
  const line = lineOf(file.content, m[0]);
11883
12024
  out.push({
11884
- infraId: (0, import_types32.infraId)("supabase", name),
12025
+ infraId: (0, import_types33.infraId)("supabase", name),
11885
12026
  name,
11886
12027
  kind: "supabase",
11887
12028
  edgeType: "CALLS",
@@ -11912,7 +12053,7 @@ function supabaseEndpointsFromFile(file, serviceDir) {
11912
12053
  seen.add(key);
11913
12054
  const line = lineOf(file.content, am[0]);
11914
12055
  out.push({
11915
- infraId: (0, import_types32.infraId)(kind, resource),
12056
+ infraId: (0, import_types33.infraId)(kind, resource),
11916
12057
  name: resource,
11917
12058
  kind,
11918
12059
  edgeType: "CALLS",
@@ -11933,7 +12074,7 @@ init_cjs_shims();
11933
12074
  var import_node_path46 = __toESM(require("path"), 1);
11934
12075
  var import_tree_sitter8 = __toESM(require("tree-sitter"), 1);
11935
12076
  var import_tree_sitter_javascript6 = __toESM(require("tree-sitter-javascript"), 1);
11936
- var import_types33 = require("@neat.is/types");
12077
+ var import_types34 = require("@neat.is/types");
11937
12078
  var FIRESTORE_CLIENT_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase\/firestore['"`]/;
11938
12079
  var FIRESTORE_ADMIN_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])firebase-admin(?:\/firestore)?['"`]/;
11939
12080
  function parserForExt2(ext) {
@@ -12197,7 +12338,7 @@ function firestoreEndpointsFromFile(file, serviceDir, imported) {
12197
12338
  }
12198
12339
  }
12199
12340
  out.push({
12200
- infraId: (0, import_types33.infraId)("firestore-collection", collPath),
12341
+ infraId: (0, import_types34.infraId)("firestore-collection", collPath),
12201
12342
  name: collPath,
12202
12343
  kind: "firestore-collection",
12203
12344
  edgeType: "CALLS",
@@ -12313,7 +12454,7 @@ async function firestoreCrossFileEndpoints(files, serviceDir) {
12313
12454
  // src/extract/calls/mongoose.ts
12314
12455
  init_cjs_shims();
12315
12456
  var import_node_path47 = __toESM(require("path"), 1);
12316
- var import_types34 = require("@neat.is/types");
12457
+ var import_types35 = require("@neat.is/types");
12317
12458
  var MONGOOSE_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongoose['"`]/;
12318
12459
  var MONGODB_IMPORT_RE = /(?:from\s+['"`]|require\(\s*['"`])mongodb['"`]/;
12319
12460
  var PLURALIZE_DISABLED_RE = /\bpluralize\s*\(\s*(?:null|false)\s*\)/;
@@ -12458,7 +12599,7 @@ function collectModelDefs(content, pluralizeOn) {
12458
12599
  function endpoint(r, file, serviceDir, matchText) {
12459
12600
  const line = lineOf(file.content, matchText);
12460
12601
  return {
12461
- infraId: (0, import_types34.infraId)(r.kind, r.name),
12602
+ infraId: (0, import_types35.infraId)(r.kind, r.name),
12462
12603
  name: r.name,
12463
12604
  kind: r.kind,
12464
12605
  edgeType: "CALLS",
@@ -12611,7 +12752,7 @@ init_cjs_shims();
12611
12752
  var import_node_path48 = __toESM(require("path"), 1);
12612
12753
  var import_tree_sitter9 = __toESM(require("tree-sitter"), 1);
12613
12754
  var import_tree_sitter_python5 = __toESM(require("tree-sitter-python"), 1);
12614
- var import_types35 = require("@neat.is/types");
12755
+ var import_types36 = require("@neat.is/types");
12615
12756
  var SQLALCHEMY_IMPORT_RE = /(?:from|import)\s+(?:flask_sqlalchemy|sqlalchemy)\b/;
12616
12757
  var PARSE_CHUNK6 = 16384;
12617
12758
  function makePyParser3() {
@@ -12765,7 +12906,7 @@ function sqlalchemyEndpointsFromFile(file, serviceDir) {
12765
12906
  if (seen.has(name)) return;
12766
12907
  seen.add(name);
12767
12908
  out.push({
12768
- infraId: (0, import_types35.infraId)("sql-table", name),
12909
+ infraId: (0, import_types36.infraId)("sql-table", name),
12769
12910
  name,
12770
12911
  kind: "sql-table",
12771
12912
  edgeType: "CALLS",
@@ -12873,7 +13014,7 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
12873
13014
  if (seen.has(key)) continue;
12874
13015
  seen.add(key);
12875
13016
  out.push({
12876
- infraId: (0, import_types35.infraId)("sql-table", t),
13017
+ infraId: (0, import_types36.infraId)("sql-table", t),
12877
13018
  name: t,
12878
13019
  kind: "sql-table",
12879
13020
  edgeType: "CALLS",
@@ -12894,7 +13035,7 @@ init_cjs_shims();
12894
13035
  var import_node_path49 = __toESM(require("path"), 1);
12895
13036
  var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
12896
13037
  var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
12897
- var import_types36 = require("@neat.is/types");
13038
+ var import_types37 = require("@neat.is/types");
12898
13039
  var SOCKET_IMPORT_RE = /(?:^|\n)\s*(?:import\s+socket\b|from\s+socket\s+import\b)/;
12899
13040
  var PARSE_CHUNK7 = 16384;
12900
13041
  function makePyParser4() {
@@ -12960,7 +13101,7 @@ function socketEndpointsFromFile(file, serviceDir) {
12960
13101
  seen.add(name);
12961
13102
  const line = node.startPosition.row + 1;
12962
13103
  out.push({
12963
- infraId: (0, import_types36.infraId)("socket", name),
13104
+ infraId: (0, import_types37.infraId)("socket", name),
12964
13105
  name,
12965
13106
  kind: "socket",
12966
13107
  edgeType: "CALLS",
@@ -12981,7 +13122,7 @@ init_cjs_shims();
12981
13122
  var import_node_path50 = __toESM(require("path"), 1);
12982
13123
  var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
12983
13124
  var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
12984
- var import_types37 = require("@neat.is/types");
13125
+ var import_types38 = require("@neat.is/types");
12985
13126
  var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
12986
13127
  var PARSE_CHUNK8 = 16384;
12987
13128
  function makePyParser5() {
@@ -13061,7 +13202,7 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
13061
13202
  seen.add(table);
13062
13203
  const line = node.startPosition.row + 1;
13063
13204
  out.push({
13064
- infraId: (0, import_types37.infraId)("sql-table", table),
13205
+ infraId: (0, import_types38.infraId)("sql-table", table),
13065
13206
  name: table,
13066
13207
  kind: "sql-table",
13067
13208
  edgeType: "CALLS",
@@ -13077,7 +13218,7 @@ init_cjs_shims();
13077
13218
  var import_node_path51 = __toESM(require("path"), 1);
13078
13219
  var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
13079
13220
  var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
13080
- var import_types38 = require("@neat.is/types");
13221
+ var import_types39 = require("@neat.is/types");
13081
13222
  var DRIZZLE_IMPORT_RE = /drizzle-orm/;
13082
13223
  var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
13083
13224
  function parserForExt3(ext) {
@@ -13168,7 +13309,7 @@ function drizzleEndpointsFromFile(file, serviceDir) {
13168
13309
  const columns = columnsFromObject(obj);
13169
13310
  const line = node.startPosition.row + 1;
13170
13311
  out.push({
13171
- infraId: (0, import_types38.infraId)("sql-table", tableName),
13312
+ infraId: (0, import_types39.infraId)("sql-table", tableName),
13172
13313
  name: tableName,
13173
13314
  kind: "sql-table",
13174
13315
  edgeType: "CALLS",
@@ -13278,7 +13419,7 @@ function drizzleForeignKeys(file, serviceDir) {
13278
13419
  // src/extract/calls/prisma.ts
13279
13420
  init_cjs_shims();
13280
13421
  var import_node_path52 = __toESM(require("path"), 1);
13281
- var import_types39 = require("@neat.is/types");
13422
+ var import_types40 = require("@neat.is/types");
13282
13423
  var SCALAR_TYPES = /* @__PURE__ */ new Set([
13283
13424
  "Int",
13284
13425
  "String",
@@ -13326,7 +13467,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
13326
13467
  if (seenTable.has(b.tableName)) return;
13327
13468
  seenTable.add(b.tableName);
13328
13469
  out.push({
13329
- infraId: (0, import_types39.infraId)("sql-table", b.tableName),
13470
+ infraId: (0, import_types40.infraId)("sql-table", b.tableName),
13330
13471
  name: b.tableName,
13331
13472
  kind: "sql-table",
13332
13473
  edgeType: "CALLS",
@@ -13498,7 +13639,7 @@ init_cjs_shims();
13498
13639
  var import_node_path53 = __toESM(require("path"), 1);
13499
13640
  var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
13500
13641
  var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
13501
- var import_types40 = require("@neat.is/types");
13642
+ var import_types41 = require("@neat.is/types");
13502
13643
  var AR_SCHEMA_RE = /ActiveRecord::Schema/;
13503
13644
  var PARSE_CHUNK9 = 16384;
13504
13645
  function makeRubyParser2() {
@@ -13696,7 +13837,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
13696
13837
  if (!table || seen.has(table.name)) return;
13697
13838
  seen.add(table.name);
13698
13839
  out.push({
13699
- infraId: (0, import_types40.infraId)("sql-table", table.name),
13840
+ infraId: (0, import_types41.infraId)("sql-table", table.name),
13700
13841
  name: table.name,
13701
13842
  kind: "sql-table",
13702
13843
  edgeType: "CALLS",
@@ -13802,7 +13943,7 @@ function railsModelEndpointsFromFile(file, serviceDir) {
13802
13943
  seen.add(table);
13803
13944
  const line = node.startPosition.row + 1;
13804
13945
  out.push({
13805
- infraId: (0, import_types40.infraId)("sql-table", table),
13946
+ infraId: (0, import_types41.infraId)("sql-table", table),
13806
13947
  name: table,
13807
13948
  kind: "sql-table",
13808
13949
  edgeType: "CALLS",
@@ -13860,7 +14001,7 @@ init_cjs_shims();
13860
14001
  var import_node_path54 = __toESM(require("path"), 1);
13861
14002
  var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
13862
14003
  var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
13863
- var import_types41 = require("@neat.is/types");
14004
+ var import_types42 = require("@neat.is/types");
13864
14005
  var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
13865
14006
  var PARSE_CHUNK10 = 16384;
13866
14007
  function makePhpParser2() {
@@ -14107,7 +14248,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
14107
14248
  }
14108
14249
  }
14109
14250
  out.push({
14110
- infraId: (0, import_types41.infraId)("sql-table", bp.table),
14251
+ infraId: (0, import_types42.infraId)("sql-table", bp.table),
14111
14252
  name: bp.table,
14112
14253
  kind: "sql-table",
14113
14254
  edgeType: "CALLS",
@@ -14250,7 +14391,7 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
14250
14391
  seen.add(table);
14251
14392
  const line = node.startPosition.row + 1;
14252
14393
  out.push({
14253
- infraId: (0, import_types41.infraId)("sql-table", table),
14394
+ infraId: (0, import_types42.infraId)("sql-table", table),
14254
14395
  name: table,
14255
14396
  kind: "sql-table",
14256
14397
  edgeType: "CALLS",
@@ -14307,7 +14448,7 @@ init_cjs_shims();
14307
14448
  var import_node_path57 = __toESM(require("path"), 1);
14308
14449
  var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
14309
14450
  var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
14310
- var import_types42 = require("@neat.is/types");
14451
+ var import_types43 = require("@neat.is/types");
14311
14452
  init_otel();
14312
14453
  var PARSE_CHUNK11 = 16384;
14313
14454
  var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
@@ -14401,7 +14542,7 @@ function goSqlEndpointsFromFile(file, serviceDir) {
14401
14542
  const columns = columnsFromSqlStatement(sql);
14402
14543
  const line = node.startPosition.row + 1;
14403
14544
  out.push({
14404
- infraId: (0, import_types42.infraId)("sql-table", table),
14545
+ infraId: (0, import_types43.infraId)("sql-table", table),
14405
14546
  name: table,
14406
14547
  kind: "sql-table",
14407
14548
  edgeType: "CALLS",
@@ -14422,7 +14563,7 @@ init_cjs_shims();
14422
14563
  var import_node_path58 = __toESM(require("path"), 1);
14423
14564
  var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
14424
14565
  var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
14425
- var import_types43 = require("@neat.is/types");
14566
+ var import_types44 = require("@neat.is/types");
14426
14567
  var GORM_IMPORT_RE = /gorm\.io\/gorm/;
14427
14568
  var PARSE_CHUNK12 = 16384;
14428
14569
  function makeGoParser4() {
@@ -14867,7 +15008,7 @@ function gormEndpointsFromFile(file, serviceDir) {
14867
15008
  const columns = [];
14868
15009
  collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
14869
15010
  out.push({
14870
- infraId: (0, import_types43.infraId)("sql-table", table),
15011
+ infraId: (0, import_types44.infraId)("sql-table", table),
14871
15012
  name: table,
14872
15013
  kind: "sql-table",
14873
15014
  edgeType: "CALLS",
@@ -14938,7 +15079,7 @@ init_cjs_shims();
14938
15079
  var import_node_path59 = __toESM(require("path"), 1);
14939
15080
  var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
14940
15081
  var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
14941
- var import_types44 = require("@neat.is/types");
15082
+ var import_types45 = require("@neat.is/types");
14942
15083
  var EFCORE_GATE = /Microsoft\.EntityFrameworkCore|DataAnnotations\.Schema|\bDbContext\b|\bDbSet\s*</;
14943
15084
  var PARSE_CHUNK13 = 16384;
14944
15085
  function makeCsParser() {
@@ -15023,7 +15164,7 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15023
15164
  if (!name || seen.has(name)) return;
15024
15165
  seen.add(name);
15025
15166
  out.push({
15026
- infraId: (0, import_types44.infraId)("sql-table", name),
15167
+ infraId: (0, import_types45.infraId)("sql-table", name),
15027
15168
  name,
15028
15169
  kind: "sql-table",
15029
15170
  edgeType: "CALLS",
@@ -15053,11 +15194,11 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15053
15194
  function edgeTypeFromEndpoint(ep) {
15054
15195
  switch (ep.edgeType) {
15055
15196
  case "PUBLISHES_TO":
15056
- return import_types45.EdgeType.PUBLISHES_TO;
15197
+ return import_types46.EdgeType.PUBLISHES_TO;
15057
15198
  case "CONSUMES_FROM":
15058
- return import_types45.EdgeType.CONSUMES_FROM;
15199
+ return import_types46.EdgeType.CONSUMES_FROM;
15059
15200
  default:
15060
- return import_types45.EdgeType.CALLS;
15201
+ return import_types46.EdgeType.CALLS;
15061
15202
  }
15062
15203
  }
15063
15204
  function isAwsKind(kind) {
@@ -15128,7 +15269,7 @@ async function addExternalEndpointEdges(graph, services) {
15128
15269
  if (!graph.hasNode(ep.infraId)) {
15129
15270
  const node = {
15130
15271
  id: ep.infraId,
15131
- type: import_types45.NodeType.InfraNode,
15272
+ type: import_types46.NodeType.InfraNode,
15132
15273
  name: ep.name,
15133
15274
  // #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
15134
15275
  // aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
@@ -15141,21 +15282,21 @@ async function addExternalEndpointEdges(graph, services) {
15141
15282
  }
15142
15283
  if (ep.columns && ep.columns.length > 0) {
15143
15284
  const node = graph.getNodeAttributes(ep.infraId);
15144
- if (node.type === import_types45.NodeType.InfraNode) {
15285
+ if (node.type === import_types46.NodeType.InfraNode) {
15145
15286
  graph.replaceNodeAttributes(ep.infraId, {
15146
15287
  ...node,
15147
15288
  columns: foldColumns(
15148
15289
  node.columns,
15149
15290
  ep.columns,
15150
- import_types45.Provenance.EXTRACTED,
15151
- (0, import_types45.confidenceForExtracted)(ep.confidenceKind)
15291
+ import_types46.Provenance.EXTRACTED,
15292
+ (0, import_types46.confidenceForExtracted)(ep.confidenceKind)
15152
15293
  )
15153
15294
  });
15154
15295
  }
15155
15296
  }
15156
15297
  if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
15157
15298
  const node = graph.getNodeAttributes(ep.infraId);
15158
- if (node.type === import_types45.NodeType.InfraNode) {
15299
+ if (node.type === import_types46.NodeType.InfraNode) {
15159
15300
  graph.replaceNodeAttributes(ep.infraId, {
15160
15301
  ...node,
15161
15302
  columns: foldSdkWrites(node.columns, ep.sdkWrites)
@@ -15163,7 +15304,7 @@ async function addExternalEndpointEdges(graph, services) {
15163
15304
  }
15164
15305
  }
15165
15306
  const edgeType = edgeTypeFromEndpoint(ep);
15166
- const confidence = (0, import_types45.confidenceForExtracted)(ep.confidenceKind);
15307
+ const confidence = (0, import_types46.confidenceForExtracted)(ep.confidenceKind);
15167
15308
  const relFile = toPosix(ep.evidence.file);
15168
15309
  const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
15169
15310
  graph,
@@ -15173,7 +15314,7 @@ async function addExternalEndpointEdges(graph, services) {
15173
15314
  );
15174
15315
  nodesAdded += n;
15175
15316
  edgesAdded += e;
15176
- if (!(0, import_types45.passesExtractedFloor)(confidence)) {
15317
+ if (!(0, import_types46.passesExtractedFloor)(confidence)) {
15177
15318
  noteExtractedDropped({
15178
15319
  source: fileNodeId,
15179
15320
  target: ep.infraId,
@@ -15193,7 +15334,7 @@ async function addExternalEndpointEdges(graph, services) {
15193
15334
  source: fileNodeId,
15194
15335
  target: ep.infraId,
15195
15336
  type: edgeType,
15196
- provenance: import_types45.Provenance.EXTRACTED,
15337
+ provenance: import_types46.Provenance.EXTRACTED,
15197
15338
  confidence,
15198
15339
  evidence: ep.evidence
15199
15340
  };
@@ -15216,7 +15357,7 @@ async function addCallEdges(graph, services) {
15216
15357
 
15217
15358
  // src/extract/table-edges.ts
15218
15359
  init_cjs_shims();
15219
- var import_types46 = require("@neat.is/types");
15360
+ var import_types47 = require("@neat.is/types");
15220
15361
  async function addTableEdges(graph, services) {
15221
15362
  let nodesAdded = 0;
15222
15363
  let edgesAdded = 0;
@@ -15244,20 +15385,20 @@ async function addTableEdges(graph, services) {
15244
15385
  }
15245
15386
  refs.push(...modelRefs);
15246
15387
  for (const ref of refs) {
15247
- const childId = (0, import_types46.infraId)("sql-table", ref.childTable);
15248
- const parentId = (0, import_types46.infraId)("sql-table", ref.parentTable);
15388
+ const childId = (0, import_types47.infraId)("sql-table", ref.childTable);
15389
+ const parentId = (0, import_types47.infraId)("sql-table", ref.parentTable);
15249
15390
  if (childId === parentId) continue;
15250
15391
  nodesAdded += ensureTableNode(graph, childId, ref.childTable);
15251
15392
  nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
15252
- const edgeId = (0, import_types46.extractedEdgeId)(childId, parentId, import_types46.EdgeType.REFERENCES);
15393
+ const edgeId = (0, import_types47.extractedEdgeId)(childId, parentId, import_types47.EdgeType.REFERENCES);
15253
15394
  if (graph.hasEdge(edgeId)) continue;
15254
15395
  const edge = {
15255
15396
  id: edgeId,
15256
15397
  source: childId,
15257
15398
  target: parentId,
15258
- type: import_types46.EdgeType.REFERENCES,
15259
- provenance: import_types46.Provenance.EXTRACTED,
15260
- confidence: (0, import_types46.confidenceForExtracted)("structural"),
15399
+ type: import_types47.EdgeType.REFERENCES,
15400
+ provenance: import_types47.Provenance.EXTRACTED,
15401
+ confidence: (0, import_types47.confidenceForExtracted)("structural"),
15261
15402
  evidence: ref.evidence
15262
15403
  };
15263
15404
  graph.addEdgeWithKey(edgeId, childId, parentId, edge);
@@ -15270,7 +15411,7 @@ function ensureTableNode(graph, id, name) {
15270
15411
  if (graph.hasNode(id)) return 0;
15271
15412
  const node = {
15272
15413
  id,
15273
- type: import_types46.NodeType.InfraNode,
15414
+ type: import_types47.NodeType.InfraNode,
15274
15415
  name,
15275
15416
  provider: "self",
15276
15417
  kind: "sql-table"
@@ -15285,15 +15426,15 @@ init_cjs_shims();
15285
15426
  // src/extract/infra/docker-compose.ts
15286
15427
  init_cjs_shims();
15287
15428
  var import_node_path60 = __toESM(require("path"), 1);
15288
- var import_types48 = require("@neat.is/types");
15429
+ var import_types49 = require("@neat.is/types");
15289
15430
 
15290
15431
  // src/extract/infra/shared.ts
15291
15432
  init_cjs_shims();
15292
- var import_types47 = require("@neat.is/types");
15433
+ var import_types48 = require("@neat.is/types");
15293
15434
  function makeInfraNode(kind, name, provider = "self", extras) {
15294
15435
  return {
15295
- id: (0, import_types47.infraId)(kind, name),
15296
- type: import_types47.NodeType.InfraNode,
15436
+ id: (0, import_types48.infraId)(kind, name),
15437
+ type: import_types48.NodeType.InfraNode,
15297
15438
  name,
15298
15439
  provider,
15299
15440
  kind,
@@ -15337,8 +15478,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
15337
15478
  source: anchorId,
15338
15479
  target: node.id,
15339
15480
  type: edgeType,
15340
- provenance: import_types47.Provenance.EXTRACTED,
15341
- confidence: (0, import_types47.confidenceForExtracted)("structural"),
15481
+ provenance: import_types48.Provenance.EXTRACTED,
15482
+ confidence: (0, import_types48.confidenceForExtracted)("structural"),
15342
15483
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
15343
15484
  };
15344
15485
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15405,15 +15546,15 @@ async function addComposeInfra(graph, scanPath, services) {
15405
15546
  for (const dep of dependsOnList(svc.depends_on)) {
15406
15547
  const targetId = composeNameToNodeId.get(dep);
15407
15548
  if (!targetId) continue;
15408
- const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types48.EdgeType.DEPENDS_ON);
15549
+ const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types49.EdgeType.DEPENDS_ON);
15409
15550
  if (graph.hasEdge(edgeId)) continue;
15410
15551
  const edge = {
15411
15552
  id: edgeId,
15412
15553
  source: sourceId,
15413
15554
  target: targetId,
15414
- type: import_types48.EdgeType.DEPENDS_ON,
15415
- provenance: import_types48.Provenance.EXTRACTED,
15416
- confidence: (0, import_types48.confidenceForExtracted)("structural"),
15555
+ type: import_types49.EdgeType.DEPENDS_ON,
15556
+ provenance: import_types49.Provenance.EXTRACTED,
15557
+ confidence: (0, import_types49.confidenceForExtracted)("structural"),
15417
15558
  evidence: { file: evidenceFile }
15418
15559
  };
15419
15560
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15427,7 +15568,7 @@ async function addComposeInfra(graph, scanPath, services) {
15427
15568
  init_cjs_shims();
15428
15569
  var import_node_path61 = __toESM(require("path"), 1);
15429
15570
  var import_node_fs27 = require("fs");
15430
- var import_types49 = require("@neat.is/types");
15571
+ var import_types50 = require("@neat.is/types");
15431
15572
  function readDockerfile(content) {
15432
15573
  let image = null;
15433
15574
  const ports = [];
@@ -15486,15 +15627,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15486
15627
  );
15487
15628
  nodesAdded += fn;
15488
15629
  edgesAdded += fe;
15489
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types49.EdgeType.RUNS_ON);
15630
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types50.EdgeType.RUNS_ON);
15490
15631
  if (!graph.hasEdge(edgeId)) {
15491
15632
  const edge = {
15492
15633
  id: edgeId,
15493
15634
  source: fileNodeId,
15494
15635
  target: node.id,
15495
- type: import_types49.EdgeType.RUNS_ON,
15496
- provenance: import_types49.Provenance.EXTRACTED,
15497
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
15636
+ type: import_types50.EdgeType.RUNS_ON,
15637
+ provenance: import_types50.Provenance.EXTRACTED,
15638
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
15498
15639
  evidence: {
15499
15640
  file: evidenceFile,
15500
15641
  ...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
@@ -15509,15 +15650,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15509
15650
  graph.addNode(portNode.id, portNode);
15510
15651
  nodesAdded++;
15511
15652
  }
15512
- const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types49.EdgeType.CONNECTS_TO);
15653
+ const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types50.EdgeType.CONNECTS_TO);
15513
15654
  if (graph.hasEdge(portEdgeId)) continue;
15514
15655
  const portEdge = {
15515
15656
  id: portEdgeId,
15516
15657
  source: fileNodeId,
15517
15658
  target: portNode.id,
15518
- type: import_types49.EdgeType.CONNECTS_TO,
15519
- provenance: import_types49.Provenance.EXTRACTED,
15520
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
15659
+ type: import_types50.EdgeType.CONNECTS_TO,
15660
+ provenance: import_types50.Provenance.EXTRACTED,
15661
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
15521
15662
  evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
15522
15663
  };
15523
15664
  graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
@@ -15531,7 +15672,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15531
15672
  init_cjs_shims();
15532
15673
  var import_node_fs28 = require("fs");
15533
15674
  var import_node_path62 = __toESM(require("path"), 1);
15534
- var import_types50 = require("@neat.is/types");
15675
+ var import_types51 = require("@neat.is/types");
15535
15676
  var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
15536
15677
  var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
15537
15678
  async function walkTfFiles(start, depth = 0, max = 5) {
@@ -15612,16 +15753,16 @@ async function addTerraformResources(graph, scanPath) {
15612
15753
  if (!target) continue;
15613
15754
  if (seen.has(target.nodeId)) continue;
15614
15755
  seen.add(target.nodeId);
15615
- const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types50.EdgeType.DEPENDS_ON);
15756
+ const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types51.EdgeType.DEPENDS_ON);
15616
15757
  if (graph.hasEdge(edgeId)) continue;
15617
15758
  const line = lineAt2(content, resource.bodyOffset + ref.index);
15618
15759
  const edge = {
15619
15760
  id: edgeId,
15620
15761
  source: resource.nodeId,
15621
15762
  target: target.nodeId,
15622
- type: import_types50.EdgeType.DEPENDS_ON,
15623
- provenance: import_types50.Provenance.EXTRACTED,
15624
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
15763
+ type: import_types51.EdgeType.DEPENDS_ON,
15764
+ provenance: import_types51.Provenance.EXTRACTED,
15765
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
15625
15766
  evidence: { file: evidenceFile, line, snippet: key }
15626
15767
  };
15627
15768
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15637,7 +15778,7 @@ init_cjs_shims();
15637
15778
  var import_node_fs29 = require("fs");
15638
15779
  var import_node_path63 = __toESM(require("path"), 1);
15639
15780
  var import_yaml3 = require("yaml");
15640
- var import_types51 = require("@neat.is/types");
15781
+ var import_types52 = require("@neat.is/types");
15641
15782
  var K8S_KIND_TO_INFRA_KIND = {
15642
15783
  Service: "k8s-service",
15643
15784
  Deployment: "k8s-deployment",
@@ -15697,7 +15838,7 @@ async function addK8sResources(graph, scanPath) {
15697
15838
  nodesAdded++;
15698
15839
  }
15699
15840
  if (isWorkload) {
15700
- const svcId = (0, import_types51.serviceId)(name);
15841
+ const svcId = (0, import_types52.serviceId)(name);
15701
15842
  if (graph.hasNode(svcId)) {
15702
15843
  const svc = graph.getNodeAttributes(svcId);
15703
15844
  graph.replaceNodeAttributes(svcId, {
@@ -15709,7 +15850,7 @@ async function addK8sResources(graph, scanPath) {
15709
15850
  edgesAdded += emitPlatformResourceEdge(
15710
15851
  graph,
15711
15852
  svcId,
15712
- import_types51.EdgeType.RUNS_ON,
15853
+ import_types52.EdgeType.RUNS_ON,
15713
15854
  infraKind,
15714
15855
  name,
15715
15856
  "kubernetes",
@@ -15728,7 +15869,7 @@ init_cjs_shims();
15728
15869
  var import_node_fs30 = require("fs");
15729
15870
  var import_node_path64 = __toESM(require("path"), 1);
15730
15871
  var import_smol_toml3 = require("smol-toml");
15731
- var import_types52 = require("@neat.is/types");
15872
+ var import_types53 = require("@neat.is/types");
15732
15873
  var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
15733
15874
  async function readWranglerConfig(dir) {
15734
15875
  for (const filename of WRANGLER_FILENAMES) {
@@ -15776,8 +15917,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
15776
15917
  source: anchorId,
15777
15918
  target: node.id,
15778
15919
  type: edgeType,
15779
- provenance: import_types52.Provenance.EXTRACTED,
15780
- confidence: (0, import_types52.confidenceForExtracted)("structural"),
15920
+ provenance: import_types53.Provenance.EXTRACTED,
15921
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
15781
15922
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
15782
15923
  };
15783
15924
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15838,15 +15979,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15838
15979
  nodesAdded++;
15839
15980
  }
15840
15981
  if (runtimeNode.id !== anchorId) {
15841
- const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types52.EdgeType.RUNS_ON);
15982
+ const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types53.EdgeType.RUNS_ON);
15842
15983
  if (!graph.hasEdge(runsOnId)) {
15843
15984
  const edge = {
15844
15985
  id: runsOnId,
15845
15986
  source: anchorId,
15846
15987
  target: runtimeNode.id,
15847
- type: import_types52.EdgeType.RUNS_ON,
15848
- provenance: import_types52.Provenance.EXTRACTED,
15849
- confidence: (0, import_types52.confidenceForExtracted)("structural"),
15988
+ type: import_types53.EdgeType.RUNS_ON,
15989
+ provenance: import_types53.Provenance.EXTRACTED,
15990
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
15850
15991
  evidence: {
15851
15992
  file: evidenceFile,
15852
15993
  ...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
@@ -15860,7 +16001,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15860
16001
  const result = addResourceEdge(
15861
16002
  graph,
15862
16003
  anchorId,
15863
- import_types52.EdgeType.CONNECTS_TO,
16004
+ import_types53.EdgeType.CONNECTS_TO,
15864
16005
  "cloudflare-route",
15865
16006
  route,
15866
16007
  evidenceFile,
@@ -15884,7 +16025,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15884
16025
  const result = addResourceEdge(
15885
16026
  graph,
15886
16027
  anchorId,
15887
- import_types52.EdgeType.DEPENDS_ON,
16028
+ import_types53.EdgeType.DEPENDS_ON,
15888
16029
  group.kind,
15889
16030
  name,
15890
16031
  evidenceFile,
@@ -15898,7 +16039,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15898
16039
  const result = addResourceEdge(
15899
16040
  graph,
15900
16041
  anchorId,
15901
- import_types52.EdgeType.DEPENDS_ON,
16042
+ import_types53.EdgeType.DEPENDS_ON,
15902
16043
  "cloudflare-cron",
15903
16044
  cron,
15904
16045
  evidenceFile,
@@ -15911,7 +16052,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15911
16052
  const result = addResourceEdge(
15912
16053
  graph,
15913
16054
  anchorId,
15914
- import_types52.EdgeType.DEPENDS_ON,
16055
+ import_types53.EdgeType.DEPENDS_ON,
15915
16056
  "cloudflare-env-var",
15916
16057
  varName,
15917
16058
  evidenceFile,
@@ -15924,15 +16065,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15924
16065
  if (!svc.service) continue;
15925
16066
  const target = workerIndex.get(svc.service);
15926
16067
  if (target && target.anchorId !== anchorId) {
15927
- const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types52.EdgeType.CALLS);
16068
+ const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types53.EdgeType.CALLS);
15928
16069
  if (!graph.hasEdge(edgeId)) {
15929
16070
  const edge = {
15930
16071
  id: edgeId,
15931
16072
  source: anchorId,
15932
16073
  target: target.anchorId,
15933
- type: import_types52.EdgeType.CALLS,
15934
- provenance: import_types52.Provenance.EXTRACTED,
15935
- confidence: (0, import_types52.confidenceForExtracted)("structural"),
16074
+ type: import_types53.EdgeType.CALLS,
16075
+ provenance: import_types53.Provenance.EXTRACTED,
16076
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
15936
16077
  evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
15937
16078
  };
15938
16079
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15943,7 +16084,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15943
16084
  const result = addResourceEdge(
15944
16085
  graph,
15945
16086
  anchorId,
15946
- import_types52.EdgeType.DEPENDS_ON,
16087
+ import_types53.EdgeType.DEPENDS_ON,
15947
16088
  "cloudflare-service-binding",
15948
16089
  svc.service,
15949
16090
  evidenceFile,
@@ -15960,7 +16101,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
15960
16101
  init_cjs_shims();
15961
16102
  var import_node_fs31 = require("fs");
15962
16103
  var import_node_path65 = __toESM(require("path"), 1);
15963
- var import_types53 = require("@neat.is/types");
16104
+ var import_types54 = require("@neat.is/types");
15964
16105
  var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
15965
16106
  async function readVercelConfig(dir) {
15966
16107
  for (const filename of VERCEL_CONFIG_FILENAMES) {
@@ -16023,12 +16164,12 @@ async function addVercelServices(graph, services, scanPath) {
16023
16164
  nodesAdded += result.nodesAdded;
16024
16165
  edgesAdded += result.edgesAdded;
16025
16166
  };
16026
- add(import_types53.EdgeType.RUNS_ON, "vercel", "vercel");
16027
- for (const cron of config.crons ?? []) add(import_types53.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16028
- for (const varName of Object.keys(config.env ?? {})) add(import_types53.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16029
- for (const varName of Object.keys(config.build?.env ?? {})) add(import_types53.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16167
+ add(import_types54.EdgeType.RUNS_ON, "vercel", "vercel");
16168
+ for (const cron of config.crons ?? []) add(import_types54.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16169
+ for (const varName of Object.keys(config.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16170
+ for (const varName of Object.keys(config.build?.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16030
16171
  for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
16031
- add(import_types53.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16172
+ add(import_types54.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16032
16173
  }
16033
16174
  }
16034
16175
  return { nodesAdded, edgesAdded };
@@ -16039,7 +16180,7 @@ init_cjs_shims();
16039
16180
  var import_node_fs32 = require("fs");
16040
16181
  var import_node_path66 = __toESM(require("path"), 1);
16041
16182
  var import_smol_toml4 = require("smol-toml");
16042
- var import_types54 = require("@neat.is/types");
16183
+ var import_types55 = require("@neat.is/types");
16043
16184
  var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
16044
16185
  async function readRailwayConfig(dir) {
16045
16186
  for (const filename of RAILWAY_FILENAMES) {
@@ -16085,9 +16226,9 @@ async function addRailwayServices(graph, services, scanPath) {
16085
16226
  nodesAdded += result.nodesAdded;
16086
16227
  edgesAdded += result.edgesAdded;
16087
16228
  };
16088
- add(import_types54.EdgeType.RUNS_ON, "railway", "railway");
16089
- add(import_types54.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16090
- add(import_types54.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16229
+ add(import_types55.EdgeType.RUNS_ON, "railway", "railway");
16230
+ add(import_types55.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16231
+ add(import_types55.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16091
16232
  }
16092
16233
  return { nodesAdded, edgesAdded };
16093
16234
  }
@@ -16097,7 +16238,7 @@ init_cjs_shims();
16097
16238
  var import_node_fs33 = require("fs");
16098
16239
  var import_node_path67 = __toESM(require("path"), 1);
16099
16240
  var import_smol_toml5 = require("smol-toml");
16100
- var import_types55 = require("@neat.is/types");
16241
+ var import_types56 = require("@neat.is/types");
16101
16242
  async function readSupabaseConfig(dir) {
16102
16243
  const relFile = import_node_path67.default.join("supabase", "config.toml");
16103
16244
  const abs = import_node_path67.default.join(dir, relFile);
@@ -16145,10 +16286,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
16145
16286
  nodesAdded += result.nodesAdded;
16146
16287
  edgesAdded += result.edgesAdded;
16147
16288
  };
16148
- add(import_types55.EdgeType.RUNS_ON, "supabase", "supabase");
16149
- for (const fn of Object.keys(config.functions ?? {})) add(import_types55.EdgeType.DEPENDS_ON, "supabase-function", fn);
16150
- if (config.storage) add(import_types55.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16151
- if (config.auth) add(import_types55.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16289
+ add(import_types56.EdgeType.RUNS_ON, "supabase", "supabase");
16290
+ for (const fn of Object.keys(config.functions ?? {})) add(import_types56.EdgeType.DEPENDS_ON, "supabase-function", fn);
16291
+ if (config.storage) add(import_types56.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16292
+ if (config.auth) add(import_types56.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16152
16293
  }
16153
16294
  return { nodesAdded, edgesAdded };
16154
16295
  }
@@ -16174,7 +16315,7 @@ init_cjs_shims();
16174
16315
  var import_node_path68 = __toESM(require("path"), 1);
16175
16316
  var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
16176
16317
  var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
16177
- var import_types56 = require("@neat.is/types");
16318
+ var import_types57 = require("@neat.is/types");
16178
16319
  var ZOD_IMPORT_RE = /\bzod\b/;
16179
16320
  var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
16180
16321
  function parserForExt4(ext) {
@@ -16280,7 +16421,7 @@ function zodShapesFromFile(file, serviceDir) {
16280
16421
  seen.add(name);
16281
16422
  const line = call.startPosition.row + 1;
16282
16423
  out.push({
16283
- infraId: (0, import_types56.infraId)("zod-schema", name),
16424
+ infraId: (0, import_types57.infraId)("zod-schema", name),
16284
16425
  name,
16285
16426
  fields,
16286
16427
  evidence: {
@@ -16315,7 +16456,7 @@ async function addZodShapes(graph, services) {
16315
16456
  if (!graph.hasNode(shape.infraId)) {
16316
16457
  const node = {
16317
16458
  id: shape.infraId,
16318
- type: import_types56.NodeType.InfraNode,
16459
+ type: import_types57.NodeType.InfraNode,
16319
16460
  name: shape.name,
16320
16461
  provider: "self",
16321
16462
  kind: "zod-schema"
@@ -16325,14 +16466,14 @@ async function addZodShapes(graph, services) {
16325
16466
  }
16326
16467
  if (shape.fields.length > 0) {
16327
16468
  const node = graph.getNodeAttributes(shape.infraId);
16328
- if (node.type === import_types56.NodeType.InfraNode) {
16469
+ if (node.type === import_types57.NodeType.InfraNode) {
16329
16470
  graph.replaceNodeAttributes(shape.infraId, {
16330
16471
  ...node,
16331
16472
  columns: foldColumns(
16332
16473
  node.columns,
16333
16474
  shape.fields,
16334
- import_types56.Provenance.EXTRACTED,
16335
- (0, import_types56.confidenceForExtracted)("structural")
16475
+ import_types57.Provenance.EXTRACTED,
16476
+ (0, import_types57.confidenceForExtracted)("structural")
16336
16477
  )
16337
16478
  });
16338
16479
  }
@@ -16346,15 +16487,15 @@ async function addZodShapes(graph, services) {
16346
16487
  );
16347
16488
  nodesAdded += n;
16348
16489
  edgesAdded += e;
16349
- const edgeId = (0, import_types56.extractedEdgeId)(fileNodeId, shape.infraId, import_types56.EdgeType.CONTAINS);
16490
+ const edgeId = (0, import_types57.extractedEdgeId)(fileNodeId, shape.infraId, import_types57.EdgeType.CONTAINS);
16350
16491
  if (!graph.hasEdge(edgeId)) {
16351
16492
  const edge = {
16352
16493
  id: edgeId,
16353
16494
  source: fileNodeId,
16354
16495
  target: shape.infraId,
16355
- type: import_types56.EdgeType.CONTAINS,
16356
- provenance: import_types56.Provenance.EXTRACTED,
16357
- confidence: (0, import_types56.confidenceForExtracted)("structural"),
16496
+ type: import_types57.EdgeType.CONTAINS,
16497
+ provenance: import_types57.Provenance.EXTRACTED,
16498
+ confidence: (0, import_types57.confidenceForExtracted)("structural"),
16358
16499
  evidence: shape.evidence
16359
16500
  };
16360
16501
  graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
@@ -16368,7 +16509,7 @@ async function addZodShapes(graph, services) {
16368
16509
 
16369
16510
  // src/extract/firestore-rules.ts
16370
16511
  init_cjs_shims();
16371
- var import_types57 = require("@neat.is/types");
16512
+ var import_types58 = require("@neat.is/types");
16372
16513
  var FIRESTORE_COLLECTION_KIND = "firestore-collection";
16373
16514
  var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
16374
16515
  function stripComments(src) {
@@ -16539,7 +16680,7 @@ async function addFirestoreRules(graph, services) {
16539
16680
  if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
16540
16681
  graph.forEachNode((id, attrs) => {
16541
16682
  const node = attrs;
16542
- if (node.type !== import_types57.NodeType.InfraNode) return;
16683
+ if (node.type !== import_types58.NodeType.InfraNode) return;
16543
16684
  if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
16544
16685
  const fields = guards.get(collectionKeyFromName(node.name));
16545
16686
  if (!fields || fields.size === 0) return;
@@ -16558,12 +16699,12 @@ var import_node_path70 = __toESM(require("path"), 1);
16558
16699
  init_cjs_shims();
16559
16700
  var import_node_fs34 = require("fs");
16560
16701
  var import_node_path69 = __toESM(require("path"), 1);
16561
- var import_types58 = require("@neat.is/types");
16702
+ var import_types59 = require("@neat.is/types");
16562
16703
  function dropOrphanedFileNodes(graph, source) {
16563
16704
  const orphans = [];
16564
16705
  graph.forEachNode((id, attrs) => {
16565
16706
  const node = attrs;
16566
- if (node.type !== import_types58.NodeType.FileNode) return;
16707
+ if (node.type !== import_types59.NodeType.FileNode) return;
16567
16708
  if (source && node.source !== source) return;
16568
16709
  if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
16569
16710
  orphans.push(id);
@@ -16577,7 +16718,7 @@ function outOfScope(graph, edge, source) {
16577
16718
  for (const endpoint2 of [edge.source, edge.target]) {
16578
16719
  if (!graph.hasNode(endpoint2)) continue;
16579
16720
  const node = graph.getNodeAttributes(endpoint2);
16580
- if (node.type !== import_types58.NodeType.FileNode) continue;
16721
+ if (node.type !== import_types59.NodeType.FileNode) continue;
16581
16722
  return node.source !== source;
16582
16723
  }
16583
16724
  return false;
@@ -16587,7 +16728,7 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
16587
16728
  const bases = [scanPath, ...serviceDirs];
16588
16729
  graph.forEachEdge((id, attrs) => {
16589
16730
  const edge = attrs;
16590
- if (edge.provenance !== import_types58.Provenance.EXTRACTED) return;
16731
+ if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
16591
16732
  if (outOfScope(graph, edge, source)) return;
16592
16733
  const evidenceFile = edge.evidence?.file;
16593
16734
  if (!evidenceFile) return;
@@ -16606,7 +16747,23 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = [], so
16606
16747
  // src/extract/index.ts
16607
16748
  var passQueue = Promise.resolve();
16608
16749
  function extractFromDirectory(graph, scanPath, opts = {}) {
16609
- const pass = passQueue.then(() => runExtractionPass(graph, scanPath, opts));
16750
+ invalidateSourceBaseline(graph, opts.source, "syncing");
16751
+ const pass = passQueue.then(async () => {
16752
+ const sourceGeneration = beginSourceExtraction(graph, opts.source, opts.sourceCommit);
16753
+ let result;
16754
+ try {
16755
+ result = await runExtractionPass(graph, scanPath, opts);
16756
+ return result;
16757
+ } finally {
16758
+ finishSourceExtraction(
16759
+ graph,
16760
+ sourceGeneration,
16761
+ opts.source,
16762
+ opts.sourceCommit,
16763
+ result ?? { extractionErrors: 1, skippedFiles: 0 }
16764
+ );
16765
+ }
16766
+ });
16610
16767
  passQueue = pass.catch(() => {
16611
16768
  });
16612
16769
  return pass;
@@ -16702,7 +16859,7 @@ async function runExtractionPass(graph, scanPath, opts) {
16702
16859
  init_cjs_shims();
16703
16860
  var import_node_fs35 = require("fs");
16704
16861
  var import_node_path71 = __toESM(require("path"), 1);
16705
- var import_types59 = require("@neat.is/types");
16862
+ var import_types60 = require("@neat.is/types");
16706
16863
  var SCHEMA_VERSION = 7;
16707
16864
  function migrateV1ToV2(payload) {
16708
16865
  const nodes = payload.graph.nodes;
@@ -16726,7 +16883,7 @@ function migrateV5ToV6(payload) {
16726
16883
  if (Array.isArray(nodes)) {
16727
16884
  for (const node of nodes) {
16728
16885
  const attrs = node.attributes;
16729
- if (!attrs || attrs.type !== import_types59.NodeType.InfraNode) continue;
16886
+ if (!attrs || attrs.type !== import_types60.NodeType.InfraNode) continue;
16730
16887
  if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
16731
16888
  if (!Array.isArray(attrs.columns)) attrs.columns = [];
16732
16889
  }
@@ -16742,12 +16899,12 @@ function migrateV2ToV3(payload) {
16742
16899
  for (const edge of edges) {
16743
16900
  const attrs = edge.attributes;
16744
16901
  if (!attrs || attrs.provenance !== "FRONTIER") continue;
16745
- attrs.provenance = import_types59.Provenance.OBSERVED;
16902
+ attrs.provenance = import_types60.Provenance.OBSERVED;
16746
16903
  const type = typeof attrs.type === "string" ? attrs.type : void 0;
16747
16904
  const source = typeof attrs.source === "string" ? attrs.source : void 0;
16748
16905
  const target = typeof attrs.target === "string" ? attrs.target : void 0;
16749
16906
  if (type && source && target) {
16750
- const newId = (0, import_types59.observedEdgeId)(source, target, type);
16907
+ const newId = (0, import_types60.observedEdgeId)(source, target, type);
16751
16908
  attrs.id = newId;
16752
16909
  if (edge.key) edge.key = newId;
16753
16910
  }
@@ -16902,7 +17059,7 @@ init_cjs_shims();
16902
17059
  var import_fastify2 = __toESM(require("fastify"), 1);
16903
17060
  var import_node_crypto6 = require("crypto");
16904
17061
  var import_cors = __toESM(require("@fastify/cors"), 1);
16905
- var import_types103 = require("@neat.is/types");
17062
+ var import_types104 = require("@neat.is/types");
16906
17063
 
16907
17064
  // src/extend/index.ts
16908
17065
  init_cjs_shims();
@@ -17249,39 +17406,39 @@ async function rollbackExtension(ctx, args) {
17249
17406
 
17250
17407
  // src/divergences.ts
17251
17408
  init_cjs_shims();
17252
- var import_types60 = require("@neat.is/types");
17409
+ var import_types61 = require("@neat.is/types");
17253
17410
  function bucketKey(source, target, type) {
17254
17411
  return `${type}|${source}|${target}`;
17255
17412
  }
17256
17413
  function bucketSourceFor(graph, edge) {
17257
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) return edge.source;
17258
- const parsed = (0, import_types60.parseFileId)(edge.source);
17414
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) return edge.source;
17415
+ const parsed = (0, import_types61.parseFileId)(edge.source);
17259
17416
  if (!parsed || !graph.hasNode(edge.target)) return edge.source;
17260
17417
  const target = graph.getNodeAttributes(edge.target);
17261
- if (target.type !== import_types60.NodeType.DatabaseNode) return edge.source;
17262
- return (0, import_types60.serviceId)(parsed.service);
17418
+ if (target.type !== import_types61.NodeType.DatabaseNode) return edge.source;
17419
+ return (0, import_types61.serviceId)(parsed.service);
17263
17420
  }
17264
17421
  function bucketEdges(graph) {
17265
17422
  const buckets2 = /* @__PURE__ */ new Map();
17266
17423
  graph.forEachEdge((id, attrs) => {
17267
17424
  const e = attrs;
17268
- const parsed = (0, import_types60.parseEdgeId)(id);
17425
+ const parsed = (0, import_types61.parseEdgeId)(id);
17269
17426
  const provenance = parsed?.provenance ?? e.provenance;
17270
17427
  const source = bucketSourceFor(graph, e);
17271
17428
  const key = bucketKey(source, e.target, e.type);
17272
17429
  const cur = buckets2.get(key) ?? { source, target: e.target, type: e.type };
17273
17430
  switch (provenance) {
17274
- case import_types60.Provenance.EXTRACTED:
17431
+ case import_types61.Provenance.EXTRACTED:
17275
17432
  cur.extracted = e;
17276
17433
  break;
17277
- case import_types60.Provenance.OBSERVED:
17434
+ case import_types61.Provenance.OBSERVED:
17278
17435
  cur.observed = e;
17279
17436
  break;
17280
- case import_types60.Provenance.INFERRED:
17437
+ case import_types61.Provenance.INFERRED:
17281
17438
  cur.inferred = e;
17282
17439
  break;
17283
17440
  default:
17284
- if (e.provenance === import_types60.Provenance.STALE) cur.stale = e;
17441
+ if (e.provenance === import_types61.Provenance.STALE) cur.stale = e;
17285
17442
  }
17286
17443
  buckets2.set(key, cur);
17287
17444
  });
@@ -17290,22 +17447,22 @@ function bucketEdges(graph) {
17290
17447
  function nodeIsFrontier(graph, nodeId) {
17291
17448
  if (!graph.hasNode(nodeId)) return false;
17292
17449
  const attrs = graph.getNodeAttributes(nodeId);
17293
- return attrs.type === import_types60.NodeType.FrontierNode;
17450
+ return attrs.type === import_types61.NodeType.FrontierNode;
17294
17451
  }
17295
17452
  function nodeIsWebsocketChannel(graph, nodeId) {
17296
17453
  if (!graph.hasNode(nodeId)) return false;
17297
17454
  const attrs = graph.getNodeAttributes(nodeId);
17298
- return attrs.type === import_types60.NodeType.WebSocketChannelNode;
17455
+ return attrs.type === import_types61.NodeType.WebSocketChannelNode;
17299
17456
  }
17300
17457
  function nodeIsServerAction(graph, nodeId) {
17301
17458
  if (!graph.hasNode(nodeId)) return false;
17302
17459
  const attrs = graph.getNodeAttributes(nodeId);
17303
- return attrs.type === import_types60.NodeType.ServerActionNode;
17460
+ return attrs.type === import_types61.NodeType.ServerActionNode;
17304
17461
  }
17305
17462
  function nodeIsSymbol(graph, nodeId) {
17306
17463
  if (!graph.hasNode(nodeId)) return false;
17307
17464
  const attrs = graph.getNodeAttributes(nodeId);
17308
- return attrs.type === import_types60.NodeType.SymbolNode;
17465
+ return attrs.type === import_types61.NodeType.SymbolNode;
17309
17466
  }
17310
17467
  function clampConfidence(n) {
17311
17468
  if (!Number.isFinite(n)) return 0;
@@ -17325,14 +17482,14 @@ function gradedConfidence(edge) {
17325
17482
  return clampConfidence(confidenceForEdge(edge));
17326
17483
  }
17327
17484
  var OBSERVABLE_EDGE_TYPES = /* @__PURE__ */ new Set([
17328
- import_types60.EdgeType.CALLS,
17329
- import_types60.EdgeType.CONNECTS_TO,
17330
- import_types60.EdgeType.PUBLISHES_TO,
17331
- import_types60.EdgeType.CONSUMES_FROM
17485
+ import_types61.EdgeType.CALLS,
17486
+ import_types61.EdgeType.CONNECTS_TO,
17487
+ import_types61.EdgeType.PUBLISHES_TO,
17488
+ import_types61.EdgeType.CONSUMES_FROM
17332
17489
  ]);
17333
17490
  function detectMissingDivergences(graph, bucket) {
17334
17491
  const out = [];
17335
- if (bucket.type === import_types60.EdgeType.CONTAINS) return out;
17492
+ if (bucket.type === import_types61.EdgeType.CONTAINS) return out;
17336
17493
  if (nodeIsSymbol(graph, bucket.source) || nodeIsSymbol(graph, bucket.target)) return out;
17337
17494
  if (bucket.extracted && !bucket.observed && OBSERVABLE_EDGE_TYPES.has(bucket.type)) {
17338
17495
  if (!nodeIsFrontier(graph, bucket.target) && !nodeIsServerAction(graph, bucket.target)) {
@@ -17374,7 +17531,7 @@ function declaredHostFor(svc) {
17374
17531
  function hasExtractedConfiguredBy(graph, svcId) {
17375
17532
  for (const edgeId of graph.outboundEdges(svcId)) {
17376
17533
  const e = graph.getEdgeAttributes(edgeId);
17377
- if (e.type === import_types60.EdgeType.CONFIGURED_BY && e.provenance === import_types60.Provenance.EXTRACTED) {
17534
+ if (e.type === import_types61.EdgeType.CONFIGURED_BY && e.provenance === import_types61.Provenance.EXTRACTED) {
17378
17535
  return true;
17379
17536
  }
17380
17537
  }
@@ -17387,10 +17544,10 @@ function detectHostMismatch(graph, svcId, svc) {
17387
17544
  const out = [];
17388
17545
  for (const edgeId of graph.outboundEdges(svcId)) {
17389
17546
  const edge = graph.getEdgeAttributes(edgeId);
17390
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) continue;
17391
- if (edge.provenance !== import_types60.Provenance.OBSERVED) continue;
17547
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17548
+ if (edge.provenance !== import_types61.Provenance.OBSERVED) continue;
17392
17549
  const target = graph.getNodeAttributes(edge.target);
17393
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17550
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
17394
17551
  const observedHost = target.host?.trim();
17395
17552
  if (!observedHost) continue;
17396
17553
  if (observedHost === declaredHost) continue;
@@ -17412,10 +17569,10 @@ function detectCompatDivergences(graph, svcId, svc) {
17412
17569
  const deps = svc.dependencies ?? {};
17413
17570
  for (const edgeId of graph.outboundEdges(svcId)) {
17414
17571
  const edge = graph.getEdgeAttributes(edgeId);
17415
- if (edge.type !== import_types60.EdgeType.CONNECTS_TO) continue;
17416
- if (edge.provenance !== import_types60.Provenance.OBSERVED) continue;
17572
+ if (edge.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17573
+ if (edge.provenance !== import_types61.Provenance.OBSERVED) continue;
17417
17574
  const target = graph.getNodeAttributes(edge.target);
17418
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17575
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
17419
17576
  for (const pair of compatPairs()) {
17420
17577
  if (pair.engine !== target.engine) continue;
17421
17578
  const declared = deps[pair.driver];
@@ -17578,11 +17735,11 @@ function symbolLocus(graph, ev) {
17578
17735
  const location = filepath ? `${filepath}${lineno !== void 0 ? `:${lineno}` : ""}` : void 0;
17579
17736
  const affected = ev.affectedNode;
17580
17737
  const affectedInGraph = affected.length > 0 && graph.hasNode(affected);
17581
- const affectedIsCode = affectedInGraph && ((0, import_types60.parseSymbolId)(affected) !== null || (0, import_types60.parseFileId)(affected) !== null);
17738
+ const affectedIsCode = affectedInGraph && ((0, import_types61.parseSymbolId)(affected) !== null || (0, import_types61.parseFileId)(affected) !== null);
17582
17739
  if (affectedIsCode) return { node: affected, ...location ? { location } : {} };
17583
17740
  if (!location) return null;
17584
17741
  if (affectedInGraph) return { node: affected, location };
17585
- const svc = (0, import_types60.serviceId)(ev.service);
17742
+ const svc = (0, import_types61.serviceId)(ev.service);
17586
17743
  if (graph.hasNode(svc)) return { node: svc, location };
17587
17744
  return null;
17588
17745
  }
@@ -17625,7 +17782,7 @@ function detectSymbolMismatches(graph, incidents) {
17625
17782
  mismatchKind: g.kind,
17626
17783
  ...g.symbol ? { symbol: g.symbol } : {},
17627
17784
  ...g.location ? { location: g.location } : {},
17628
- provenance: import_types60.Provenance.INFERRED,
17785
+ provenance: import_types61.Provenance.INFERRED,
17629
17786
  incidentId: g.latest.id,
17630
17787
  errorMessage: g.latest.errorMessage,
17631
17788
  incidentCount: g.count,
@@ -17642,7 +17799,7 @@ var OBSERVED_FAILING_CONFIDENCE = 0.6;
17642
17799
  function detectObservedFailingEdge(graph, bucket) {
17643
17800
  if (!bucket.extracted || !bucket.observed) return [];
17644
17801
  if (!OBSERVABLE_EDGE_TYPES.has(bucket.type)) return [];
17645
- if (bucket.observed.provenance !== import_types60.Provenance.OBSERVED) return [];
17802
+ if (bucket.observed.provenance !== import_types61.Provenance.OBSERVED) return [];
17646
17803
  const signal = bucket.observed.signal;
17647
17804
  if (!signal) return [];
17648
17805
  const { spanCount, errorCount } = signal;
@@ -17656,7 +17813,7 @@ function detectObservedFailingEdge(graph, bucket) {
17656
17813
  source: bucket.source,
17657
17814
  target: bucket.target,
17658
17815
  failureKind: "error-rate",
17659
- provenance: import_types60.Provenance.INFERRED,
17816
+ provenance: import_types61.Provenance.INFERRED,
17660
17817
  edgeType: bucket.type,
17661
17818
  observed: bucket.observed,
17662
17819
  spanCount,
@@ -17761,7 +17918,7 @@ function detectObservedFailingIncidents(graph, incidents) {
17761
17918
  source: g.node,
17762
17919
  target: g.node,
17763
17920
  failureKind: g.kind,
17764
- provenance: import_types60.Provenance.INFERRED,
17921
+ provenance: import_types61.Provenance.INFERRED,
17765
17922
  ...g.location ? { location: g.location } : {},
17766
17923
  incidentId: g.latest.id,
17767
17924
  errorMessage: g.latest.errorMessage,
@@ -17780,24 +17937,24 @@ function involvesNode(d, nodeId) {
17780
17937
  function datastoreEverObserved(graph, nodeId) {
17781
17938
  if (!graph.hasNode(nodeId)) return false;
17782
17939
  const n = graph.getNodeAttributes(nodeId);
17783
- if (n.type === import_types60.NodeType.DatabaseNode) {
17940
+ if (n.type === import_types61.NodeType.DatabaseNode) {
17784
17941
  const via = n.discoveredVia;
17785
17942
  if (via === "otel" || via === "merged") return true;
17786
17943
  }
17787
17944
  for (const edgeId of graph.inboundEdges(nodeId)) {
17788
17945
  const e = graph.getEdgeAttributes(edgeId);
17789
- if (e.provenance === import_types60.Provenance.OBSERVED || e.provenance === import_types60.Provenance.STALE) return true;
17946
+ if (e.provenance === import_types61.Provenance.OBSERVED || e.provenance === import_types61.Provenance.STALE) return true;
17790
17947
  }
17791
17948
  return false;
17792
17949
  }
17793
17950
  function serviceHasObservedSameEngineStore(graph, buckets2, serviceId17, engine, excludeTarget) {
17794
17951
  for (const bucket of buckets2.values()) {
17795
- if (bucket.type !== import_types60.EdgeType.CONNECTS_TO) continue;
17952
+ if (bucket.type !== import_types61.EdgeType.CONNECTS_TO) continue;
17796
17953
  if (bucket.source !== serviceId17) continue;
17797
17954
  if (bucket.target === excludeTarget) continue;
17798
17955
  if (!graph.hasNode(bucket.target)) continue;
17799
17956
  const target = graph.getNodeAttributes(bucket.target);
17800
- if (target.type !== import_types60.NodeType.DatabaseNode) continue;
17957
+ if (target.type !== import_types61.NodeType.DatabaseNode) continue;
17801
17958
  if (target.engine !== engine) continue;
17802
17959
  if (bucket.observed || datastoreEverObserved(graph, bucket.target)) return true;
17803
17960
  }
@@ -17807,10 +17964,10 @@ var DEAD_CODE_PROBE_CONFIDENCE = 0.1;
17807
17964
  function dampenDeadCodeProbes(graph, buckets2, all) {
17808
17965
  return all.map((d) => {
17809
17966
  if (d.type !== "missing-observed") return d;
17810
- if (!d.extracted || d.edgeType !== import_types60.EdgeType.CONNECTS_TO) return d;
17967
+ if (!d.extracted || d.edgeType !== import_types61.EdgeType.CONNECTS_TO) return d;
17811
17968
  if (!graph.hasNode(d.target)) return d;
17812
17969
  const target = graph.getNodeAttributes(d.target);
17813
- if (target.type !== import_types60.NodeType.DatabaseNode) return d;
17970
+ if (target.type !== import_types61.NodeType.DatabaseNode) return d;
17814
17971
  if (d.extracted.evidence?.hostSource !== "literal") return d;
17815
17972
  if (datastoreEverObserved(graph, d.target)) return d;
17816
17973
  const engine = target.engine;
@@ -17830,7 +17987,7 @@ function suppressHostMismatchHalves(all) {
17830
17987
  for (const d of all) {
17831
17988
  if (d.type !== "host-mismatch") continue;
17832
17989
  observedHalf.add(`${d.source}->${d.target}`);
17833
- declaredHalf.add((0, import_types60.databaseId)(d.extractedHost));
17990
+ declaredHalf.add((0, import_types61.databaseId)(d.extractedHost));
17834
17991
  }
17835
17992
  if (observedHalf.size === 0) return all;
17836
17993
  return all.filter((d) => {
@@ -17850,14 +18007,14 @@ function computeDivergences(graph, opts = {}) {
17850
18007
  }
17851
18008
  graph.forEachNode((nodeId, attrs) => {
17852
18009
  const n = attrs;
17853
- if (n.type === import_types60.NodeType.ServiceNode) {
18010
+ if (n.type === import_types61.NodeType.ServiceNode) {
17854
18011
  const svc = n;
17855
18012
  for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
17856
18013
  for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
17857
18014
  for (const d of detectDeployDivergence(svc)) all.push(d);
17858
18015
  return;
17859
18016
  }
17860
- if (n.type === import_types60.NodeType.InfraNode && n.kind === "sql-table") {
18017
+ if (n.type === import_types61.NodeType.InfraNode && n.kind === "sql-table") {
17861
18018
  for (const d of detectColumnDrift(n)) all.push(d);
17862
18019
  }
17863
18020
  });
@@ -17922,7 +18079,7 @@ function computeDivergences(graph, opts = {}) {
17922
18079
  const bloc = "location" in b && b.location ? b.location : "";
17923
18080
  return aloc.localeCompare(bloc);
17924
18081
  });
17925
- return import_types60.DivergenceResultSchema.parse({
18082
+ return import_types61.DivergenceResultSchema.parse({
17926
18083
  divergences: filtered,
17927
18084
  totalAffected: filtered.length,
17928
18085
  computedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -17976,10 +18133,40 @@ function queryLogEntries(opts) {
17976
18133
 
17977
18134
  // src/goodybag.ts
17978
18135
  init_cjs_shims();
17979
- var import_types61 = require("@neat.is/types");
18136
+ var import_types62 = require("@neat.is/types");
17980
18137
  var CODE_FILEPATH_ATTR2 = "code.filepath";
17981
18138
  var CODE_LINENO_ATTR2 = "code.lineno";
17982
18139
  var BLAST_NEAREST_LIMIT = 5;
18140
+ function deployContextOf(ev) {
18141
+ const a = ev.attributes;
18142
+ if (!a) return void 0;
18143
+ const str = (k) => typeof a[k] === "string" ? a[k] : void 0;
18144
+ const int = (k) => typeof a[k] === "number" && Number.isFinite(a[k]) ? Math.trunc(a[k]) : void 0;
18145
+ const strs = (k) => {
18146
+ const v = a[k];
18147
+ return Array.isArray(v) && v.every((x) => typeof x === "string") && v.length > 0 ? v : void 0;
18148
+ };
18149
+ const ctx = {};
18150
+ const fault = str("k8s.fault");
18151
+ if (fault) ctx.fault = fault;
18152
+ const waiting = str("k8s.waitingReason");
18153
+ if (waiting) ctx.waitingReason = waiting;
18154
+ const image = str("k8s.image");
18155
+ if (image) ctx.image = image;
18156
+ const restarts = int("k8s.restartCount");
18157
+ if (restarts !== void 0) ctx.restartCount = restarts;
18158
+ const termReason = str("k8s.terminatedReason");
18159
+ if (termReason) ctx.terminatedReason = termReason;
18160
+ const exitCode = int("k8s.exitCode");
18161
+ if (exitCode !== void 0) ctx.exitCode = exitCode;
18162
+ const env = strs("k8s.containerEnv");
18163
+ if (env) ctx.containerEnv = env;
18164
+ const args = strs("k8s.containerArgs");
18165
+ if (args) ctx.containerArgs = args;
18166
+ const log = str("k8s.processLog");
18167
+ if (log) ctx.processLog = log;
18168
+ return Object.keys(ctx).length > 0 ? ctx : void 0;
18169
+ }
17983
18170
  function grainOf2(graph, nodeId) {
17984
18171
  if (graph.hasNode(nodeId)) {
17985
18172
  const t = graph.getNodeAttributes(nodeId).type;
@@ -18002,7 +18189,7 @@ function locusOf(graph, ev) {
18002
18189
  ...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
18003
18190
  ...symbol ? { symbol } : {},
18004
18191
  service: node?.service ?? ev.service,
18005
- provenance: import_types61.Provenance.OBSERVED
18192
+ provenance: import_types62.Provenance.OBSERVED
18006
18193
  };
18007
18194
  }
18008
18195
  function locusFromNode(graph, nodeId) {
@@ -18018,7 +18205,7 @@ function locusFromNode(graph, nodeId) {
18018
18205
  ...typeof end === "number" ? { lineEnd: end } : {},
18019
18206
  ...n.qualname ? { symbol: shortLabel(graph, nodeId) } : {},
18020
18207
  ...n.service ? { service: n.service } : {},
18021
- provenance: import_types61.Provenance.INFERRED
18208
+ provenance: import_types62.Provenance.INFERRED
18022
18209
  };
18023
18210
  }
18024
18211
  function promoteCauseLocus(graph, causeNode, incidents) {
@@ -18027,11 +18214,16 @@ function promoteCauseLocus(graph, causeNode, incidents) {
18027
18214
  );
18028
18215
  if (native) {
18029
18216
  const l = locusOf(graph, native);
18030
- if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types61.Provenance.INFERRED };
18217
+ if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types62.Provenance.INFERRED };
18031
18218
  }
18032
18219
  return locusFromNode(graph, causeNode);
18033
18220
  }
18034
18221
  function divergenceSummary(d) {
18222
+ if (d.type === "observed-symbol-mismatch" || d.source === d.target) {
18223
+ const symbol = "symbol" in d && d.symbol ? d.symbol : d.source;
18224
+ const at = "location" in d && d.location ? ` at ${d.location}` : "";
18225
+ return `${symbol}${at}`;
18226
+ }
18035
18227
  const column = "column" in d && d.column ? `.${d.column}` : "";
18036
18228
  const label = "table" in d && d.table ? `${d.table}${column}` : `${d.source} \u2192 ${d.target}`;
18037
18229
  return label;
@@ -18076,7 +18268,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18076
18268
  const chain = (rc.traversalPath ?? []).map((node, i) => ({
18077
18269
  node,
18078
18270
  grain: grainOf2(graph, node),
18079
- provenance: provs[i] ?? provs[provs.length - 1] ?? import_types61.Provenance.INFERRED
18271
+ provenance: provs[i] ?? provs[provs.length - 1] ?? import_types62.Provenance.INFERRED
18080
18272
  }));
18081
18273
  rootCause = {
18082
18274
  node: rc.rootCauseNode,
@@ -18107,7 +18299,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18107
18299
  kind: "incident",
18108
18300
  id: errorEvent.id,
18109
18301
  at: errorEvent.timestamp,
18110
- incidentKind: (0, import_types61.incidentKindOf)(errorEvent),
18302
+ incidentKind: (0, import_types62.incidentKindOf)(errorEvent),
18111
18303
  service: errorEvent.service,
18112
18304
  affectedNode: affected,
18113
18305
  message: errorEvent.errorMessage,
@@ -18122,10 +18314,14 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
18122
18314
  ...nearest.length > 0 ? { blastRadius: { totalAffected: blast.totalAffected, nearest } } : {},
18123
18315
  ...policyCards.length > 0 ? { policies: policyCards } : {},
18124
18316
  ...divergences.length > 0 ? { divergence: divergences } : {},
18317
+ ...(() => {
18318
+ const dc = deployContextOf(errorEvent);
18319
+ return dc ? { deployContext: dc } : {};
18320
+ })(),
18125
18321
  headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
18126
18322
  };
18127
18323
  card.grade = gradeIncidentCard(card);
18128
- return import_types61.IncidentCardSchema.parse(card);
18324
+ return import_types62.IncidentCardSchema.parse(card);
18129
18325
  }
18130
18326
  var GRADE_PRIORS_VERSION = "sniper-architecture-priors-2026-10-08";
18131
18327
  var GRADE_WEIGHTS = {
@@ -18232,7 +18428,7 @@ function gradeIncidentCard(card) {
18232
18428
 
18233
18429
  // src/ask.ts
18234
18430
  init_cjs_shims();
18235
- var import_types62 = require("@neat.is/types");
18431
+ var import_types63 = require("@neat.is/types");
18236
18432
  var DEFAULT_MAX_NODES = 3;
18237
18433
  var MAX_FACTS_PER_SECTION = 6;
18238
18434
  var INTENT_RULES = [
@@ -18468,14 +18664,23 @@ function idBody(id) {
18468
18664
  return colon >= 0 ? id.slice(colon + 1) : id;
18469
18665
  }
18470
18666
  var TYPE_NOUNS = [
18471
- { nouns: ["database", "db", "table"], type: import_types62.NodeType.DatabaseNode },
18472
- { nouns: ["service", "api", "backend"], type: import_types62.NodeType.ServiceNode },
18473
- { nouns: ["route", "endpoint"], type: import_types62.NodeType.RouteNode },
18474
- { nouns: ["file"], type: import_types62.NodeType.FileNode },
18475
- { nouns: ["config"], type: import_types62.NodeType.ConfigNode }
18667
+ { nouns: ["database", "db", "table"], type: import_types63.NodeType.DatabaseNode },
18668
+ { nouns: ["service", "api", "backend"], type: import_types63.NodeType.ServiceNode },
18669
+ { nouns: ["route", "endpoint"], type: import_types63.NodeType.RouteNode },
18670
+ { nouns: ["file"], type: import_types63.NodeType.FileNode },
18671
+ { nouns: ["config"], type: import_types63.NodeType.ConfigNode }
18476
18672
  ];
18477
18673
  var EMBED_MIN_SCORE = 0.35;
18478
18674
  async function resolveEntities(graph, question, searchIndex, maxNodes) {
18675
+ const verbatim = [];
18676
+ for (const word of question.split(/\s+/)) {
18677
+ const id = word.replace(/^["'`(<]+|["'`)>?!.,;]+$/g, "");
18678
+ if (!id || !graph.hasNode(id) || verbatim.some((m) => m.nodeId === id)) continue;
18679
+ const node = graph.getNodeAttributes(id);
18680
+ if (node.type === import_types63.NodeType.FrontierNode) continue;
18681
+ verbatim.push({ nodeId: id, label: nodeName(node), via: "id", score: 1 });
18682
+ }
18683
+ if (verbatim.length > 0) return { matched: verbatim.slice(0, maxNodes) };
18479
18684
  const qTokens = queryTokens(question);
18480
18685
  const normalized = question.toLowerCase();
18481
18686
  const best = /* @__PURE__ */ new Map();
@@ -18486,7 +18691,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18486
18691
  };
18487
18692
  graph.forEachNode((id, attrs) => {
18488
18693
  const node = attrs;
18489
- if (node.type === import_types62.NodeType.FrontierNode) return;
18694
+ if (node.type === import_types63.NodeType.FrontierNode) return;
18490
18695
  const name = nodeName(node);
18491
18696
  const body = idBody(id);
18492
18697
  const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
@@ -18505,7 +18710,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
18505
18710
  const res = await searchIndex.search(question, 10);
18506
18711
  if (res.provider !== "substring") {
18507
18712
  for (const m of res.matches) {
18508
- if (m.node.type === import_types62.NodeType.FrontierNode) continue;
18713
+ if (m.node.type === import_types63.NodeType.FrontierNode) continue;
18509
18714
  if (!graph.hasNode(m.node.id)) continue;
18510
18715
  const already = best.get(m.node.id);
18511
18716
  if (!already && m.score < EMBED_MIN_SCORE) continue;
@@ -18565,7 +18770,7 @@ function edgeSignalNote(e) {
18565
18770
  function buildRootCauseSection(graph, node, incidents, now) {
18566
18771
  const result = getRootCause(graph, node, void 0, incidents, { now });
18567
18772
  if (!result) return null;
18568
- const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types62.Provenance.OBSERVED;
18773
+ const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types63.Provenance.OBSERVED;
18569
18774
  const facts = [
18570
18775
  {
18571
18776
  text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
@@ -18615,7 +18820,7 @@ function buildObservedSection(graph, node) {
18615
18820
  if (result.observed && result.inboundObservedCount > 0) {
18616
18821
  facts.push({
18617
18822
  text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
18618
- provenance: import_types62.Provenance.OBSERVED
18823
+ provenance: import_types63.Provenance.OBSERVED
18619
18824
  });
18620
18825
  } else {
18621
18826
  return null;
@@ -18638,10 +18843,10 @@ function buildBlastSection(graph, node) {
18638
18843
  }
18639
18844
  function buildDatabaseCallersSection(graph, node) {
18640
18845
  const callers = getBlastRadius(graph, node).affectedNodes.filter((item) => {
18641
- if (graph.getNodeAttributes(item.nodeId).type !== import_types62.NodeType.ServiceNode) return false;
18846
+ if (graph.getNodeAttributes(item.nodeId).type !== import_types63.NodeType.ServiceNode) return false;
18642
18847
  return item.path.slice(1, -1).every((id) => {
18643
18848
  const type = graph.getNodeAttributes(id).type;
18644
- return type === import_types62.NodeType.FileNode || type === import_types62.NodeType.SymbolNode;
18849
+ return type === import_types63.NodeType.FileNode || type === import_types63.NodeType.SymbolNode;
18645
18850
  });
18646
18851
  });
18647
18852
  return {
@@ -18660,7 +18865,7 @@ function buildIncidentsSection(node, incidents) {
18660
18865
  const facts = ordered.map((ev) => ({
18661
18866
  text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
18662
18867
  // ErrorEvents are observation records — OBSERVED by definition.
18663
- provenance: import_types62.Provenance.OBSERVED
18868
+ provenance: import_types63.Provenance.OBSERVED
18664
18869
  }));
18665
18870
  return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
18666
18871
  }
@@ -18683,8 +18888,8 @@ function runtimeEdgeState(graph) {
18683
18888
  let observed = false;
18684
18889
  let stale = false;
18685
18890
  graph.forEachEdge((_id, attrs) => {
18686
- if (attrs.provenance === import_types62.Provenance.OBSERVED) observed = true;
18687
- if (attrs.provenance === import_types62.Provenance.STALE) stale = true;
18891
+ if (attrs.provenance === import_types63.Provenance.OBSERVED) observed = true;
18892
+ if (attrs.provenance === import_types63.Provenance.STALE) stale = true;
18688
18893
  });
18689
18894
  return { observed, stale };
18690
18895
  }
@@ -18752,7 +18957,7 @@ function buildGlobalIncidentsSection(incidents) {
18752
18957
  }
18753
18958
  const byKey = /* @__PURE__ */ new Map();
18754
18959
  for (const ev of incidents) {
18755
- const key = ev.affectedNode || (0, import_types62.serviceId)(ev.service);
18960
+ const key = ev.affectedNode || (0, import_types63.serviceId)(ev.service);
18756
18961
  const cur = byKey.get(key);
18757
18962
  if (!cur) {
18758
18963
  byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
@@ -18767,7 +18972,7 @@ function buildGlobalIncidentsSection(incidents) {
18767
18972
  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);
18768
18973
  const facts = rows.map((r) => ({
18769
18974
  text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
18770
- provenance: import_types62.Provenance.OBSERVED
18975
+ provenance: import_types63.Provenance.OBSERVED
18771
18976
  }));
18772
18977
  return {
18773
18978
  heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
@@ -18780,7 +18985,7 @@ function buildOverviewSections(graph, incidents) {
18780
18985
  graph.forEachNode((_id, attrs) => {
18781
18986
  const node = attrs;
18782
18987
  nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
18783
- if (node.type === import_types62.NodeType.ServiceNode) services.push(node.id);
18988
+ if (node.type === import_types63.NodeType.ServiceNode) services.push(node.id);
18784
18989
  });
18785
18990
  const edgeByProv = /* @__PURE__ */ new Map();
18786
18991
  graph.forEachEdge((_id, attrs) => {
@@ -18792,10 +18997,10 @@ function buildOverviewSections(graph, incidents) {
18792
18997
  const shapeFacts = [
18793
18998
  { text: `${graph.order} nodes, ${graph.size} edges` },
18794
18999
  {
18795
- text: `${count(import_types62.NodeType.ServiceNode)} services, ${count(import_types62.NodeType.FileNode)} files, ${count(import_types62.NodeType.SymbolNode)} symbols, ${count(import_types62.NodeType.DatabaseNode)} databases`
19000
+ text: `${count(import_types63.NodeType.ServiceNode)} services, ${count(import_types63.NodeType.FileNode)} files, ${count(import_types63.NodeType.SymbolNode)} symbols, ${count(import_types63.NodeType.DatabaseNode)} databases`
18796
19001
  }
18797
19002
  ];
18798
- for (const p of [import_types62.Provenance.EXTRACTED, import_types62.Provenance.OBSERVED, import_types62.Provenance.INFERRED, import_types62.Provenance.STALE]) {
19003
+ for (const p of [import_types63.Provenance.EXTRACTED, import_types63.Provenance.OBSERVED, import_types63.Provenance.INFERRED, import_types63.Provenance.STALE]) {
18799
19004
  const n = edgeByProv.get(p) ?? 0;
18800
19005
  if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
18801
19006
  }
@@ -18812,7 +19017,7 @@ function buildOverviewSections(graph, incidents) {
18812
19017
  if (incidents && incidents.length > 0) {
18813
19018
  const incCount = /* @__PURE__ */ new Map();
18814
19019
  for (const ev of incidents) {
18815
- const key = ev.affectedNode || (0, import_types62.serviceId)(ev.service);
19020
+ const key = ev.affectedNode || (0, import_types63.serviceId)(ev.service);
18816
19021
  incCount.set(key, (incCount.get(key) ?? 0) + 1);
18817
19022
  }
18818
19023
  const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
@@ -18820,7 +19025,7 @@ function buildOverviewSections(graph, incidents) {
18820
19025
  heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
18821
19026
  facts: top.map(([k, n]) => ({
18822
19027
  text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
18823
- provenance: import_types62.Provenance.OBSERVED
19028
+ provenance: import_types63.Provenance.OBSERVED
18824
19029
  }))
18825
19030
  });
18826
19031
  }
@@ -18951,7 +19156,7 @@ async function askGraph(graph, question, opts = {}) {
18951
19156
  let scope;
18952
19157
  if (primary) {
18953
19158
  scope = "node";
18954
- const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types62.NodeType.DatabaseNode && /\b(?:which|what)\s+services?\s+(?:talks?\s+to|connects?\s+to|uses?|hits?|calls?|reads?\s+from|writes?\s+to)\b/i.test(question);
19159
+ const callersQuestion = intent === "dependencies" && graph.getNodeAttributes(primary).type === import_types63.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);
18955
19160
  if (callersQuestion) sections.push(buildDatabaseCallersSection(graph, primary));
18956
19161
  for (const kind of SECTION_ORDER[intent]) {
18957
19162
  if (callersQuestion && kind === "blast") continue;
@@ -18969,7 +19174,7 @@ async function askGraph(graph, question, opts = {}) {
18969
19174
  const provSet = /* @__PURE__ */ new Set();
18970
19175
  for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
18971
19176
  const confidence = sections[0]?.facts[0]?.confidence;
18972
- return import_types62.AskResultSchema.parse({
19177
+ return import_types63.AskResultSchema.parse({
18973
19178
  question,
18974
19179
  intent,
18975
19180
  matched,
@@ -19116,7 +19321,7 @@ init_cjs_shims();
19116
19321
  var import_node_fs39 = require("fs");
19117
19322
  var import_node_os3 = __toESM(require("os"), 1);
19118
19323
  var import_node_path75 = __toESM(require("path"), 1);
19119
- var import_types63 = require("@neat.is/types");
19324
+ var import_types64 = require("@neat.is/types");
19120
19325
  var LOCK_TIMEOUT_MS = 5e3;
19121
19326
  var LOCK_RETRY_MS = 50;
19122
19327
  function neatHome() {
@@ -19342,10 +19547,10 @@ async function readRegistry() {
19342
19547
  throw err;
19343
19548
  }
19344
19549
  const parsed = JSON.parse(raw);
19345
- return import_types63.RegistryFileSchema.parse(parsed);
19550
+ return import_types64.RegistryFileSchema.parse(parsed);
19346
19551
  }
19347
19552
  async function writeRegistry(reg) {
19348
- const validated = import_types63.RegistryFileSchema.parse(reg);
19553
+ const validated = import_types64.RegistryFileSchema.parse(reg);
19349
19554
  await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
19350
19555
  }
19351
19556
  var RegistryError = class extends Error {
@@ -19494,11 +19699,11 @@ async function pruneRegistry(opts = {}) {
19494
19699
  init_cjs_shims();
19495
19700
  var import_node_fs40 = require("fs");
19496
19701
  var import_zod = require("zod");
19497
- var import_types64 = require("@neat.is/types");
19702
+ var import_types65 = require("@neat.is/types");
19498
19703
  var SSE_HEARTBEAT_MS = 3e4;
19499
19704
  var SSE_BACKPRESSURE_CAP = 1e3;
19500
19705
  var INCIDENT_TRIGGER_STREAM_SCOPE = "incident-only-v1";
19501
- var IncidentTriggerSchema = import_types64.IncidentEventPayloadSchema.extend({
19706
+ var IncidentTriggerSchema = import_types65.IncidentEventPayloadSchema.extend({
19502
19707
  incidentId: import_zod.z.string().regex(/^[A-Za-z0-9:_-]{1,100}$/),
19503
19708
  affectedNode: import_zod.z.string().min(1).max(512),
19504
19709
  service: import_zod.z.string().min(1).max(256),
@@ -19526,12 +19731,12 @@ function loadIncidentReplay(errorsPath, cursor) {
19526
19731
  if (!isExtractionFailure(row)) throw new Error("incident replay unavailable");
19527
19732
  continue;
19528
19733
  }
19529
- const event = import_types64.ErrorEventSchema.parse(row);
19734
+ const event = import_types65.ErrorEventSchema.parse(row);
19530
19735
  const trigger = IncidentTriggerSchema.parse({
19531
19736
  incidentId: event.id,
19532
19737
  affectedNode: event.affectedNode,
19533
19738
  service: event.service,
19534
- incidentKind: (0, import_types64.incidentKindOf)(event),
19739
+ incidentKind: (0, import_types65.incidentKindOf)(event),
19535
19740
  at: event.timestamp
19536
19741
  });
19537
19742
  const prior = seen.get(trigger.incidentId), encoded = JSON.stringify(trigger);
@@ -19906,7 +20111,7 @@ function renderVerdict({
19906
20111
  }
19907
20112
 
19908
20113
  // src/pr-verdict.ts
19909
- var import_types65 = require("@neat.is/types");
20114
+ var import_types66 = require("@neat.is/types");
19910
20115
 
19911
20116
  // src/connectors/hosted-repos.ts
19912
20117
  init_cjs_shims();
@@ -19967,6 +20172,7 @@ var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
19967
20172
  });
19968
20173
  try {
19969
20174
  await Promise.race([clone, timeout]);
20175
+ return await git.resolveRef({ fs: fs43, dir: destDir, ref: "HEAD" });
19970
20176
  } finally {
19971
20177
  if (timer) clearTimeout(timer);
19972
20178
  }
@@ -20018,6 +20224,19 @@ function scrubCloneToken(s) {
20018
20224
  function needsSync(r) {
20019
20225
  return r.syncStatus === void 0 || r.syncStatus === "syncing";
20020
20226
  }
20227
+ function validRepoRow(row) {
20228
+ if (!row || typeof row !== "object") return false;
20229
+ const r = row;
20230
+ if (typeof r.owner !== "string" || typeof r.name !== "string" || typeof r.cloneUrl !== "string") return false;
20231
+ if (!/^[A-Za-z0-9_.-]+$/.test(r.owner) || !/^[A-Za-z0-9_.-]+$/.test(r.name)) return false;
20232
+ if (r.syncStatus !== void 0 && !["syncing", "synced", "failed"].includes(r.syncStatus)) return false;
20233
+ try {
20234
+ const url = new URL(r.cloneUrl);
20235
+ return url.protocol === "https:" && url.hostname === "github.com" && !url.port && !url.search && !url.hash && url.pathname === `/${r.owner}/${r.name}.git`;
20236
+ } catch {
20237
+ return false;
20238
+ }
20239
+ }
20021
20240
  async function syncOneRepo(r, input) {
20022
20241
  const { deps, graph } = input;
20023
20242
  const cloneRepo = input.cloneRepo ?? defaultCloneRepo;
@@ -20026,20 +20245,30 @@ async function syncOneRepo(r, input) {
20026
20245
  const tmpRoot = input.tmpRoot ?? import_node_os4.default.tmpdir();
20027
20246
  let dir;
20028
20247
  try {
20248
+ invalidateSourceBaseline(graph, label, "syncing");
20029
20249
  dir = await (0, import_promises.mkdtemp)(import_node_path76.default.join(tmpRoot, "neat-repo-"));
20030
20250
  await cpPostStatus(deps, r.owner, r.name, { syncStatus: "syncing", detail: "cloning" }).catch(() => {
20031
20251
  });
20032
- await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
20033
- const extracted = await extract(graph, dir, { source: label });
20252
+ const sha = await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
20253
+ const extracted = await extract(graph, dir, {
20254
+ source: label,
20255
+ ...typeof sha === "string" ? { sourceCommit: { repository: label, sha } } : {}
20256
+ });
20257
+ input.onExtracted?.(label);
20258
+ const errors = extracted?.extractionErrors ?? 0;
20259
+ const skipped = extracted?.skippedFiles ?? 0;
20260
+ const incomplete = errors > 0 || skipped > 0;
20261
+ if (incomplete) invalidateSourceBaseline(graph, label);
20034
20262
  const nodes = extracted?.nodesAdded ?? 0;
20035
20263
  const edges = extracted?.edgesAdded ?? 0;
20036
20264
  await cpPostStatus(deps, r.owner, r.name, {
20037
20265
  syncStatus: "synced",
20038
- detail: `extracted ${nodes} node${nodes === 1 ? "" : "s"}, ${edges} edge${edges === 1 ? "" : "s"}`,
20266
+ detail: `extracted ${nodes} node${nodes === 1 ? "" : "s"}, ${edges} edge${edges === 1 ? "" : "s"}` + (incomplete ? ` (incomplete: ${errors} errors, ${skipped} skipped files)` : ""),
20039
20267
  lastSyncAt: new Date(input.now?.() ?? Date.now()).toISOString()
20040
20268
  });
20041
20269
  return true;
20042
20270
  } catch (err) {
20271
+ invalidateSourceBaseline(graph, label);
20043
20272
  input.onError?.(label, err);
20044
20273
  await cpPostStatus(deps, r.owner, r.name, {
20045
20274
  syncStatus: "failed",
@@ -20058,13 +20287,30 @@ async function runRepoSyncPassCounted(input) {
20058
20287
  try {
20059
20288
  repos = await cpGet(`/internal/projects/${input.deps.projectId}/repos`, input.deps);
20060
20289
  } catch (err) {
20290
+ invalidateSourceBaseline(input.graph);
20061
20291
  input.onSkip?.("(all)", `control plane repo list unreadable \u2014 ${err.message}`);
20062
20292
  return counts;
20063
20293
  }
20064
- if (!Array.isArray(repos)) return counts;
20294
+ if (!Array.isArray(repos)) {
20295
+ invalidateSourceBaseline(input.graph);
20296
+ return counts;
20297
+ }
20065
20298
  counts.listed = true;
20066
- for (const r of repos) {
20067
- if (!input.forceResync && !needsSync(r)) continue;
20299
+ const validRepos = repos.filter(validRepoRow);
20300
+ const invalidCount = repos.length - validRepos.length;
20301
+ if (invalidCount) {
20302
+ counts.failed += invalidCount;
20303
+ for (let index = 0; index < invalidCount; index++) {
20304
+ input.onSkip?.("(invalid)", "control plane repo row invalid");
20305
+ }
20306
+ }
20307
+ retainSourceBaselines(input.graph, validRepos.map((r) => `${r.owner}/${r.name}`));
20308
+ for (const r of validRepos) {
20309
+ if (r.syncStatus === "failed") invalidateSourceBaseline(input.graph, `${r.owner}/${r.name}`);
20310
+ }
20311
+ for (const r of validRepos) {
20312
+ const forced = typeof input.forceResync === "function" ? input.forceResync(`${r.owner}/${r.name}`) : input.forceResync === true;
20313
+ if (!forced && !needsSync(r)) continue;
20068
20314
  if (await syncOneRepo(r, input)) counts.synced++;
20069
20315
  else counts.failed++;
20070
20316
  }
@@ -20077,14 +20323,20 @@ async function startRepoSync(input) {
20077
20323
  let inFlight = null;
20078
20324
  let again = false;
20079
20325
  let lastPass;
20080
- let bootResyncDone = false;
20326
+ const bootExtracted = /* @__PURE__ */ new Set();
20081
20327
  const run = async () => {
20082
20328
  try {
20083
20329
  do {
20084
20330
  again = false;
20085
20331
  const startedAt = new Date(now()).toISOString();
20086
- const counts = await runRepoSyncPassCounted({ ...input, forceResync: !bootResyncDone });
20087
- if (counts.listed) bootResyncDone = true;
20332
+ const counts = await runRepoSyncPassCounted({
20333
+ ...input,
20334
+ forceResync: (repo) => !bootExtracted.has(repo),
20335
+ onExtracted: (repo) => {
20336
+ bootExtracted.add(repo);
20337
+ input.onExtracted?.(repo);
20338
+ }
20339
+ });
20088
20340
  lastPass = { ...counts, startedAt, finishedAt: new Date(now()).toISOString() };
20089
20341
  } while (again && !stopped);
20090
20342
  } finally {
@@ -20153,7 +20405,7 @@ var PrVerdictError = class extends Error {
20153
20405
  details;
20154
20406
  };
20155
20407
  function parsePrVerdictRequest(body) {
20156
- const parsed = import_types65.PrVerdictBodySchema.safeParse(body);
20408
+ const parsed = import_types66.PrVerdictBodySchema.safeParse(body);
20157
20409
  if (!parsed.success) {
20158
20410
  throw new PrVerdictError("invalid pr-verdict body", 400, void 0, parsed.error.issues);
20159
20411
  }
@@ -20502,15 +20754,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
20502
20754
 
20503
20755
  // src/connectors/index.ts
20504
20756
  init_cjs_shims();
20505
- var import_types66 = require("@neat.is/types");
20757
+ var import_types67 = require("@neat.is/types");
20506
20758
  var NO_ENV = "unknown";
20507
20759
  function staticCallSiteFor(graph, serviceName, targetNodeId) {
20508
20760
  if (!graph.hasNode(targetNodeId)) return void 0;
20509
20761
  const sites = [];
20510
20762
  for (const edgeId of graph.inboundEdges(targetNodeId)) {
20511
20763
  const edge = graph.getEdgeAttributes(edgeId);
20512
- if (edge.provenance !== import_types66.Provenance.EXTRACTED) continue;
20513
- const parsed = (0, import_types66.parseFileId)(edge.source);
20764
+ if (edge.provenance !== import_types67.Provenance.EXTRACTED) continue;
20765
+ const parsed = (0, import_types67.parseFileId)(edge.source);
20514
20766
  if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
20515
20767
  const site = { relPath: edge.evidence.file };
20516
20768
  if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
@@ -20521,7 +20773,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
20521
20773
  function routeCallSiteFor(graph, targetNodeId) {
20522
20774
  if (!graph.hasNode(targetNodeId)) return void 0;
20523
20775
  const attrs = graph.getNodeAttributes(targetNodeId);
20524
- if (attrs.type !== import_types66.NodeType.RouteNode || !attrs.path) return void 0;
20776
+ if (attrs.type !== import_types67.NodeType.RouteNode || !attrs.path) return void 0;
20525
20777
  const site = { relPath: attrs.path };
20526
20778
  if (attrs.line !== void 0) site.line = attrs.line;
20527
20779
  return site;
@@ -21245,23 +21497,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
21245
21497
 
21246
21498
  // src/connectors/supabase/resolve.ts
21247
21499
  init_cjs_shims();
21248
- var import_types68 = require("@neat.is/types");
21500
+ var import_types69 = require("@neat.is/types");
21249
21501
  function createSupabaseResolveTarget(graph, config) {
21250
21502
  return (signal, _ctx) => {
21251
21503
  if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
21252
21504
  return null;
21253
21505
  }
21254
- const subResourceId = (0, import_types68.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
21506
+ const subResourceId = (0, import_types69.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
21255
21507
  if (graph.hasNode(subResourceId)) {
21256
- return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
21508
+ return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
21257
21509
  }
21258
- const bareResourceId = (0, import_types68.infraId)(signal.targetKind, signal.targetName);
21510
+ const bareResourceId = (0, import_types69.infraId)(signal.targetKind, signal.targetName);
21259
21511
  if (graph.hasNode(bareResourceId)) {
21260
- return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
21512
+ return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
21261
21513
  }
21262
- const projectLevelId = (0, import_types68.infraId)("supabase", config.nodeRef);
21514
+ const projectLevelId = (0, import_types69.infraId)("supabase", config.nodeRef);
21263
21515
  if (graph.hasNode(projectLevelId)) {
21264
- return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types68.EdgeType.CALLS };
21516
+ return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types69.EdgeType.CALLS };
21265
21517
  }
21266
21518
  return null;
21267
21519
  };
@@ -21354,7 +21606,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
21354
21606
 
21355
21607
  // src/connectors/railway/index.ts
21356
21608
  init_cjs_shims();
21357
- var import_types72 = require("@neat.is/types");
21609
+ var import_types73 = require("@neat.is/types");
21358
21610
 
21359
21611
  // src/connectors/railway/client.ts
21360
21612
  init_cjs_shims();
@@ -21505,7 +21757,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
21505
21757
  const out = [];
21506
21758
  graph.forEachNode((_id, attrs) => {
21507
21759
  const node = attrs;
21508
- if (node.type !== import_types72.NodeType.RouteNode) return;
21760
+ if (node.type !== import_types73.NodeType.RouteNode) return;
21509
21761
  const route = attrs;
21510
21762
  if (route.service !== serviceName) return;
21511
21763
  out.push({
@@ -21609,12 +21861,12 @@ function createRailwayResolveTarget(config) {
21609
21861
  const serviceName = config.serviceNameById[config.serviceId];
21610
21862
  if (!serviceName) return null;
21611
21863
  if (signal.targetKind === ROUTE_TARGET_KIND) {
21612
- return { targetNodeId: signal.targetName, serviceName, edgeType: import_types72.EdgeType.CALLS };
21864
+ return { targetNodeId: signal.targetName, serviceName, edgeType: import_types73.EdgeType.CALLS };
21613
21865
  }
21614
21866
  if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
21615
21867
  const peerName = config.serviceNameById[signal.targetName];
21616
21868
  if (!peerName) return null;
21617
- return { targetNodeId: (0, import_types72.serviceId)(peerName), serviceName, edgeType: import_types72.EdgeType.CONNECTS_TO };
21869
+ return { targetNodeId: (0, import_types73.serviceId)(peerName), serviceName, edgeType: import_types73.EdgeType.CONNECTS_TO };
21618
21870
  }
21619
21871
  return null;
21620
21872
  };
@@ -21802,11 +22054,11 @@ function mapLogEntriesToSignals(entries) {
21802
22054
 
21803
22055
  // src/connectors/firebase/resolve.ts
21804
22056
  init_cjs_shims();
21805
- var import_types74 = require("@neat.is/types");
22057
+ var import_types75 = require("@neat.is/types");
21806
22058
 
21807
22059
  // src/connectors/infer-service.ts
21808
22060
  init_cjs_shims();
21809
- var import_types73 = require("@neat.is/types");
22061
+ var import_types74 = require("@neat.is/types");
21810
22062
  function normalizeName(name) {
21811
22063
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
21812
22064
  }
@@ -21817,11 +22069,11 @@ function inferServiceName(graph, resourceName, method, path82) {
21817
22069
  const owners = /* @__PURE__ */ new Set();
21818
22070
  graph.forEachNode((_id, attrs) => {
21819
22071
  const node = attrs;
21820
- if (node.type === import_types73.NodeType.ServiceNode && typeof node.name === "string") {
22072
+ if (node.type === import_types74.NodeType.ServiceNode && typeof node.name === "string") {
21821
22073
  services.push(node.name);
21822
22074
  return;
21823
22075
  }
21824
- if (node.type !== import_types73.NodeType.RouteNode) return;
22076
+ if (node.type !== import_types74.NodeType.RouteNode) return;
21825
22077
  const route = attrs;
21826
22078
  if (!route.pathTemplate || normalizePathTemplate(route.pathTemplate) !== wantedPath) return;
21827
22079
  const routeMethod = route.method.toUpperCase();
@@ -21848,7 +22100,7 @@ function routeEntriesFor(graph, serviceName) {
21848
22100
  const entries = [];
21849
22101
  graph.forEachNode((_id, attrs) => {
21850
22102
  const node = attrs;
21851
- if (node.type !== import_types74.NodeType.RouteNode) return;
22103
+ if (node.type !== import_types75.NodeType.RouteNode) return;
21852
22104
  const route = attrs;
21853
22105
  if (route.service !== serviceName) return;
21854
22106
  entries.push({
@@ -21880,7 +22132,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
21880
22132
  return {
21881
22133
  targetNodeId: match.routeNodeId,
21882
22134
  serviceName,
21883
- edgeType: import_types74.EdgeType.CALLS
22135
+ edgeType: import_types75.EdgeType.CALLS
21884
22136
  };
21885
22137
  };
21886
22138
  }
@@ -21913,7 +22165,7 @@ init_cjs_shims();
21913
22165
 
21914
22166
  // src/connectors/cloudflare/connector.ts
21915
22167
  init_cjs_shims();
21916
- var import_types76 = require("@neat.is/types");
22168
+ var import_types77 = require("@neat.is/types");
21917
22169
 
21918
22170
  // src/connectors/cloudflare/client.ts
21919
22171
  init_cjs_shims();
@@ -22077,7 +22329,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
22077
22329
  graph.forEachNode((id, attrs) => {
22078
22330
  if (found) return;
22079
22331
  const a = attrs;
22080
- if (a.type === import_types76.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
22332
+ if (a.type === import_types77.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
22081
22333
  found = id;
22082
22334
  }
22083
22335
  });
@@ -22089,7 +22341,7 @@ function findMatchingRouteNode(graph, serviceName, method, path82) {
22089
22341
  graph.forEachNode((id, attrs) => {
22090
22342
  if (found) return;
22091
22343
  const a = attrs;
22092
- if (a.type !== import_types76.NodeType.RouteNode || a.service !== serviceName) return;
22344
+ if (a.type !== import_types77.NodeType.RouteNode || a.service !== serviceName) return;
22093
22345
  if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
22094
22346
  const routeMethod = (a.method ?? "").toUpperCase();
22095
22347
  if (routeMethod !== "ALL" && routeMethod !== method) return;
@@ -22108,11 +22360,11 @@ function createCloudflareResolveTarget(config, graph) {
22108
22360
  };
22109
22361
  const mapping = config.workers?.[scriptName];
22110
22362
  if (mapping) {
22111
- const wholeFileId = (0, import_types76.fileId)(mapping.service, mapping.entryFile);
22363
+ const wholeFileId = (0, import_types77.fileId)(mapping.service, mapping.entryFile);
22112
22364
  return {
22113
22365
  targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
22114
22366
  serviceName: mapping.service,
22115
- edgeType: import_types76.EdgeType.CALLS
22367
+ edgeType: import_types77.EdgeType.CALLS
22116
22368
  };
22117
22369
  }
22118
22370
  const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
@@ -22121,13 +22373,13 @@ function createCloudflareResolveTarget(config, graph) {
22121
22373
  return {
22122
22374
  targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
22123
22375
  serviceName: fileNode.service,
22124
- edgeType: import_types76.EdgeType.CALLS
22376
+ edgeType: import_types77.EdgeType.CALLS
22125
22377
  };
22126
22378
  }
22127
22379
  return {
22128
- targetNodeId: (0, import_types76.infraId)("cloudflare-worker", scriptName),
22380
+ targetNodeId: (0, import_types77.infraId)("cloudflare-worker", scriptName),
22129
22381
  serviceName: scriptName,
22130
- edgeType: import_types76.EdgeType.CALLS,
22382
+ edgeType: import_types77.EdgeType.CALLS,
22131
22383
  ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
22132
22384
  };
22133
22385
  };
@@ -22323,14 +22575,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
22323
22575
 
22324
22576
  // src/connectors/neon/resolve.ts
22325
22577
  init_cjs_shims();
22326
- var import_types80 = require("@neat.is/types");
22578
+ var import_types81 = require("@neat.is/types");
22327
22579
  function createNeonResolveTarget(config) {
22328
22580
  return (signal) => {
22329
22581
  if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
22330
22582
  return {
22331
- targetNodeId: (0, import_types80.infraId)("sql-table", signal.targetName),
22583
+ targetNodeId: (0, import_types81.infraId)("sql-table", signal.targetName),
22332
22584
  serviceName: config.serviceName,
22333
- edgeType: import_types80.EdgeType.CALLS,
22585
+ edgeType: import_types81.EdgeType.CALLS,
22334
22586
  ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
22335
22587
  };
22336
22588
  };
@@ -22511,14 +22763,14 @@ function mapLogEntriesToSignals2(entries) {
22511
22763
 
22512
22764
  // src/connectors/cloud-run/resolve.ts
22513
22765
  init_cjs_shims();
22514
- var import_types84 = require("@neat.is/types");
22766
+ var import_types85 = require("@neat.is/types");
22515
22767
  var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
22516
22768
  function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
22517
22769
  let found = null;
22518
22770
  graph.forEachNode((_id, attrs) => {
22519
22771
  if (found) return;
22520
22772
  const node = attrs;
22521
- if (node.type !== import_types84.NodeType.RouteNode) return;
22773
+ if (node.type !== import_types85.NodeType.RouteNode) return;
22522
22774
  const route = attrs;
22523
22775
  if (route.service !== serviceName || !route.pathTemplate) return;
22524
22776
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -22543,13 +22795,13 @@ function createCloudRunResolveTarget(graph, config) {
22543
22795
  normalizePathTemplate(path82)
22544
22796
  );
22545
22797
  if (routeNodeId) {
22546
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types84.EdgeType.CALLS };
22798
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types85.EdgeType.CALLS };
22547
22799
  }
22548
22800
  }
22549
22801
  return {
22550
- targetNodeId: (0, import_types84.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
22802
+ targetNodeId: (0, import_types85.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
22551
22803
  serviceName: mappedService ?? gcpServiceName,
22552
- edgeType: import_types84.EdgeType.CALLS,
22804
+ edgeType: import_types85.EdgeType.CALLS,
22553
22805
  ensureInfraNode: {
22554
22806
  kind: CLOUD_RUN_SERVICE_INFRA_KIND,
22555
22807
  name: gcpServiceName,
@@ -22731,14 +22983,14 @@ function mapLogEntriesToSignals3(entries) {
22731
22983
 
22732
22984
  // src/connectors/gcp-lb/resolve.ts
22733
22985
  init_cjs_shims();
22734
- var import_types88 = require("@neat.is/types");
22986
+ var import_types89 = require("@neat.is/types");
22735
22987
  var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
22736
22988
  function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
22737
22989
  let found = null;
22738
22990
  graph.forEachNode((_id, attrs) => {
22739
22991
  if (found) return;
22740
22992
  const node = attrs;
22741
- if (node.type !== import_types88.NodeType.RouteNode) return;
22993
+ if (node.type !== import_types89.NodeType.RouteNode) return;
22742
22994
  const route = attrs;
22743
22995
  if (route.service !== serviceName || !route.pathTemplate) return;
22744
22996
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -22763,13 +23015,13 @@ function createGcpLbResolveTarget(graph, config) {
22763
23015
  normalizePathTemplate(path82)
22764
23016
  );
22765
23017
  if (routeNodeId) {
22766
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types88.EdgeType.CALLS };
23018
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types89.EdgeType.CALLS };
22767
23019
  }
22768
23020
  }
22769
23021
  return {
22770
- targetNodeId: (0, import_types88.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
23022
+ targetNodeId: (0, import_types89.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
22771
23023
  serviceName: mappedService ?? backendServiceName,
22772
- edgeType: import_types88.EdgeType.CALLS,
23024
+ edgeType: import_types89.EdgeType.CALLS,
22773
23025
  ensureInfraNode: {
22774
23026
  kind: GCP_LB_BACKEND_INFRA_KIND,
22775
23027
  name: backendServiceName,
@@ -22810,7 +23062,7 @@ function createGcpLbConnector(graph, config = {}) {
22810
23062
 
22811
23063
  // src/connectors/render/index.ts
22812
23064
  init_cjs_shims();
22813
- var import_types91 = require("@neat.is/types");
23065
+ var import_types92 = require("@neat.is/types");
22814
23066
 
22815
23067
  // src/connectors/render/types.ts
22816
23068
  init_cjs_shims();
@@ -22888,7 +23140,7 @@ function buildRenderRouteIndex(graph, serviceName) {
22888
23140
  const out = [];
22889
23141
  graph.forEachNode((_id, attrs) => {
22890
23142
  const node = attrs;
22891
- if (node.type !== import_types91.NodeType.RouteNode) return;
23143
+ if (node.type !== import_types92.NodeType.RouteNode) return;
22892
23144
  const route = attrs;
22893
23145
  if (route.service !== serviceName) return;
22894
23146
  out.push({
@@ -22973,7 +23225,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
22973
23225
  function createRenderResolveTarget(config) {
22974
23226
  return (signal) => {
22975
23227
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
22976
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types91.EdgeType.CALLS };
23228
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types92.EdgeType.CALLS };
22977
23229
  }
22978
23230
  return null;
22979
23231
  };
@@ -23111,21 +23363,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
23111
23363
 
23112
23364
  // src/connectors/planetscale/resolve.ts
23113
23365
  init_cjs_shims();
23114
- var import_types95 = require("@neat.is/types");
23366
+ var import_types96 = require("@neat.is/types");
23115
23367
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
23116
23368
  function createPlanetscaleResolveTarget(graph, config) {
23117
23369
  const databaseName = `${config.organization}/${config.database}`;
23118
23370
  return (signal, _ctx) => {
23119
23371
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
23120
- const tableId = (0, import_types95.infraId)("sql-table", signal.targetName);
23372
+ const tableId = (0, import_types96.infraId)("sql-table", signal.targetName);
23121
23373
  if (graph.hasNode(tableId)) {
23122
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types95.EdgeType.CALLS };
23374
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types96.EdgeType.CALLS };
23123
23375
  }
23124
- const providerId = (0, import_types95.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
23376
+ const providerId = (0, import_types96.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
23125
23377
  return {
23126
23378
  targetNodeId: providerId,
23127
23379
  serviceName: config.serviceName,
23128
- edgeType: import_types95.EdgeType.CALLS,
23380
+ edgeType: import_types96.EdgeType.CALLS,
23129
23381
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
23130
23382
  };
23131
23383
  };
@@ -23390,7 +23642,7 @@ function mapBuildsToSignals(builds, serviceName) {
23390
23642
 
23391
23643
  // src/connectors/eas/resolve.ts
23392
23644
  init_cjs_shims();
23393
- var import_types100 = require("@neat.is/types");
23645
+ var import_types101 = require("@neat.is/types");
23394
23646
  var NO_ENV2 = "unknown";
23395
23647
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
23396
23648
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -23406,8 +23658,8 @@ function configBasenamesForPhase(phase) {
23406
23658
  function configNodeService(graph, configNodeId) {
23407
23659
  for (const edgeId of graph.inboundEdges(configNodeId)) {
23408
23660
  const edge = graph.getEdgeAttributes(edgeId);
23409
- if (edge.type !== import_types100.EdgeType.CONFIGURED_BY) continue;
23410
- const parsed = (0, import_types100.parseFileId)(edge.source);
23661
+ if (edge.type !== import_types101.EdgeType.CONFIGURED_BY) continue;
23662
+ const parsed = (0, import_types101.parseFileId)(edge.source);
23411
23663
  if (parsed) return parsed.service;
23412
23664
  }
23413
23665
  return null;
@@ -23418,7 +23670,7 @@ function findConfigNode(graph, basenames, serviceName) {
23418
23670
  graph.forEachNode((id, attrs) => {
23419
23671
  if (scoped) return;
23420
23672
  const node = attrs;
23421
- if (node.type !== import_types100.NodeType.ConfigNode) return;
23673
+ if (node.type !== import_types101.NodeType.ConfigNode) return;
23422
23674
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
23423
23675
  if (anyMatch === null) anyMatch = id;
23424
23676
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -23435,13 +23687,13 @@ function createEasResolveTarget(graph) {
23435
23687
  if (basenames.length > 0) {
23436
23688
  const configNodeId = findConfigNode(graph, basenames, serviceName);
23437
23689
  if (configNodeId) {
23438
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types100.EdgeType.CALLS };
23690
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types101.EdgeType.CALLS };
23439
23691
  }
23440
23692
  }
23441
23693
  return {
23442
23694
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
23443
23695
  serviceName,
23444
- edgeType: import_types100.EdgeType.CALLS
23696
+ edgeType: import_types101.EdgeType.CALLS
23445
23697
  };
23446
23698
  };
23447
23699
  }
@@ -24076,7 +24328,7 @@ function serializeGraph(graph) {
24076
24328
  graph.forEachEdge((_id, attrs) => {
24077
24329
  edges.push(attrs);
24078
24330
  });
24079
- return { nodes, edges };
24331
+ return { nodes, edges, sourceBaselines: readSourceBaselines(graph) };
24080
24332
  }
24081
24333
  function projectFromReq(req, singleProject, registry) {
24082
24334
  const params = req.params;
@@ -24259,11 +24511,11 @@ function registerRoutes(scope, ctx) {
24259
24511
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
24260
24512
  const parsed = [];
24261
24513
  for (const c of candidates) {
24262
- const r = import_types103.DivergenceTypeSchema.safeParse(c);
24514
+ const r = import_types104.DivergenceTypeSchema.safeParse(c);
24263
24515
  if (!r.success) {
24264
24516
  return reply.code(400).send({
24265
24517
  error: `unknown divergence type "${c}"`,
24266
- allowed: import_types103.DivergenceTypeSchema.options
24518
+ allowed: import_types104.DivergenceTypeSchema.options
24267
24519
  });
24268
24520
  }
24269
24521
  parsed.push(r.data);
@@ -24700,7 +24952,7 @@ function registerRoutes(scope, ctx) {
24700
24952
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
24701
24953
  let violations = await log.readAll();
24702
24954
  if (req.query.severity) {
24703
- const sev = import_types103.PolicySeveritySchema.safeParse(req.query.severity);
24955
+ const sev = import_types104.PolicySeveritySchema.safeParse(req.query.severity);
24704
24956
  if (!sev.success) {
24705
24957
  return reply.code(400).send({
24706
24958
  error: "invalid severity",
@@ -24739,7 +24991,7 @@ function registerRoutes(scope, ctx) {
24739
24991
  scope.post("/policies/check", async (req, reply) => {
24740
24992
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
24741
24993
  if (!proj) return;
24742
- const parsed = import_types103.PoliciesCheckBodySchema.safeParse(req.body ?? {});
24994
+ const parsed = import_types104.PoliciesCheckBodySchema.safeParse(req.body ?? {});
24743
24995
  if (!parsed.success) {
24744
24996
  return reply.code(400).send({
24745
24997
  error: "invalid /policies/check body",
@@ -25108,7 +25360,7 @@ init_otel();
25108
25360
 
25109
25361
  // src/hang-sensor.ts
25110
25362
  init_cjs_shims();
25111
- var import_types104 = require("@neat.is/types");
25363
+ var import_types105 = require("@neat.is/types");
25112
25364
  var RECONCILE_INCIDENT_LIMIT = 500;
25113
25365
  function stageHangSurfaces(graph, incidents) {
25114
25366
  const boundaries = /* @__PURE__ */ new Set();
@@ -25121,7 +25373,7 @@ function stageHangSurfaces(graph, incidents) {
25121
25373
  if (!isBoundaryTimeoutSymptom(ctx)) continue;
25122
25374
  const hop = resolveHangHop(graph, boundary, incidents);
25123
25375
  if (!hop) continue;
25124
- if (stageFrontierEdge(graph, hop.source, hop.target, import_types104.EdgeType.CALLS)) staged++;
25376
+ if (stageFrontierEdge(graph, hop.source, hop.target, import_types105.EdgeType.CALLS)) staged++;
25125
25377
  }
25126
25378
  return staged;
25127
25379
  }
@@ -25194,7 +25446,7 @@ function credentialRecord(provider, cred) {
25194
25446
  return { token: cred.accessToken };
25195
25447
  }
25196
25448
  }
25197
- function hostedOptions(provider, summary, serviceName, firebaseServiceMap) {
25449
+ function hostedOptions(provider, summary, serviceName, firebaseServiceMap, serviceMaps = {}) {
25198
25450
  switch (provider) {
25199
25451
  case "supabase": {
25200
25452
  const ref = summary.projectRef;
@@ -25213,9 +25465,12 @@ function hostedOptions(provider, summary, serviceName, firebaseServiceMap) {
25213
25465
  case "firebase": {
25214
25466
  return { inferServices: true, excludeCloudRun: true, ...firebaseServiceMap ?? {} };
25215
25467
  }
25468
+ // Same no-setup rule as Firebase: infer the owning service from the graph; an unknown one stays coarse.
25469
+ // NEAT_CLOUD_RUN_SERVICE_MAP / NEAT_GCP_LB_BACKEND_SERVICE_MAP are optional overrides whose entries win.
25216
25470
  case "cloud-run":
25471
+ return { inferServices: true, ...serviceMaps.cloudRun ? { serviceMap: serviceMaps.cloudRun } : {} };
25217
25472
  case "gcp-lb":
25218
- return { inferServices: true };
25473
+ return { inferServices: true, ...serviceMaps.gcpLb ? { backendServiceMap: serviceMaps.gcpLb } : {} };
25219
25474
  default:
25220
25475
  return null;
25221
25476
  }
@@ -25240,6 +25495,19 @@ function parseFirebaseServiceMap(raw) {
25240
25495
  return void 0;
25241
25496
  }
25242
25497
  }
25498
+ function parseServiceNameMap(raw) {
25499
+ if (!raw) return void 0;
25500
+ try {
25501
+ const parsed = JSON.parse(raw);
25502
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
25503
+ const entries = Object.entries(parsed);
25504
+ if (entries.length === 0) return void 0;
25505
+ if (entries.some(([, v]) => typeof v !== "string" || v.length === 0)) return void 0;
25506
+ return Object.fromEntries(entries);
25507
+ } catch {
25508
+ return void 0;
25509
+ }
25510
+ }
25243
25511
  function pushHandlesPath(projectDir) {
25244
25512
  return (0, import_node_path79.join)(projectDir, "neat-out", "connectors-hosted.json");
25245
25513
  }
@@ -25361,7 +25629,10 @@ function startConnectionLoops(c, input, startLoop) {
25361
25629
  onSkip?.(name, "no project selected yet \u2014 not pullable");
25362
25630
  continue;
25363
25631
  }
25364
- const options = hostedOptions(name, c, project, input.firebaseServiceMap);
25632
+ const options = hostedOptions(name, c, project, input.firebaseServiceMap, {
25633
+ ...input.cloudRunServiceMap ? { cloudRun: input.cloudRunServiceMap } : {},
25634
+ ...input.gcpLbBackendServiceMap ? { gcpLb: input.gcpLbBackendServiceMap } : {}
25635
+ });
25365
25636
  if (!options) {
25366
25637
  onSkip?.(name, "no hosted option mapping for this provider");
25367
25638
  continue;
@@ -25471,6 +25742,8 @@ async function maybeStartHostedConnectors(input) {
25471
25742
  projectDir: input.projectDir,
25472
25743
  project: input.project,
25473
25744
  ...parseFirebaseServiceMap(env.NEAT_FIREBASE_SERVICE_MAP) ? { firebaseServiceMap: parseFirebaseServiceMap(env.NEAT_FIREBASE_SERVICE_MAP) } : {},
25745
+ ...parseServiceNameMap(env.NEAT_CLOUD_RUN_SERVICE_MAP) ? { cloudRunServiceMap: parseServiceNameMap(env.NEAT_CLOUD_RUN_SERVICE_MAP) } : {},
25746
+ ...parseServiceNameMap(env.NEAT_GCP_LB_BACKEND_SERVICE_MAP) ? { gcpLbBackendServiceMap: parseServiceNameMap(env.NEAT_GCP_LB_BACKEND_SERVICE_MAP) } : {},
25474
25747
  ...input.errorsPath ? { errorsPath: input.errorsPath } : {},
25475
25748
  ...input.onSkip ? { onSkip: input.onSkip } : {},
25476
25749
  ...input.intervalMs !== void 0 ? { intervalMs: input.intervalMs } : {}
@@ -25592,6 +25865,15 @@ async function fetchPodLog(transport, namespace, podName, opts = {}) {
25592
25865
  return void 0;
25593
25866
  }
25594
25867
  }
25868
+ function hasLogContent(text) {
25869
+ return typeof text === "string" && text.trim().length > 0;
25870
+ }
25871
+ async function fetchPodProcessLog(transport, namespace, podName, opts = {}) {
25872
+ const previous = await fetchPodLog(transport, namespace, podName, { ...opts, previous: true });
25873
+ if (hasLogContent(previous)) return previous;
25874
+ const current = await fetchPodLog(transport, namespace, podName, { ...opts, previous: false });
25875
+ return hasLogContent(current) ? current : void 0;
25876
+ }
25595
25877
 
25596
25878
  // src/connectors/kubernetes/kubeconfig.ts
25597
25879
  init_cjs_shims();
@@ -26017,7 +26299,7 @@ function mapWorkloadsToSignals(deployments, pods, config, logs) {
26017
26299
 
26018
26300
  // src/connectors/kubernetes/resolve.ts
26019
26301
  init_cjs_shims();
26020
- var import_types106 = require("@neat.is/types");
26302
+ var import_types107 = require("@neat.is/types");
26021
26303
  var NO_ENV3 = "unknown";
26022
26304
  function createK8sResolveTarget(graph) {
26023
26305
  return (signal) => {
@@ -26028,7 +26310,7 @@ function createK8sResolveTarget(graph) {
26028
26310
  return {
26029
26311
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV3),
26030
26312
  serviceName,
26031
- edgeType: import_types106.EdgeType.CALLS
26313
+ edgeType: import_types107.EdgeType.CALLS
26032
26314
  };
26033
26315
  };
26034
26316
  }
@@ -26138,11 +26420,10 @@ var KubernetesConnector = class {
26138
26420
  const targets = faultedPods(deployments, pods, this.config);
26139
26421
  await Promise.all(
26140
26422
  targets.map(async (t) => {
26141
- const text = await fetchPodLog(transport, namespace, t.podName, {
26423
+ const text = await fetchPodProcessLog(transport, namespace, t.podName, {
26142
26424
  ...t.container ? { container: t.container } : {},
26143
26425
  tailLines: PROCESS_LOG_TAIL_LINES,
26144
26426
  limitBytes: PROCESS_LOG_LIMIT_BYTES,
26145
- previous: true,
26146
26427
  ...opts
26147
26428
  });
26148
26429
  if (typeof text === "string" && text.length > 0) logs.set(podLogKey(t.podName, t.container), text);
@@ -26183,7 +26464,7 @@ function unroutedErrorsPath(neatHome3) {
26183
26464
  }
26184
26465
 
26185
26466
  // src/daemon.ts
26186
- var import_types109 = require("@neat.is/types");
26467
+ var import_types110 = require("@neat.is/types");
26187
26468
  function daemonJsonPath(scanPath) {
26188
26469
  return import_node_path82.default.join(scanPath, "neat-out", "daemon.json");
26189
26470
  }
@@ -26320,7 +26601,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
26320
26601
  if (!serviceName) return true;
26321
26602
  if (serviceNameMatchesProject(serviceName, project)) return true;
26322
26603
  return graph.someNode(
26323
- (_id, attrs) => attrs.type === import_types109.NodeType.ServiceNode && attrs.name === serviceName
26604
+ (_id, attrs) => attrs.type === import_types110.NodeType.ServiceNode && attrs.name === serviceName
26324
26605
  );
26325
26606
  }
26326
26607
  async function bootstrapProject(entry, connectors = [], neatHome3) {