@neat.is/core 0.9.13-dev.20260901 → 0.9.13

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/neatd.js CHANGED
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  reconcileDaemonRecordSync,
4
4
  startDaemon
5
- } from "./chunk-WE3AFQYL.js";
5
+ } from "./chunk-BKSM2YLV.js";
6
6
  import {
7
7
  listProjects,
8
8
  registryPath
9
- } from "./chunk-RBZNXA5L.js";
9
+ } from "./chunk-RL6H3VVD.js";
10
10
  import {
11
11
  BindAuthorityError,
12
12
  __require
package/dist/server.cjs CHANGED
@@ -5428,6 +5428,14 @@ function mergeColumnsAt(graph, tableNodeId, columns, provenance, confidence) {
5428
5428
  function mergeObservedColumns(graph, tableNodeId, columns) {
5429
5429
  mergeColumnsAt(graph, tableNodeId, columns, import_types7.Provenance.OBSERVED, OBSERVED_COLUMN_CONFIDENCE);
5430
5430
  }
5431
+ function mergeObservedDeployState(graph, serviceNodeId, state) {
5432
+ if (!graph.hasNode(serviceNodeId)) return;
5433
+ const attrs = {};
5434
+ if (typeof state.image === "string" && state.image.length > 0) attrs["observedImage"] = state.image;
5435
+ if (typeof state.readyReplicas === "number") attrs["observedReadyReplicas"] = state.readyReplicas;
5436
+ if (Object.keys(attrs).length === 0) return;
5437
+ graph.mergeNodeAttributes(serviceNodeId, attrs);
5438
+ }
5431
5439
  function ensureDatabaseNode(graph, host, engine) {
5432
5440
  const id = (0, import_types7.databaseId)(host);
5433
5441
  if (graph.hasNode(id)) return id;
@@ -7044,6 +7052,11 @@ function isSaturated(ctx) {
7044
7052
  function isBoundaryTimeoutSymptom(ctx) {
7045
7053
  return ctx.errorsEmittedHere > 0 && ctx.boundaryTimeout === true && ctx.errorsFromCallers === 0 && ctx.hasOutboundDeps === true && ctx.observedErroringDownstream !== true;
7046
7054
  }
7055
+ var UNREACHABLE_INBOUND_ERROR_RATE = 0.5;
7056
+ var UNREACHABLE_MIN_INBOUND = 3;
7057
+ function isUnreachableSeed(ctx) {
7058
+ return ctx.callCount >= UNREACHABLE_MIN_INBOUND && ctx.errorsFromCallers > 0 && ctx.errorsFromCallers >= UNREACHABLE_INBOUND_ERROR_RATE * ctx.callCount && ctx.errorsEmittedHere === 0 && ctx.outboundVolume === 0;
7059
+ }
7047
7060
  function classifyNode(ctx) {
7048
7061
  if (ctx.errorsEmittedHere > 0) {
7049
7062
  if ((ctx.stale || isSaturated(ctx)) && ctx.errorsFromCallers >= ctx.errorsEmittedHere) {
@@ -7052,6 +7065,7 @@ function classifyNode(ctx) {
7052
7065
  if (isBoundaryTimeoutSymptom(ctx)) return "symptom-only";
7053
7066
  return "primary-failure";
7054
7067
  }
7068
+ if (isUnreachableSeed(ctx)) return "unreachable";
7055
7069
  if (ctx.errorsFromCallers > 0) return "symptom-only";
7056
7070
  return "unrelated";
7057
7071
  }
@@ -7338,6 +7352,16 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7338
7352
  confidence: Math.min(legacy.confidence, 0.4),
7339
7353
  ...lastProv ? { provenance: lastProv } : {}
7340
7354
  });
7355
+ } else if (seedCtx && isUnreachableSeed(seedCtx)) {
7356
+ const name = displayNameOf(seedNode);
7357
+ candidates.push({
7358
+ node: seedNode,
7359
+ classification: "unreachable",
7360
+ reason: `${name} is unreachable: its callers' requests fail (${seedCtx.errorsFromCallers} erroring inbound calls) and it produced no telemetry of its own \u2014 no server spans, no outbound calls \u2014 so it never served. The failure is observed, but its cause is not in the trace: a startup failure, a crash before the first span, or an unschedulable / unhealthy pod. Inspect ${name}'s deploy state and logs \u2014 there is no code fault to find in the graph here.`,
7361
+ context: seedCtx,
7362
+ confidence: legacy.confidence,
7363
+ provenance: import_types8.Provenance.OBSERVED
7364
+ });
7341
7365
  } else if (seedCtx && isBoundaryTimeoutSymptom(seedCtx)) {
7342
7366
  const pointer = structuralUpstreamPointer(graph, seedNode, incidents);
7343
7367
  const seedName = displayNameOf(seedNode);
@@ -7687,6 +7711,25 @@ function detectColumnDrift(node) {
7687
7711
  }
7688
7712
  return out;
7689
7713
  }
7714
+ var RECOMMENDATION_DEPLOY_IMAGE_MISMATCH = "The running image differs from the manifest-declared image \u2014 the rollout has not taken (the old ReplicaSet is still serving). Re-apply the deployment or investigate why the new image failed to roll out.";
7715
+ var DEPLOY_DIVERGENCE_CONFIDENCE = 0.9;
7716
+ function detectDeployDivergence(svc) {
7717
+ const out = [];
7718
+ if (typeof svc.declaredImage === "string" && typeof svc.observedImage === "string" && svc.declaredImage !== svc.observedImage) {
7719
+ out.push({
7720
+ type: "deploy-mismatch",
7721
+ kind: "image",
7722
+ source: svc.id,
7723
+ target: svc.id,
7724
+ declaredImage: svc.declaredImage,
7725
+ observedImage: svc.observedImage,
7726
+ confidence: DEPLOY_DIVERGENCE_CONFIDENCE,
7727
+ reason: `Service ${svc.name} declares image ${svc.declaredImage} but its running pods report ${svc.observedImage} \u2014 the deploy has not taken (the old version is still serving), so no incident fires.`,
7728
+ recommendation: RECOMMENDATION_DEPLOY_IMAGE_MISMATCH
7729
+ });
7730
+ }
7731
+ return out;
7732
+ }
7690
7733
  var SYMBOL_MISMATCH_PATTERNS = [
7691
7734
  {
7692
7735
  // "'ListProductsResponse' object has no attribute 'products_list'" and kin.
@@ -8014,6 +8057,7 @@ function computeDivergences(graph, opts = {}) {
8014
8057
  const svc = n;
8015
8058
  for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
8016
8059
  for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
8060
+ for (const d of detectDeployDivergence(svc)) all.push(d);
8017
8061
  return;
8018
8062
  }
8019
8063
  if (n.type === import_types9.NodeType.InfraNode && n.kind === "sql-table") {
@@ -8054,7 +8098,12 @@ function computeDivergences(graph, opts = {}) {
8054
8098
  // orders last so at equal confidence the structural and symbol divergences
8055
8099
  // lead, per the contract ("rank below the definitive structural and symbol
8056
8100
  // divergences").
8057
- "observed-failing": 6
8101
+ "observed-failing": 6,
8102
+ // Deploy mismatch (ADR-225) is a definitive structural declared-vs-observed
8103
+ // divergence carrying high confidence (0.9), so the confidence sort already
8104
+ // places it among the structural leaders; this slot only breaks an exact
8105
+ // confidence tie and sits last as a stable tiebreaker.
8106
+ "deploy-mismatch": 7
8058
8107
  };
8059
8108
  filtered.sort((a, b) => {
8060
8109
  if (b.confidence !== a.confidence) return b.confidence - a.confidence;
@@ -18602,6 +18651,11 @@ async function runConnectorPoll(connector, ctx, graph, resolveTarget) {
18602
18651
  unresolved++;
18603
18652
  continue;
18604
18653
  }
18654
+ if (signal.deployState) {
18655
+ ensureServiceNode(graph, resolved.serviceName, NO_ENV);
18656
+ mergeObservedDeployState(graph, resolved.targetNodeId, signal.deployState);
18657
+ continue;
18658
+ }
18605
18659
  if (signal.incident) {
18606
18660
  ensureServiceNode(graph, resolved.serviceName, NO_ENV);
18607
18661
  if (!ctx.errorsPath || !graph.hasNode(resolved.targetNodeId)) {