@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/neatd.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
reconcileDaemonRecordSync,
|
|
4
4
|
startDaemon
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RQTW7IV3.js";
|
|
6
6
|
import {
|
|
7
7
|
listProjects,
|
|
8
8
|
registryPath
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZGZYZ33B.js";
|
|
10
10
|
import {
|
|
11
11
|
BindAuthorityError,
|
|
12
12
|
__require
|
package/dist/server.cjs
CHANGED
|
@@ -4777,7 +4777,7 @@ function ensureObservedSymbolNode(graph, fileNodeId, service, relPath, fn, line)
|
|
|
4777
4777
|
}
|
|
4778
4778
|
return sid;
|
|
4779
4779
|
}
|
|
4780
|
-
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
4780
|
+
function landObservedSymbol(graph, fileNodeId, service, relPath, callSite, mint = true) {
|
|
4781
4781
|
const line = callSite.line;
|
|
4782
4782
|
if (line === void 0) return fileNodeId;
|
|
4783
4783
|
let sawSymbol = false;
|
|
@@ -4792,7 +4792,7 @@ function landObservedSymbol(graph, fileNodeId, service, relPath, callSite) {
|
|
|
4792
4792
|
}
|
|
4793
4793
|
});
|
|
4794
4794
|
if (candidates.length > 0) return pickContainingSymbol(candidates, callSite.fn);
|
|
4795
|
-
if (sawSymbol && callSite.fn) {
|
|
4795
|
+
if (mint && sawSymbol && callSite.fn) {
|
|
4796
4796
|
return ensureObservedSymbolNode(graph, fileNodeId, service, relPath, callSite.fn, line);
|
|
4797
4797
|
}
|
|
4798
4798
|
return fileNodeId;
|
|
@@ -5198,6 +5198,20 @@ function incidentAffectedNode(span, graph, scanPath) {
|
|
|
5198
5198
|
const callSite = callSiteFromSpan(span, serviceNode, scanPath);
|
|
5199
5199
|
if (callSite) {
|
|
5200
5200
|
const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
|
|
5201
|
+
const canonicalService = serviceNode && typeof serviceNode.name === "string" ? serviceNode.name : span.service;
|
|
5202
|
+
if (graph) {
|
|
5203
|
+
const fusedFileId = (0, import_types7.fileId)(canonicalService, relPath);
|
|
5204
|
+
if (graph.hasNode(fusedFileId)) {
|
|
5205
|
+
return landObservedSymbol(
|
|
5206
|
+
graph,
|
|
5207
|
+
fusedFileId,
|
|
5208
|
+
canonicalService,
|
|
5209
|
+
relPath,
|
|
5210
|
+
{ ...callSite, relPath },
|
|
5211
|
+
false
|
|
5212
|
+
);
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5201
5215
|
return (0, import_types7.fileId)(span.service, relPath);
|
|
5202
5216
|
}
|
|
5203
5217
|
return sid;
|
|
@@ -5536,7 +5550,11 @@ async function handleSpan(ctx, span) {
|
|
|
5536
5550
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
5537
5551
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
5538
5552
|
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
5539
|
-
|
|
5553
|
+
// Attribute to where the failure originated — the symbol / file / service
|
|
5554
|
+
// the throwing span named (incidentAffectedNode, ADR-191) — the same
|
|
5555
|
+
// source-based attribution the durable receiver write uses, not the
|
|
5556
|
+
// outbound edge target this span happened to mint.
|
|
5557
|
+
affectedNode: incidentAffectedNode(span, ctx.graph, ctx.scanPath)
|
|
5540
5558
|
};
|
|
5541
5559
|
await appendErrorEvent(ctx, ev);
|
|
5542
5560
|
}
|
|
@@ -6046,7 +6064,11 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
|
|
|
6046
6064
|
}
|
|
6047
6065
|
var INCIDENT_ROOT_CAUSE_CONFIDENCE = 0.6;
|
|
6048
6066
|
function incidentMatchesNode(ev, nodeId) {
|
|
6049
|
-
|
|
6067
|
+
if (ev.affectedNode === nodeId) return true;
|
|
6068
|
+
if (ev.service === nodeId.replace(/^service:/, "")) return true;
|
|
6069
|
+
const sym = (0, import_types8.parseSymbolId)(ev.affectedNode);
|
|
6070
|
+
if (sym && (0, import_types8.fileId)(sym.service, sym.relPath) === nodeId) return true;
|
|
6071
|
+
return false;
|
|
6050
6072
|
}
|
|
6051
6073
|
function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
6052
6074
|
const pool = incidents && incidents.length > 0 ? incidents : errorEvent ? [errorEvent] : [];
|
|
@@ -6064,8 +6086,8 @@ function localizeFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
6064
6086
|
const reasonParts = [`${latest.service}: ${latest.errorMessage}`];
|
|
6065
6087
|
if (location) reasonParts.push(`surfaced at ${location}`);
|
|
6066
6088
|
const rootCauseReason = `${reasonParts.join(" \u2014 ")}${tail}`;
|
|
6067
|
-
const
|
|
6068
|
-
const fileNode =
|
|
6089
|
+
const localizesFiner = latest.affectedNode !== nodeId && (latest.affectedNode.startsWith("file:") || latest.affectedNode.startsWith("symbol:"));
|
|
6090
|
+
const fileNode = localizesFiner ? latest.affectedNode : void 0;
|
|
6069
6091
|
const fixRecommendation = location ? `Inspect ${location}${route ? ` handling ${route}` : ""}` : route ? `Inspect ${latest.service}'s handler for ${route}` : void 0;
|
|
6070
6092
|
return {
|
|
6071
6093
|
rootCauseNode: fileNode ?? nodeId,
|
|
@@ -6550,6 +6572,22 @@ function findLoadOrigin(graph, alertNodeId, incidents, now) {
|
|
|
6550
6572
|
}
|
|
6551
6573
|
return best ? { node: best.node, ctx: best.ctx } : null;
|
|
6552
6574
|
}
|
|
6575
|
+
var LOAD_ORIGIN_CONFIDENCE_CEILING = 0.9;
|
|
6576
|
+
function loadOriginConfidence(originCtx, seedCtx) {
|
|
6577
|
+
const cleanSplit = seedCtx.errorsFromCallers > 0 && seedCtx.errorsEmittedHere === 0;
|
|
6578
|
+
const partialSplit = seedCtx.errorsFromCallers > seedCtx.errorsEmittedHere;
|
|
6579
|
+
let evidence = 0;
|
|
6580
|
+
evidence += cleanSplit ? 0.45 : partialSplit ? 0.2 : 0;
|
|
6581
|
+
evidence += seedCtx.stale ? 0.2 : 0;
|
|
6582
|
+
evidence += isSaturated(seedCtx) ? 0.15 : 0;
|
|
6583
|
+
evidence += (volumeWeight(originCtx.outboundVolume) - 0.5) * 0.4;
|
|
6584
|
+
const anchor = 0.45;
|
|
6585
|
+
const confidence = anchor + Math.min(1, evidence) * (LOAD_ORIGIN_CONFIDENCE_CEILING - anchor);
|
|
6586
|
+
return Math.max(0, Math.min(LOAD_ORIGIN_CONFIDENCE_CEILING, confidence));
|
|
6587
|
+
}
|
|
6588
|
+
function displayNameOf(nodeId) {
|
|
6589
|
+
return nodeId.replace(/^[a-z]+:/, "");
|
|
6590
|
+
}
|
|
6553
6591
|
function getRootCause(graph, errorNodeId, errorEvent, incidents, opts) {
|
|
6554
6592
|
const legacy = legacyRootCause(graph, errorNodeId, errorEvent, incidents);
|
|
6555
6593
|
if (!legacy) return null;
|
|
@@ -6564,20 +6602,20 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
6564
6602
|
const candidates = [];
|
|
6565
6603
|
if (seedCtx && isVictimSeed(seedCtx)) {
|
|
6566
6604
|
const origin = findLoadOrigin(graph, errorNodeId, incidents, now);
|
|
6605
|
+
const staleNote = seedCtx.stale ? "; it has gone STALE under load" : "";
|
|
6606
|
+
const satNote = isSaturated(seedCtx) ? `; its inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
6567
6607
|
if (origin) {
|
|
6568
|
-
const
|
|
6569
|
-
const
|
|
6608
|
+
const originName = displayNameOf(origin.node);
|
|
6609
|
+
const seedName = displayNameOf(seedNode);
|
|
6570
6610
|
candidates.push({
|
|
6571
6611
|
node: origin.node,
|
|
6572
6612
|
classification: "primary-failure",
|
|
6573
|
-
reason:
|
|
6613
|
+
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).`,
|
|
6574
6614
|
context: origin.ctx,
|
|
6575
|
-
confidence:
|
|
6615
|
+
confidence: loadOriginConfidence(origin.ctx, seedCtx),
|
|
6576
6616
|
provenance: import_types8.Provenance.OBSERVED
|
|
6577
6617
|
});
|
|
6578
6618
|
}
|
|
6579
|
-
const staleNote = seedCtx.stale ? "; the node has gone STALE" : "";
|
|
6580
|
-
const satNote = isSaturated(seedCtx) ? `; inbound p95 ${Math.round(seedCtx.latencyP95Ms)}ms is saturated` : "";
|
|
6581
6619
|
candidates.push({
|
|
6582
6620
|
node: seedNode,
|
|
6583
6621
|
classification: "symptom-only",
|
|
@@ -6609,16 +6647,27 @@ function enrichWithNavigation(graph, errorNodeId, legacy, incidents, now) {
|
|
|
6609
6647
|
edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
|
|
6610
6648
|
}
|
|
6611
6649
|
}
|
|
6650
|
+
const fixRecommendation = fixRecommendationForTop(top, seedNode, legacy);
|
|
6612
6651
|
return import_types8.RootCauseResultSchema.parse({
|
|
6613
6652
|
rootCauseNode: top.node,
|
|
6614
6653
|
rootCauseReason: top.reason,
|
|
6615
6654
|
traversalPath,
|
|
6616
6655
|
edgeProvenances,
|
|
6617
6656
|
confidence: top.confidence,
|
|
6618
|
-
...
|
|
6657
|
+
...fixRecommendation ? { fixRecommendation } : {},
|
|
6619
6658
|
candidates
|
|
6620
6659
|
});
|
|
6621
6660
|
}
|
|
6661
|
+
function fixRecommendationForTop(top, seedNode, legacy) {
|
|
6662
|
+
if (top.classification === "primary-failure" && top.node === seedNode) {
|
|
6663
|
+
return legacy.fixRecommendation;
|
|
6664
|
+
}
|
|
6665
|
+
const name = top.node.replace(/^service:/, "");
|
|
6666
|
+
if (top.classification === "primary-failure") {
|
|
6667
|
+
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.`;
|
|
6668
|
+
}
|
|
6669
|
+
return `${name} is a saturated/starved downstream victim; investigate its inbound load and upstream callers, not its own handler.`;
|
|
6670
|
+
}
|
|
6622
6671
|
|
|
6623
6672
|
// src/divergences.ts
|
|
6624
6673
|
function bucketKey(source, target, type) {
|