@neat.is/types 0.7.10 → 0.8.0

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/index.js CHANGED
@@ -170,10 +170,30 @@ var EdgeEvidenceSchema = z2.object({
170
170
  method: z2.string().optional(),
171
171
  pathTemplate: z2.string().optional()
172
172
  });
173
+ var LatencyMsSchema = z2.object({
174
+ p50: z2.number().nonnegative(),
175
+ p95: z2.number().nonnegative()
176
+ });
177
+ var EdgeAnomalySchema = z2.union([
178
+ z2.object({ source: z2.string(), rule: z2.string() }),
179
+ z2.boolean()
180
+ ]);
173
181
  var EdgeSignalSchema = z2.object({
174
182
  spanCount: z2.number().int().nonnegative(),
175
183
  errorCount: z2.number().int().nonnegative(),
176
- lastObservedAgeMs: z2.number().nonnegative().optional()
184
+ lastObservedAgeMs: z2.number().nonnegative().optional(),
185
+ // Per-edge latency (ADR-190). `latencyMs` is derived at each observation from
186
+ // `latencyHist`, a bounded log-linear (HDR-style) histogram — a sparse
187
+ // bucket→count map, never raw durations — maintained by upsertObservedEdge via
188
+ // latency-digest.ts. Both are `.optional()` growth (ADR-031): a legacy edge and
189
+ // a connector edge without a provider latency carry neither and read honestly
190
+ // absent. `latencyHist` is the ingest accumulator `latencyMs` is read from;
191
+ // consumers read `latencyMs`.
192
+ latencyMs: LatencyMsSchema.optional(),
193
+ latencyHist: z2.record(z2.string(), z2.number().int().nonnegative()).optional(),
194
+ // A pre-thresholded external alert riding on the edge (ADR-190). Optional and
195
+ // empty until an alert source is wired.
196
+ anomalous: EdgeAnomalySchema.optional()
177
197
  });
178
198
  var GraphEdgeSchema = z2.object({
179
199
  id: z2.string(),
@@ -526,13 +546,98 @@ var LogEntrySchema = z4.object({
526
546
 
527
547
  // src/results.ts
528
548
  import { z as z5 } from "zod";
549
+ var NodeContextSchema = z5.object({
550
+ // Errors originating at this node: incidents localized here plus its own
551
+ // outbound CALLS that fail. A node that emits errors is a candidate cause.
552
+ errorsEmittedHere: z5.number().int().nonnegative(),
553
+ // Errors arriving from callers: the inbound edges' errorCount. Errors arriving
554
+ // with none emitted here is the victim signature.
555
+ errorsFromCallers: z5.number().int().nonnegative(),
556
+ // Inbound call volume through the node — how hard production hits it.
557
+ callCount: z5.number().int().nonnegative(),
558
+ // Outbound call volume — how hard this node drives its own dependencies. A
559
+ // pure driver of load (high out, no in) is where an overload originates.
560
+ outboundVolume: z5.number().int().nonnegative(),
561
+ // Staleness: ms since the node was last observed. A stale node under inbound
562
+ // load is a starved victim, not a cause.
563
+ lastObservedAgeMs: z5.number().nonnegative().optional(),
564
+ // Saturation: the worst inbound p95 latency (ms), from ADR-190. High absolute
565
+ // latency with low error emission reads as saturated.
566
+ latencyP95Ms: z5.number().nonnegative().optional(),
567
+ // Is the node fed by STALE edges — did it stop responding?
568
+ stale: z5.boolean()
569
+ });
570
+ var NodeClassificationSchema = z5.enum([
571
+ "primary-failure",
572
+ "symptom-only",
573
+ "unrelated"
574
+ ]);
575
+ var RootCauseCandidateSchema = z5.object({
576
+ node: z5.string(),
577
+ classification: NodeClassificationSchema,
578
+ reason: z5.string(),
579
+ context: NodeContextSchema,
580
+ confidence: z5.number().min(0).max(1),
581
+ provenance: ProvenanceSchema.optional()
582
+ });
529
583
  var RootCauseResultSchema = z5.object({
530
584
  rootCauseNode: z5.string(),
531
585
  rootCauseReason: z5.string(),
532
586
  traversalPath: z5.array(z5.string()),
533
587
  edgeProvenances: z5.array(ProvenanceSchema),
534
588
  confidence: z5.number().min(0).max(1),
535
- fixRecommendation: z5.string().optional()
589
+ fixRecommendation: z5.string().optional(),
590
+ // Agent-driven navigation (ADR-189): the ranked candidate set with per-node
591
+ // classification + evidence. `candidates[0]` is the top-ranked cause and the
592
+ // legacy `rootCauseNode` above tracks it. Optional growth (ADR-031); present
593
+ // by default, the legacy verdict fields stay populated for one deprecation
594
+ // cycle. A saturated downstream victim classifies `symptom-only` here and the
595
+ // ranking walks up to the load origin instead of naming the victim.
596
+ candidates: z5.array(RootCauseCandidateSchema).optional()
597
+ });
598
+ var RelatePathSchema = z5.object({
599
+ // origin → ... → target, the node ids along the path.
600
+ nodes: z5.array(z5.string()).min(2),
601
+ // The edge type of each hop (length = nodes.length - 1).
602
+ edgeTypes: z5.array(EdgeTypeSchema),
603
+ // The provenance of each hop.
604
+ provenance: z5.array(ProvenanceSchema),
605
+ // The grain of each node on the path ('service' | 'file' | 'symbol' | other
606
+ // node type), so a cross-grain descent is legible.
607
+ grain: z5.array(z5.string()),
608
+ // Does the failure run end to end — errorCount / latency / anomalous on every
609
+ // hop? A signal-carrying path turns reachability into cause-confirmation.
610
+ carriesSignal: z5.boolean()
611
+ });
612
+ var RelateResultSchema = z5.object({
613
+ a: z5.string(),
614
+ b: z5.string(),
615
+ related: z5.boolean(),
616
+ direction: z5.enum(["a->b", "b->a"]).nullable(),
617
+ paths: z5.array(RelatePathSchema),
618
+ // True when only a coarser-grain link is in evidence than a and b's own grain
619
+ // — the fine link was never observed, so the coarser one is returned and the
620
+ // gap flagged rather than a finer link synthesized (file-awareness.md §6).
621
+ grainGap: z5.boolean().optional(),
622
+ // The terminal-honesty label when related is false.
623
+ note: z5.string().optional()
624
+ });
625
+ var ExpandNeighbourSchema = z5.object({
626
+ node: z5.string(),
627
+ edgeType: EdgeTypeSchema,
628
+ provenance: ProvenanceSchema,
629
+ classification: NodeClassificationSchema,
630
+ context: NodeContextSchema
631
+ });
632
+ var ExpandResultSchema = z5.object({
633
+ origin: z5.string(),
634
+ direction: z5.enum(["up", "down"]),
635
+ node: z5.object({
636
+ id: z5.string(),
637
+ classification: NodeClassificationSchema,
638
+ context: NodeContextSchema
639
+ }),
640
+ neighbours: z5.array(ExpandNeighbourSchema)
536
641
  });
537
642
  var BlastRadiusAffectedNodeSchema = z5.object({
538
643
  nodeId: z5.string(),
@@ -585,7 +690,21 @@ var ObservedDependenciesResultSchema = z5.object({
585
690
  inboundObservedCount: z5.number().int().nonnegative(),
586
691
  // Are there EXTRACTED outbound edges but no OBSERVED ones? Only then is
587
692
  // "static deps exist but no runtime traffic — is OTel running?" the honest note.
588
- hasExtractedOutbound: z5.boolean()
693
+ hasExtractedOutbound: z5.boolean(),
694
+ // Node-level *inbound* traffic block (ADR-190): how hard and how recently
695
+ // production hits THIS node, sourced from its inbound OBSERVED edges — the
696
+ // "served N× in {window}, last seen {age}" story the navigation reads and
697
+ // neat-action renders. `inboundVolume` is the summed inbound-edge count
698
+ // (distinct from `inboundObservedCount`, the number of inbound edges).
699
+ // `window` labels the count ("7d" | "lifetime") so a consumer never renders a
700
+ // window the data doesn't have; the cumulative signal is "lifetime" today.
701
+ // `inboundLastObserved` is when production last called this node, raw ISO8601
702
+ // and never pre-formatted — absent when there is no inbound observation.
703
+ // All three are optional growth (ADR-031); the producer emits `inboundVolume`
704
+ // and `window` together, `inboundLastObserved` when there is inbound traffic.
705
+ inboundVolume: z5.number().int().nonnegative().optional(),
706
+ window: z5.enum(["7d", "lifetime"]).optional(),
707
+ inboundLastObserved: z5.string().datetime().optional()
589
708
  });
590
709
 
591
710
  // src/identity.ts
@@ -1080,6 +1199,9 @@ var MCP_TOOL_NAMES = [
1080
1199
  "get_recent_stale_edges",
1081
1200
  "check_policies",
1082
1201
  "get_divergences",
1202
+ // Two-way RCA navigation (ADR-189): step the graph and confirm a link.
1203
+ "expand",
1204
+ "relate",
1083
1205
  // Six /neat extend tools (ADR-081, ADR-086, #387).
1084
1206
  "neat_list_uninstrumented",
1085
1207
  "neat_lookup_instrumentation",
@@ -1293,11 +1415,14 @@ export {
1293
1415
  DivergenceTypeSchema,
1294
1416
  EMPTY_REGISTRY,
1295
1417
  EXTRACTED_CONFIDENCE,
1418
+ EdgeAnomalySchema,
1296
1419
  EdgeEvidenceSchema,
1297
1420
  EdgeSignalSchema,
1298
1421
  EdgeType,
1299
1422
  EdgeTypeSchema,
1300
1423
  ErrorEventSchema,
1424
+ ExpandNeighbourSchema,
1425
+ ExpandResultSchema,
1301
1426
  ExtractionCoverageSchema,
1302
1427
  FieldGuardRuleSchema,
1303
1428
  FileNodeSchema,
@@ -1314,12 +1439,15 @@ export {
1314
1439
  HypotheticalActionSchema,
1315
1440
  IncidentsResponseSchema,
1316
1441
  InfraNodeSchema,
1442
+ LatencyMsSchema,
1317
1443
  LogEntrySchema,
1318
1444
  LogSourceSchema,
1319
1445
  LogsResponseSchema,
1320
1446
  MCP_TOOL_NAMES,
1321
1447
  MissingExtractedDivergenceSchema,
1322
1448
  MissingObservedDivergenceSchema,
1449
+ NodeClassificationSchema,
1450
+ NodeContextSchema,
1323
1451
  NodeType,
1324
1452
  NodeTypeSchema,
1325
1453
  ObservedDependenciesResultSchema,
@@ -1341,6 +1469,9 @@ export {
1341
1469
  RegistryEntrySchema,
1342
1470
  RegistryFileSchema,
1343
1471
  RegistryStatusSchema,
1472
+ RelatePathSchema,
1473
+ RelateResultSchema,
1474
+ RootCauseCandidateSchema,
1344
1475
  RootCauseResultSchema,
1345
1476
  RouteNodeSchema,
1346
1477
  SearchMatchSchema,