@neat.is/core 0.9.7-dev.20260827 → 0.9.7
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
package/dist/cli.cjs
CHANGED
|
@@ -16373,6 +16373,139 @@ function detectSymbolMismatches(graph, incidents) {
|
|
|
16373
16373
|
}
|
|
16374
16374
|
return out;
|
|
16375
16375
|
}
|
|
16376
|
+
var OBSERVED_FAILING_ERROR_RATE = 0.5;
|
|
16377
|
+
var OBSERVED_FAILING_MIN_SPANS = 5;
|
|
16378
|
+
var OBSERVED_FAILING_CONFIDENCE = 0.6;
|
|
16379
|
+
function detectObservedFailingEdge(graph, bucket) {
|
|
16380
|
+
if (!bucket.extracted || !bucket.observed) return [];
|
|
16381
|
+
if (!OBSERVABLE_EDGE_TYPES.has(bucket.type)) return [];
|
|
16382
|
+
if (bucket.observed.provenance !== import_types57.Provenance.OBSERVED) return [];
|
|
16383
|
+
const signal = bucket.observed.signal;
|
|
16384
|
+
if (!signal) return [];
|
|
16385
|
+
const { spanCount, errorCount } = signal;
|
|
16386
|
+
if (spanCount < OBSERVED_FAILING_MIN_SPANS) return [];
|
|
16387
|
+
const errorRate = errorCount / spanCount;
|
|
16388
|
+
if (errorRate < OBSERVED_FAILING_ERROR_RATE) return [];
|
|
16389
|
+
const pct = Math.round(errorRate * 100);
|
|
16390
|
+
return [
|
|
16391
|
+
{
|
|
16392
|
+
type: "observed-failing",
|
|
16393
|
+
source: bucket.source,
|
|
16394
|
+
target: bucket.target,
|
|
16395
|
+
failureKind: "error-rate",
|
|
16396
|
+
provenance: import_types57.Provenance.INFERRED,
|
|
16397
|
+
edgeType: bucket.type,
|
|
16398
|
+
observed: bucket.observed,
|
|
16399
|
+
spanCount,
|
|
16400
|
+
errorCount,
|
|
16401
|
+
errorRate: clampConfidence(errorRate),
|
|
16402
|
+
confidence: OBSERVED_FAILING_CONFIDENCE,
|
|
16403
|
+
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.`,
|
|
16404
|
+
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."
|
|
16405
|
+
}
|
|
16406
|
+
];
|
|
16407
|
+
}
|
|
16408
|
+
var OBSERVED_FAILURE_PATTERNS = [
|
|
16409
|
+
{
|
|
16410
|
+
kind: "connection-refused",
|
|
16411
|
+
patterns: [/\bECONNREFUSED\b/i, /\bconnection refused\b/i]
|
|
16412
|
+
},
|
|
16413
|
+
{
|
|
16414
|
+
kind: "deadline-exceeded",
|
|
16415
|
+
patterns: [/\bDEADLINE_EXCEEDED\b/i, /\bdeadline exceeded\b/i]
|
|
16416
|
+
},
|
|
16417
|
+
{
|
|
16418
|
+
kind: "timeout",
|
|
16419
|
+
patterns: [/\bETIMEDOUT\b/i, /\btimed[\s-]?out\b/i, /\btimeout\b/i]
|
|
16420
|
+
},
|
|
16421
|
+
{
|
|
16422
|
+
kind: "unavailable",
|
|
16423
|
+
patterns: [
|
|
16424
|
+
/\bUNAVAILABLE\b/i,
|
|
16425
|
+
/\bservice unavailable\b/i,
|
|
16426
|
+
/\bECONNRESET\b/i,
|
|
16427
|
+
/\bconnection reset\b/i,
|
|
16428
|
+
/\bno healthy upstream\b/i
|
|
16429
|
+
]
|
|
16430
|
+
}
|
|
16431
|
+
];
|
|
16432
|
+
function classifyObservedFailure(ev) {
|
|
16433
|
+
const haystack = [ev.errorType, ev.exceptionType, ev.errorMessage].filter((s) => typeof s === "string").join(" \n ");
|
|
16434
|
+
for (const entry2 of OBSERVED_FAILURE_PATTERNS) {
|
|
16435
|
+
for (const re of entry2.patterns) {
|
|
16436
|
+
if (re.test(haystack)) return entry2.kind;
|
|
16437
|
+
}
|
|
16438
|
+
}
|
|
16439
|
+
const code = ev.httpStatusCode;
|
|
16440
|
+
if (typeof code === "number" && code >= 500 && code < 600) return "server-error";
|
|
16441
|
+
return null;
|
|
16442
|
+
}
|
|
16443
|
+
function observedFailureLabel(kind) {
|
|
16444
|
+
switch (kind) {
|
|
16445
|
+
case "error-rate":
|
|
16446
|
+
return "a high error rate";
|
|
16447
|
+
case "connection-refused":
|
|
16448
|
+
return "a refused connection";
|
|
16449
|
+
case "deadline-exceeded":
|
|
16450
|
+
return "a deadline exceeded";
|
|
16451
|
+
case "timeout":
|
|
16452
|
+
return "a timeout";
|
|
16453
|
+
case "unavailable":
|
|
16454
|
+
return "an unavailable or reset connection";
|
|
16455
|
+
case "server-error":
|
|
16456
|
+
return "a server error (5xx)";
|
|
16457
|
+
}
|
|
16458
|
+
}
|
|
16459
|
+
function detectObservedFailingIncidents(graph, incidents) {
|
|
16460
|
+
const groups = /* @__PURE__ */ new Map();
|
|
16461
|
+
for (const ev of incidents) {
|
|
16462
|
+
const kind = classifyObservedFailure(ev);
|
|
16463
|
+
if (!kind) continue;
|
|
16464
|
+
const locus = symbolLocus(graph, ev);
|
|
16465
|
+
if (!locus) continue;
|
|
16466
|
+
const key = `${locus.node}|${kind}`;
|
|
16467
|
+
const existing = groups.get(key);
|
|
16468
|
+
if (!existing) {
|
|
16469
|
+
groups.set(key, {
|
|
16470
|
+
node: locus.node,
|
|
16471
|
+
kind,
|
|
16472
|
+
...locus.location ? { location: locus.location } : {},
|
|
16473
|
+
latest: ev,
|
|
16474
|
+
count: 1,
|
|
16475
|
+
...typeof ev.httpStatusCode === "number" ? { httpStatusCode: ev.httpStatusCode } : {}
|
|
16476
|
+
});
|
|
16477
|
+
} else {
|
|
16478
|
+
existing.count += 1;
|
|
16479
|
+
if (ev.timestamp.localeCompare(existing.latest.timestamp) > 0) {
|
|
16480
|
+
existing.latest = ev;
|
|
16481
|
+
if (locus.location) existing.location = locus.location;
|
|
16482
|
+
if (typeof ev.httpStatusCode === "number") existing.httpStatusCode = ev.httpStatusCode;
|
|
16483
|
+
}
|
|
16484
|
+
}
|
|
16485
|
+
}
|
|
16486
|
+
const out = [];
|
|
16487
|
+
for (const g of groups.values()) {
|
|
16488
|
+
const where = g.location ? ` at ${g.location}` : "";
|
|
16489
|
+
const label = observedFailureLabel(g.kind);
|
|
16490
|
+
const times = g.count > 1 ? ` (${g.count} recorded incidents)` : " (1 recorded incident)";
|
|
16491
|
+
out.push({
|
|
16492
|
+
type: "observed-failing",
|
|
16493
|
+
source: g.node,
|
|
16494
|
+
target: g.node,
|
|
16495
|
+
failureKind: g.kind,
|
|
16496
|
+
provenance: import_types57.Provenance.INFERRED,
|
|
16497
|
+
...g.location ? { location: g.location } : {},
|
|
16498
|
+
incidentId: g.latest.id,
|
|
16499
|
+
errorMessage: g.latest.errorMessage,
|
|
16500
|
+
incidentCount: g.count,
|
|
16501
|
+
...typeof g.httpStatusCode === "number" ? { httpStatusCode: g.httpStatusCode } : {},
|
|
16502
|
+
confidence: OBSERVED_FAILING_CONFIDENCE,
|
|
16503
|
+
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.`,
|
|
16504
|
+
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.`
|
|
16505
|
+
});
|
|
16506
|
+
}
|
|
16507
|
+
return out;
|
|
16508
|
+
}
|
|
16376
16509
|
function involvesNode(d, nodeId) {
|
|
16377
16510
|
return d.source === nodeId || d.target === nodeId;
|
|
16378
16511
|
}
|
|
@@ -16445,6 +16578,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16445
16578
|
const buckets2 = bucketEdges(graph);
|
|
16446
16579
|
for (const bucket of buckets2.values()) {
|
|
16447
16580
|
for (const d of detectMissingDivergences(graph, bucket)) all.push(d);
|
|
16581
|
+
for (const d of detectObservedFailingEdge(graph, bucket)) all.push(d);
|
|
16448
16582
|
}
|
|
16449
16583
|
graph.forEachNode((nodeId, attrs) => {
|
|
16450
16584
|
const n = attrs;
|
|
@@ -16460,6 +16594,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16460
16594
|
});
|
|
16461
16595
|
if (opts.incidents && opts.incidents.length > 0) {
|
|
16462
16596
|
for (const d of detectSymbolMismatches(graph, opts.incidents)) all.push(d);
|
|
16597
|
+
for (const d of detectObservedFailingIncidents(graph, opts.incidents)) all.push(d);
|
|
16463
16598
|
}
|
|
16464
16599
|
const reconciled = suppressHostMismatchHalves(all);
|
|
16465
16600
|
const dampened = dampenDeadCodeProbes(graph, buckets2, reconciled);
|
|
@@ -16486,7 +16621,12 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16486
16621
|
// type; this only breaks a confidence tie, and it orders last so a same-
|
|
16487
16622
|
// confidence edge finding leads. In practice it carries the INFERRED grade
|
|
16488
16623
|
// (0.6), so it sits below the high-confidence edge divergences already.
|
|
16489
|
-
"observed-symbol-mismatch": 5
|
|
16624
|
+
"observed-symbol-mismatch": 5,
|
|
16625
|
+
// Behavioral-failure (ADR-220) also carries the INFERRED grade (0.6); it
|
|
16626
|
+
// orders last so at equal confidence the structural and symbol divergences
|
|
16627
|
+
// lead, per the contract ("rank below the definitive structural and symbol
|
|
16628
|
+
// divergences").
|
|
16629
|
+
"observed-failing": 6
|
|
16490
16630
|
};
|
|
16491
16631
|
filtered.sort((a, b) => {
|
|
16492
16632
|
if (b.confidence !== a.confidence) return b.confidence - a.confidence;
|
|
@@ -16500,7 +16640,13 @@ function computeDivergences(graph, opts = {}) {
|
|
|
16500
16640
|
if (ac !== bc) return ac.localeCompare(bc);
|
|
16501
16641
|
const asym = "symbol" in a && a.symbol ? a.symbol : "";
|
|
16502
16642
|
const bsym = "symbol" in b && b.symbol ? b.symbol : "";
|
|
16503
|
-
return asym.localeCompare(bsym);
|
|
16643
|
+
if (asym !== bsym) return asym.localeCompare(bsym);
|
|
16644
|
+
const afk = "failureKind" in a && a.failureKind ? a.failureKind : "";
|
|
16645
|
+
const bfk = "failureKind" in b && b.failureKind ? b.failureKind : "";
|
|
16646
|
+
if (afk !== bfk) return afk.localeCompare(bfk);
|
|
16647
|
+
const aloc = "location" in a && a.location ? a.location : "";
|
|
16648
|
+
const bloc = "location" in b && b.location ? b.location : "";
|
|
16649
|
+
return aloc.localeCompare(bloc);
|
|
16504
16650
|
});
|
|
16505
16651
|
return import_types57.DivergenceResultSchema.parse({
|
|
16506
16652
|
divergences: filtered,
|
|
@@ -17565,6 +17711,10 @@ function divergenceLine(d) {
|
|
|
17565
17711
|
const member = d.symbol ? ` ${d.symbol}` : "";
|
|
17566
17712
|
return `[${d.type}] ${d.source}${member}${at} \u2014 ${d.reason}`;
|
|
17567
17713
|
}
|
|
17714
|
+
if (d.type === "observed-failing" && !d.edgeType) {
|
|
17715
|
+
const at = d.location ? ` at ${d.location}` : "";
|
|
17716
|
+
return `[${d.type}] ${d.source}${at} \u2014 ${d.reason}`;
|
|
17717
|
+
}
|
|
17568
17718
|
return `[${d.type}] ${d.source} \u2192 ${d.target} \u2014 ${d.reason}`;
|
|
17569
17719
|
}
|
|
17570
17720
|
function buildDivergenceSection(graph, node, incidents) {
|
|
@@ -28569,6 +28719,14 @@ function formatDivergenceLine(d) {
|
|
|
28569
28719
|
const member = d.symbol ? ` ${d.symbol}` : "";
|
|
28570
28720
|
return ` \u2022 [${d.type}] ${d.source}${member}${at} (${d.mismatchKind}) \u2014 confidence ${d.confidence.toFixed(2)}`;
|
|
28571
28721
|
}
|
|
28722
|
+
case "observed-failing": {
|
|
28723
|
+
if (d.edgeType) {
|
|
28724
|
+
const rate = d.errorRate !== void 0 ? ` ${Math.round(d.errorRate * 100)}% errors` : "";
|
|
28725
|
+
return ` \u2022 [${d.type}] ${d.source} \u2192 ${d.target} (${d.edgeType}) \u2014${rate} (${d.failureKind}) \u2014 confidence ${d.confidence.toFixed(2)}`;
|
|
28726
|
+
}
|
|
28727
|
+
const at = d.location ? ` at ${d.location}` : "";
|
|
28728
|
+
return ` \u2022 [${d.type}] ${d.source}${at} (${d.failureKind}) \u2014 confidence ${d.confidence.toFixed(2)}`;
|
|
28729
|
+
}
|
|
28572
28730
|
}
|
|
28573
28731
|
}
|
|
28574
28732
|
async function runDivergences(client, input) {
|
|
@@ -29790,6 +29948,9 @@ function divergenceKey(d) {
|
|
|
29790
29948
|
case "compat-violation":
|
|
29791
29949
|
extra = `${d.rule.kind}:${d.rule.package ?? ""}`;
|
|
29792
29950
|
break;
|
|
29951
|
+
case "observed-failing":
|
|
29952
|
+
extra = `${d.failureKind}:${d.location ?? ""}`;
|
|
29953
|
+
break;
|
|
29793
29954
|
default:
|
|
29794
29955
|
extra = "";
|
|
29795
29956
|
}
|
|
@@ -29821,6 +29982,14 @@ function formatDivergenceLine2(d) {
|
|
|
29821
29982
|
const member = d.symbol ? ` ${d.symbol}` : " a member";
|
|
29822
29983
|
return `\u26A0 divergence [observed-symbol-mismatch] ${d.source}${at} reads${member} the runtime object does not have (${d.mismatchKind})`;
|
|
29823
29984
|
}
|
|
29985
|
+
case "observed-failing": {
|
|
29986
|
+
if (d.edgeType) {
|
|
29987
|
+
const rate = d.errorRate !== void 0 ? `, ${Math.round(d.errorRate * 100)}% errors` : "";
|
|
29988
|
+
return `\u26A0 divergence [observed-failing] ${d.source} \u2192 ${d.target} declared and observed, but failing (${d.failureKind}${rate})`;
|
|
29989
|
+
}
|
|
29990
|
+
const at = d.location ? ` at ${d.location}` : "";
|
|
29991
|
+
return `\u26A0 divergence [observed-failing] ${d.source}${at} declares a call observed failing (${d.failureKind})`;
|
|
29992
|
+
}
|
|
29824
29993
|
}
|
|
29825
29994
|
}
|
|
29826
29995
|
function formatStaleLine(edgeId) {
|