@neat.is/core 0.8.1-dev.20260817 → 0.8.1
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/{chunk-OJ6BW63H.js → chunk-RQTW7IV3.js} +2 -2
- package/dist/{chunk-3PXRQH53.js → chunk-ZGZYZ33B.js} +68 -17
- package/dist/chunk-ZGZYZ33B.js.map +1 -0
- package/dist/cli.cjs +62 -13
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.cjs +62 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +62 -13
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +62 -13
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-3PXRQH53.js.map +0 -1
- /package/dist/{chunk-OJ6BW63H.js.map → chunk-RQTW7IV3.js.map} +0 -0
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
startStalenessLoop,
|
|
21
21
|
touchLastSeen,
|
|
22
22
|
writeAtomically
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-ZGZYZ33B.js";
|
|
24
24
|
import {
|
|
25
25
|
assertBindAuthority,
|
|
26
26
|
buildOtelReceiver,
|
|
@@ -891,4 +891,4 @@ export {
|
|
|
891
891
|
resolveHost,
|
|
892
892
|
startDaemon
|
|
893
893
|
};
|
|
894
|
-
//# sourceMappingURL=chunk-
|
|
894
|
+
//# sourceMappingURL=chunk-RQTW7IV3.js.map
|
|
@@ -3794,7 +3794,7 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
|
|
|
3794
3794
|
}
|
|
3795
3795
|
return sid;
|
|
3796
3796
|
}
|
|
3797
|
-
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
3797
|
+
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint = true) {
|
|
3798
3798
|
const line = callSite.line;
|
|
3799
3799
|
if (line === void 0) return fileNodeId;
|
|
3800
3800
|
let sawSymbol = false;
|
|
@@ -3809,7 +3809,7 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
|
3809
3809
|
}
|
|
3810
3810
|
});
|
|
3811
3811
|
if (candidates.length > 0) return pickContainingSymbol(candidates, callSite.fn);
|
|
3812
|
-
if (sawSymbol && callSite.fn) {
|
|
3812
|
+
if (mint && sawSymbol && callSite.fn) {
|
|
3813
3813
|
return ensureObservedSymbolNode(graph, fileNodeId, service, relPath, callSite.fn, line);
|
|
3814
3814
|
}
|
|
3815
3815
|
return fileNodeId;
|
|
@@ -4215,6 +4215,20 @@ function incidentAffectedNode(span, graph, scanPath) {
|
|
|
4215
4215
|
const callSite = callSiteFromSpan(span, serviceNode, scanPath);
|
|
4216
4216
|
if (callSite) {
|
|
4217
4217
|
const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
|
|
4218
|
+
const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
|
|
4219
|
+
if (graph) {
|
|
4220
|
+
const fusedFileId = fileId3(canonicalService, relPath);
|
|
4221
|
+
if (graph.hasNode(fusedFileId)) {
|
|
4222
|
+
return landObservedSymbol(
|
|
4223
|
+
graph,
|
|
4224
|
+
fusedFileId,
|
|
4225
|
+
canonicalService,
|
|
4226
|
+
relPath,
|
|
4227
|
+
{ ...callSite, relPath },
|
|
4228
|
+
false
|
|
4229
|
+
);
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4218
4232
|
return fileId3(span.service, relPath);
|
|
4219
4233
|
}
|
|
4220
4234
|
return sid;
|
|
@@ -4578,7 +4592,11 @@ async function handleSpan(ctx, span) {
|
|
|
4578
4592
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
4579
4593
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
4580
4594
|
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
4581
|
-
|
|
4595
|
+
// Attribute to where the failure originated — the symbol / file / service
|
|
4596
|
+
// the throwing span named (incidentAffectedNode, ADR-191) — the same
|
|
4597
|
+
// source-based attribution the durable receiver write uses, not the
|
|
4598
|
+
// outbound edge target this span happened to mint.
|
|
4599
|
+
affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
|
|
4582
4600
|
};
|
|
4583
4601
|
await appendErrorEvent(ctx, ev);
|
|
4584
4602
|
}
|
|
@@ -4857,7 +4875,9 @@ import {
|
|
|
4857
4875
|
Provenance as Provenance6,
|
|
4858
4876
|
RelateResultSchema,
|
|
4859
4877
|
RootCauseResultSchema,
|
|
4860
|
-
TransitiveDependenciesResultSchema
|
|
4878
|
+
TransitiveDependenciesResultSchema,
|
|
4879
|
+
fileId as fileId4,
|
|
4880
|
+
parseSymbolId
|
|
4861
4881
|
} from "@neat.is/types";
|
|
4862
4882
|
var ROOT_CAUSE_MAX_DEPTH = 5;
|
|
4863
4883
|
var BLAST_RADIUS_DEFAULT_DEPTH = 10;
|
|
@@ -5099,7 +5119,11 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
5099
5119
|
}
|
|
5100
5120
|
var INCIDENT_ROOT_CAUSE_CONFIDENCE = 0.6;
|
|
5101
5121
|
function incidentMatchesNode(ev, nodeId) {
|
|
5102
|
-
|
|
5122
|
+
if (ev.affectedNode === nodeId) return true;
|
|
5123
|
+
if (ev.service === nodeId.replace(/^service:/, "")) return true;
|
|
5124
|
+
const sym = parseSymbolId(ev.affectedNode);
|
|
5125
|
+
if (sym && fileId4(sym.service, sym.relPath) === nodeId) return true;
|
|
5126
|
+
return false;
|
|
5103
5127
|
}
|
|
5104
5128
|
function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
5105
5129
|
const pool = incidents && incidents.length > 0 ? incidents : errorEvent ? [errorEvent] : [];
|
|
@@ -5117,8 +5141,8 @@ function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
5117
5141
|
const reasonParts = [`${latest.service}: ${latest.errorMessage}`];
|
|
5118
5142
|
if (location) reasonParts.push(`surfaced at ${location}`);
|
|
5119
5143
|
const rootCauseReason = `${reasonParts.join(" \u2014 ")}${tail}`;
|
|
5120
|
-
const
|
|
5121
|
-
const fileNode =
|
|
5144
|
+
const localizesFiner = latest.affectedNode !== nodeId && (latest.affectedNode.startsWith("file:") || latest.affectedNode.startsWith("symbol:"));
|
|
5145
|
+
const fileNode = localizesFiner ? latest.affectedNode : void 0;
|
|
5122
5146
|
const fixRecommendation = location ? `Inspect ${location}${route ? ` handling ${route}` : ""}` : route ? `Inspect ${latest.service}'s handler for ${route}` : void 0;
|
|
5123
5147
|
return {
|
|
5124
5148
|
rootCauseNode: fileNode ?? nodeId,
|
|
@@ -5603,6 +5627,22 @@ function findLoadOrigin(graph, alertNodeId, incidents, now) {
|
|
|
5603
5627
|
}
|
|
5604
5628
|
return best ? { node: best.node, ctx: best.ctx } : null;
|
|
5605
5629
|
}
|
|
5630
|
+
var LOAD_ORIGIN_CONFIDENCE_CEILING = 0.9;
|
|
5631
|
+
function loadOriginConfidence(originCtx, seedCtx) {
|
|
5632
|
+
const cleanSplit = seedCtx.errorsFromCallers > 0 && seedCtx.errorsEmittedHere === 0;
|
|
5633
|
+
const partialSplit = seedCtx.errorsFromCallers > seedCtx.errorsEmittedHere;
|
|
5634
|
+
let evidence = 0;
|
|
5635
|
+
evidence += cleanSplit ? 0.45 : partialSplit ? 0.2 : 0;
|
|
5636
|
+
evidence += seedCtx.stale ? 0.2 : 0;
|
|
5637
|
+
evidence += isSaturated(seedCtx) ? 0.15 : 0;
|
|
5638
|
+
evidence += (volumeWeight(originCtx.outboundVolume) - 0.5) * 0.4;
|
|
5639
|
+
const anchor = 0.45;
|
|
5640
|
+
const confidence = anchor + Math.min(1, evidence) * (LOAD_ORIGIN_CONFIDENCE_CEILING - anchor);
|
|
5641
|
+
return Math.max(0, Math.min(LOAD_ORIGIN_CONFIDENCE_CEILING, confidence));
|
|
5642
|
+
}
|
|
5643
|
+
function displayNameOf(nodeId) {
|
|
5644
|
+
return nodeId.replace(/^[a-z]+:/, "");
|
|
5645
|
+
}
|
|
5606
5646
|
function getRootCause(graph, errorNodeId, errorEvent, incidents, opts) {
|
|
5607
5647
|
const legacy = legacyRootCause(graph, errorNodeId, errorEvent, incidents);
|
|
5608
5648
|
if (!legacy) return null;
|
|
@@ -5617,20 +5657,20 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
5617
5657
|
const candidates = [];
|
|
5618
5658
|
if (seedCtx && isVictimSeed(seedCtx)) {
|
|
5619
5659
|
const origin = findLoadOrigin(graph, errorNodeId, incidents, now);
|
|
5660
|
+
const staleNote = seedCtx.stale ? "; it has gone STALE under load" : "";
|
|
5661
|
+
const satNote = isSaturated(seedCtx) ? `; its inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
5620
5662
|
if (origin) {
|
|
5621
|
-
const
|
|
5622
|
-
const
|
|
5663
|
+
const originName = displayNameOf(origin.node);
|
|
5664
|
+
const seedName = displayNameOf(seedNode);
|
|
5623
5665
|
candidates.push({
|
|
5624
5666
|
node: origin.node,
|
|
5625
5667
|
classification: "primary-failure",
|
|
5626
|
-
reason:
|
|
5668
|
+
reason: `${originName} is the root cause: it overloads the failing subgraph, and the alerting node ${seedName} is a downstream symptom, not the fault \u2014 errors reach ${seedName} from its callers (${seedCtx.errorsFromCallers}), none originate there${staleNote}${satNote}. ${originName} is the upstream source driving that load (${origin.ctx.outboundVolume} observed outbound calls).`,
|
|
5627
5669
|
context: origin.ctx,
|
|
5628
|
-
confidence:
|
|
5670
|
+
confidence: loadOriginConfidence(origin.ctx, seedCtx),
|
|
5629
5671
|
provenance: Provenance6.OBSERVED
|
|
5630
5672
|
});
|
|
5631
5673
|
}
|
|
5632
|
-
const staleNote = seedCtx.stale ? "; the node has gone STALE" : "";
|
|
5633
|
-
const satNote = isSaturated(seedCtx) ? `; inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
5634
5674
|
candidates.push({
|
|
5635
5675
|
node: seedNode,
|
|
5636
5676
|
classification: "symptom-only",
|
|
@@ -5662,16 +5702,27 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
5662
5702
|
edgeProvenances = [top.provenance ?? Provenance6.OBSERVED];
|
|
5663
5703
|
}
|
|
5664
5704
|
}
|
|
5705
|
+
const fixRecommendation = fixRecommendationForTop(top, seedNode, legacy);
|
|
5665
5706
|
return RootCauseResultSchema.parse({
|
|
5666
5707
|
rootCauseNode: top.node,
|
|
5667
5708
|
rootCauseReason: top.reason,
|
|
5668
5709
|
traversalPath,
|
|
5669
5710
|
edgeProvenances,
|
|
5670
5711
|
confidence: top.confidence,
|
|
5671
|
-
...
|
|
5712
|
+
...fixRecommendation ? { fixRecommendation } : {},
|
|
5672
5713
|
candidates
|
|
5673
5714
|
});
|
|
5674
5715
|
}
|
|
5716
|
+
function fixRecommendationForTop(top, seedNode, legacy) {
|
|
5717
|
+
if (top.classification === "primary-failure" && top.node === seedNode) {
|
|
5718
|
+
return legacy.fixRecommendation;
|
|
5719
|
+
}
|
|
5720
|
+
const name = top.node.replace(/^service:/, "");
|
|
5721
|
+
if (top.classification === "primary-failure") {
|
|
5722
|
+
return `Reduce or throttle the load from ${name} (or scale the saturated downstream capacity it drives) \u2014 the failure originates at this overloading source, not the starved callee.`;
|
|
5723
|
+
}
|
|
5724
|
+
return `${name} is a saturated/starved downstream victim; investigate its inbound load and upstream callers, not its own handler.`;
|
|
5725
|
+
}
|
|
5675
5726
|
|
|
5676
5727
|
// src/extract/services.ts
|
|
5677
5728
|
import { promises as fs12 } from "fs";
|
|
@@ -16076,7 +16127,7 @@ function createFirebaseConnector(graph, serviceMap) {
|
|
|
16076
16127
|
}
|
|
16077
16128
|
|
|
16078
16129
|
// src/connectors/cloudflare/connector.ts
|
|
16079
|
-
import { EdgeType as EdgeType29, NodeType as NodeType29, fileId as
|
|
16130
|
+
import { EdgeType as EdgeType29, NodeType as NodeType29, fileId as fileId5, infraId as infraId21 } from "@neat.is/types";
|
|
16080
16131
|
|
|
16081
16132
|
// src/connectors/cloudflare/client.ts
|
|
16082
16133
|
import { randomUUID } from "crypto";
|
|
@@ -16266,7 +16317,7 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
16266
16317
|
};
|
|
16267
16318
|
const mapping = config.workers?.[scriptName];
|
|
16268
16319
|
if (mapping) {
|
|
16269
|
-
const wholeFileId =
|
|
16320
|
+
const wholeFileId = fileId5(mapping.service, mapping.entryFile);
|
|
16270
16321
|
return {
|
|
16271
16322
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
16272
16323
|
serviceName: mapping.service,
|
|
@@ -18924,4 +18975,4 @@ export {
|
|
|
18924
18975
|
deprovisionConnector,
|
|
18925
18976
|
buildApi
|
|
18926
18977
|
};
|
|
18927
|
-
//# sourceMappingURL=chunk-
|
|
18978
|
+
//# sourceMappingURL=chunk-ZGZYZ33B.js.map
|