@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
@@ -1,10 +1,15 @@
1
+ import {
2
+ findDaemonByProject,
3
+ getProject,
4
+ listProjects
5
+ } from "./chunk-RGYC5U2Q.js";
1
6
  import {
2
7
  BEARER_DELEGATED,
3
8
  columnsFromSqlStatement,
4
9
  mountBearerAuth,
5
10
  readAuthEnv,
6
11
  tableFromSqlStatement
7
- } from "./chunk-EFBWQIKG.js";
12
+ } from "./chunk-QPG2QXCW.js";
8
13
 
9
14
  // src/graph.ts
10
15
  import GraphDefault from "graphology";
@@ -2036,8 +2041,8 @@ function chiRoutesFromSource(source, parser) {
2036
2041
  chiWalk(tree.rootNode, "", out);
2037
2042
  return out;
2038
2043
  }
2039
- function stripChiRegex(path77) {
2040
- return path77.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
2044
+ function stripChiRegex(path76) {
2045
+ return path76.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
2041
2046
  }
2042
2047
  function chiWalk(node, prefix, out) {
2043
2048
  for (let i = 0; i < node.namedChildCount; i++) {
@@ -2709,9 +2714,9 @@ function rubyRocketRoute(args) {
2709
2714
  if (!pair || pair.type !== "pair") continue;
2710
2715
  const k = pair.childForFieldName("key");
2711
2716
  if (k?.type !== "string") continue;
2712
- const path77 = rubyLiteral(k);
2713
- if (path77 === null) continue;
2714
- return { path: path77, target: rubyLiteral(pair.childForFieldName("value")) };
2717
+ const path76 = rubyLiteral(k);
2718
+ if (path76 === null) continue;
2719
+ return { path: path76, target: rubyLiteral(pair.childForFieldName("value")) };
2715
2720
  }
2716
2721
  return null;
2717
2722
  }
@@ -4658,7 +4663,29 @@ function ensureFrontierNode(graph, host, ts) {
4658
4663
  graph.addNode(id, node);
4659
4664
  return id;
4660
4665
  }
4661
- function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence, durationMs) {
4666
+ var EDGE_ERROR_MESSAGE_MAX = 512;
4667
+ function buildEdgeErrorExemplar(detail, ts) {
4668
+ return {
4669
+ ...detail.exceptionType !== void 0 ? { exceptionType: detail.exceptionType } : {},
4670
+ ...detail.message !== void 0 ? { message: detail.message.slice(0, EDGE_ERROR_MESSAGE_MAX) } : {},
4671
+ ...detail.httpStatusCode !== void 0 ? { httpStatusCode: detail.httpStatusCode } : {},
4672
+ at: ts
4673
+ };
4674
+ }
4675
+ function edgeErrorDetailFromSpan(span) {
4676
+ const exceptionType = span.exception?.type;
4677
+ const message = span.exception?.message;
4678
+ const httpStatusCode = httpResponseStatus(span);
4679
+ if (exceptionType === void 0 && message === void 0 && httpStatusCode === void 0) {
4680
+ return void 0;
4681
+ }
4682
+ return {
4683
+ ...exceptionType !== void 0 ? { exceptionType } : {},
4684
+ ...message !== void 0 ? { message } : {},
4685
+ ...httpStatusCode !== void 0 ? { httpStatusCode } : {}
4686
+ };
4687
+ }
4688
+ function upsertObservedEdge(graph, type, source, target, ts, isError = false, evidence, durationMs, errorDetail) {
4662
4689
  if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
4663
4690
  const grain = source.startsWith("file:") || source.startsWith("symbol:") ? "file" : "service";
4664
4691
  const id = makeObservedEdgeId(type, source, target);
@@ -4668,13 +4695,15 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
4668
4695
  const newErrorCount = (existing.signal?.errorCount ?? 0) + (isError ? 1 : 0);
4669
4696
  const latencyHist2 = durationMs !== void 0 ? recordLatency({ ...existing.signal?.latencyHist ?? {} }, durationMs) : existing.signal?.latencyHist;
4670
4697
  const latencyMs2 = latencyPercentiles(latencyHist2) ?? existing.signal?.latencyMs;
4698
+ const lastError2 = isError && errorDetail ? buildEdgeErrorExemplar(errorDetail, ts) : existing.signal?.lastError;
4671
4699
  const newSignal = {
4672
4700
  spanCount: newSpanCount,
4673
4701
  errorCount: newErrorCount,
4674
4702
  lastObservedAgeMs: 0,
4675
4703
  ...latencyHist2 ? { latencyHist: latencyHist2 } : {},
4676
4704
  ...latencyMs2 ? { latencyMs: latencyMs2 } : {},
4677
- ...existing.signal?.anomalous !== void 0 ? { anomalous: existing.signal.anomalous } : {}
4705
+ ...existing.signal?.anomalous !== void 0 ? { anomalous: existing.signal.anomalous } : {},
4706
+ ...lastError2 ? { lastError: lastError2 } : {}
4678
4707
  };
4679
4708
  const updated = {
4680
4709
  ...existing,
@@ -4691,12 +4720,14 @@ function upsertObservedEdge(graph, type, source, target, ts, isError = false, ev
4691
4720
  }
4692
4721
  const latencyHist = durationMs !== void 0 ? recordLatency({}, durationMs) : void 0;
4693
4722
  const latencyMs = latencyHist ? latencyPercentiles(latencyHist) : void 0;
4723
+ const lastError = isError && errorDetail ? buildEdgeErrorExemplar(errorDetail, ts) : void 0;
4694
4724
  const signal = {
4695
4725
  spanCount: 1,
4696
4726
  errorCount: isError ? 1 : 0,
4697
4727
  lastObservedAgeMs: 0,
4698
4728
  ...latencyHist ? { latencyHist } : {},
4699
- ...latencyMs ? { latencyMs } : {}
4729
+ ...latencyMs ? { latencyMs } : {},
4730
+ ...lastError ? { lastError } : {}
4700
4731
  };
4701
4732
  const edge = {
4702
4733
  id,
@@ -5037,6 +5068,7 @@ async function handleSpan(ctx, span) {
5037
5068
  const sourceId = ensureServiceNode(ctx.graph, span.service, env);
5038
5069
  const isError = spanRecordsError(span);
5039
5070
  const durationMs = span.durationNanos > 0n && !spanIsStreaming(span) ? Number(span.durationNanos) / 1e6 : void 0;
5071
+ const errorDetail = isError ? edgeErrorDetailFromSpan(span) : void 0;
5040
5072
  const sourceServiceNode = ctx.graph.getNodeAttributes(sourceId);
5041
5073
  const callSite = callSiteFromSpan(span, sourceServiceNode, ctx.scanPath);
5042
5074
  cacheSpanService(span, nowMs, callSite);
@@ -5076,7 +5108,8 @@ async function handleSpan(ctx, span) {
5076
5108
  ts,
5077
5109
  isError,
5078
5110
  callSiteEvidence,
5079
- durationMs
5111
+ durationMs,
5112
+ errorDetail
5080
5113
  );
5081
5114
  if (result) affectedNode = targetId;
5082
5115
  if (span.dbSystem === "mongodb" && span.dbCollection) {
@@ -5089,7 +5122,8 @@ async function handleSpan(ctx, span) {
5089
5122
  ts,
5090
5123
  isError,
5091
5124
  callSiteEvidence,
5092
- durationMs
5125
+ durationMs,
5126
+ errorDetail
5093
5127
  );
5094
5128
  }
5095
5129
  if (span.dbTable) {
@@ -5102,7 +5136,8 @@ async function handleSpan(ctx, span) {
5102
5136
  ts,
5103
5137
  isError,
5104
5138
  callSiteEvidence,
5105
- durationMs
5139
+ durationMs,
5140
+ errorDetail
5106
5141
  );
5107
5142
  mergeObservedColumns(ctx.graph, tableId, span.dbColumns);
5108
5143
  }
@@ -5122,7 +5157,8 @@ async function handleSpan(ctx, span) {
5122
5157
  ts,
5123
5158
  isError,
5124
5159
  callSiteEvidence,
5125
- durationMs
5160
+ durationMs,
5161
+ errorDetail
5126
5162
  );
5127
5163
  if (result) affectedNode = targetId;
5128
5164
  } else if (span.graphqlOperationName && span.graphqlOperationType && spanServesGraphqlOperation(span.kind)) {
@@ -5140,7 +5176,8 @@ async function handleSpan(ctx, span) {
5140
5176
  ts,
5141
5177
  isError,
5142
5178
  callSiteEvidence,
5143
- durationMs
5179
+ durationMs,
5180
+ errorDetail
5144
5181
  );
5145
5182
  if (result) affectedNode = targetId;
5146
5183
  } else if (span.rpcSystem === "grpc" && span.rpcService && span.rpcMethod && spanServesGrpcMethod(span.kind)) {
@@ -5153,7 +5190,8 @@ async function handleSpan(ctx, span) {
5153
5190
  ts,
5154
5191
  isError,
5155
5192
  callSiteEvidence,
5156
- durationMs
5193
+ durationMs,
5194
+ errorDetail
5157
5195
  );
5158
5196
  if (result) affectedNode = targetId;
5159
5197
  } else if (span.websocketChannel && spanServesWebsocketChannel(span.kind)) {
@@ -5170,7 +5208,8 @@ async function handleSpan(ctx, span) {
5170
5208
  ts,
5171
5209
  isError,
5172
5210
  callSiteEvidence,
5173
- durationMs
5211
+ durationMs,
5212
+ errorDetail
5174
5213
  );
5175
5214
  if (result) affectedNode = targetId;
5176
5215
  } else {
@@ -5187,7 +5226,8 @@ async function handleSpan(ctx, span) {
5187
5226
  ts,
5188
5227
  isError,
5189
5228
  callSiteEvidence,
5190
- durationMs
5229
+ durationMs,
5230
+ errorDetail
5191
5231
  );
5192
5232
  affectedNode = targetId;
5193
5233
  resolvedViaAddress = true;
@@ -5201,7 +5241,8 @@ async function handleSpan(ctx, span) {
5201
5241
  ts,
5202
5242
  isError,
5203
5243
  callSiteEvidence,
5204
- durationMs
5244
+ durationMs,
5245
+ errorDetail
5205
5246
  );
5206
5247
  affectedNode = frontierNodeId;
5207
5248
  resolvedViaAddress = true;
@@ -5228,7 +5269,8 @@ async function handleSpan(ctx, span) {
5228
5269
  ts,
5229
5270
  isError,
5230
5271
  fallbackEvidence,
5231
- durationMs
5272
+ durationMs,
5273
+ errorDetail
5232
5274
  );
5233
5275
  }
5234
5276
  }
@@ -5243,7 +5285,7 @@ async function handleSpan(ctx, span) {
5243
5285
  );
5244
5286
  if (routeNodeId) {
5245
5287
  const routeSvc = ctx.graph.getNodeAttributes(routeNodeId).service;
5246
- upsertObservedEdge(ctx.graph, EdgeType5.CONTAINS, serviceId(routeSvc), routeNodeId, ts, isError, void 0, durationMs);
5288
+ upsertObservedEdge(ctx.graph, EdgeType5.CONTAINS, serviceId(routeSvc), routeNodeId, ts, isError, void 0, durationMs, errorDetail);
5247
5289
  }
5248
5290
  }
5249
5291
  if (span.statusCode === 2) {
@@ -5726,19 +5768,19 @@ function confidenceFromMix(edges, now = Date.now()) {
5726
5768
  function longestIncomingWalk(graph, start, maxDepth) {
5727
5769
  let best = { path: [start], edges: [] };
5728
5770
  const visited = /* @__PURE__ */ new Set([start]);
5729
- function step(node, path77, edges) {
5730
- if (path77.length > best.path.length) {
5731
- best = { path: [...path77], edges: [...edges] };
5771
+ function step(node, path76, edges) {
5772
+ if (path76.length > best.path.length) {
5773
+ best = { path: [...path76], edges: [...edges] };
5732
5774
  }
5733
- if (path77.length - 1 >= maxDepth) return;
5775
+ if (path76.length - 1 >= maxDepth) return;
5734
5776
  const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
5735
5777
  for (const [srcId, edge] of incoming) {
5736
5778
  if (visited.has(srcId)) continue;
5737
5779
  visited.add(srcId);
5738
- path77.push(srcId);
5780
+ path76.push(srcId);
5739
5781
  edges.push(edge);
5740
- step(srcId, path77, edges);
5741
- path77.pop();
5782
+ step(srcId, path76, edges);
5783
+ path76.pop();
5742
5784
  edges.pop();
5743
5785
  visited.delete(srcId);
5744
5786
  }
@@ -5953,20 +5995,20 @@ function dominantFailingCall(graph, serviceId17, visited) {
5953
5995
  return best;
5954
5996
  }
5955
5997
  function followFailingCallChain(graph, originServiceId, maxDepth) {
5956
- const path77 = [originServiceId];
5998
+ const path76 = [originServiceId];
5957
5999
  const edges = [];
5958
6000
  const visited = /* @__PURE__ */ new Set([originServiceId]);
5959
6001
  let current = originServiceId;
5960
6002
  for (let depth = 0; depth < maxDepth; depth++) {
5961
6003
  const hop = dominantFailingCall(graph, current, visited);
5962
6004
  if (!hop) break;
5963
- path77.push(hop.nextService);
6005
+ path76.push(hop.nextService);
5964
6006
  edges.push(hop.edge);
5965
6007
  visited.add(hop.nextService);
5966
6008
  current = hop.nextService;
5967
6009
  }
5968
6010
  if (edges.length === 0) return null;
5969
- return { path: path77, edges, culprit: current };
6011
+ return { path: path76, edges, culprit: current };
5970
6012
  }
5971
6013
  function isStaleCallEdge(e) {
5972
6014
  return e.type === EdgeType6.CALLS && e.provenance === Provenance6.STALE;
@@ -6002,26 +6044,26 @@ function dominantStaleCall(graph, serviceId17, visited) {
6002
6044
  return best;
6003
6045
  }
6004
6046
  function followStaleCallChain(graph, originServiceId, maxDepth) {
6005
- const path77 = [originServiceId];
6047
+ const path76 = [originServiceId];
6006
6048
  const edges = [];
6007
6049
  const visited = /* @__PURE__ */ new Set([originServiceId]);
6008
6050
  let current = originServiceId;
6009
6051
  for (let depth = 0; depth < maxDepth; depth++) {
6010
6052
  const hop = dominantStaleCall(graph, current, visited);
6011
6053
  if (!hop) break;
6012
- path77.push(hop.nextService);
6054
+ path76.push(hop.nextService);
6013
6055
  edges.push(hop.edge);
6014
6056
  visited.add(hop.nextService);
6015
6057
  current = hop.nextService;
6016
6058
  }
6017
6059
  if (edges.length === 0) return null;
6018
- return { path: path77, edges, culprit: current };
6060
+ return { path: path76, edges, culprit: current };
6019
6061
  }
6020
6062
  function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6021
6063
  const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
6022
6064
  if (!chain) return null;
6023
6065
  const culprit = chain.culprit;
6024
- const path77 = [...chain.path];
6066
+ const path76 = [...chain.path];
6025
6067
  const edgeProvenances = chain.edges.map((e) => e.provenance);
6026
6068
  const baseConfidence = confidenceFromMix(chain.edges);
6027
6069
  const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
@@ -6029,14 +6071,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6029
6071
  if (loc) {
6030
6072
  let rootCauseNode = culprit;
6031
6073
  if (loc.fileNode) {
6032
- path77.push(loc.fileNode);
6074
+ path76.push(loc.fileNode);
6033
6075
  edgeProvenances.push(Provenance6.OBSERVED);
6034
6076
  rootCauseNode = loc.fileNode;
6035
6077
  }
6036
6078
  return RootCauseResultSchema.parse({
6037
6079
  rootCauseNode,
6038
6080
  rootCauseReason: loc.rootCauseReason,
6039
- traversalPath: path77,
6081
+ traversalPath: path76,
6040
6082
  edgeProvenances,
6041
6083
  confidence,
6042
6084
  ...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
@@ -6048,7 +6090,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6048
6090
  return RootCauseResultSchema.parse({
6049
6091
  rootCauseNode: culprit,
6050
6092
  rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
6051
- traversalPath: path77,
6093
+ traversalPath: path76,
6052
6094
  edgeProvenances,
6053
6095
  confidence,
6054
6096
  fixRecommendation: `Inspect ${culpritName}'s failing handler`
@@ -6701,10 +6743,10 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
6701
6743
  traversalPath = staleChain.path;
6702
6744
  edgeProvenances = staleChain.edges.map((e) => e.provenance);
6703
6745
  } else if (top.node !== seedNode) {
6704
- const path77 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
6705
- if (path77) {
6706
- traversalPath = path77.nodes;
6707
- edgeProvenances = path77.edges.map((e) => e.provenance);
6746
+ const path76 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
6747
+ if (path76) {
6748
+ traversalPath = path76.nodes;
6749
+ edgeProvenances = path76.edges.map((e) => e.provenance);
6708
6750
  } else {
6709
6751
  traversalPath = [errorNodeId, top.node];
6710
6752
  edgeProvenances = [top.provenance ?? Provenance6.OBSERVED];
@@ -16320,6 +16362,11 @@ function detectObservedFailingEdge(graph, bucket) {
16320
16362
  spanCount,
16321
16363
  errorCount,
16322
16364
  errorRate: clampConfidence(errorRate),
16365
+ // The bounded last-error exemplar rides the finding as evidence (ADR-236):
16366
+ // the error rate says HOW MUCH is failing, the exemplar says WHAT failed —
16367
+ // a timeout vs a deadlock vs a connection-refused, which `errorCount`
16368
+ // alone cannot name. Present only when the observed edge carries one.
16369
+ ...signal.lastError ? { lastError: signal.lastError } : {},
16323
16370
  confidence: OBSERVED_FAILING_CONFIDENCE,
16324
16371
  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.`,
16325
16372
  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."
@@ -16911,440 +16958,6 @@ function parseExtraProjects(raw) {
16911
16958
  return raw.split(",").map((p) => p.trim()).filter((p) => p.length > 0 && p !== DEFAULT_PROJECT);
16912
16959
  }
16913
16960
 
16914
- // src/registry.ts
16915
- import { promises as fs36 } from "fs";
16916
- import os2 from "os";
16917
- import path71 from "path";
16918
- import {
16919
- RegistryFileSchema
16920
- } from "@neat.is/types";
16921
- var LOCK_TIMEOUT_MS = 5e3;
16922
- var LOCK_RETRY_MS = 50;
16923
- function neatHome() {
16924
- const override = process.env.NEAT_HOME;
16925
- if (override && override.length > 0) return path71.resolve(override);
16926
- return path71.join(os2.homedir(), ".neat");
16927
- }
16928
- function registryPath() {
16929
- return path71.join(neatHome(), "projects.json");
16930
- }
16931
- function registryLockPath() {
16932
- return path71.join(neatHome(), "projects.json.lock");
16933
- }
16934
- function daemonPidPath() {
16935
- return path71.join(neatHome(), "neatd.pid");
16936
- }
16937
- function daemonsDir() {
16938
- return path71.join(neatHome(), "daemons");
16939
- }
16940
- function isFiniteInt(v) {
16941
- return typeof v === "number" && Number.isFinite(v);
16942
- }
16943
- function parseDaemonRecord(raw) {
16944
- let obj;
16945
- try {
16946
- obj = JSON.parse(raw);
16947
- } catch {
16948
- return void 0;
16949
- }
16950
- if (typeof obj !== "object" || obj === null) return void 0;
16951
- const r = obj;
16952
- const ports = r.ports;
16953
- if (typeof r.project !== "string" || typeof r.projectPath !== "string" || !isFiniteInt(r.pid) || r.status !== "running" && r.status !== "stopped" || typeof r.startedAt !== "string" || typeof r.neatVersion !== "string" || !ports || !isFiniteInt(ports.rest) || !isFiniteInt(ports.otlp) || !isFiniteInt(ports.web)) {
16954
- return void 0;
16955
- }
16956
- return {
16957
- project: r.project,
16958
- projectPath: r.projectPath,
16959
- pid: r.pid,
16960
- status: r.status,
16961
- ports: { rest: ports.rest, otlp: ports.otlp, web: ports.web },
16962
- startedAt: r.startedAt,
16963
- neatVersion: r.neatVersion
16964
- };
16965
- }
16966
- var defaultDiscoveryProbe = { isPidAlive: isPidAliveDefault };
16967
- async function discoverDaemons(probe = defaultDiscoveryProbe) {
16968
- const dir = daemonsDir();
16969
- let names;
16970
- try {
16971
- names = await fs36.readdir(dir);
16972
- } catch (err) {
16973
- if (err.code === "ENOENT") return [];
16974
- throw err;
16975
- }
16976
- const out = [];
16977
- for (const name of names) {
16978
- if (!name.endsWith(".json")) continue;
16979
- const file = path71.join(dir, name);
16980
- let raw;
16981
- try {
16982
- raw = await fs36.readFile(file, "utf8");
16983
- } catch {
16984
- continue;
16985
- }
16986
- const record = parseDaemonRecord(raw);
16987
- if (!record) continue;
16988
- const live = record.status === "running" && probe.isPidAlive(record.pid);
16989
- out.push({ record, live, source: file });
16990
- }
16991
- out.sort((a, b) => a.record.project.localeCompare(b.record.project));
16992
- return out;
16993
- }
16994
- async function removeDaemonRecord(source) {
16995
- await fs36.unlink(source).catch(() => {
16996
- });
16997
- }
16998
- async function listMachineProjects(probe = defaultDiscoveryProbe) {
16999
- const discovered = await discoverDaemons(probe);
17000
- const byPath = /* @__PURE__ */ new Map();
17001
- for (const d of discovered) {
17002
- const key = await normalizeProjectPath(d.record.projectPath);
17003
- byPath.set(key, {
17004
- project: d.record.project,
17005
- projectPath: d.record.projectPath,
17006
- state: d.live ? "running" : "stopped",
17007
- ports: d.record.ports,
17008
- pid: d.record.pid
17009
- });
17010
- }
17011
- let legacy = [];
17012
- try {
17013
- legacy = (await readRegistry()).projects;
17014
- } catch {
17015
- legacy = [];
17016
- }
17017
- for (const entry of legacy) {
17018
- const key = await normalizeProjectPath(entry.path);
17019
- if (byPath.has(key)) continue;
17020
- byPath.set(key, {
17021
- project: entry.name,
17022
- projectPath: entry.path,
17023
- state: "registered",
17024
- registryStatus: entry.status
17025
- });
17026
- }
17027
- return [...byPath.values()].sort((a, b) => a.project.localeCompare(b.project));
17028
- }
17029
- async function findDaemonByProject(name, probe = defaultDiscoveryProbe) {
17030
- const discovered = await discoverDaemons(probe);
17031
- return discovered.find((d) => d.record.project === name);
17032
- }
17033
- function signalDaemonStop(pid) {
17034
- try {
17035
- process.kill(pid, "SIGTERM");
17036
- return true;
17037
- } catch (err) {
17038
- if (err.code === "ESRCH") return false;
17039
- throw err;
17040
- }
17041
- }
17042
- function isPidAliveDefault(pid) {
17043
- try {
17044
- process.kill(pid, 0);
17045
- return true;
17046
- } catch (err) {
17047
- return err.code === "EPERM";
17048
- }
17049
- }
17050
- async function readPidFile(file) {
17051
- try {
17052
- const raw = await fs36.readFile(file, "utf8");
17053
- const pid = Number.parseInt(raw.trim(), 10);
17054
- return Number.isInteger(pid) && pid > 0 ? pid : void 0;
17055
- } catch {
17056
- return void 0;
17057
- }
17058
- }
17059
- var defaultLockHolderProbe = {
17060
- isPidAlive: isPidAliveDefault,
17061
- daemonPidFromFile: () => readPidFile(daemonPidPath()),
17062
- async daemonResponds() {
17063
- const base = process.env.NEAT_API_URL ?? "http://localhost:8080";
17064
- try {
17065
- await fetch(`${base}/health`, { signal: AbortSignal.timeout(750) });
17066
- return true;
17067
- } catch {
17068
- return false;
17069
- }
17070
- }
17071
- };
17072
- async function readLockPid(lockPath) {
17073
- return readPidFile(lockPath);
17074
- }
17075
- async function classifyLockHolder(lockPath, probe = defaultLockHolderProbe) {
17076
- const lockPid = await readLockPid(lockPath);
17077
- const daemonPid = await probe.daemonPidFromFile();
17078
- if (lockPid !== void 0 && lockPid !== process.pid && probe.isPidAlive(lockPid)) {
17079
- return { kind: lockPid === daemonPid ? "daemon" : "command", pid: lockPid };
17080
- }
17081
- if (daemonPid !== void 0 && daemonPid !== process.pid && probe.isPidAlive(daemonPid) && // Guards against a stale pidfile whose PID got reused.
17082
- await probe.daemonResponds()) {
17083
- return { kind: "daemon", pid: daemonPid };
17084
- }
17085
- return { kind: "stale" };
17086
- }
17087
- function lockHolderMessage(holder, lockPath, timeoutMs) {
17088
- switch (holder.kind) {
17089
- case "daemon":
17090
- return `The neat daemon (pid ${holder.pid}) is holding the registry lock. Register this project through the daemon, or stop neatd and re-run \`neat init\`.`;
17091
- case "command":
17092
- return `Another neat command (pid ${holder.pid}) is holding the registry lock. Wait for it to finish, or check \`ps\` if you're not sure what's running.`;
17093
- case "stale":
17094
- return `timed out after ${timeoutMs}ms waiting for ${lockPath}. Another neat process is holding the lock; if no such process exists, remove the file by hand.`;
17095
- }
17096
- }
17097
- async function normalizeProjectPath(input) {
17098
- const resolved = path71.resolve(input);
17099
- try {
17100
- return await fs36.realpath(resolved);
17101
- } catch {
17102
- return resolved;
17103
- }
17104
- }
17105
- async function writeAtomically(target, contents) {
17106
- await fs36.mkdir(path71.dirname(target), { recursive: true });
17107
- const tmp = `${target}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
17108
- const fd = await fs36.open(tmp, "w");
17109
- try {
17110
- await fd.writeFile(contents, "utf8");
17111
- await fd.sync();
17112
- } finally {
17113
- await fd.close();
17114
- }
17115
- await fs36.rename(tmp, target);
17116
- }
17117
- async function acquireLock(lockPath, timeoutMs = LOCK_TIMEOUT_MS, probe = defaultLockHolderProbe) {
17118
- const deadline = Date.now() + timeoutMs;
17119
- await fs36.mkdir(path71.dirname(lockPath), { recursive: true });
17120
- let probedHolder = false;
17121
- while (true) {
17122
- try {
17123
- const fd = await fs36.open(lockPath, "wx");
17124
- try {
17125
- await fd.writeFile(`${process.pid}
17126
- `, "utf8");
17127
- } finally {
17128
- await fd.close();
17129
- }
17130
- return;
17131
- } catch (err) {
17132
- const code = err.code;
17133
- if (code !== "EEXIST") throw err;
17134
- if (!probedHolder) {
17135
- probedHolder = true;
17136
- const holder = await classifyLockHolder(lockPath, probe);
17137
- if (holder.kind === "daemon") {
17138
- throw new RegistryLockError(lockHolderMessage(holder, lockPath, timeoutMs));
17139
- }
17140
- if (holder.kind === "stale" && await isReclaimableLock(lockPath)) {
17141
- await fs36.unlink(lockPath).catch(() => {
17142
- });
17143
- continue;
17144
- }
17145
- }
17146
- if (Date.now() >= deadline) {
17147
- const holder = await classifyLockHolder(lockPath, probe);
17148
- throw new RegistryLockError(lockHolderMessage(holder, lockPath, timeoutMs));
17149
- }
17150
- await new Promise((r) => setTimeout(r, LOCK_RETRY_MS));
17151
- }
17152
- }
17153
- }
17154
- var LOCK_UNSTAMPED_GRACE_MS = 5e3;
17155
- async function isReclaimableLock(lockPath) {
17156
- const pid = await readLockPid(lockPath);
17157
- if (pid !== void 0) return true;
17158
- try {
17159
- const stat = await fs36.stat(lockPath);
17160
- return Date.now() - stat.mtimeMs > LOCK_UNSTAMPED_GRACE_MS;
17161
- } catch {
17162
- return false;
17163
- }
17164
- }
17165
- async function releaseLock(lockPath) {
17166
- await fs36.unlink(lockPath).catch(() => {
17167
- });
17168
- }
17169
- async function withLock(fn) {
17170
- const lock = registryLockPath();
17171
- await acquireLock(lock);
17172
- try {
17173
- return await fn();
17174
- } finally {
17175
- await releaseLock(lock);
17176
- }
17177
- }
17178
- async function readRegistry() {
17179
- const file = registryPath();
17180
- let raw;
17181
- try {
17182
- raw = await fs36.readFile(file, "utf8");
17183
- } catch (err) {
17184
- if (err.code === "ENOENT") {
17185
- return { version: 1, projects: [] };
17186
- }
17187
- throw err;
17188
- }
17189
- const parsed = JSON.parse(raw);
17190
- return RegistryFileSchema.parse(parsed);
17191
- }
17192
- async function writeRegistry(reg) {
17193
- const validated = RegistryFileSchema.parse(reg);
17194
- await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
17195
- }
17196
- var RegistryError = class extends Error {
17197
- constructor(message) {
17198
- super(message);
17199
- this.name = "RegistryError";
17200
- }
17201
- };
17202
- var RegistryLockError = class extends RegistryError {
17203
- constructor(message) {
17204
- super(message);
17205
- this.name = "RegistryLockError";
17206
- }
17207
- };
17208
- var ProjectNameCollisionError = class extends RegistryError {
17209
- projectName;
17210
- constructor(name) {
17211
- super(`a project named "${name}" is already registered`);
17212
- this.name = "ProjectNameCollisionError";
17213
- this.projectName = name;
17214
- }
17215
- };
17216
- async function addProject(opts) {
17217
- const resolvedPath = await normalizeProjectPath(opts.path);
17218
- return withLock(async () => {
17219
- const reg = await readRegistry();
17220
- const byName = reg.projects.find((p) => p.name === opts.name);
17221
- const byPath = reg.projects.find((p) => p.path === resolvedPath);
17222
- if (byName && byName.path !== resolvedPath) {
17223
- throw new ProjectNameCollisionError(opts.name);
17224
- }
17225
- const now = (/* @__PURE__ */ new Date()).toISOString();
17226
- if (byName && byName.path === resolvedPath) {
17227
- byName.lastSeenAt = now;
17228
- if (opts.languages) byName.languages = opts.languages;
17229
- if (opts.status) byName.status = opts.status;
17230
- await writeRegistry(reg);
17231
- return byName;
17232
- }
17233
- if (byPath && byPath.name !== opts.name) {
17234
- throw new ProjectNameCollisionError(byPath.name);
17235
- }
17236
- const entry = {
17237
- name: opts.name,
17238
- path: resolvedPath,
17239
- registeredAt: now,
17240
- languages: opts.languages ?? [],
17241
- status: opts.status ?? "active"
17242
- };
17243
- reg.projects.push(entry);
17244
- await writeRegistry(reg);
17245
- return entry;
17246
- });
17247
- }
17248
- async function getProject(name) {
17249
- const reg = await readRegistry();
17250
- return reg.projects.find((p) => p.name === name);
17251
- }
17252
- async function findProjectByPath(dir) {
17253
- const here = await normalizeProjectPath(dir);
17254
- const { projects } = await readRegistry();
17255
- let best;
17256
- for (const entry of projects) {
17257
- const inside = here === entry.path || here.startsWith(entry.path + path71.sep);
17258
- if (inside && (!best || entry.path.length > best.path.length)) best = entry;
17259
- }
17260
- return best;
17261
- }
17262
- async function listProjects() {
17263
- const reg = await readRegistry();
17264
- return reg.projects;
17265
- }
17266
- async function setStatus(name, status) {
17267
- return withLock(async () => {
17268
- const reg = await readRegistry();
17269
- const entry = reg.projects.find((p) => p.name === name);
17270
- if (!entry) throw new RegistryError(`no project named "${name}"`);
17271
- entry.status = status;
17272
- await writeRegistry(reg);
17273
- return entry;
17274
- });
17275
- }
17276
- async function touchLastSeen(name, at = (/* @__PURE__ */ new Date()).toISOString()) {
17277
- await withLock(async () => {
17278
- const reg = await readRegistry();
17279
- const entry = reg.projects.find((p) => p.name === name);
17280
- if (!entry) return;
17281
- entry.lastSeenAt = at;
17282
- await writeRegistry(reg);
17283
- });
17284
- }
17285
- async function removeProject(name) {
17286
- return withLock(async () => {
17287
- const reg = await readRegistry();
17288
- const idx = reg.projects.findIndex((p) => p.name === name);
17289
- if (idx < 0) return void 0;
17290
- const [removed] = reg.projects.splice(idx, 1);
17291
- await writeRegistry(reg);
17292
- return removed;
17293
- });
17294
- }
17295
- var DAY_MS2 = 24 * 60 * 60 * 1e3;
17296
- var DEFAULT_PRUNE_TTL_MS = 7 * DAY_MS2;
17297
- function pruneTtlMs() {
17298
- const raw = process.env.NEAT_REGISTRY_PRUNE_TTL_MS;
17299
- if (!raw) return DEFAULT_PRUNE_TTL_MS;
17300
- const n = Number.parseInt(raw, 10);
17301
- if (Number.isFinite(n) && n >= 0) return n;
17302
- console.warn(
17303
- `[neat] NEAT_REGISTRY_PRUNE_TTL_MS could not be parsed (${raw}); using default ${DEFAULT_PRUNE_TTL_MS}ms`
17304
- );
17305
- return DEFAULT_PRUNE_TTL_MS;
17306
- }
17307
- async function statPathStatus(p) {
17308
- try {
17309
- const stat = await fs36.stat(p);
17310
- return stat.isDirectory() ? "present" : "unknown";
17311
- } catch (err) {
17312
- return err.code === "ENOENT" ? "gone" : "unknown";
17313
- }
17314
- }
17315
- async function pruneRegistry(opts = {}) {
17316
- const ttlMs = opts.ttlMs ?? pruneTtlMs();
17317
- const statPath = opts.statPath ?? statPathStatus;
17318
- const now = opts.now ?? Date.now;
17319
- return withLock(async () => {
17320
- const reg = await readRegistry();
17321
- const removed = [];
17322
- const kept = [];
17323
- for (const entry of reg.projects) {
17324
- const status = await statPath(entry.path);
17325
- if (status !== "gone") {
17326
- kept.push(entry);
17327
- continue;
17328
- }
17329
- if (ttlMs <= 0) {
17330
- removed.push(entry);
17331
- continue;
17332
- }
17333
- const lastSeen = Date.parse(entry.lastSeenAt ?? entry.registeredAt);
17334
- const age = now() - (Number.isFinite(lastSeen) ? lastSeen : 0);
17335
- if (age > ttlMs) {
17336
- removed.push(entry);
17337
- } else {
17338
- kept.push(entry);
17339
- }
17340
- }
17341
- if (removed.length === 0) return [];
17342
- reg.projects = kept;
17343
- await writeRegistry(reg);
17344
- return removed;
17345
- });
17346
- }
17347
-
17348
16961
  // src/api.ts
17349
16962
  import Fastify from "fastify";
17350
16963
  import { timingSafeEqual } from "crypto";
@@ -17352,14 +16965,14 @@ import cors from "@fastify/cors";
17352
16965
  import { DivergenceTypeSchema, PoliciesCheckBodySchema, PolicySeveritySchema } from "@neat.is/types";
17353
16966
 
17354
16967
  // src/extend/index.ts
17355
- import { promises as fs38 } from "fs";
17356
- import path73 from "path";
17357
- import os3 from "os";
16968
+ import { promises as fs37 } from "fs";
16969
+ import path72 from "path";
16970
+ import os2 from "os";
17358
16971
  import { resolve as registryResolve, list as registryList } from "@neat.is/instrumentation-registry";
17359
16972
 
17360
16973
  // src/installers/package-manager.ts
17361
- import { promises as fs37 } from "fs";
17362
- import path72 from "path";
16974
+ import { promises as fs36 } from "fs";
16975
+ import path71 from "path";
17363
16976
  import { spawn } from "child_process";
17364
16977
  var LOCKFILE_PRIORITY = [
17365
16978
  { lockfile: "bun.lockb", pm: "bun", args: ["install", "--no-summary"] },
@@ -17374,29 +16987,29 @@ var LOCKFILE_PRIORITY = [
17374
16987
  var NPM_FALLBACK_ARGS = ["install", "--no-audit", "--no-fund", "--prefer-offline"];
17375
16988
  async function exists2(p) {
17376
16989
  try {
17377
- await fs37.access(p);
16990
+ await fs36.access(p);
17378
16991
  return true;
17379
16992
  } catch {
17380
16993
  return false;
17381
16994
  }
17382
16995
  }
17383
16996
  async function detectPackageManager(serviceDir) {
17384
- let dir = path72.resolve(serviceDir);
16997
+ let dir = path71.resolve(serviceDir);
17385
16998
  const stops = /* @__PURE__ */ new Set();
17386
16999
  for (let i = 0; i < 64; i++) {
17387
17000
  if (stops.has(dir)) break;
17388
17001
  stops.add(dir);
17389
17002
  for (const candidate of LOCKFILE_PRIORITY) {
17390
- const lockPath = path72.join(dir, candidate.lockfile);
17003
+ const lockPath = path71.join(dir, candidate.lockfile);
17391
17004
  if (await exists2(lockPath)) {
17392
17005
  return { pm: candidate.pm, cwd: dir, args: [...candidate.args] };
17393
17006
  }
17394
17007
  }
17395
- const parent = path72.dirname(dir);
17008
+ const parent = path71.dirname(dir);
17396
17009
  if (parent === dir) break;
17397
17010
  dir = parent;
17398
17011
  }
17399
- return { pm: "npm", cwd: path72.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
17012
+ return { pm: "npm", cwd: path71.resolve(serviceDir), args: [...NPM_FALLBACK_ARGS] };
17400
17013
  }
17401
17014
  async function runPackageManagerInstall(cmd) {
17402
17015
  return new Promise((resolve) => {
@@ -17438,15 +17051,15 @@ ${err.message}`
17438
17051
  // src/extend/index.ts
17439
17052
  async function fileExists2(p) {
17440
17053
  try {
17441
- await fs38.access(p);
17054
+ await fs37.access(p);
17442
17055
  return true;
17443
17056
  } catch {
17444
17057
  return false;
17445
17058
  }
17446
17059
  }
17447
17060
  async function readPackageJson(scanPath) {
17448
- const pkgPath = path73.join(scanPath, "package.json");
17449
- const raw = await fs38.readFile(pkgPath, "utf8");
17061
+ const pkgPath = path72.join(scanPath, "package.json");
17062
+ const raw = await fs37.readFile(pkgPath, "utf8");
17450
17063
  return JSON.parse(raw);
17451
17064
  }
17452
17065
  var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
@@ -17460,15 +17073,15 @@ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
17460
17073
  async function findHookFiles(scanPath) {
17461
17074
  const found = [];
17462
17075
  const walk11 = async (dir) => {
17463
- const entries = await fs38.readdir(dir, { withFileTypes: true }).catch(() => []);
17076
+ const entries = await fs37.readdir(dir, { withFileTypes: true }).catch(() => []);
17464
17077
  for (const entry of entries) {
17465
17078
  if (entry.isDirectory()) {
17466
17079
  if (entry.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry.name)) continue;
17467
- await walk11(path73.join(dir, entry.name));
17080
+ await walk11(path72.join(dir, entry.name));
17468
17081
  } else if (entry.isFile()) {
17469
17082
  if ((entry.name.startsWith("instrumentation") || entry.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry.name)) {
17470
- const rel = path73.relative(scanPath, path73.join(dir, entry.name));
17471
- found.push(rel.split(path73.sep).join("/"));
17083
+ const rel = path72.relative(scanPath, path72.join(dir, entry.name));
17084
+ found.push(rel.split(path72.sep).join("/"));
17472
17085
  }
17473
17086
  }
17474
17087
  }
@@ -17479,7 +17092,7 @@ async function findHookFiles(scanPath) {
17479
17092
  async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
17480
17093
  let fallback = null;
17481
17094
  for (const file of hookFiles) {
17482
- const content = await fs38.readFile(path73.join(scanPath, file), "utf8");
17095
+ const content = await fs37.readFile(path72.join(scanPath, file), "utf8");
17483
17096
  const patched = splicedContent(content, snippet2);
17484
17097
  if (patched !== null) return { file, content, patched };
17485
17098
  if (fallback === null) fallback = { file, content };
@@ -17487,12 +17100,12 @@ async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
17487
17100
  return { file: fallback.file, content: fallback.content, patched: null };
17488
17101
  }
17489
17102
  function extendLogPath() {
17490
- return process.env.NEAT_EXTEND_LOG ?? path73.join(os3.homedir(), ".neat", "extend-log.ndjson");
17103
+ return process.env.NEAT_EXTEND_LOG ?? path72.join(os2.homedir(), ".neat", "extend-log.ndjson");
17491
17104
  }
17492
17105
  async function appendExtendLog(entry) {
17493
17106
  const logPath = extendLogPath();
17494
- await fs38.mkdir(path73.dirname(logPath), { recursive: true });
17495
- await fs38.appendFile(logPath, JSON.stringify(entry) + "\n", "utf8");
17107
+ await fs37.mkdir(path72.dirname(logPath), { recursive: true });
17108
+ await fs37.appendFile(logPath, JSON.stringify(entry) + "\n", "utf8");
17496
17109
  }
17497
17110
  function splicedContent(fileContent, snippet2) {
17498
17111
  if (fileContent.includes("__INSTRUMENTATION_BLOCK__")) {
@@ -17550,7 +17163,7 @@ function lookupInstrumentation(library, installedVersion) {
17550
17163
  }
17551
17164
  async function describeProjectInstrumentation(ctx) {
17552
17165
  const hookFiles = await findHookFiles(ctx.scanPath);
17553
- const envNeat = await fileExists2(path73.join(ctx.scanPath, ".env.neat"));
17166
+ const envNeat = await fileExists2(path72.join(ctx.scanPath, ".env.neat"));
17554
17167
  const registryInstrPackages = new Set(
17555
17168
  registryList().map((e) => e.instrumentation_package).filter((p) => !!p)
17556
17169
  );
@@ -17572,7 +17185,7 @@ async function applyExtension(ctx, args, options) {
17572
17185
  );
17573
17186
  }
17574
17187
  for (const file of hookFiles) {
17575
- const content = await fs38.readFile(path73.join(ctx.scanPath, file), "utf8");
17188
+ const content = await fs37.readFile(path72.join(ctx.scanPath, file), "utf8");
17576
17189
  if (content.includes(args.registration_snippet)) {
17577
17190
  return { library: args.library, filesTouched: [], depsAdded: [], installOutput: "", alreadyApplied: true };
17578
17191
  }
@@ -17584,18 +17197,18 @@ async function applyExtension(ctx, args, options) {
17584
17197
  );
17585
17198
  }
17586
17199
  const primaryFile = primary.file;
17587
- const primaryPath = path73.join(ctx.scanPath, primaryFile);
17200
+ const primaryPath = path72.join(ctx.scanPath, primaryFile);
17588
17201
  const filesTouched = [];
17589
17202
  const depsAdded = [];
17590
- const pkgPath = path73.join(ctx.scanPath, "package.json");
17203
+ const pkgPath = path72.join(ctx.scanPath, "package.json");
17591
17204
  const pkg = await readPackageJson(ctx.scanPath);
17592
17205
  if (!(pkg.dependencies ?? {})[args.instrumentation_package]) {
17593
17206
  pkg.dependencies = { ...pkg.dependencies ?? {}, [args.instrumentation_package]: args.version };
17594
- await fs38.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
17207
+ await fs37.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
17595
17208
  filesTouched.push("package.json");
17596
17209
  depsAdded.push(`${args.instrumentation_package}@${args.version}`);
17597
17210
  }
17598
- await fs38.writeFile(primaryPath, primary.patched, "utf8");
17211
+ await fs37.writeFile(primaryPath, primary.patched, "utf8");
17599
17212
  filesTouched.push(primaryFile);
17600
17213
  const cmd = await detectPackageManager(ctx.scanPath);
17601
17214
  const installer = options?.runInstall ?? runPackageManagerInstall;
@@ -17626,7 +17239,7 @@ async function dryRunExtension(ctx, args) {
17626
17239
  };
17627
17240
  }
17628
17241
  for (const file of hookFiles) {
17629
- const content = await fs38.readFile(path73.join(ctx.scanPath, file), "utf8");
17242
+ const content = await fs37.readFile(path72.join(ctx.scanPath, file), "utf8");
17630
17243
  if (content.includes(args.registration_snippet)) {
17631
17244
  return {
17632
17245
  library: args.library,
@@ -17661,28 +17274,28 @@ async function rollbackExtension(ctx, args) {
17661
17274
  if (!await fileExists2(logPath)) {
17662
17275
  return { undone: false, message: "no apply found for library" };
17663
17276
  }
17664
- const raw = await fs38.readFile(logPath, "utf8");
17277
+ const raw = await fs37.readFile(logPath, "utf8");
17665
17278
  const entries = raw.trim().split("\n").filter(Boolean).map((line) => JSON.parse(line));
17666
17279
  const match = [...entries].reverse().find((e) => e.project === ctx.project && e.library === args.library);
17667
17280
  if (!match) {
17668
17281
  return { undone: false, message: "no apply found for library" };
17669
17282
  }
17670
- const pkgPath = path73.join(ctx.scanPath, "package.json");
17283
+ const pkgPath = path72.join(ctx.scanPath, "package.json");
17671
17284
  if (await fileExists2(pkgPath)) {
17672
17285
  const pkg = await readPackageJson(ctx.scanPath);
17673
17286
  if (pkg.dependencies?.[match.instrumentation_package]) {
17674
17287
  const { [match.instrumentation_package]: _removed, ...rest } = pkg.dependencies;
17675
17288
  pkg.dependencies = rest;
17676
- await fs38.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
17289
+ await fs37.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
17677
17290
  }
17678
17291
  }
17679
17292
  const hookFiles = await findHookFiles(ctx.scanPath);
17680
17293
  for (const file of hookFiles) {
17681
- const filePath = path73.join(ctx.scanPath, file);
17682
- const content = await fs38.readFile(filePath, "utf8");
17294
+ const filePath = path72.join(ctx.scanPath, file);
17295
+ const content = await fs37.readFile(filePath, "utf8");
17683
17296
  if (content.includes(match.registration_snippet)) {
17684
17297
  const filtered = content.split("\n").filter((line) => !line.includes(match.registration_snippet)).join("\n");
17685
- await fs38.writeFile(filePath, filtered, "utf8");
17298
+ await fs37.writeFile(filePath, filtered, "utf8");
17686
17299
  break;
17687
17300
  }
17688
17301
  }
@@ -18777,9 +18390,9 @@ data: ${JSON.stringify(envelope.payload)}
18777
18390
 
18778
18391
  // src/pr-verdict.ts
18779
18392
  import { createHash } from "crypto";
18780
- import { promises as fs39 } from "fs";
18781
- import os5 from "os";
18782
- import path75 from "path";
18393
+ import { promises as fs38 } from "fs";
18394
+ import os4 from "os";
18395
+ import path74 from "path";
18783
18396
 
18784
18397
  // ../action/src/graph.mjs
18785
18398
  import { readFileSync as readFileSync3 } from "fs";
@@ -19054,8 +18667,8 @@ function renderVerdict({
19054
18667
  import { PrVerdictBodySchema } from "@neat.is/types";
19055
18668
 
19056
18669
  // src/connectors/hosted-repos.ts
19057
- import os4 from "os";
19058
- import path74 from "path";
18670
+ import os3 from "os";
18671
+ import path73 from "path";
19059
18672
  import { mkdtemp, rm } from "fs/promises";
19060
18673
  var CP_REQUEST_TIMEOUT_MS = 1e4;
19061
18674
  var DEFAULT_SYNC_INTERVAL_MS = 5 * 6e4;
@@ -19084,7 +18697,7 @@ async function cpPostStatus(deps, owner, name, body) {
19084
18697
  if (!res.ok && res.status !== 404) throw new Error(`control plane status POST \u2192 HTTP ${res.status}`);
19085
18698
  }
19086
18699
  var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
19087
- const [{ default: git }, httpMod, fs41] = await Promise.all([
18700
+ const [{ default: git }, httpMod, fs40] = await Promise.all([
19088
18701
  import("isomorphic-git"),
19089
18702
  import("isomorphic-git/http/node"),
19090
18703
  import("fs")
@@ -19095,7 +18708,7 @@ var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
19095
18708
  const username = parsed.password ? parsed.username : "x-access-token";
19096
18709
  const cleanUrl = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
19097
18710
  const clone = git.clone({
19098
- fs: fs41,
18711
+ fs: fs40,
19099
18712
  http,
19100
18713
  dir: destDir,
19101
18714
  url: cleanUrl,
@@ -19116,7 +18729,7 @@ var defaultCloneRepo = async (cloneUrl, ref, destDir) => {
19116
18729
  }
19117
18730
  };
19118
18731
  var defaultCloneCommit = async (cloneUrl, sha, destDir) => {
19119
- const [{ default: git }, httpMod, fs41] = await Promise.all([
18732
+ const [{ default: git }, httpMod, fs40] = await Promise.all([
19120
18733
  import("isomorphic-git"),
19121
18734
  import("isomorphic-git/http/node"),
19122
18735
  import("fs")
@@ -19127,10 +18740,10 @@ var defaultCloneCommit = async (cloneUrl, sha, destDir) => {
19127
18740
  const username = parsed.password ? parsed.username : "x-access-token";
19128
18741
  const cleanUrl = `${parsed.protocol}//${parsed.host}${parsed.pathname}`;
19129
18742
  const clone = (async () => {
19130
- await git.init({ fs: fs41, dir: destDir });
19131
- await git.addRemote({ fs: fs41, dir: destDir, remote: "origin", url: cleanUrl });
18743
+ await git.init({ fs: fs40, dir: destDir });
18744
+ await git.addRemote({ fs: fs40, dir: destDir, remote: "origin", url: cleanUrl });
19132
18745
  await git.fetch({
19133
- fs: fs41,
18746
+ fs: fs40,
19134
18747
  http,
19135
18748
  dir: destDir,
19136
18749
  remote: "origin",
@@ -19142,7 +18755,7 @@ var defaultCloneCommit = async (cloneUrl, sha, destDir) => {
19142
18755
  tags: false,
19143
18756
  ...password ? { onAuth: () => ({ username, password }) } : {}
19144
18757
  });
19145
- await git.checkout({ fs: fs41, dir: destDir, ref: sha, force: true });
18758
+ await git.checkout({ fs: fs40, dir: destDir, ref: sha, force: true });
19146
18759
  })();
19147
18760
  clone.catch(() => {
19148
18761
  });
@@ -19167,10 +18780,10 @@ async function syncOneRepo(r, input) {
19167
18780
  const cloneRepo = input.cloneRepo ?? defaultCloneRepo;
19168
18781
  const extract = input.extract ?? extractFromDirectory;
19169
18782
  const label = `${r.owner}/${r.name}`;
19170
- const tmpRoot = input.tmpRoot ?? os4.tmpdir();
18783
+ const tmpRoot = input.tmpRoot ?? os3.tmpdir();
19171
18784
  let dir;
19172
18785
  try {
19173
- dir = await mkdtemp(path74.join(tmpRoot, "neat-repo-"));
18786
+ dir = await mkdtemp(path73.join(tmpRoot, "neat-repo-"));
19174
18787
  await cpPostStatus(deps, r.owner, r.name, { syncStatus: "syncing", detail: "cloning" }).catch(() => {
19175
18788
  });
19176
18789
  await cloneRepo(r.cloneUrl, r.defaultBranch, dir);
@@ -19339,9 +18952,9 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19339
18952
  const startedAt = now();
19340
18953
  const cloneCommit = deps.cloneCommit ?? defaultCloneCommit;
19341
18954
  const extract = deps.extract ?? extractFromDirectory;
19342
- const root = await fs39.mkdtemp(path75.join(deps.tmpRoot ?? os5.tmpdir(), "neat-pr-"));
19343
- const baseDir = path75.join(root, "base");
19344
- const headDir = path75.join(root, "head");
18955
+ const root = await fs38.mkdtemp(path74.join(deps.tmpRoot ?? os4.tmpdir(), "neat-pr-"));
18956
+ const baseDir = path74.join(root, "base");
18957
+ const headDir = path74.join(root, "head");
19345
18958
  const stage = async (name, run) => {
19346
18959
  const left = deadline - now();
19347
18960
  if (left <= 0) throw new PrVerdictError(`verdict ran out of time before ${name}`, 504, name);
@@ -19364,8 +18977,8 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19364
18977
  };
19365
18978
  const extractOpts = { source: `${req.owner}/${req.name}`, announce: false };
19366
18979
  try {
19367
- await fs39.mkdir(baseDir);
19368
- await fs39.mkdir(headDir);
18980
+ await fs38.mkdir(baseDir);
18981
+ await fs38.mkdir(headDir);
19369
18982
  await stage("clone-base", () => cloneCommit(req.cloneUrl, req.baseSha, baseDir));
19370
18983
  await stage("clone-head", () => cloneCommit(req.cloneUrl, req.headSha, headDir));
19371
18984
  const baseGraph = makeGraph();
@@ -19387,7 +19000,7 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19387
19000
  const found = observedBreakFrom(node, getObservedDependencies(ctx.liveGraph, node.id));
19388
19001
  if (found) observedBreaks.push(found);
19389
19002
  }
19390
- const { marker, body } = renderVerdict({
19003
+ const { marker, body: rendered } = renderVerdict({
19391
19004
  graph: head,
19392
19005
  delta,
19393
19006
  changedFiles,
@@ -19395,6 +19008,7 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19395
19008
  observedBreaks,
19396
19009
  tone: req.tone ?? "loud"
19397
19010
  });
19011
+ const body = rendered.startsWith(marker) ? rendered.slice(marker.length).replace(/^(?:\r?\n)+/, "") : rendered;
19398
19012
  return {
19399
19013
  marker,
19400
19014
  body,
@@ -19406,7 +19020,7 @@ async function computePrVerdict(req, ctx, deps, deadline) {
19406
19020
  durationMs: now() - startedAt
19407
19021
  };
19408
19022
  } finally {
19409
- await fs39.rm(root, { recursive: true, force: true }).catch(() => {
19023
+ await fs38.rm(root, { recursive: true, force: true }).catch(() => {
19410
19024
  });
19411
19025
  }
19412
19026
  }
@@ -19414,13 +19028,13 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "neat-out"]);
19414
19028
  async function hashTree(dir) {
19415
19029
  const out = /* @__PURE__ */ new Map();
19416
19030
  const walk11 = async (rel) => {
19417
- const entries = await fs39.readdir(path75.join(dir, rel), { withFileTypes: true }).catch(() => []);
19031
+ const entries = await fs38.readdir(path74.join(dir, rel), { withFileTypes: true }).catch(() => []);
19418
19032
  for (const entry of entries) {
19419
19033
  const child = rel ? `${rel}/${entry.name}` : entry.name;
19420
19034
  if (entry.isDirectory()) {
19421
19035
  if (!SKIP_DIRS.has(entry.name)) await walk11(child);
19422
19036
  } else if (entry.isFile()) {
19423
- const bytes = await fs39.readFile(path75.join(dir, child)).catch(() => null);
19037
+ const bytes = await fs38.readFile(path74.join(dir, child)).catch(() => null);
19424
19038
  if (bytes) out.set(child, createHash("sha1").update(bytes).digest("hex"));
19425
19039
  }
19426
19040
  }
@@ -19437,9 +19051,9 @@ async function changedPathsBetween(baseDir, headDir) {
19437
19051
  }
19438
19052
 
19439
19053
  // src/connectors-config.ts
19440
- import os6 from "os";
19441
- import path76 from "path";
19442
- import { promises as fs40 } from "fs";
19054
+ import os5 from "os";
19055
+ import path75 from "path";
19056
+ import { promises as fs39 } from "fs";
19443
19057
  var CONNECTORS_CONFIG_VERSION = 1;
19444
19058
  var EnvRefUnsetError = class extends Error {
19445
19059
  ref;
@@ -19451,19 +19065,19 @@ var EnvRefUnsetError = class extends Error {
19451
19065
  this.varName = varName;
19452
19066
  }
19453
19067
  };
19454
- function neatHome2() {
19068
+ function neatHome() {
19455
19069
  const override = process.env.NEAT_HOME;
19456
- if (override && override.length > 0) return path76.resolve(override);
19457
- return path76.join(os6.homedir(), ".neat");
19070
+ if (override && override.length > 0) return path75.resolve(override);
19071
+ return path75.join(os5.homedir(), ".neat");
19458
19072
  }
19459
- function connectorsConfigPath(home = neatHome2()) {
19460
- return path76.join(home, "connectors.json");
19073
+ function connectorsConfigPath(home = neatHome()) {
19074
+ return path75.join(home, "connectors.json");
19461
19075
  }
19462
19076
  var MODE_MASK_LOOSER_THAN_0600 = 63;
19463
19077
  async function warnIfModeLooserThan0600(file) {
19464
19078
  if (process.platform === "win32") return;
19465
19079
  try {
19466
- const stat = await fs40.stat(file);
19080
+ const stat = await fs39.stat(file);
19467
19081
  if ((stat.mode & MODE_MASK_LOOSER_THAN_0600) !== 0) {
19468
19082
  const mode = (stat.mode & 511).toString(8).padStart(3, "0");
19469
19083
  console.warn(
@@ -19473,11 +19087,11 @@ async function warnIfModeLooserThan0600(file) {
19473
19087
  } catch {
19474
19088
  }
19475
19089
  }
19476
- async function readConnectorsConfig(home = neatHome2()) {
19090
+ async function readConnectorsConfig(home = neatHome()) {
19477
19091
  const file = connectorsConfigPath(home);
19478
19092
  let raw;
19479
19093
  try {
19480
- raw = await fs40.readFile(file, "utf8");
19094
+ raw = await fs39.readFile(file, "utf8");
19481
19095
  } catch (err) {
19482
19096
  if (err.code === "ENOENT") {
19483
19097
  return { version: CONNECTORS_CONFIG_VERSION, connectors: [] };
@@ -19587,8 +19201,8 @@ function connectorMatchesProject(entry, project) {
19587
19201
  }
19588
19202
  var CONNECTORS_LOCK_TIMEOUT_MS = 5e3;
19589
19203
  var CONNECTORS_LOCK_RETRY_MS = 50;
19590
- function connectorsConfigLockPath(home = neatHome2()) {
19591
- return path76.join(home, "connectors.json.lock");
19204
+ function connectorsConfigLockPath(home = neatHome()) {
19205
+ return path75.join(home, "connectors.json.lock");
19592
19206
  }
19593
19207
  function isEnvRef(value) {
19594
19208
  return value.length > 1 && value.startsWith("$");
@@ -19601,9 +19215,9 @@ function redactCredentialRef(ref) {
19601
19215
  return out;
19602
19216
  }
19603
19217
  async function writeConfigAtomically0600(file, contents) {
19604
- await fs40.mkdir(path76.dirname(file), { recursive: true });
19218
+ await fs39.mkdir(path75.dirname(file), { recursive: true });
19605
19219
  const tmp = `${file}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
19606
- const fd = await fs40.open(tmp, "w", 384);
19220
+ const fd = await fs39.open(tmp, "w", 384);
19607
19221
  try {
19608
19222
  await fd.writeFile(contents, "utf8");
19609
19223
  await fd.chmod(384);
@@ -19611,14 +19225,14 @@ async function writeConfigAtomically0600(file, contents) {
19611
19225
  } finally {
19612
19226
  await fd.close();
19613
19227
  }
19614
- await fs40.rename(tmp, file);
19228
+ await fs39.rename(tmp, file);
19615
19229
  }
19616
19230
  async function acquireConnectorsLock(lockPath, timeoutMs = CONNECTORS_LOCK_TIMEOUT_MS) {
19617
19231
  const deadline = Date.now() + timeoutMs;
19618
- await fs40.mkdir(path76.dirname(lockPath), { recursive: true });
19232
+ await fs39.mkdir(path75.dirname(lockPath), { recursive: true });
19619
19233
  for (; ; ) {
19620
19234
  try {
19621
- const fd = await fs40.open(lockPath, "wx");
19235
+ const fd = await fs39.open(lockPath, "wx");
19622
19236
  try {
19623
19237
  await fd.writeFile(`${process.pid}
19624
19238
  `, "utf8");
@@ -19638,7 +19252,7 @@ async function acquireConnectorsLock(lockPath, timeoutMs = CONNECTORS_LOCK_TIMEO
19638
19252
  }
19639
19253
  }
19640
19254
  async function releaseConnectorsLock(lockPath) {
19641
- await fs40.unlink(lockPath).catch(() => {
19255
+ await fs39.unlink(lockPath).catch(() => {
19642
19256
  });
19643
19257
  }
19644
19258
  async function withConnectorsLock(home, fn) {
@@ -19657,7 +19271,7 @@ function serializeConfig(config) {
19657
19271
  2
19658
19272
  ) + "\n";
19659
19273
  }
19660
- async function upsertConnectorEntry(entry, home = neatHome2()) {
19274
+ async function upsertConnectorEntry(entry, home = neatHome()) {
19661
19275
  const file = connectorsConfigPath(home);
19662
19276
  return withConnectorsLock(home, async () => {
19663
19277
  const config = await readConnectorsConfig(home);
@@ -19670,7 +19284,7 @@ async function upsertConnectorEntry(entry, home = neatHome2()) {
19670
19284
  return { replaced };
19671
19285
  });
19672
19286
  }
19673
- async function removeConnectorEntry(id, home = neatHome2()) {
19287
+ async function removeConnectorEntry(id, home = neatHome()) {
19674
19288
  const file = connectorsConfigPath(home);
19675
19289
  return withConnectorsLock(home, async () => {
19676
19290
  const config = await readConnectorsConfig(home);
@@ -20378,10 +19992,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
20378
19992
  // src/connectors/supabase/map.ts
20379
19993
  var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
20380
19994
  var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
20381
- function targetFromRestPath(path77) {
20382
- const rpcMatch = REST_RPC_PATH_RE.exec(path77);
19995
+ function targetFromRestPath(path76) {
19996
+ const rpcMatch = REST_RPC_PATH_RE.exec(path76);
20383
19997
  if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
20384
- const tableMatch = REST_TABLE_PATH_RE.exec(path77);
19998
+ const tableMatch = REST_TABLE_PATH_RE.exec(path76);
20385
19999
  if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
20386
20000
  return null;
20387
20001
  }
@@ -20976,9 +20590,9 @@ function parseFirebaseTargetName(targetName) {
20976
20590
  const secondSep = rest.indexOf(FIELD_SEP);
20977
20591
  if (secondSep === -1) return null;
20978
20592
  const method = rest.slice(0, secondSep);
20979
- const path77 = rest.slice(secondSep + 1);
20980
- if (!resourceName || !method || !path77) return null;
20981
- return { resourceName, method, path: path77 };
20593
+ const path76 = rest.slice(secondSep + 1);
20594
+ if (!resourceName || !method || !path76) return null;
20595
+ return { resourceName, method, path: path76 };
20982
20596
  }
20983
20597
  function resourceNameFor(type, labels) {
20984
20598
  if (!labels) return null;
@@ -21016,14 +20630,14 @@ function mapLogEntryToSignal(entry) {
21016
20630
  if (!req) return null;
21017
20631
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
21018
20632
  const method = req.requestMethod.toUpperCase();
21019
- const path77 = pathFromRequestUrl(req.requestUrl);
21020
- if (path77 === null) return null;
20633
+ const path76 = pathFromRequestUrl(req.requestUrl);
20634
+ if (path76 === null) return null;
21021
20635
  const timestamp = entry.timestamp;
21022
20636
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
21023
20637
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
21024
20638
  return {
21025
20639
  targetKind: resourceType,
21026
- targetName: packFirebaseTargetName({ resourceName, method, path: path77 }),
20640
+ targetName: packFirebaseTargetName({ resourceName, method, path: path76 }),
21027
20641
  callCount: 1,
21028
20642
  errorCount: isError ? 1 : 0,
21029
20643
  lastObservedIso: timestamp
@@ -21046,9 +20660,9 @@ import { NodeType as NodeType35 } from "@neat.is/types";
21046
20660
  function normalizeName(name) {
21047
20661
  return name.toLowerCase().replace(/[^a-z0-9]/g, "");
21048
20662
  }
21049
- function inferServiceName(graph, resourceName, method, path77) {
20663
+ function inferServiceName(graph, resourceName, method, path76) {
21050
20664
  const wantedMethod = method.toUpperCase();
21051
- const wantedPath = normalizePathTemplate(path77);
20665
+ const wantedPath = normalizePathTemplate(path76);
21052
20666
  const services = [];
21053
20667
  const owners = /* @__PURE__ */ new Set();
21054
20668
  graph.forEachNode((_id, attrs) => {
@@ -21256,7 +20870,7 @@ function mapEventToSignal(event) {
21256
20870
  if (Number.isNaN(observedAt.getTime())) return null;
21257
20871
  const statusCode = metadata?.statusCode;
21258
20872
  const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
21259
- const path77 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
20873
+ const path76 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
21260
20874
  return {
21261
20875
  targetKind: CLOUDFLARE_TARGET_KIND,
21262
20876
  targetName: scriptName,
@@ -21264,7 +20878,7 @@ function mapEventToSignal(event) {
21264
20878
  errorCount: isError ? 1 : 0,
21265
20879
  lastObservedIso: observedAt.toISOString(),
21266
20880
  method,
21267
- ...path77 ? { path: path77 } : {},
20881
+ ...path76 ? { path: path76 } : {},
21268
20882
  ...typeof statusCode === "number" ? { statusCode } : {},
21269
20883
  ...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
21270
20884
  };
@@ -21310,8 +20924,8 @@ function findTaggedWorkerFileNode(graph, workerName) {
21310
20924
  });
21311
20925
  return found;
21312
20926
  }
21313
- function findMatchingRouteNode(graph, serviceName, method, path77) {
21314
- const normalizedPath = normalizePathTemplate(path77);
20927
+ function findMatchingRouteNode(graph, serviceName, method, path76) {
20928
+ const normalizedPath = normalizePathTemplate(path76);
21315
20929
  let found = null;
21316
20930
  graph.forEachNode((id, attrs) => {
21317
20931
  if (found) return;
@@ -21328,10 +20942,10 @@ function createCloudflareResolveTarget(config, graph) {
21328
20942
  return (signal) => {
21329
20943
  if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
21330
20944
  const scriptName = signal.targetName;
21331
- const { method, path: path77 } = signal;
20945
+ const { method, path: path76 } = signal;
21332
20946
  const resolveRouteGrain = (serviceName, wholeFileId) => {
21333
- if (!method || !path77) return wholeFileId;
21334
- return findMatchingRouteNode(graph, serviceName, method, path77) ?? wholeFileId;
20947
+ if (!method || !path76) return wholeFileId;
20948
+ return findMatchingRouteNode(graph, serviceName, method, path76) ?? wholeFileId;
21335
20949
  };
21336
20950
  const mapping = config.workers?.[scriptName];
21337
20951
  if (mapping) {
@@ -21661,9 +21275,9 @@ function parseCloudRunTargetName(targetName) {
21661
21275
  const secondSep = rest.indexOf(FIELD_SEP2);
21662
21276
  if (secondSep === -1) return null;
21663
21277
  const method = rest.slice(0, secondSep);
21664
- const path77 = rest.slice(secondSep + 1);
21665
- if (!serviceName || !method || !path77) return null;
21666
- return { serviceName, method, path: path77 };
21278
+ const path76 = rest.slice(secondSep + 1);
21279
+ if (!serviceName || !method || !path76) return null;
21280
+ return { serviceName, method, path: path76 };
21667
21281
  }
21668
21282
 
21669
21283
  // src/connectors/cloud-run/map.ts
@@ -21692,14 +21306,14 @@ function mapLogEntryToSignal2(entry) {
21692
21306
  if (!req) return null;
21693
21307
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
21694
21308
  const method = req.requestMethod.toUpperCase();
21695
- const path77 = pathFromRequestUrl2(req.requestUrl);
21696
- if (path77 === null) return null;
21309
+ const path76 = pathFromRequestUrl2(req.requestUrl);
21310
+ if (path76 === null) return null;
21697
21311
  const timestamp = entry.timestamp;
21698
21312
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
21699
21313
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
21700
21314
  return {
21701
21315
  targetKind: CLOUD_RUN_TARGET_KIND,
21702
- targetName: packCloudRunTargetName({ serviceName, method, path: path77 }),
21316
+ targetName: packCloudRunTargetName({ serviceName, method, path: path76 }),
21703
21317
  callCount: 1,
21704
21318
  errorCount: isError ? 1 : 0,
21705
21319
  lastObservedIso: timestamp
@@ -21737,14 +21351,14 @@ function createCloudRunResolveTarget(graph, config) {
21737
21351
  if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
21738
21352
  const identity = parseCloudRunTargetName(signal.targetName);
21739
21353
  if (!identity) return null;
21740
- const { serviceName: gcpServiceName, method, path: path77 } = identity;
21741
- const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method, path77) ?? void 0 : void 0);
21354
+ const { serviceName: gcpServiceName, method, path: path76 } = identity;
21355
+ const mappedService = config.serviceMap?.[gcpServiceName] ?? (config.inferServices ? inferServiceName(graph, gcpServiceName, method, path76) ?? void 0 : void 0);
21742
21356
  if (mappedService) {
21743
21357
  const routeNodeId = findMatchingRouteNode2(
21744
21358
  graph,
21745
21359
  mappedService,
21746
21360
  method,
21747
- normalizePathTemplate(path77)
21361
+ normalizePathTemplate(path76)
21748
21362
  );
21749
21363
  if (routeNodeId) {
21750
21364
  return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: EdgeType32.CALLS };
@@ -21872,9 +21486,9 @@ function parseGcpLbTargetName(targetName) {
21872
21486
  const secondSep = rest.indexOf(FIELD_SEP3);
21873
21487
  if (secondSep === -1) return null;
21874
21488
  const method = rest.slice(0, secondSep);
21875
- const path77 = rest.slice(secondSep + 1);
21876
- if (!backendServiceName || !method || !path77) return null;
21877
- return { backendServiceName, method, path: path77 };
21489
+ const path76 = rest.slice(secondSep + 1);
21490
+ if (!backendServiceName || !method || !path76) return null;
21491
+ return { backendServiceName, method, path: path76 };
21878
21492
  }
21879
21493
 
21880
21494
  // src/connectors/gcp-lb/map.ts
@@ -21903,14 +21517,14 @@ function mapLogEntryToSignal3(entry) {
21903
21517
  if (!req) return null;
21904
21518
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
21905
21519
  const method = req.requestMethod.toUpperCase();
21906
- const path77 = pathFromRequestUrl3(req.requestUrl);
21907
- if (path77 === null) return null;
21520
+ const path76 = pathFromRequestUrl3(req.requestUrl);
21521
+ if (path76 === null) return null;
21908
21522
  const timestamp = entry.timestamp;
21909
21523
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
21910
21524
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
21911
21525
  return {
21912
21526
  targetKind: GCP_LB_TARGET_KIND,
21913
- targetName: packGcpLbTargetName({ backendServiceName, method, path: path77 }),
21527
+ targetName: packGcpLbTargetName({ backendServiceName, method, path: path76 }),
21914
21528
  callCount: 1,
21915
21529
  errorCount: isError ? 1 : 0,
21916
21530
  lastObservedIso: timestamp
@@ -21948,14 +21562,14 @@ function createGcpLbResolveTarget(graph, config) {
21948
21562
  if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
21949
21563
  const identity = parseGcpLbTargetName(signal.targetName);
21950
21564
  if (!identity) return null;
21951
- const { backendServiceName, method, path: path77 } = identity;
21952
- const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method, path77) ?? void 0 : void 0);
21565
+ const { backendServiceName, method, path: path76 } = identity;
21566
+ const mappedService = config.backendServiceMap?.[backendServiceName] ?? (config.inferServices ? inferServiceName(graph, backendServiceName, method, path76) ?? void 0 : void 0);
21953
21567
  if (mappedService) {
21954
21568
  const routeNodeId = findMatchingRouteNode3(
21955
21569
  graph,
21956
21570
  mappedService,
21957
21571
  method,
21958
- normalizePathTemplate(path77)
21572
+ normalizePathTemplate(path76)
21959
21573
  );
21960
21574
  if (routeNodeId) {
21961
21575
  return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: EdgeType33.CALLS };
@@ -24416,25 +24030,6 @@ export {
24416
24030
  pathsForProject,
24417
24031
  Projects,
24418
24032
  parseExtraProjects,
24419
- registryPath,
24420
- registryLockPath,
24421
- removeDaemonRecord,
24422
- listMachineProjects,
24423
- findDaemonByProject,
24424
- signalDaemonStop,
24425
- normalizeProjectPath,
24426
- writeAtomically,
24427
- readRegistry,
24428
- RegistryError,
24429
- ProjectNameCollisionError,
24430
- addProject,
24431
- getProject,
24432
- findProjectByPath,
24433
- listProjects,
24434
- setStatus,
24435
- touchLastSeen,
24436
- removeProject,
24437
- pruneRegistry,
24438
24033
  maybeStartRepoSync,
24439
24034
  readConnectorsConfig,
24440
24035
  resolveCredential,
@@ -24457,4 +24052,4 @@ export {
24457
24052
  deprovisionConnector,
24458
24053
  buildApi
24459
24054
  };
24460
- //# sourceMappingURL=chunk-KTJK2PAH.js.map
24055
+ //# sourceMappingURL=chunk-6QMWJAWR.js.map