@neat.is/core 0.8.1-dev.20260816 → 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
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
resolveHost,
|
|
7
7
|
resolveNeatVersion,
|
|
8
8
|
writeDaemonRecord
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RQTW7IV3.js";
|
|
10
10
|
import {
|
|
11
11
|
buildSearchIndex
|
|
12
12
|
} from "./chunk-BC53SCT7.js";
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
startStalenessLoop,
|
|
75
75
|
upsertConnectorEntry,
|
|
76
76
|
validateConnectorEntry
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-ZGZYZ33B.js";
|
|
78
78
|
import {
|
|
79
79
|
startOtelGrpcReceiver
|
|
80
80
|
} from "./chunk-FCO5Z3RW.js";
|
package/dist/index.cjs
CHANGED
|
@@ -1464,7 +1464,11 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
1464
1464
|
}
|
|
1465
1465
|
var INCIDENT_ROOT_CAUSE_CONFIDENCE = 0.6;
|
|
1466
1466
|
function incidentMatchesNode(ev, nodeId) {
|
|
1467
|
-
|
|
1467
|
+
if (ev.affectedNode === nodeId) return true;
|
|
1468
|
+
if (ev.service === nodeId.replace(/^service:/, "")) return true;
|
|
1469
|
+
const sym = (0, import_types.parseSymbolId)(ev.affectedNode);
|
|
1470
|
+
if (sym && (0, import_types.fileId)(sym.service, sym.relPath) === nodeId) return true;
|
|
1471
|
+
return false;
|
|
1468
1472
|
}
|
|
1469
1473
|
function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
1470
1474
|
const pool = incidents && incidents.length > 0 ? incidents : errorEvent ? [errorEvent] : [];
|
|
@@ -1482,8 +1486,8 @@ function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
1482
1486
|
const reasonParts = [`${latest.service}: ${latest.errorMessage}`];
|
|
1483
1487
|
if (location) reasonParts.push(`surfaced at ${location}`);
|
|
1484
1488
|
const rootCauseReason = `${reasonParts.join(" \u2014 ")}${tail}`;
|
|
1485
|
-
const
|
|
1486
|
-
const fileNode =
|
|
1489
|
+
const localizesFiner = latest.affectedNode !== nodeId && (latest.affectedNode.startsWith("file:") || latest.affectedNode.startsWith("symbol:"));
|
|
1490
|
+
const fileNode = localizesFiner ? latest.affectedNode : void 0;
|
|
1487
1491
|
const fixRecommendation = location ? `Inspect ${location}${route ? ` handling ${route}` : ""}` : route ? `Inspect ${latest.service}'s handler for ${route}` : void 0;
|
|
1488
1492
|
return {
|
|
1489
1493
|
rootCauseNode: fileNode ?? nodeId,
|
|
@@ -1968,6 +1972,22 @@ function findLoadOrigin(graph, alertNodeId, incidents, now) {
|
|
|
1968
1972
|
}
|
|
1969
1973
|
return best ? { node: best.node, ctx: best.ctx } : null;
|
|
1970
1974
|
}
|
|
1975
|
+
var LOAD_ORIGIN_CONFIDENCE_CEILING = 0.9;
|
|
1976
|
+
function loadOriginConfidence(originCtx, seedCtx) {
|
|
1977
|
+
const cleanSplit = seedCtx.errorsFromCallers > 0 && seedCtx.errorsEmittedHere === 0;
|
|
1978
|
+
const partialSplit = seedCtx.errorsFromCallers > seedCtx.errorsEmittedHere;
|
|
1979
|
+
let evidence = 0;
|
|
1980
|
+
evidence += cleanSplit ? 0.45 : partialSplit ? 0.2 : 0;
|
|
1981
|
+
evidence += seedCtx.stale ? 0.2 : 0;
|
|
1982
|
+
evidence += isSaturated(seedCtx) ? 0.15 : 0;
|
|
1983
|
+
evidence += (volumeWeight(originCtx.outboundVolume) - 0.5) * 0.4;
|
|
1984
|
+
const anchor = 0.45;
|
|
1985
|
+
const confidence = anchor + Math.min(1, evidence) * (LOAD_ORIGIN_CONFIDENCE_CEILING - anchor);
|
|
1986
|
+
return Math.max(0, Math.min(LOAD_ORIGIN_CONFIDENCE_CEILING, confidence));
|
|
1987
|
+
}
|
|
1988
|
+
function displayNameOf(nodeId) {
|
|
1989
|
+
return nodeId.replace(/^[a-z]+:/, "");
|
|
1990
|
+
}
|
|
1971
1991
|
function getRootCause(graph, errorNodeId, errorEvent, incidents, opts) {
|
|
1972
1992
|
const legacy = legacyRootCause(graph, errorNodeId, errorEvent, incidents);
|
|
1973
1993
|
if (!legacy) return null;
|
|
@@ -1982,20 +2002,20 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
1982
2002
|
const candidates = [];
|
|
1983
2003
|
if (seedCtx && isVictimSeed(seedCtx)) {
|
|
1984
2004
|
const origin = findLoadOrigin(graph, errorNodeId, incidents, now);
|
|
2005
|
+
const staleNote = seedCtx.stale ? "; it has gone STALE under load" : "";
|
|
2006
|
+
const satNote = isSaturated(seedCtx) ? `; its inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
1985
2007
|
if (origin) {
|
|
1986
|
-
const
|
|
1987
|
-
const
|
|
2008
|
+
const originName = displayNameOf(origin.node);
|
|
2009
|
+
const seedName = displayNameOf(seedNode);
|
|
1988
2010
|
candidates.push({
|
|
1989
2011
|
node: origin.node,
|
|
1990
2012
|
classification: "primary-failure",
|
|
1991
|
-
reason:
|
|
2013
|
+
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).`,
|
|
1992
2014
|
context: origin.ctx,
|
|
1993
|
-
confidence:
|
|
2015
|
+
confidence: loadOriginConfidence(origin.ctx, seedCtx),
|
|
1994
2016
|
provenance: import_types.Provenance.OBSERVED
|
|
1995
2017
|
});
|
|
1996
2018
|
}
|
|
1997
|
-
const staleNote = seedCtx.stale ? "; the node has gone STALE" : "";
|
|
1998
|
-
const satNote = isSaturated(seedCtx) ? `; inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
1999
2019
|
candidates.push({
|
|
2000
2020
|
node: seedNode,
|
|
2001
2021
|
classification: "symptom-only",
|
|
@@ -2027,16 +2047,27 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
2027
2047
|
edgeProvenances = [top.provenance ?? import_types.Provenance.OBSERVED];
|
|
2028
2048
|
}
|
|
2029
2049
|
}
|
|
2050
|
+
const fixRecommendation = fixRecommendationForTop(top, seedNode, legacy);
|
|
2030
2051
|
return import_types.RootCauseResultSchema.parse({
|
|
2031
2052
|
rootCauseNode: top.node,
|
|
2032
2053
|
rootCauseReason: top.reason,
|
|
2033
2054
|
traversalPath,
|
|
2034
2055
|
edgeProvenances,
|
|
2035
2056
|
confidence: top.confidence,
|
|
2036
|
-
...
|
|
2057
|
+
...fixRecommendation ? { fixRecommendation } : {},
|
|
2037
2058
|
candidates
|
|
2038
2059
|
});
|
|
2039
2060
|
}
|
|
2061
|
+
function fixRecommendationForTop(top, seedNode, legacy) {
|
|
2062
|
+
if (top.classification === "primary-failure" && top.node === seedNode) {
|
|
2063
|
+
return legacy.fixRecommendation;
|
|
2064
|
+
}
|
|
2065
|
+
const name = top.node.replace(/^service:/, "");
|
|
2066
|
+
if (top.classification === "primary-failure") {
|
|
2067
|
+
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.`;
|
|
2068
|
+
}
|
|
2069
|
+
return `${name} is a saturated/starved downstream victim; investigate its inbound load and upstream callers, not its own handler.`;
|
|
2070
|
+
}
|
|
2040
2071
|
|
|
2041
2072
|
// src/policy.ts
|
|
2042
2073
|
var DEFAULT_ACTION_BY_SEVERITY = {
|
|
@@ -5371,7 +5402,7 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
|
|
|
5371
5402
|
}
|
|
5372
5403
|
return sid;
|
|
5373
5404
|
}
|
|
5374
|
-
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
5405
|
+
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint = true) {
|
|
5375
5406
|
const line = callSite.line;
|
|
5376
5407
|
if (line === void 0) return fileNodeId;
|
|
5377
5408
|
let sawSymbol = false;
|
|
@@ -5386,7 +5417,7 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
|
5386
5417
|
}
|
|
5387
5418
|
});
|
|
5388
5419
|
if (candidates.length > 0) return pickContainingSymbol(candidates, callSite.fn);
|
|
5389
|
-
if (sawSymbol && callSite.fn) {
|
|
5420
|
+
if (mint && sawSymbol && callSite.fn) {
|
|
5390
5421
|
return ensureObservedSymbolNode(graph, fileNodeId, service, relPath, callSite.fn, line);
|
|
5391
5422
|
}
|
|
5392
5423
|
return fileNodeId;
|
|
@@ -5792,6 +5823,20 @@ function incidentAffectedNode(span, graph, scanPath) {
|
|
|
5792
5823
|
const callSite = callSiteFromSpan(span, serviceNode, scanPath);
|
|
5793
5824
|
if (callSite) {
|
|
5794
5825
|
const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
|
|
5826
|
+
const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
|
|
5827
|
+
if (graph) {
|
|
5828
|
+
const fusedFileId = (0, import_types8.fileId)(canonicalService, relPath);
|
|
5829
|
+
if (graph.hasNode(fusedFileId)) {
|
|
5830
|
+
return landObservedSymbol(
|
|
5831
|
+
graph,
|
|
5832
|
+
fusedFileId,
|
|
5833
|
+
canonicalService,
|
|
5834
|
+
relPath,
|
|
5835
|
+
{ ...callSite, relPath },
|
|
5836
|
+
false
|
|
5837
|
+
);
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
5795
5840
|
return (0, import_types8.fileId)(span.service, relPath);
|
|
5796
5841
|
}
|
|
5797
5842
|
return sid;
|
|
@@ -6155,7 +6200,11 @@ async function handleSpan(ctx, span) {
|
|
|
6155
6200
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
6156
6201
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
6157
6202
|
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
6158
|
-
|
|
6203
|
+
// Attribute to where the failure originated — the symbol / file / service
|
|
6204
|
+
// the throwing span named (incidentAffectedNode, ADR-191) — the same
|
|
6205
|
+
// source-based attribution the durable receiver write uses, not the
|
|
6206
|
+
// outbound edge target this span happened to mint.
|
|
6207
|
+
affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
|
|
6159
6208
|
};
|
|
6160
6209
|
await appendErrorEvent(ctx, ev);
|
|
6161
6210
|
}
|