@neat.is/core 0.9.7-dev.20260827 → 0.9.8-dev.20260828
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-XYAZOGEX.js → chunk-JSUPWMH3.js} +2 -2
- package/dist/{chunk-XOGTJVUM.js → chunk-KZBFP7L6.js} +153 -3
- package/dist/{chunk-XOGTJVUM.js.map → chunk-KZBFP7L6.js.map} +1 -1
- package/dist/cli.cjs +171 -2
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +152 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +152 -2
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +152 -2
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- /package/dist/{chunk-XYAZOGEX.js.map → chunk-JSUPWMH3.js.map} +0 -0
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
startStalenessLoop,
|
|
21
21
|
touchLastSeen,
|
|
22
22
|
writeAtomically
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KZBFP7L6.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-JSUPWMH3.js.map
|
|
@@ -15587,6 +15587,139 @@ function detectSymbolMismatches(graph, incidents) {
|
|
|
15587
15587
|
}
|
|
15588
15588
|
return out;
|
|
15589
15589
|
}
|
|
15590
|
+
var OBSERVED_FAILING_ERROR_RATE = 0.5;
|
|
15591
|
+
var OBSERVED_FAILING_MIN_SPANS = 5;
|
|
15592
|
+
var OBSERVED_FAILING_CONFIDENCE = 0.6;
|
|
15593
|
+
function detectObservedFailingEdge(graph, bucket) {
|
|
15594
|
+
if (!bucket.extracted || !bucket.observed) return [];
|
|
15595
|
+
if (!OBSERVABLE_EDGE_TYPES.has(bucket.type)) return [];
|
|
15596
|
+
if (bucket.observed.provenance !== Provenance24.OBSERVED) return [];
|
|
15597
|
+
const signal = bucket.observed.signal;
|
|
15598
|
+
if (!signal) return [];
|
|
15599
|
+
const { spanCount, errorCount } = signal;
|
|
15600
|
+
if (spanCount < OBSERVED_FAILING_MIN_SPANS) return [];
|
|
15601
|
+
const errorRate = errorCount / spanCount;
|
|
15602
|
+
if (errorRate < OBSERVED_FAILING_ERROR_RATE) return [];
|
|
15603
|
+
const pct = Math.round(errorRate * 100);
|
|
15604
|
+
return [
|
|
15605
|
+
{
|
|
15606
|
+
type: "observed-failing",
|
|
15607
|
+
source: bucket.source,
|
|
15608
|
+
target: bucket.target,
|
|
15609
|
+
failureKind: "error-rate",
|
|
15610
|
+
provenance: Provenance24.INFERRED,
|
|
15611
|
+
edgeType: bucket.type,
|
|
15612
|
+
observed: bucket.observed,
|
|
15613
|
+
spanCount,
|
|
15614
|
+
errorCount,
|
|
15615
|
+
errorRate: clampConfidence(errorRate),
|
|
15616
|
+
confidence: OBSERVED_FAILING_CONFIDENCE,
|
|
15617
|
+
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.`,
|
|
15618
|
+
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."
|
|
15619
|
+
}
|
|
15620
|
+
];
|
|
15621
|
+
}
|
|
15622
|
+
var OBSERVED_FAILURE_PATTERNS = [
|
|
15623
|
+
{
|
|
15624
|
+
kind: "connection-refused",
|
|
15625
|
+
patterns: [/\bECONNREFUSED\b/i, /\bconnection refused\b/i]
|
|
15626
|
+
},
|
|
15627
|
+
{
|
|
15628
|
+
kind: "deadline-exceeded",
|
|
15629
|
+
patterns: [/\bDEADLINE_EXCEEDED\b/i, /\bdeadline exceeded\b/i]
|
|
15630
|
+
},
|
|
15631
|
+
{
|
|
15632
|
+
kind: "timeout",
|
|
15633
|
+
patterns: [/\bETIMEDOUT\b/i, /\btimed[\s-]?out\b/i, /\btimeout\b/i]
|
|
15634
|
+
},
|
|
15635
|
+
{
|
|
15636
|
+
kind: "unavailable",
|
|
15637
|
+
patterns: [
|
|
15638
|
+
/\bUNAVAILABLE\b/i,
|
|
15639
|
+
/\bservice unavailable\b/i,
|
|
15640
|
+
/\bECONNRESET\b/i,
|
|
15641
|
+
/\bconnection reset\b/i,
|
|
15642
|
+
/\bno healthy upstream\b/i
|
|
15643
|
+
]
|
|
15644
|
+
}
|
|
15645
|
+
];
|
|
15646
|
+
function classifyObservedFailure(ev) {
|
|
15647
|
+
const haystack = [ev.errorType, ev.exceptionType, ev.errorMessage].filter((s) => typeof s === "string").join(" \n ");
|
|
15648
|
+
for (const entry of OBSERVED_FAILURE_PATTERNS) {
|
|
15649
|
+
for (const re of entry.patterns) {
|
|
15650
|
+
if (re.test(haystack)) return entry.kind;
|
|
15651
|
+
}
|
|
15652
|
+
}
|
|
15653
|
+
const code = ev.httpStatusCode;
|
|
15654
|
+
if (typeof code === "number" && code >= 500 && code < 600) return "server-error";
|
|
15655
|
+
return null;
|
|
15656
|
+
}
|
|
15657
|
+
function observedFailureLabel(kind) {
|
|
15658
|
+
switch (kind) {
|
|
15659
|
+
case "error-rate":
|
|
15660
|
+
return "a high error rate";
|
|
15661
|
+
case "connection-refused":
|
|
15662
|
+
return "a refused connection";
|
|
15663
|
+
case "deadline-exceeded":
|
|
15664
|
+
return "a deadline exceeded";
|
|
15665
|
+
case "timeout":
|
|
15666
|
+
return "a timeout";
|
|
15667
|
+
case "unavailable":
|
|
15668
|
+
return "an unavailable or reset connection";
|
|
15669
|
+
case "server-error":
|
|
15670
|
+
return "a server error (5xx)";
|
|
15671
|
+
}
|
|
15672
|
+
}
|
|
15673
|
+
function detectObservedFailingIncidents(graph, incidents) {
|
|
15674
|
+
const groups = /* @__PURE__ */ new Map();
|
|
15675
|
+
for (const ev of incidents) {
|
|
15676
|
+
const kind = classifyObservedFailure(ev);
|
|
15677
|
+
if (!kind) continue;
|
|
15678
|
+
const locus = symbolLocus(graph, ev);
|
|
15679
|
+
if (!locus) continue;
|
|
15680
|
+
const key = `${locus.node}|${kind}`;
|
|
15681
|
+
const existing = groups.get(key);
|
|
15682
|
+
if (!existing) {
|
|
15683
|
+
groups.set(key, {
|
|
15684
|
+
node: locus.node,
|
|
15685
|
+
kind,
|
|
15686
|
+
...locus.location ? { location: locus.location } : {},
|
|
15687
|
+
latest: ev,
|
|
15688
|
+
count: 1,
|
|
15689
|
+
...typeof ev.httpStatusCode === "number" ? { httpStatusCode: ev.httpStatusCode } : {}
|
|
15690
|
+
});
|
|
15691
|
+
} else {
|
|
15692
|
+
existing.count += 1;
|
|
15693
|
+
if (ev.timestamp.localeCompare(existing.latest.timestamp) > 0) {
|
|
15694
|
+
existing.latest = ev;
|
|
15695
|
+
if (locus.location) existing.location = locus.location;
|
|
15696
|
+
if (typeof ev.httpStatusCode === "number") existing.httpStatusCode = ev.httpStatusCode;
|
|
15697
|
+
}
|
|
15698
|
+
}
|
|
15699
|
+
}
|
|
15700
|
+
const out = [];
|
|
15701
|
+
for (const g of groups.values()) {
|
|
15702
|
+
const where = g.location ? ` at ${g.location}` : "";
|
|
15703
|
+
const label = observedFailureLabel(g.kind);
|
|
15704
|
+
const times = g.count > 1 ? ` (${g.count} recorded incidents)` : " (1 recorded incident)";
|
|
15705
|
+
out.push({
|
|
15706
|
+
type: "observed-failing",
|
|
15707
|
+
source: g.node,
|
|
15708
|
+
target: g.node,
|
|
15709
|
+
failureKind: g.kind,
|
|
15710
|
+
provenance: Provenance24.INFERRED,
|
|
15711
|
+
...g.location ? { location: g.location } : {},
|
|
15712
|
+
incidentId: g.latest.id,
|
|
15713
|
+
errorMessage: g.latest.errorMessage,
|
|
15714
|
+
incidentCount: g.count,
|
|
15715
|
+
...typeof g.httpStatusCode === "number" ? { httpStatusCode: g.httpStatusCode } : {},
|
|
15716
|
+
confidence: OBSERVED_FAILING_CONFIDENCE,
|
|
15717
|
+
reason: `Code${where} declares an external call that production observes failing \u2014 ${g.latest.service} recorded ${label}: "${g.latest.errorMessage}"${times}. The declared call (EXTRACTED) and the observed failure (OBSERVED) diverge \u2014 the dependency is reached and does not work.`,
|
|
15718
|
+
recommendation: `The declared call is running in production and failing at the transport or response level (${label}). Check the target host/endpoint the code reaches, connectivity, and the call\u2019s deadline \u2014 a wrong or unreachable host and an exceeded deadline both land here.`
|
|
15719
|
+
});
|
|
15720
|
+
}
|
|
15721
|
+
return out;
|
|
15722
|
+
}
|
|
15590
15723
|
function involvesNode(d, nodeId) {
|
|
15591
15724
|
return d.source === nodeId || d.target === nodeId;
|
|
15592
15725
|
}
|
|
@@ -15659,6 +15792,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
15659
15792
|
const buckets2 = bucketEdges(graph);
|
|
15660
15793
|
for (const bucket of buckets2.values()) {
|
|
15661
15794
|
for (const d of detectMissingDivergences(graph, bucket)) all.push(d);
|
|
15795
|
+
for (const d of detectObservedFailingEdge(graph, bucket)) all.push(d);
|
|
15662
15796
|
}
|
|
15663
15797
|
graph.forEachNode((nodeId, attrs) => {
|
|
15664
15798
|
const n = attrs;
|
|
@@ -15674,6 +15808,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
15674
15808
|
});
|
|
15675
15809
|
if (opts.incidents && opts.incidents.length > 0) {
|
|
15676
15810
|
for (const d of detectSymbolMismatches(graph, opts.incidents)) all.push(d);
|
|
15811
|
+
for (const d of detectObservedFailingIncidents(graph, opts.incidents)) all.push(d);
|
|
15677
15812
|
}
|
|
15678
15813
|
const reconciled = suppressHostMismatchHalves(all);
|
|
15679
15814
|
const dampened = dampenDeadCodeProbes(graph, buckets2, reconciled);
|
|
@@ -15700,7 +15835,12 @@ function computeDivergences(graph, opts = {}) {
|
|
|
15700
15835
|
// type; this only breaks a confidence tie, and it orders last so a same-
|
|
15701
15836
|
// confidence edge finding leads. In practice it carries the INFERRED grade
|
|
15702
15837
|
// (0.6), so it sits below the high-confidence edge divergences already.
|
|
15703
|
-
"observed-symbol-mismatch": 5
|
|
15838
|
+
"observed-symbol-mismatch": 5,
|
|
15839
|
+
// Behavioral-failure (ADR-220) also carries the INFERRED grade (0.6); it
|
|
15840
|
+
// orders last so at equal confidence the structural and symbol divergences
|
|
15841
|
+
// lead, per the contract ("rank below the definitive structural and symbol
|
|
15842
|
+
// divergences").
|
|
15843
|
+
"observed-failing": 6
|
|
15704
15844
|
};
|
|
15705
15845
|
filtered.sort((a, b) => {
|
|
15706
15846
|
if (b.confidence !== a.confidence) return b.confidence - a.confidence;
|
|
@@ -15714,7 +15854,13 @@ function computeDivergences(graph, opts = {}) {
|
|
|
15714
15854
|
if (ac !== bc) return ac.localeCompare(bc);
|
|
15715
15855
|
const asym = "symbol" in a && a.symbol ? a.symbol : "";
|
|
15716
15856
|
const bsym = "symbol" in b && b.symbol ? b.symbol : "";
|
|
15717
|
-
return asym.localeCompare(bsym);
|
|
15857
|
+
if (asym !== bsym) return asym.localeCompare(bsym);
|
|
15858
|
+
const afk = "failureKind" in a && a.failureKind ? a.failureKind : "";
|
|
15859
|
+
const bfk = "failureKind" in b && b.failureKind ? b.failureKind : "";
|
|
15860
|
+
if (afk !== bfk) return afk.localeCompare(bfk);
|
|
15861
|
+
const aloc = "location" in a && a.location ? a.location : "";
|
|
15862
|
+
const bloc = "location" in b && b.location ? b.location : "";
|
|
15863
|
+
return aloc.localeCompare(bloc);
|
|
15718
15864
|
});
|
|
15719
15865
|
return DivergenceResultSchema.parse({
|
|
15720
15866
|
divergences: filtered,
|
|
@@ -17162,6 +17308,10 @@ function divergenceLine(d) {
|
|
|
17162
17308
|
const member = d.symbol ? ` ${d.symbol}` : "";
|
|
17163
17309
|
return `[${d.type}] ${d.source}${member}${at} \u2014 ${d.reason}`;
|
|
17164
17310
|
}
|
|
17311
|
+
if (d.type === "observed-failing" && !d.edgeType) {
|
|
17312
|
+
const at = d.location ? ` at ${d.location}` : "";
|
|
17313
|
+
return `[${d.type}] ${d.source}${at} \u2014 ${d.reason}`;
|
|
17314
|
+
}
|
|
17165
17315
|
return `[${d.type}] ${d.source} \u2192 ${d.target} \u2014 ${d.reason}`;
|
|
17166
17316
|
}
|
|
17167
17317
|
function buildDivergenceSection(graph, node, incidents) {
|
|
@@ -22154,4 +22304,4 @@ export {
|
|
|
22154
22304
|
deprovisionConnector,
|
|
22155
22305
|
buildApi
|
|
22156
22306
|
};
|
|
22157
|
-
//# sourceMappingURL=chunk-
|
|
22307
|
+
//# sourceMappingURL=chunk-KZBFP7L6.js.map
|