@neat.is/core 0.9.13 → 0.9.15-dev.20260902
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-BKSM2YLV.js → chunk-NV4WWJSU.js} +45 -5
- package/dist/chunk-NV4WWJSU.js.map +1 -0
- package/dist/{chunk-RL6H3VVD.js → chunk-SSLPBQWY.js} +107 -37
- package/dist/chunk-SSLPBQWY.js.map +1 -0
- package/dist/cli.cjs +156 -58
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +7 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +138 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +138 -41
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +73 -36
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-BKSM2YLV.js.map +0 -1
- package/dist/chunk-RL6H3VVD.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -440,6 +440,7 @@ interface StalenessLoopOptions {
|
|
|
440
440
|
staleEventsPath?: string;
|
|
441
441
|
project?: string;
|
|
442
442
|
onPolicyTrigger?: (graph: NeatGraph) => Promise<void> | void;
|
|
443
|
+
onReconcile?: (graph: NeatGraph) => Promise<void> | void;
|
|
443
444
|
}
|
|
444
445
|
declare function startStalenessLoop(graph: NeatGraph, options?: StalenessLoopOptions): () => void;
|
|
445
446
|
declare function readErrorEvents(errorsPath: string, opts?: {
|
package/dist/index.d.ts
CHANGED
|
@@ -440,6 +440,7 @@ interface StalenessLoopOptions {
|
|
|
440
440
|
staleEventsPath?: string;
|
|
441
441
|
project?: string;
|
|
442
442
|
onPolicyTrigger?: (graph: NeatGraph) => Promise<void> | void;
|
|
443
|
+
onReconcile?: (graph: NeatGraph) => Promise<void> | void;
|
|
443
444
|
}
|
|
444
445
|
declare function startStalenessLoop(graph: NeatGraph, options?: StalenessLoopOptions): () => void;
|
|
445
446
|
declare function readErrorEvents(errorsPath: string, opts?: {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeSpanToProject,
|
|
3
3
|
startDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NV4WWJSU.js";
|
|
5
5
|
import {
|
|
6
6
|
ProjectNameCollisionError,
|
|
7
7
|
addProject,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
thresholdForEdgeType,
|
|
38
38
|
touchLastSeen,
|
|
39
39
|
writeAtomically
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-SSLPBQWY.js";
|
|
41
41
|
import {
|
|
42
42
|
startOtelGrpcReceiver
|
|
43
43
|
} from "./chunk-ERE47MCR.js";
|
package/dist/neatd.cjs
CHANGED
|
@@ -1247,13 +1247,19 @@ function resolveOwningService(graph, nodeId) {
|
|
|
1247
1247
|
}
|
|
1248
1248
|
return null;
|
|
1249
1249
|
}
|
|
1250
|
+
function isFrontierEdge(e) {
|
|
1251
|
+
return e.provenance === import_types.Provenance.FRONTIER;
|
|
1252
|
+
}
|
|
1253
|
+
function rankOf(p) {
|
|
1254
|
+
return p === import_types.Provenance.FRONTIER ? -1 : import_types.PROV_RANK[p];
|
|
1255
|
+
}
|
|
1250
1256
|
function bestEdgeBySource(graph, edgeIds) {
|
|
1251
1257
|
const best = /* @__PURE__ */ new Map();
|
|
1252
1258
|
for (const id of edgeIds) {
|
|
1253
1259
|
const e = graph.getEdgeAttributes(id);
|
|
1254
|
-
if (isFrontierNode(graph, e.source)) continue;
|
|
1260
|
+
if (isFrontierNode(graph, e.source) || isFrontierEdge(e)) continue;
|
|
1255
1261
|
const cur = best.get(e.source);
|
|
1256
|
-
if (!cur ||
|
|
1262
|
+
if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
|
|
1257
1263
|
best.set(e.source, e);
|
|
1258
1264
|
}
|
|
1259
1265
|
}
|
|
@@ -1263,9 +1269,9 @@ function bestEdgeByTarget(graph, edgeIds) {
|
|
|
1263
1269
|
const best = /* @__PURE__ */ new Map();
|
|
1264
1270
|
for (const id of edgeIds) {
|
|
1265
1271
|
const e = graph.getEdgeAttributes(id);
|
|
1266
|
-
if (isFrontierNode(graph, e.target)) continue;
|
|
1272
|
+
if (isFrontierNode(graph, e.target) || isFrontierEdge(e)) continue;
|
|
1267
1273
|
const cur = best.get(e.target);
|
|
1268
|
-
if (!cur ||
|
|
1274
|
+
if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
|
|
1269
1275
|
best.set(e.target, e);
|
|
1270
1276
|
}
|
|
1271
1277
|
}
|
|
@@ -1275,7 +1281,10 @@ var PROVENANCE_CEILING = {
|
|
|
1275
1281
|
OBSERVED: 1,
|
|
1276
1282
|
INFERRED: 0.7,
|
|
1277
1283
|
EXTRACTED: 0.5,
|
|
1278
|
-
STALE: 0.3
|
|
1284
|
+
STALE: 0.3,
|
|
1285
|
+
// A FRONTIER surface (ADR-226) is a proposal about a cause NEAT could not observe
|
|
1286
|
+
// — the least-trusted claim it makes, below STALE (which was at least once seen).
|
|
1287
|
+
FRONTIER: 0.2
|
|
1279
1288
|
};
|
|
1280
1289
|
function volumeWeight(spanCount) {
|
|
1281
1290
|
if (!spanCount || spanCount <= 0) return 0.5;
|
|
@@ -1510,7 +1519,7 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
|
|
|
1510
1519
|
});
|
|
1511
1520
|
}
|
|
1512
1521
|
function isFailingCallEdge(e) {
|
|
1513
|
-
return e.type === import_types.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
|
|
1522
|
+
return e.type === import_types.EdgeType.CALLS && !isFrontierEdge(e) && (e.signal?.errorCount ?? 0) > 0;
|
|
1514
1523
|
}
|
|
1515
1524
|
function callSourcesForService(graph, serviceId17) {
|
|
1516
1525
|
const ids = [serviceId17];
|
|
@@ -1533,8 +1542,8 @@ function failingCallDominates(e, id, curEdge, curId) {
|
|
|
1533
1542
|
const ec = e.signal?.errorCount ?? 0;
|
|
1534
1543
|
const cc = curEdge.signal?.errorCount ?? 0;
|
|
1535
1544
|
if (ec !== cc) return ec > cc;
|
|
1536
|
-
if (
|
|
1537
|
-
return
|
|
1545
|
+
if (rankOf(e.provenance) !== rankOf(curEdge.provenance)) {
|
|
1546
|
+
return rankOf(e.provenance) > rankOf(curEdge.provenance);
|
|
1538
1547
|
}
|
|
1539
1548
|
return id < curId;
|
|
1540
1549
|
}
|
|
@@ -1585,11 +1594,11 @@ function dominantStaleCall(graph, serviceId17, visited) {
|
|
|
1585
1594
|
for (const edgeId of graph.outboundEdges(src)) {
|
|
1586
1595
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1587
1596
|
if (e.type !== import_types.EdgeType.CALLS) continue;
|
|
1588
|
-
if (isFrontierNode(graph, e.target)) continue;
|
|
1597
|
+
if (isFrontierNode(graph, e.target) || isFrontierEdge(e)) continue;
|
|
1589
1598
|
const owner = resolveOwningService(graph, e.target);
|
|
1590
1599
|
if (!owner || visited.has(owner.id)) continue;
|
|
1591
1600
|
const cur = bestByCallee.get(owner.id);
|
|
1592
|
-
if (!cur ||
|
|
1601
|
+
if (!cur || rankOf(e.provenance) > rankOf(cur.provenance)) {
|
|
1593
1602
|
bestByCallee.set(owner.id, e);
|
|
1594
1603
|
}
|
|
1595
1604
|
}
|
|
@@ -1862,6 +1871,7 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
|
|
|
1862
1871
|
for (const edgeId of graph.inboundEdges(n)) {
|
|
1863
1872
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1864
1873
|
if (e.type === import_types.EdgeType.CONTAINS) continue;
|
|
1874
|
+
if (isFrontierEdge(e)) continue;
|
|
1865
1875
|
errorsFromCallers += e.signal?.errorCount ?? 0;
|
|
1866
1876
|
inboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
|
|
1867
1877
|
if (e.provenance === import_types.Provenance.STALE) stale = true;
|
|
@@ -1875,6 +1885,7 @@ function nodeContext(graph, nodeId, incidents, now = Date.now()) {
|
|
|
1875
1885
|
for (const edgeId of graph.outboundEdges(n)) {
|
|
1876
1886
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1877
1887
|
if (e.type === import_types.EdgeType.CONTAINS) continue;
|
|
1888
|
+
if (isFrontierEdge(e)) continue;
|
|
1878
1889
|
outboundVolume += e.callCount ?? e.signal?.spanCount ?? 0;
|
|
1879
1890
|
if (e.type === import_types.EdgeType.CALLS) outboundErrors += e.signal?.errorCount ?? 0;
|
|
1880
1891
|
if (e.provenance === import_types.Provenance.STALE) stale = true;
|
|
@@ -2158,22 +2169,44 @@ function routeMatches(declared, incident) {
|
|
|
2158
2169
|
const b = normalizeRoute(incident);
|
|
2159
2170
|
return a === b || a.startsWith(b) || b.startsWith(a);
|
|
2160
2171
|
}
|
|
2161
|
-
function
|
|
2162
|
-
const
|
|
2163
|
-
const callees = declaredOutboundCallees(graph, boundaryNode);
|
|
2172
|
+
function firstDeclaredCallee(graph, node, route) {
|
|
2173
|
+
const callees = declaredOutboundCallees(graph, node);
|
|
2164
2174
|
if (callees.length === 0) return null;
|
|
2165
2175
|
const narrowed = route !== void 0 ? callees.filter((c) => c.route !== void 0 && routeMatches(c.route, route)) : callees;
|
|
2166
2176
|
const chosen = narrowed.length === 1 ? narrowed[0] : callees.length === 1 ? callees[0] : null;
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
if (
|
|
2173
|
-
|
|
2174
|
-
|
|
2177
|
+
return chosen ? chosen.target : null;
|
|
2178
|
+
}
|
|
2179
|
+
function observedOutboundNextServices(graph, nodeId) {
|
|
2180
|
+
const targets = /* @__PURE__ */ new Set();
|
|
2181
|
+
for (const n of nodeScope(graph, nodeId)) {
|
|
2182
|
+
if (!graph.hasNode(n)) continue;
|
|
2183
|
+
for (const edgeId of graph.outboundEdges(n)) {
|
|
2184
|
+
const e = graph.getEdgeAttributes(edgeId);
|
|
2185
|
+
if (!DEP_EDGE_TYPES.has(e.type)) continue;
|
|
2186
|
+
if (e.provenance !== import_types.Provenance.OBSERVED) continue;
|
|
2187
|
+
if (e.target !== nodeId) targets.add(e.target);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
return [...targets];
|
|
2191
|
+
}
|
|
2192
|
+
function resolveHangHop(graph, boundaryNode, incidents) {
|
|
2193
|
+
const route = boundaryIncidentRoute(boundaryNode, incidents);
|
|
2194
|
+
const own = firstDeclaredCallee(graph, boundaryNode, route);
|
|
2195
|
+
if (own) {
|
|
2196
|
+
return route !== void 0 ? { source: boundaryNode, target: own, route } : { source: boundaryNode, target: own };
|
|
2197
|
+
}
|
|
2198
|
+
const resolved = observedOutboundNextServices(graph, boundaryNode).map((n) => ({ source: n, target: firstDeclaredCallee(graph, n, route) })).filter((r) => r.target !== null);
|
|
2199
|
+
if (resolved.length === 1) {
|
|
2200
|
+
const hop = resolved[0];
|
|
2201
|
+
return route !== void 0 ? { ...hop, route } : hop;
|
|
2175
2202
|
}
|
|
2176
|
-
return
|
|
2203
|
+
return null;
|
|
2204
|
+
}
|
|
2205
|
+
function stagedHangProposal(graph, boundaryNode, incidents) {
|
|
2206
|
+
const hop = resolveHangHop(graph, boundaryNode, incidents);
|
|
2207
|
+
if (!hop) return null;
|
|
2208
|
+
if (!graph.hasEdge((0, import_types.frontierEdgeId)(hop.source, hop.target, import_types.EdgeType.CALLS))) return null;
|
|
2209
|
+
return hop.route !== void 0 ? { node: hop.target, route: hop.route } : { node: hop.target };
|
|
2177
2210
|
}
|
|
2178
2211
|
function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
|
|
2179
2212
|
const legacy = tagged.result;
|
|
@@ -2219,28 +2252,28 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
|
|
|
2219
2252
|
provenance: import_types.Provenance.OBSERVED
|
|
2220
2253
|
});
|
|
2221
2254
|
} else if (seedCtx && isBoundaryTimeoutSymptom(seedCtx)) {
|
|
2222
|
-
const pointer = structuralUpstreamPointer(graph, seedNode, incidents);
|
|
2223
2255
|
const seedName = displayNameOf(seedNode);
|
|
2224
|
-
const
|
|
2225
|
-
|
|
2226
|
-
const causeName = displayNameOf(pointer.node);
|
|
2227
|
-
candidates.push({
|
|
2228
|
-
node: pointer.node,
|
|
2229
|
-
classification: "primary-failure",
|
|
2230
|
-
reason: `${causeName} is the likely root cause (structural, INFERRED \u2014 not observed): the boundary ${seedName} only timed out waiting, and the actual culprit hung without exporting a span, so this is walked from the declared call graph${routeNote}, not from runtime signal. Restore instrumentation / inspect ${causeName} to confirm.`,
|
|
2231
|
-
context: nodeContext(graph, pointer.node, incidents, now),
|
|
2232
|
-
confidence: Math.min(legacy.confidence, PROVENANCE_CEILING.EXTRACTED),
|
|
2233
|
-
provenance: import_types.Provenance.INFERRED
|
|
2234
|
-
});
|
|
2235
|
-
}
|
|
2256
|
+
const proposal = stagedHangProposal(graph, seedNode, incidents);
|
|
2257
|
+
const routeNote = proposal?.route ? ` serving ${proposal.route}` : "";
|
|
2236
2258
|
candidates.push({
|
|
2237
2259
|
node: seedNode,
|
|
2238
2260
|
classification: "symptom-only",
|
|
2239
|
-
reason:
|
|
2261
|
+
reason: proposal ? `${seedName} timed out waiting on a downstream that hung and exported no span \u2014 a boundary reporting an upstream fault, not the fault itself. The cause is unobservable; NEAT proposes the staged FRONTIER surface below, a hypothesis to confirm, not an observed cause.` : `${seedName} timed out but nothing it can see downstream is erroring \u2014 the cause is downstream and unobserved (the culprit hung and exported no span). No FRONTIER surface${routeNote} is staged, so no cause is proposed; inspect ${seedName}'s declared downstream and restore instrumentation.`,
|
|
2240
2262
|
context: seedCtx,
|
|
2241
2263
|
confidence: Math.min(legacy.confidence, 0.3),
|
|
2242
2264
|
...lastProv ? { provenance: lastProv } : {}
|
|
2243
2265
|
});
|
|
2266
|
+
if (proposal) {
|
|
2267
|
+
const causeName = displayNameOf(proposal.node);
|
|
2268
|
+
candidates.push({
|
|
2269
|
+
node: proposal.node,
|
|
2270
|
+
classification: "primary-failure",
|
|
2271
|
+
reason: `${causeName} is the proposed hang cause (FRONTIER \u2014 a hypothesis, not observed): the boundary ${seedName} only timed out waiting and the culprit hung without exporting a span, so NEAT staged a FRONTIER surface on the unobservable hop${routeNote}. It graduates to OBSERVED when ${causeName} comes back; until then, inspect it / restore instrumentation to confirm, or it is culled.`,
|
|
2272
|
+
context: nodeContext(graph, proposal.node, incidents, now),
|
|
2273
|
+
confidence: Math.min(legacy.confidence, PROVENANCE_CEILING.FRONTIER),
|
|
2274
|
+
provenance: import_types.Provenance.FRONTIER
|
|
2275
|
+
});
|
|
2276
|
+
}
|
|
2244
2277
|
} else if (staleChain) {
|
|
2245
2278
|
const culprit = staleChain.culprit;
|
|
2246
2279
|
const culpritName = displayNameOf(culprit);
|
|
@@ -2304,6 +2337,9 @@ function fixRecommendationForTop(top, seedNode, legacy) {
|
|
|
2304
2337
|
return legacy.fixRecommendation;
|
|
2305
2338
|
}
|
|
2306
2339
|
const name = top.node.replace(/^service:/, "");
|
|
2340
|
+
if (top.classification === "symptom-only" && top.context.boundaryTimeout === true) {
|
|
2341
|
+
return `${name} timed out waiting on a downstream that hung and exported no span \u2014 the cause is unobservable from traces. Inspect the FRONTIER surface NEAT staged on the unobservable hop (see candidates); it graduates to OBSERVED when that service recovers. Restore instrumentation on that path to confirm, rather than treating ${name} as the fault.`;
|
|
2342
|
+
}
|
|
2307
2343
|
if (top.provenance === import_types.Provenance.STALE) {
|
|
2308
2344
|
return `Live telemetry for this path has gone quiet; the last-observed topology traces the failure downstream to ${name}. Restore instrumentation (or re-run with live traces) to confirm, then inspect ${name}.`;
|
|
2309
2345
|
}
|
|
@@ -6969,6 +7005,32 @@ function promoteFrontierNodes(graph, opts = {}) {
|
|
|
6969
7005
|
}
|
|
6970
7006
|
return promoted;
|
|
6971
7007
|
}
|
|
7008
|
+
function stageFrontierEdge(graph, source, target, type) {
|
|
7009
|
+
if (!graph.hasNode(source) || !graph.hasNode(target)) return false;
|
|
7010
|
+
if (graph.hasEdge((0, import_types8.observedEdgeId)(source, target, type))) return false;
|
|
7011
|
+
const key = (0, import_types8.frontierEdgeId)(source, target, type);
|
|
7012
|
+
if (graph.hasEdge(key)) return false;
|
|
7013
|
+
graph.addEdgeWithKey(key, source, target, {
|
|
7014
|
+
id: key,
|
|
7015
|
+
source,
|
|
7016
|
+
target,
|
|
7017
|
+
type,
|
|
7018
|
+
provenance: import_types8.Provenance.FRONTIER
|
|
7019
|
+
});
|
|
7020
|
+
return true;
|
|
7021
|
+
}
|
|
7022
|
+
function promoteFrontierEdges(graph) {
|
|
7023
|
+
const graduated = [];
|
|
7024
|
+
graph.forEachEdge((edgeId, attrs) => {
|
|
7025
|
+
const e = attrs;
|
|
7026
|
+
if (e.provenance !== import_types8.Provenance.FRONTIER) return;
|
|
7027
|
+
if (graph.hasEdge((0, import_types8.observedEdgeId)(e.source, e.target, e.type))) {
|
|
7028
|
+
graduated.push(edgeId);
|
|
7029
|
+
}
|
|
7030
|
+
});
|
|
7031
|
+
for (const edgeId of graduated) graph.dropEdge(edgeId);
|
|
7032
|
+
return graduated.length;
|
|
7033
|
+
}
|
|
6972
7034
|
function rewireFrontierEdges(graph, frontierId2, serviceId17) {
|
|
6973
7035
|
const inbound = [...graph.inboundEdges(frontierId2)];
|
|
6974
7036
|
const outbound = [...graph.outboundEdges(frontierId2)];
|
|
@@ -7074,6 +7136,7 @@ function startStalenessLoop(graph, options = {}) {
|
|
|
7074
7136
|
project: options.project
|
|
7075
7137
|
});
|
|
7076
7138
|
if (options.onPolicyTrigger) await options.onPolicyTrigger(graph);
|
|
7139
|
+
if (options.onReconcile) await options.onReconcile(graph);
|
|
7077
7140
|
} catch (err) {
|
|
7078
7141
|
console.error("staleness tick failed", err);
|
|
7079
7142
|
}
|
|
@@ -23203,6 +23266,36 @@ async function buildApi(opts) {
|
|
|
23203
23266
|
// src/daemon.ts
|
|
23204
23267
|
init_otel();
|
|
23205
23268
|
|
|
23269
|
+
// src/hang-sensor.ts
|
|
23270
|
+
init_cjs_shims();
|
|
23271
|
+
var import_types101 = require("@neat.is/types");
|
|
23272
|
+
var RECONCILE_INCIDENT_LIMIT = 500;
|
|
23273
|
+
function stageHangSurfaces(graph, incidents) {
|
|
23274
|
+
const boundaries = /* @__PURE__ */ new Set();
|
|
23275
|
+
for (const ev of incidents) {
|
|
23276
|
+
if (ev.affectedNode && graph.hasNode(ev.affectedNode)) boundaries.add(ev.affectedNode);
|
|
23277
|
+
}
|
|
23278
|
+
let staged = 0;
|
|
23279
|
+
for (const boundary of boundaries) {
|
|
23280
|
+
const ctx = nodeContext(graph, boundary, incidents);
|
|
23281
|
+
if (!isBoundaryTimeoutSymptom(ctx)) continue;
|
|
23282
|
+
const hop = resolveHangHop(graph, boundary, incidents);
|
|
23283
|
+
if (!hop) continue;
|
|
23284
|
+
if (stageFrontierEdge(graph, hop.source, hop.target, import_types101.EdgeType.CALLS)) staged++;
|
|
23285
|
+
}
|
|
23286
|
+
return staged;
|
|
23287
|
+
}
|
|
23288
|
+
async function reconcileFrontierSurfaces(graph, errorsPath) {
|
|
23289
|
+
promoteFrontierEdges(graph);
|
|
23290
|
+
let incidents = [];
|
|
23291
|
+
try {
|
|
23292
|
+
incidents = await readErrorEvents(errorsPath, { limit: RECONCILE_INCIDENT_LIMIT });
|
|
23293
|
+
} catch {
|
|
23294
|
+
incidents = [];
|
|
23295
|
+
}
|
|
23296
|
+
stageHangSurfaces(graph, incidents);
|
|
23297
|
+
}
|
|
23298
|
+
|
|
23206
23299
|
// src/connectors/kubernetes/index.ts
|
|
23207
23300
|
init_cjs_shims();
|
|
23208
23301
|
|
|
@@ -23552,7 +23645,7 @@ function mapWorkloadsToSignals(deployments, pods, config) {
|
|
|
23552
23645
|
|
|
23553
23646
|
// src/connectors/kubernetes/resolve.ts
|
|
23554
23647
|
init_cjs_shims();
|
|
23555
|
-
var
|
|
23648
|
+
var import_types103 = require("@neat.is/types");
|
|
23556
23649
|
var NO_ENV3 = "unknown";
|
|
23557
23650
|
function createK8sResolveTarget(graph) {
|
|
23558
23651
|
return (signal) => {
|
|
@@ -23563,7 +23656,7 @@ function createK8sResolveTarget(graph) {
|
|
|
23563
23656
|
return {
|
|
23564
23657
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV3),
|
|
23565
23658
|
serviceName,
|
|
23566
|
-
edgeType:
|
|
23659
|
+
edgeType: import_types103.EdgeType.CALLS
|
|
23567
23660
|
};
|
|
23568
23661
|
};
|
|
23569
23662
|
}
|
|
@@ -23698,7 +23791,7 @@ function unroutedErrorsPath(neatHome4) {
|
|
|
23698
23791
|
}
|
|
23699
23792
|
|
|
23700
23793
|
// src/daemon.ts
|
|
23701
|
-
var
|
|
23794
|
+
var import_types106 = require("@neat.is/types");
|
|
23702
23795
|
function daemonJsonPath(scanPath) {
|
|
23703
23796
|
return import_node_path77.default.join(scanPath, "neat-out", "daemon.json");
|
|
23704
23797
|
}
|
|
@@ -23841,7 +23934,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
|
|
|
23841
23934
|
if (!serviceName) return true;
|
|
23842
23935
|
if (serviceNameMatchesProject(serviceName, project)) return true;
|
|
23843
23936
|
return graph.someNode(
|
|
23844
|
-
(_id, attrs) => attrs.type ===
|
|
23937
|
+
(_id, attrs) => attrs.type === import_types106.NodeType.ServiceNode && attrs.name === serviceName
|
|
23845
23938
|
);
|
|
23846
23939
|
}
|
|
23847
23940
|
async function bootstrapProject(entry2, connectors = [], neatHome4) {
|
|
@@ -23885,7 +23978,11 @@ async function bootstrapProject(entry2, connectors = [], neatHome4) {
|
|
|
23885
23978
|
const stopPersist = startPersistLoop(graph, outPath, { exitOnSignal: false });
|
|
23886
23979
|
const stopStaleness = startStalenessLoop(graph, {
|
|
23887
23980
|
staleEventsPath: paths.staleEventsPath,
|
|
23888
|
-
project: entry2.name
|
|
23981
|
+
project: entry2.name,
|
|
23982
|
+
// Graduate FRONTIER surfaces whose OBSERVED twin has arrived + stage surfaces
|
|
23983
|
+
// for current hangs (ADR-226), each post-ingest tick — the periodic point
|
|
23984
|
+
// where OBSERVED state has settled and the errors ledger is current.
|
|
23985
|
+
onReconcile: (g) => reconcileFrontierSurfaces(g, paths.errorsPath)
|
|
23889
23986
|
});
|
|
23890
23987
|
const stopConnectors = await startConnectorPolling({
|
|
23891
23988
|
project: entry2.name,
|