@neat.is/types 0.7.9 → 0.8.0-rc.1

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.cjs CHANGED
@@ -49,11 +49,14 @@ __export(index_exports, {
49
49
  DivergenceTypeSchema: () => DivergenceTypeSchema,
50
50
  EMPTY_REGISTRY: () => EMPTY_REGISTRY,
51
51
  EXTRACTED_CONFIDENCE: () => EXTRACTED_CONFIDENCE,
52
+ EdgeAnomalySchema: () => EdgeAnomalySchema,
52
53
  EdgeEvidenceSchema: () => EdgeEvidenceSchema,
53
54
  EdgeSignalSchema: () => EdgeSignalSchema,
54
55
  EdgeType: () => EdgeType,
55
56
  EdgeTypeSchema: () => EdgeTypeSchema,
56
57
  ErrorEventSchema: () => ErrorEventSchema,
58
+ ExpandNeighbourSchema: () => ExpandNeighbourSchema,
59
+ ExpandResultSchema: () => ExpandResultSchema,
57
60
  ExtractionCoverageSchema: () => ExtractionCoverageSchema,
58
61
  FieldGuardRuleSchema: () => FieldGuardRuleSchema,
59
62
  FileNodeSchema: () => FileNodeSchema,
@@ -70,12 +73,15 @@ __export(index_exports, {
70
73
  HypotheticalActionSchema: () => HypotheticalActionSchema,
71
74
  IncidentsResponseSchema: () => IncidentsResponseSchema,
72
75
  InfraNodeSchema: () => InfraNodeSchema,
76
+ LatencyMsSchema: () => LatencyMsSchema,
73
77
  LogEntrySchema: () => LogEntrySchema,
74
78
  LogSourceSchema: () => LogSourceSchema,
75
79
  LogsResponseSchema: () => LogsResponseSchema,
76
80
  MCP_TOOL_NAMES: () => MCP_TOOL_NAMES,
77
81
  MissingExtractedDivergenceSchema: () => MissingExtractedDivergenceSchema,
78
82
  MissingObservedDivergenceSchema: () => MissingObservedDivergenceSchema,
83
+ NodeClassificationSchema: () => NodeClassificationSchema,
84
+ NodeContextSchema: () => NodeContextSchema,
79
85
  NodeType: () => NodeType,
80
86
  NodeTypeSchema: () => NodeTypeSchema,
81
87
  ObservedDependenciesResultSchema: () => ObservedDependenciesResultSchema,
@@ -97,6 +103,9 @@ __export(index_exports, {
97
103
  RegistryEntrySchema: () => RegistryEntrySchema,
98
104
  RegistryFileSchema: () => RegistryFileSchema,
99
105
  RegistryStatusSchema: () => RegistryStatusSchema,
106
+ RelatePathSchema: () => RelatePathSchema,
107
+ RelateResultSchema: () => RelateResultSchema,
108
+ RootCauseCandidateSchema: () => RootCauseCandidateSchema,
100
109
  RootCauseResultSchema: () => RootCauseResultSchema,
101
110
  RouteNodeSchema: () => RouteNodeSchema,
102
111
  SearchMatchSchema: () => SearchMatchSchema,
@@ -324,10 +333,30 @@ var EdgeEvidenceSchema = import_zod2.z.object({
324
333
  method: import_zod2.z.string().optional(),
325
334
  pathTemplate: import_zod2.z.string().optional()
326
335
  });
336
+ var LatencyMsSchema = import_zod2.z.object({
337
+ p50: import_zod2.z.number().nonnegative(),
338
+ p95: import_zod2.z.number().nonnegative()
339
+ });
340
+ var EdgeAnomalySchema = import_zod2.z.union([
341
+ import_zod2.z.object({ source: import_zod2.z.string(), rule: import_zod2.z.string() }),
342
+ import_zod2.z.boolean()
343
+ ]);
327
344
  var EdgeSignalSchema = import_zod2.z.object({
328
345
  spanCount: import_zod2.z.number().int().nonnegative(),
329
346
  errorCount: import_zod2.z.number().int().nonnegative(),
330
- lastObservedAgeMs: import_zod2.z.number().nonnegative().optional()
347
+ lastObservedAgeMs: import_zod2.z.number().nonnegative().optional(),
348
+ // Per-edge latency (ADR-190). `latencyMs` is derived at each observation from
349
+ // `latencyHist`, a bounded log-linear (HDR-style) histogram — a sparse
350
+ // bucket→count map, never raw durations — maintained by upsertObservedEdge via
351
+ // latency-digest.ts. Both are `.optional()` growth (ADR-031): a legacy edge and
352
+ // a connector edge without a provider latency carry neither and read honestly
353
+ // absent. `latencyHist` is the ingest accumulator `latencyMs` is read from;
354
+ // consumers read `latencyMs`.
355
+ latencyMs: LatencyMsSchema.optional(),
356
+ latencyHist: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.number().int().nonnegative()).optional(),
357
+ // A pre-thresholded external alert riding on the edge (ADR-190). Optional and
358
+ // empty until an alert source is wired.
359
+ anomalous: EdgeAnomalySchema.optional()
331
360
  });
332
361
  var GraphEdgeSchema = import_zod2.z.object({
333
362
  id: import_zod2.z.string(),
@@ -680,13 +709,98 @@ var LogEntrySchema = import_zod4.z.object({
680
709
 
681
710
  // src/results.ts
682
711
  var import_zod5 = require("zod");
712
+ var NodeContextSchema = import_zod5.z.object({
713
+ // Errors originating at this node: incidents localized here plus its own
714
+ // outbound CALLS that fail. A node that emits errors is a candidate cause.
715
+ errorsEmittedHere: import_zod5.z.number().int().nonnegative(),
716
+ // Errors arriving from callers: the inbound edges' errorCount. Errors arriving
717
+ // with none emitted here is the victim signature.
718
+ errorsFromCallers: import_zod5.z.number().int().nonnegative(),
719
+ // Inbound call volume through the node — how hard production hits it.
720
+ callCount: import_zod5.z.number().int().nonnegative(),
721
+ // Outbound call volume — how hard this node drives its own dependencies. A
722
+ // pure driver of load (high out, no in) is where an overload originates.
723
+ outboundVolume: import_zod5.z.number().int().nonnegative(),
724
+ // Staleness: ms since the node was last observed. A stale node under inbound
725
+ // load is a starved victim, not a cause.
726
+ lastObservedAgeMs: import_zod5.z.number().nonnegative().optional(),
727
+ // Saturation: the worst inbound p95 latency (ms), from ADR-190. High absolute
728
+ // latency with low error emission reads as saturated.
729
+ latencyP95Ms: import_zod5.z.number().nonnegative().optional(),
730
+ // Is the node fed by STALE edges — did it stop responding?
731
+ stale: import_zod5.z.boolean()
732
+ });
733
+ var NodeClassificationSchema = import_zod5.z.enum([
734
+ "primary-failure",
735
+ "symptom-only",
736
+ "unrelated"
737
+ ]);
738
+ var RootCauseCandidateSchema = import_zod5.z.object({
739
+ node: import_zod5.z.string(),
740
+ classification: NodeClassificationSchema,
741
+ reason: import_zod5.z.string(),
742
+ context: NodeContextSchema,
743
+ confidence: import_zod5.z.number().min(0).max(1),
744
+ provenance: ProvenanceSchema.optional()
745
+ });
683
746
  var RootCauseResultSchema = import_zod5.z.object({
684
747
  rootCauseNode: import_zod5.z.string(),
685
748
  rootCauseReason: import_zod5.z.string(),
686
749
  traversalPath: import_zod5.z.array(import_zod5.z.string()),
687
750
  edgeProvenances: import_zod5.z.array(ProvenanceSchema),
688
751
  confidence: import_zod5.z.number().min(0).max(1),
689
- fixRecommendation: import_zod5.z.string().optional()
752
+ fixRecommendation: import_zod5.z.string().optional(),
753
+ // Agent-driven navigation (ADR-189): the ranked candidate set with per-node
754
+ // classification + evidence. `candidates[0]` is the top-ranked cause and the
755
+ // legacy `rootCauseNode` above tracks it. Optional growth (ADR-031); present
756
+ // by default, the legacy verdict fields stay populated for one deprecation
757
+ // cycle. A saturated downstream victim classifies `symptom-only` here and the
758
+ // ranking walks up to the load origin instead of naming the victim.
759
+ candidates: import_zod5.z.array(RootCauseCandidateSchema).optional()
760
+ });
761
+ var RelatePathSchema = import_zod5.z.object({
762
+ // origin → ... → target, the node ids along the path.
763
+ nodes: import_zod5.z.array(import_zod5.z.string()).min(2),
764
+ // The edge type of each hop (length = nodes.length - 1).
765
+ edgeTypes: import_zod5.z.array(EdgeTypeSchema),
766
+ // The provenance of each hop.
767
+ provenance: import_zod5.z.array(ProvenanceSchema),
768
+ // The grain of each node on the path ('service' | 'file' | 'symbol' | other
769
+ // node type), so a cross-grain descent is legible.
770
+ grain: import_zod5.z.array(import_zod5.z.string()),
771
+ // Does the failure run end to end — errorCount / latency / anomalous on every
772
+ // hop? A signal-carrying path turns reachability into cause-confirmation.
773
+ carriesSignal: import_zod5.z.boolean()
774
+ });
775
+ var RelateResultSchema = import_zod5.z.object({
776
+ a: import_zod5.z.string(),
777
+ b: import_zod5.z.string(),
778
+ related: import_zod5.z.boolean(),
779
+ direction: import_zod5.z.enum(["a->b", "b->a"]).nullable(),
780
+ paths: import_zod5.z.array(RelatePathSchema),
781
+ // True when only a coarser-grain link is in evidence than a and b's own grain
782
+ // — the fine link was never observed, so the coarser one is returned and the
783
+ // gap flagged rather than a finer link synthesized (file-awareness.md §6).
784
+ grainGap: import_zod5.z.boolean().optional(),
785
+ // The terminal-honesty label when related is false.
786
+ note: import_zod5.z.string().optional()
787
+ });
788
+ var ExpandNeighbourSchema = import_zod5.z.object({
789
+ node: import_zod5.z.string(),
790
+ edgeType: EdgeTypeSchema,
791
+ provenance: ProvenanceSchema,
792
+ classification: NodeClassificationSchema,
793
+ context: NodeContextSchema
794
+ });
795
+ var ExpandResultSchema = import_zod5.z.object({
796
+ origin: import_zod5.z.string(),
797
+ direction: import_zod5.z.enum(["up", "down"]),
798
+ node: import_zod5.z.object({
799
+ id: import_zod5.z.string(),
800
+ classification: NodeClassificationSchema,
801
+ context: NodeContextSchema
802
+ }),
803
+ neighbours: import_zod5.z.array(ExpandNeighbourSchema)
690
804
  });
691
805
  var BlastRadiusAffectedNodeSchema = import_zod5.z.object({
692
806
  nodeId: import_zod5.z.string(),
@@ -739,7 +853,21 @@ var ObservedDependenciesResultSchema = import_zod5.z.object({
739
853
  inboundObservedCount: import_zod5.z.number().int().nonnegative(),
740
854
  // Are there EXTRACTED outbound edges but no OBSERVED ones? Only then is
741
855
  // "static deps exist but no runtime traffic — is OTel running?" the honest note.
742
- hasExtractedOutbound: import_zod5.z.boolean()
856
+ hasExtractedOutbound: import_zod5.z.boolean(),
857
+ // Node-level *inbound* traffic block (ADR-190): how hard and how recently
858
+ // production hits THIS node, sourced from its inbound OBSERVED edges — the
859
+ // "served N× in {window}, last seen {age}" story the navigation reads and
860
+ // neat-action renders. `inboundVolume` is the summed inbound-edge count
861
+ // (distinct from `inboundObservedCount`, the number of inbound edges).
862
+ // `window` labels the count ("7d" | "lifetime") so a consumer never renders a
863
+ // window the data doesn't have; the cumulative signal is "lifetime" today.
864
+ // `inboundLastObserved` is when production last called this node, raw ISO8601
865
+ // and never pre-formatted — absent when there is no inbound observation.
866
+ // All three are optional growth (ADR-031); the producer emits `inboundVolume`
867
+ // and `window` together, `inboundLastObserved` when there is inbound traffic.
868
+ inboundVolume: import_zod5.z.number().int().nonnegative().optional(),
869
+ window: import_zod5.z.enum(["7d", "lifetime"]).optional(),
870
+ inboundLastObserved: import_zod5.z.string().datetime().optional()
743
871
  });
744
872
 
745
873
  // src/identity.ts
@@ -1234,6 +1362,9 @@ var MCP_TOOL_NAMES = [
1234
1362
  "get_recent_stale_edges",
1235
1363
  "check_policies",
1236
1364
  "get_divergences",
1365
+ // Two-way RCA navigation (ADR-189): step the graph and confirm a link.
1366
+ "expand",
1367
+ "relate",
1237
1368
  // Six /neat extend tools (ADR-081, ADR-086, #387).
1238
1369
  "neat_list_uninstrumented",
1239
1370
  "neat_lookup_instrumentation",
@@ -1448,11 +1579,14 @@ function passesExtractedFloor(confidence) {
1448
1579
  DivergenceTypeSchema,
1449
1580
  EMPTY_REGISTRY,
1450
1581
  EXTRACTED_CONFIDENCE,
1582
+ EdgeAnomalySchema,
1451
1583
  EdgeEvidenceSchema,
1452
1584
  EdgeSignalSchema,
1453
1585
  EdgeType,
1454
1586
  EdgeTypeSchema,
1455
1587
  ErrorEventSchema,
1588
+ ExpandNeighbourSchema,
1589
+ ExpandResultSchema,
1456
1590
  ExtractionCoverageSchema,
1457
1591
  FieldGuardRuleSchema,
1458
1592
  FileNodeSchema,
@@ -1469,12 +1603,15 @@ function passesExtractedFloor(confidence) {
1469
1603
  HypotheticalActionSchema,
1470
1604
  IncidentsResponseSchema,
1471
1605
  InfraNodeSchema,
1606
+ LatencyMsSchema,
1472
1607
  LogEntrySchema,
1473
1608
  LogSourceSchema,
1474
1609
  LogsResponseSchema,
1475
1610
  MCP_TOOL_NAMES,
1476
1611
  MissingExtractedDivergenceSchema,
1477
1612
  MissingObservedDivergenceSchema,
1613
+ NodeClassificationSchema,
1614
+ NodeContextSchema,
1478
1615
  NodeType,
1479
1616
  NodeTypeSchema,
1480
1617
  ObservedDependenciesResultSchema,
@@ -1496,6 +1633,9 @@ function passesExtractedFloor(confidence) {
1496
1633
  RegistryEntrySchema,
1497
1634
  RegistryFileSchema,
1498
1635
  RegistryStatusSchema,
1636
+ RelatePathSchema,
1637
+ RelateResultSchema,
1638
+ RootCauseCandidateSchema,
1499
1639
  RootCauseResultSchema,
1500
1640
  RouteNodeSchema,
1501
1641
  SearchMatchSchema,