@neat.is/core 0.10.6-dev.20261007 → 0.10.6-dev.20261008

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.
Files changed (46) hide show
  1. package/dist/{chunk-KTJK2PAH.js → chunk-6QMWJAWR.js} +204 -609
  2. package/dist/chunk-6QMWJAWR.js.map +1 -0
  3. package/dist/{chunk-VL7ANDPI.js → chunk-EMFX3V77.js} +10 -8
  4. package/dist/{chunk-VL7ANDPI.js.map → chunk-EMFX3V77.js.map} +1 -1
  5. package/dist/chunk-MR64ICXX.js +19 -0
  6. package/dist/chunk-MR64ICXX.js.map +1 -0
  7. package/dist/{chunk-EFBWQIKG.js → chunk-QPG2QXCW.js} +11 -27
  8. package/dist/chunk-QPG2QXCW.js.map +1 -0
  9. package/dist/chunk-RGYC5U2Q.js +511 -0
  10. package/dist/chunk-RGYC5U2Q.js.map +1 -0
  11. package/dist/{chunk-LXQCL4MP.js → chunk-TZXSWSHX.js} +2 -2
  12. package/dist/{chunk-BC53SCT7.js → chunk-VFZ6CXLI.js} +20 -6
  13. package/dist/chunk-VFZ6CXLI.js.map +1 -0
  14. package/dist/cli.cjs +300 -74
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.d.cts +2 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +249 -76
  19. package/dist/cli.js.map +1 -1
  20. package/dist/index.cjs +58 -15
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +3 -99
  23. package/dist/index.d.ts +3 -99
  24. package/dist/index.js +18 -15
  25. package/dist/neatd.cjs +58 -15
  26. package/dist/neatd.cjs.map +1 -1
  27. package/dist/neatd.js +7 -4
  28. package/dist/neatd.js.map +1 -1
  29. package/dist/otel-grpc-CCCI772O.js +11 -0
  30. package/dist/registry.cjs +570 -0
  31. package/dist/registry.cjs.map +1 -0
  32. package/dist/registry.d.cts +220 -0
  33. package/dist/registry.d.ts +220 -0
  34. package/dist/registry.js +62 -0
  35. package/dist/registry.js.map +1 -0
  36. package/dist/server.cjs +78 -21
  37. package/dist/server.cjs.map +1 -1
  38. package/dist/server.js +10 -6
  39. package/dist/server.js.map +1 -1
  40. package/package.json +8 -3
  41. package/dist/chunk-BC53SCT7.js.map +0 -1
  42. package/dist/chunk-EFBWQIKG.js.map +0 -1
  43. package/dist/chunk-KTJK2PAH.js.map +0 -1
  44. package/dist/otel-grpc-B7ABHLV7.js +0 -10
  45. /package/dist/{chunk-LXQCL4MP.js.map → chunk-TZXSWSHX.js.map} +0 -0
  46. /package/dist/{otel-grpc-B7ABHLV7.js.map → otel-grpc-CCCI772O.js.map} +0 -0
package/dist/server.cjs CHANGED
@@ -5678,7 +5678,29 @@ function ensureFrontierNode(graph, host, ts) {
5678
5678
  graph.addNode(id, node);
5679
5679
  return id;
5680
5680
  }
5681
- function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence, durationMs) {
5681
+ var EDGE_ERROR_MESSAGE_MAX = 512;
5682
+ function buildEdgeErrorExemplar(detail, ts) {
5683
+ return {
5684
+ ...detail.exceptionType !== void 0 ? { exceptionType: detail.exceptionType } : {},
5685
+ ...detail.message !== void 0 ? { message: detail.message.slice(0, EDGE_ERROR_MESSAGE_MAX) } : {},
5686
+ ...detail.httpStatusCode !== void 0 ? { httpStatusCode: detail.httpStatusCode } : {},
5687
+ at: ts
5688
+ };
5689
+ }
5690
+ function edgeErrorDetailFromSpan(span) {
5691
+ const exceptionType = span.exception?.type;
5692
+ const message = span.exception?.message;
5693
+ const httpStatusCode = httpResponseStatus(span);
5694
+ if (exceptionType === void 0 && message === void 0 && httpStatusCode === void 0) {
5695
+ return void 0;
5696
+ }
5697
+ return {
5698
+ ...exceptionType !== void 0 ? { exceptionType } : {},
5699
+ ...message !== void 0 ? { message } : {},
5700
+ ...httpStatusCode !== void 0 ? { httpStatusCode } : {}
5701
+ };
5702
+ }
5703
+ function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence, durationMs, errorDetail) {
5682
5704
  if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
5683
5705
  const grain = source.startsWith("file:") || source.startsWith("symbol:") ? "file" : "service";
5684
5706
  const id = makeObservedEdgeId(type, source, target);
@@ -5688,13 +5710,15 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
5688
5710
  const newErrorCount = (existing.signal?.errorCount ?? 0) + (isError ? 1 : 0);
5689
5711
  const latencyHist2 = durationMs !== void 0 ? recordLatency({ ...existing.signal?.latencyHist ?? {} }, durationMs) : existing.signal?.latencyHist;
5690
5712
  const latencyMs2 = latencyPercentiles(latencyHist2) ?? existing.signal?.latencyMs;
5713
+ const lastError2 = isError && errorDetail ? buildEdgeErrorExemplar(errorDetail, ts) : existing.signal?.lastError;
5691
5714
  const newSignal = {
5692
5715
  spanCount: newSpanCount,
5693
5716
  errorCount: newErrorCount,
5694
5717
  lastObservedAgeMs: 0,
5695
5718
  ...latencyHist2 ? { latencyHist: latencyHist2 } : {},
5696
5719
  ...latencyMs2 ? { latencyMs: latencyMs2 } : {},
5697
- ...existing.signal?.anomalous !== void 0 ? { anomalous: existing.signal.anomalous } : {}
5720
+ ...existing.signal?.anomalous !== void 0 ? { anomalous: existing.signal.anomalous } : {},
5721
+ ...lastError2 ? { lastError: lastError2 } : {}
5698
5722
  };
5699
5723
  const updated = {
5700
5724
  ...existing,
@@ -5711,12 +5735,14 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
5711
5735
  }
5712
5736
  const latencyHist = durationMs !== void 0 ? recordLatency({}, durationMs) : void 0;
5713
5737
  const latencyMs = latencyHist ? latencyPercentiles(latencyHist) : void 0;
5738
+ const lastError = isError && errorDetail ? buildEdgeErrorExemplar(errorDetail, ts) : void 0;
5714
5739
  const signal = {
5715
5740
  spanCount: 1,
5716
5741
  errorCount: isError ? 1 : 0,
5717
5742
  lastObservedAgeMs: 0,
5718
5743
  ...latencyHist ? { latencyHist } : {},
5719
- ...latencyMs ? { latencyMs } : {}
5744
+ ...latencyMs ? { latencyMs } : {},
5745
+ ...lastError ? { lastError } : {}
5720
5746
  };
5721
5747
  const edge = {
5722
5748
  id,
@@ -6049,6 +6075,7 @@ async function handleSpan(ctx, span) {
6049
6075
  const sourceId = ensureServiceNode(ctx.graph, span.service, env);
6050
6076
  const isError = spanRecordsError(span);
6051
6077
  const durationMs = span.durationNanos > 0n && !spanIsStreaming(span) ? Number(span.durationNanos) / 1e6 : void 0;
6078
+ const errorDetail = isError ? edgeErrorDetailFromSpan(span) : void 0;
6052
6079
  const sourceServiceNode = ctx.graph.getNodeAttributes(sourceId);
6053
6080
  const callSite = callSiteFromSpan(span, sourceServiceNode, ctx.scanPath);
6054
6081
  cacheSpanService(span, nowMs, callSite);
@@ -6088,7 +6115,8 @@ async function handleSpan(ctx, span) {
6088
6115
  ts,
6089
6116
  isError,
6090
6117
  callSiteEvidence,
6091
- durationMs
6118
+ durationMs,
6119
+ errorDetail
6092
6120
  );
6093
6121
  if (result) affectedNode = targetId;
6094
6122
  if (span.dbSystem === "mongodb" && span.dbCollection) {
@@ -6101,7 +6129,8 @@ async function handleSpan(ctx, span) {
6101
6129
  ts,
6102
6130
  isError,
6103
6131
  callSiteEvidence,
6104
- durationMs
6132
+ durationMs,
6133
+ errorDetail
6105
6134
  );
6106
6135
  }
6107
6136
  if (span.dbTable) {
@@ -6114,7 +6143,8 @@ async function handleSpan(ctx, span) {
6114
6143
  ts,
6115
6144
  isError,
6116
6145
  callSiteEvidence,
6117
- durationMs
6146
+ durationMs,
6147
+ errorDetail
6118
6148
  );
6119
6149
  mergeObservedColumns(ctx.graph, tableId, span.dbColumns);
6120
6150
  }
@@ -6134,7 +6164,8 @@ async function handleSpan(ctx, span) {
6134
6164
  ts,
6135
6165
  isError,
6136
6166
  callSiteEvidence,
6137
- durationMs
6167
+ durationMs,
6168
+ errorDetail
6138
6169
  );
6139
6170
  if (result) affectedNode = targetId;
6140
6171
  } else if (span.graphqlOperationName && span.graphqlOperationType && spanServesGraphqlOperation(span.kind)) {
@@ -6152,7 +6183,8 @@ async function handleSpan(ctx, span) {
6152
6183
  ts,
6153
6184
  isError,
6154
6185
  callSiteEvidence,
6155
- durationMs
6186
+ durationMs,
6187
+ errorDetail
6156
6188
  );
6157
6189
  if (result) affectedNode = targetId;
6158
6190
  } else if (span.rpcSystem === "grpc" && span.rpcService && span.rpcMethod && spanServesGrpcMethod(span.kind)) {
@@ -6165,7 +6197,8 @@ async function handleSpan(ctx, span) {
6165
6197
  ts,
6166
6198
  isError,
6167
6199
  callSiteEvidence,
6168
- durationMs
6200
+ durationMs,
6201
+ errorDetail
6169
6202
  );
6170
6203
  if (result) affectedNode = targetId;
6171
6204
  } else if (span.websocketChannel && spanServesWebsocketChannel(span.kind)) {
@@ -6182,7 +6215,8 @@ async function handleSpan(ctx, span) {
6182
6215
  ts,
6183
6216
  isError,
6184
6217
  callSiteEvidence,
6185
- durationMs
6218
+ durationMs,
6219
+ errorDetail
6186
6220
  );
6187
6221
  if (result) affectedNode = targetId;
6188
6222
  } else {
@@ -6199,7 +6233,8 @@ async function handleSpan(ctx, span) {
6199
6233
  ts,
6200
6234
  isError,
6201
6235
  callSiteEvidence,
6202
- durationMs
6236
+ durationMs,
6237
+ errorDetail
6203
6238
  );
6204
6239
  affectedNode = targetId;
6205
6240
  resolvedViaAddress = true;
@@ -6213,7 +6248,8 @@ async function handleSpan(ctx, span) {
6213
6248
  ts,
6214
6249
  isError,
6215
6250
  callSiteEvidence,
6216
- durationMs
6251
+ durationMs,
6252
+ errorDetail
6217
6253
  );
6218
6254
  affectedNode = frontierNodeId;
6219
6255
  resolvedViaAddress = true;
@@ -6240,7 +6276,8 @@ async function handleSpan(ctx, span) {
6240
6276
  ts,
6241
6277
  isError,
6242
6278
  fallbackEvidence,
6243
- durationMs
6279
+ durationMs,
6280
+ errorDetail
6244
6281
  );
6245
6282
  }
6246
6283
  }
@@ -6255,7 +6292,7 @@ async function handleSpan(ctx, span) {
6255
6292
  );
6256
6293
  if (routeNodeId) {
6257
6294
  const routeSvc = ctx.graph.getNodeAttributes(routeNodeId).service;
6258
- upsertObservedEdge(ctx.graph, import_types7.EdgeType.CONTAINS, (0, import_types7.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs);
6295
+ upsertObservedEdge(ctx.graph, import_types7.EdgeType.CONTAINS, (0, import_types7.serviceId)(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
6259
6296
  }
6260
6297
  }
6261
6298
  if (span.statusCode === 2) {
@@ -8123,6 +8160,11 @@ function detectObservedFailingEdge(graph, bucket) {
8123
8160
  spanCount,
8124
8161
  errorCount,
8125
8162
  errorRate: clampConfidence(errorRate),
8163
+ // The bounded last-error exemplar rides the finding as evidence (ADR-236):
8164
+ // the error rate says HOW MUCH is failing, the exemplar says WHAT failed —
8165
+ // a timeout vs a deadlock vs a connection-refused, which `errorCount`
8166
+ // alone cannot name. Present only when the observed edge carries one.
8167
+ ...signal.lastError ? { lastError: signal.lastError } : {},
8126
8168
  confidence: OBSERVED_FAILING_CONFIDENCE,
8127
8169
  reason: `Code declares ${bucket.source} \u2192 ${bucket.target} (${bucket.type}) and production observes it, but ${errorCount}/${spanCount} observed calls fail (${pct}% error rate) \u2014 the declared dependency is predominantly failing. The declared intent (EXTRACTED) and the observed behaviour (OBSERVED) diverge.`,
8128
8170
  recommendation: "Treat this as a broken declared dependency, not a coverage gap: production runs the call the code declares and most calls error. Check the dependency\u2019s health, recent deploys, and the observed error responses on this edge."
@@ -19498,7 +19540,7 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19498
19540
  const found = observedBreakFrom(node, getObservedDependencies(ctx.liveGraph, node.id));
19499
19541
  if (found) observedBreaks.push(found);
19500
19542
  }
19501
- const { marker, body } = renderVerdict({
19543
+ const { marker, body: rendered } = renderVerdict({
19502
19544
  graph: head,
19503
19545
  delta,
19504
19546
  changedFiles,
@@ -19506,6 +19548,7 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19506
19548
  observedBreaks,
19507
19549
  tone: req.tone ?? "loud"
19508
19550
  });
19551
+ const body = rendered.startsWith(marker) ? rendered.slice(marker.length).replace(/^(?:\r?\n)+/, "") : rendered;
19509
19552
  return {
19510
19553
  marker,
19511
19554
  body,
@@ -24403,13 +24446,25 @@ async function makeTransformersEmbedder() {
24403
24446
  }
24404
24447
  };
24405
24448
  }
24406
- async function pickEmbedder() {
24407
- const host = ollamaHost();
24408
- if (host && await ollamaReachable(host)) {
24409
- return makeOllamaEmbedder(host);
24449
+ async function pickEmbedder(provider) {
24450
+ if (provider !== "transformers") {
24451
+ const host = ollamaHost();
24452
+ if (host && await ollamaReachable(host)) {
24453
+ return makeOllamaEmbedder(host);
24454
+ }
24410
24455
  }
24456
+ if (provider === "ollama") return null;
24411
24457
  return makeTransformersEmbedder();
24412
24458
  }
24459
+ function searchProviderFromEnv(env = process.env, warn = console.warn) {
24460
+ const value = env.NEAT_SEARCH_PROVIDER;
24461
+ if (!value) return void 0;
24462
+ if (value === "substring" || value === "ollama" || value === "transformers") return value;
24463
+ warn(
24464
+ `semantic_search: NEAT_SEARCH_PROVIDER="${value}" is not substring, ollama, or transformers; using automatic selection`
24465
+ );
24466
+ return void 0;
24467
+ }
24413
24468
  async function readCache(cachePath) {
24414
24469
  try {
24415
24470
  const raw = await import_node_fs44.promises.readFile(cachePath, "utf8");
@@ -24573,7 +24628,8 @@ async function buildSearchIndex(graph, options = {}) {
24573
24628
  if (options.embedder) {
24574
24629
  embedder = options.embedder;
24575
24630
  } else if (options.forceProvider !== "substring") {
24576
- const factory = options.embedderFactory ?? pickEmbedder;
24631
+ const forcedProvider = options.forceProvider;
24632
+ const factory = options.embedderFactory ?? (() => pickEmbedder(forcedProvider));
24577
24633
  embedder = await resolveEmbedderBounded(
24578
24634
  factory,
24579
24635
  options.initTimeoutMs ?? searchInitTimeoutMs()
@@ -24617,7 +24673,8 @@ async function bootProject(registry, name, scanPath, baseDir) {
24617
24673
  startPersistLoop(graph, paths.snapshotPath);
24618
24674
  startStalenessLoop(graph, { staleEventsPath: paths.staleEventsPath });
24619
24675
  const searchIndex = await buildSearchIndex(graph, {
24620
- cachePath: paths.embeddingsCachePath
24676
+ cachePath: paths.embeddingsCachePath,
24677
+ forceProvider: searchProviderFromEnv()
24621
24678
  }).catch((err) => {
24622
24679
  console.warn(
24623
24680
  `[${name}] semantic_search: index build failed (${err.message}); falling back to inline substring`