@skyhook-io/radar-app 1.13.5 → 1.14.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/package.json +9 -9
- package/src/App.tsx +66 -28
- package/src/api/client.authRedirect.test.ts +12 -1
- package/src/api/client.prometheusStatus.test.ts +24 -0
- package/src/api/client.ts +324 -16
- package/src/api/diagnose.ts +32 -1
- package/src/api/drain-plan.test.ts +86 -0
- package/src/api/quotas.test.ts +26 -0
- package/src/api/quotas.ts +20 -0
- package/src/api/workloadMetrics.test.ts +40 -0
- package/src/api/workloadMetrics.ts +68 -0
- package/src/components/CloudConnectFlow.tsx +343 -46
- package/src/components/CloudFunnelButton.tsx +110 -37
- package/src/components/ConnectionErrorView.tsx +9 -10
- package/src/components/DebugOverlay.tsx +10 -6
- package/src/components/SyncProgressPanel.tsx +73 -0
- package/src/components/audit/AuditView.tsx +2 -0
- package/src/components/cloudConnectHandoff.test.ts +245 -0
- package/src/components/cloudConnectHandoff.ts +276 -0
- package/src/components/curl/ServiceCurlButton.tsx +19 -26
- package/src/components/diagnose/AgentCase.tsx +18 -5
- package/src/components/diagnose/AnalysisStory.test.tsx +308 -0
- package/src/components/diagnose/AnalysisStory.tsx +564 -0
- package/src/components/diagnose/DiagnoseContext.test.ts +10 -0
- package/src/components/diagnose/DiagnoseContext.tsx +26 -8
- package/src/components/diagnose/DiagnoseSurface.tsx +20 -14
- package/src/components/diagnose/InvestigationEvidencePane.story.test.tsx +771 -0
- package/src/components/diagnose/InvestigationEvidencePane.test.tsx +8 -33
- package/src/components/diagnose/InvestigationEvidencePane.tsx +809 -168
- package/src/components/diagnose/InvestigationResourceEvidence.test.tsx +30 -0
- package/src/components/diagnose/InvestigationResourceEvidence.tsx +20 -0
- package/src/components/diagnose/InvestigationView.tsx +493 -529
- package/src/components/diagnose/investigationCase.test.tsx +267 -129
- package/src/components/diagnose/investigationCase.ts +122 -77
- package/src/components/diagnose/investigationEvidence/adapters/changes.ts +60 -0
- package/src/components/diagnose/investigationEvidence/adapters/diagnose.test.ts +573 -0
- package/src/components/diagnose/investigationEvidence/adapters/diagnose.ts +935 -0
- package/src/components/diagnose/investigationEvidence/adapters/events.ts +96 -0
- package/src/components/diagnose/investigationEvidence/adapters/helm.test.ts +242 -0
- package/src/components/diagnose/investigationEvidence/adapters/helm.ts +208 -0
- package/src/components/diagnose/investigationEvidence/adapters/issues.ts +172 -0
- package/src/components/diagnose/investigationEvidence/adapters/logs.test.ts +283 -0
- package/src/components/diagnose/investigationEvidence/adapters/logs.ts +183 -0
- package/src/components/diagnose/investigationEvidence/adapters/permissions.test.ts +528 -0
- package/src/components/diagnose/investigationEvidence/adapters/permissions.ts +292 -0
- package/src/components/diagnose/investigationEvidence/adapters/prometheus.test.ts +1641 -0
- package/src/components/diagnose/investigationEvidence/adapters/prometheus.ts +769 -0
- package/src/components/diagnose/investigationEvidence/adapters/resource.test.ts +81 -0
- package/src/components/diagnose/investigationEvidence/adapters/resource.ts +285 -0
- package/src/components/diagnose/investigationEvidence/adapters/topology.ts +207 -0
- package/src/components/diagnose/investigationEvidence/builder.ts +427 -0
- package/src/components/diagnose/investigationEvidence/evidenceFixtures.ts +179 -0
- package/src/components/diagnose/investigationEvidence/identity.test.ts +632 -0
- package/src/components/diagnose/investigationEvidence/identity.ts +261 -0
- package/src/components/diagnose/investigationEvidence/index.ts +55 -0
- package/src/components/diagnose/investigationEvidence/observations.ts +978 -0
- package/src/components/diagnose/investigationEvidence/parse.ts +467 -0
- package/src/components/diagnose/investigationEvidence/projection.test.ts +2736 -0
- package/src/components/diagnose/investigationEvidence/types.ts +514 -0
- package/src/components/diagnose/investigationEvidencePresentation.test.ts +2 -0
- package/src/components/diagnose/investigationEvidencePresentation.ts +3 -0
- package/src/components/diagnose/investigationState.test.ts +316 -58
- package/src/components/diagnose/investigationState.ts +257 -44
- package/src/components/diagnose/investigationStory.test.ts +161 -0
- package/src/components/diagnose/investigationStory.ts +207 -0
- package/src/components/diagnose/parts.test.tsx +9 -6
- package/src/components/diagnose/parts.tsx +977 -193
- package/src/components/diagnose/storyParts.test.tsx +426 -0
- package/src/components/diagnose/target.test.ts +19 -0
- package/src/components/diagnose/target.ts +3 -2
- package/src/components/diagnose/toolCallLabel.test.ts +51 -0
- package/src/components/diagnose/toolCallLabel.ts +135 -0
- package/src/components/diagnose/useDisclosureReveal.ts +10 -11
- package/src/components/gitops/GitOpsView.tsx +7 -0
- package/src/components/gitops/RemoteDestinationCloudHint.tsx +26 -0
- package/src/components/helm/HelmCompareRoute.tsx +18 -4
- package/src/components/helm/HelmReleaseDrawer.tsx +11 -26
- package/src/components/helm/InstallWizard.tsx +8 -3
- package/src/components/home/MCPSetupDialog.tsx +15 -9
- package/src/components/portforward/PortForwardManager.tsx +6 -13
- package/src/components/resource/PrometheusCharts.overlays.test.ts +22 -0
- package/src/components/resource/PrometheusCharts.tsx +4 -3
- package/src/components/resource/PrometheusChartsGrid.render.test.tsx +99 -0
- package/src/components/resource/PrometheusChartsGrid.tsx +75 -35
- package/src/components/resource/RightsizingStrip.test.ts +38 -0
- package/src/components/resource/RightsizingStrip.tsx +15 -3
- package/src/components/resource/WorkloadMetricsHelpDialog.test.tsx +79 -0
- package/src/components/resource/WorkloadMetricsHelpDialog.tsx +145 -0
- package/src/components/resource/WorkloadMetricsSection.render.test.tsx +351 -0
- package/src/components/resource/WorkloadMetricsSection.tsx +480 -0
- package/src/components/resource/workloadMetricValues.test.ts +65 -0
- package/src/components/resource/workloadMetricValues.ts +30 -0
- package/src/components/resources/PodFilePreview.tsx +3 -3
- package/src/components/resources/ResourcesView.tsx +44 -6
- package/src/components/resources/renderers/NamespaceRenderer.tsx +7 -1
- package/src/components/resources/renderers/PodRenderer.tsx +4 -0
- package/src/components/resources/renderers/RolloutRenderer.tsx +15 -1
- package/src/components/resources/renderers/ServiceRenderer.tsx +2 -1
- package/src/components/resources/renderers/WorkloadRenderer.tsx +3 -0
- package/src/components/rightsizing/RightsizingScanView.tsx +21 -0
- package/src/components/settings/SettingsDialog.tsx +98 -16
- package/src/components/traffic/TrafficFlowList.tsx +229 -70
- package/src/components/traffic/TrafficGraph.tsx +6 -6
- package/src/components/traffic/TrafficView.tsx +10 -9
- package/src/components/traffic/trafficFilters.test.ts +28 -1
- package/src/components/traffic/trafficFilters.ts +31 -0
- package/src/components/ui/CommandPalette.tsx +10 -6
- package/src/components/ui/DiagnosticsOverlay.tsx +10 -6
- package/src/components/ui/Disclosure.tsx +47 -0
- package/src/components/ui/Markdown.tsx +23 -11
- package/src/components/ui/ShortcutHelpOverlay.tsx +3 -1
- package/src/components/ui/UpdateNotification.tsx +18 -2
- package/src/components/workload/WorkloadView.tsx +19 -8
- package/src/context/ConnectionContext.tsx +48 -3
- package/src/context/DiagnoseCustomization.tsx +1 -0
- package/src/index.css +36 -6
- package/src/utils/navigation.ts +1 -1
- package/src/utils/topology-namespace.test.ts +64 -0
- package/src/utils/topology-namespace.ts +18 -0
- package/src/components/diagnose/investigationEvidence.test.ts +0 -6617
- package/src/components/diagnose/investigationEvidence.ts +0 -5572
- package/src/components/gitops/GitOpsActions.tsx +0 -1
- package/src/components/gitops/GitOpsStatusBadge.tsx +0 -1
- package/src/components/gitops/ManagedResourcesList.tsx +0 -1
- package/src/components/gitops/SyncCountdown.tsx +0 -1
- package/src/components/gitops/index.ts +0 -4
- package/src/components/helm/ManifestDiffViewer.tsx +0 -69
- package/src/components/logs/JsonLogLine.tsx +0 -1
- package/src/components/logs/LogCore.tsx +0 -2
- package/src/components/logs/useLogBuffer.ts +0 -2
- package/src/components/logs/useLogSearch.ts +0 -1
- package/src/components/resource-drawer/ResourceDrawer.tsx +0 -216
- package/src/components/resources/drawer-components.tsx +0 -1
- package/src/components/resources/renderers/AlertRenderer.tsx +0 -1
- package/src/components/resources/renderers/CNPGBackupRenderer.tsx +0 -1
- package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +0 -1
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +0 -1
- package/src/components/resources/renderers/CertificateRenderer.tsx +0 -1
- package/src/components/resources/renderers/CertificateRequestRenderer.tsx +0 -1
- package/src/components/resources/renderers/ChallengeRenderer.tsx +0 -1
- package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +0 -1
- package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +0 -1
- package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/ConfigMapRenderer.tsx +0 -1
- package/src/components/resources/renderers/CronJobRenderer.tsx +0 -1
- package/src/components/resources/renderers/CronWorkflowRenderer.tsx +0 -1
- package/src/components/resources/renderers/EventRenderer.tsx +0 -1
- package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/ExternalSecretRenderer.tsx +0 -1
- package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +0 -1
- package/src/components/resources/renderers/GRPCRouteRenderer.tsx +0 -1
- package/src/components/resources/renderers/GatewayClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/GatewayRenderer.tsx +0 -1
- package/src/components/resources/renderers/GenericRenderer.tsx +0 -1
- package/src/components/resources/renderers/GitRepositoryRenderer.tsx +0 -1
- package/src/components/resources/renderers/HTTPRouteRenderer.tsx +0 -1
- package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +0 -1
- package/src/components/resources/renderers/IngressClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/IngressRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioGatewayRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +0 -1
- package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +0 -1
- package/src/components/resources/renderers/JobRenderer.tsx +0 -1
- package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +0 -1
- package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +0 -1
- package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +0 -1
- package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeEventingRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeFlowRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeRouteRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeServiceRenderer.tsx +0 -1
- package/src/components/resources/renderers/KnativeSourceRenderer.tsx +0 -1
- package/src/components/resources/renderers/KustomizationRenderer.tsx +0 -1
- package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/LeaseRenderer.tsx +0 -1
- package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +0 -1
- package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +0 -1
- package/src/components/resources/renderers/OrderRenderer.tsx +0 -1
- package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +0 -1
- package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +0 -1
- package/src/components/resources/renderers/PodMonitorRenderer.tsx +0 -1
- package/src/components/resources/renderers/PriorityClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +0 -1
- package/src/components/resources/renderers/ReplicaSetRenderer.tsx +0 -1
- package/src/components/resources/renderers/RuntimeClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/SbomReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/SealedSecretRenderer.tsx +0 -1
- package/src/components/resources/renderers/SecretRenderer.tsx +0 -1
- package/src/components/resources/renderers/SecretStoreRenderer.tsx +0 -1
- package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +0 -1
- package/src/components/resources/renderers/SimpleRouteRenderer.tsx +0 -1
- package/src/components/resources/renderers/StorageClassRenderer.tsx +0 -1
- package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +0 -1
- package/src/components/resources/renderers/VPARenderer.tsx +0 -1
- package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +0 -1
- package/src/components/resources/renderers/VeleroVSLRenderer.tsx +0 -1
- package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +0 -1
- package/src/components/resources/renderers/WebhookConfigRenderer.tsx +0 -1
- package/src/components/resources/renderers/WorkflowRenderer.tsx +0 -1
- package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +0 -1
- package/src/components/resources/renderers/argo-cells.tsx +0 -1
- package/src/components/resources/renderers/certmanager-cells.tsx +0 -1
- package/src/components/resources/renderers/cnpg-cells.tsx +0 -1
- package/src/components/resources/renderers/eso-cells.tsx +0 -1
- package/src/components/resources/renderers/flux-cells.tsx +0 -1
- package/src/components/resources/renderers/index.ts +0 -94
- package/src/components/resources/renderers/istio-cells.tsx +0 -1
- package/src/components/resources/renderers/karpenter-cells.tsx +0 -1
- package/src/components/resources/renderers/keda-cells.tsx +0 -1
- package/src/components/resources/renderers/knative-cells.tsx +0 -1
- package/src/components/resources/renderers/kyverno-cells.tsx +0 -1
- package/src/components/resources/renderers/prometheus-cells.tsx +0 -1
- package/src/components/resources/renderers/traefik-cells.tsx +0 -1
- package/src/components/resources/renderers/trivy-cells.tsx +0 -1
- package/src/components/resources/renderers/trivy-shared.tsx +0 -1
- package/src/components/resources/renderers/velero-cells.tsx +0 -1
- package/src/components/resources/resource-utils-argo.ts +0 -2
- package/src/components/resources/resource-utils-certmanager.ts +0 -2
- package/src/components/resources/resource-utils-eso.ts +0 -2
- package/src/components/resources/resource-utils-flux.ts +0 -2
- package/src/components/resources/resource-utils-istio.ts +0 -2
- package/src/components/resources/resource-utils-karpenter.ts +0 -2
- package/src/components/resources/resource-utils-knative.ts +0 -2
- package/src/components/resources/resource-utils-kyverno.ts +0 -2
- package/src/components/resources/resource-utils-prometheus.ts +0 -2
- package/src/components/resources/resource-utils-traefik.ts +0 -1
- package/src/components/resources/resource-utils-trivy.ts +0 -2
- package/src/components/resources/resource-utils-velero.ts +0 -2
- package/src/components/shared/EditableYamlView.tsx +0 -24
- package/src/components/timeline/DiffViewer.tsx +0 -1
- package/src/components/traffic/index.ts +0 -3
- package/src/components/ui/ForceDeleteConfirmDialog.tsx +0 -1
- package/src/components/ui/MetricsChart.tsx +0 -1
- package/src/components/ui/ResourceBar.tsx +0 -1
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
investigationClosedEventIsLive,
|
|
15
15
|
investigationClosedRunIsUnavailable,
|
|
16
16
|
investigationEvidenceInputsEqual,
|
|
17
|
+
investigationEvidenceCoverageGaps,
|
|
17
18
|
investigationEvidenceCoverageLimited,
|
|
18
19
|
investigationEvidenceConflictsWithHealthy,
|
|
19
20
|
investigationHealthConflictExplainedBy,
|
|
@@ -22,7 +23,10 @@ import {
|
|
|
22
23
|
investigationInteractionsBlocked,
|
|
23
24
|
investigationIsReadOnly,
|
|
24
25
|
investigationPaneCenteredScrollTop,
|
|
25
|
-
|
|
26
|
+
investigationAssessmentTurnIndexes,
|
|
27
|
+
investigationHealthSignals,
|
|
28
|
+
investigationSettledAnswerTurnIndexes,
|
|
29
|
+
investigationIsAssessmentTurn,
|
|
26
30
|
} from "./investigationState";
|
|
27
31
|
|
|
28
32
|
describe("investigation terminal presentation", () => {
|
|
@@ -169,6 +173,38 @@ describe("investigation terminal presentation", () => {
|
|
|
169
173
|
});
|
|
170
174
|
|
|
171
175
|
describe("investigation evidence projection stability", () => {
|
|
176
|
+
it("does not call a resource read partial when Diagnose cannot bundle the kind", () => {
|
|
177
|
+
const projection = {
|
|
178
|
+
limitations: [],
|
|
179
|
+
coverage: { attempted: 1, projected: 1, limited: 0, checked: 0 },
|
|
180
|
+
sources: [
|
|
181
|
+
{ id: "resource", tool: "get_resource", confirmedSuccess: true },
|
|
182
|
+
],
|
|
183
|
+
groups: [
|
|
184
|
+
{
|
|
185
|
+
latest: { relevance: "target" as const, source: { id: "resource" } },
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
expect(
|
|
190
|
+
investigationEvidenceCoverageGaps(projection, "HorizontalPodAutoscaler"),
|
|
191
|
+
).toEqual({ noEvidence: false, noTargetDiagnosis: false });
|
|
192
|
+
expect(
|
|
193
|
+
investigationEvidenceCoverageLimited(
|
|
194
|
+
projection,
|
|
195
|
+
"HorizontalPodAutoscaler",
|
|
196
|
+
),
|
|
197
|
+
).toBe(false);
|
|
198
|
+
expect(investigationEvidenceCoverageGaps(projection, "Deployment")).toEqual(
|
|
199
|
+
{
|
|
200
|
+
noEvidence: false,
|
|
201
|
+
noTargetDiagnosis: true,
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
expect(investigationEvidenceCoverageLimited(projection, "Deployment")).toBe(
|
|
205
|
+
true,
|
|
206
|
+
);
|
|
207
|
+
});
|
|
172
208
|
it("treats zero projected producer evidence as limited coverage", () => {
|
|
173
209
|
expect(
|
|
174
210
|
investigationEvidenceCoverageLimited({
|
|
@@ -817,85 +853,71 @@ describe("investigation action gating", () => {
|
|
|
817
853
|
});
|
|
818
854
|
});
|
|
819
855
|
|
|
820
|
-
describe("
|
|
821
|
-
const linkedItem = {
|
|
822
|
-
status: "linked" as const,
|
|
823
|
-
ref: "ev_x",
|
|
824
|
-
role: "context" as const,
|
|
825
|
-
claim: "c",
|
|
826
|
-
};
|
|
856
|
+
describe("investigationAssessmentTurnIndexes", () => {
|
|
827
857
|
const assessment = {
|
|
828
858
|
status: "done" as const,
|
|
829
859
|
diagnosis: { healthy: true, rootCause: "", report: "", remediation: [] },
|
|
830
860
|
};
|
|
831
|
-
it("keeps the assessment
|
|
832
|
-
|
|
861
|
+
it("keeps the assessment across answers that only restate a root cause", () => {
|
|
862
|
+
// Agents restate the cause on most answers; without an explicit revision
|
|
863
|
+
// signal every question would rewrite Findings.
|
|
864
|
+
const restating = {
|
|
833
865
|
status: "done" as const,
|
|
834
|
-
question: "
|
|
835
|
-
diagnosis: { rootCause: "", report: "because", remediation: [] },
|
|
836
|
-
};
|
|
837
|
-
expect(investigationLiveCaseTurnIndex([assessment, answer], 0)).toBe(0);
|
|
838
|
-
});
|
|
839
|
-
it("moves to an answer turn that carries a bound case or linked root-cause refs", () => {
|
|
840
|
-
const cited = {
|
|
841
|
-
status: "done" as const,
|
|
842
|
-
question: "chart it and cite it",
|
|
866
|
+
question: "get the secret",
|
|
843
867
|
diagnosis: {
|
|
844
|
-
rootCause: "",
|
|
868
|
+
rootCause: "Secret x does not exist",
|
|
845
869
|
report: "",
|
|
846
870
|
remediation: [],
|
|
847
|
-
evidence: [linkedItem],
|
|
848
871
|
},
|
|
849
872
|
};
|
|
850
|
-
expect(
|
|
851
|
-
|
|
873
|
+
expect(investigationAssessmentTurnIndexes([assessment, restating])).toEqual(
|
|
874
|
+
[0],
|
|
875
|
+
);
|
|
876
|
+
expect(investigationIsAssessmentTurn(restating)).toBe(false);
|
|
877
|
+
});
|
|
878
|
+
it("accepts a question turn only when it revises with a complete verdict", () => {
|
|
879
|
+
const revised = {
|
|
852
880
|
status: "done" as const,
|
|
853
|
-
question: "
|
|
881
|
+
question: "could it be OOM?",
|
|
854
882
|
diagnosis: {
|
|
855
|
-
rootCause: "
|
|
883
|
+
rootCause: "The container is OOM-killed.",
|
|
884
|
+
summary: "The app runs out of memory.",
|
|
885
|
+
revisesAssessment: true,
|
|
856
886
|
report: "",
|
|
857
887
|
remediation: [],
|
|
858
|
-
rootCauseEvidence: { status: "linked" as const, refs: ["ev_x"] },
|
|
859
888
|
},
|
|
860
889
|
};
|
|
861
|
-
expect(
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
},
|
|
890
|
+
expect(investigationAssessmentTurnIndexes([assessment, revised])).toEqual([
|
|
891
|
+
0, 1,
|
|
892
|
+
]);
|
|
893
|
+
const flagOnly = {
|
|
894
|
+
...revised,
|
|
895
|
+
diagnosis: { ...revised.diagnosis, summary: undefined },
|
|
868
896
|
};
|
|
869
|
-
expect(
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
});
|
|
873
|
-
it("ignores apply, explanation, running, and superseded turns", () => {
|
|
874
|
-
const cited = {
|
|
875
|
-
status: "done" as const,
|
|
876
|
-
question: "cite",
|
|
897
|
+
expect(investigationIsAssessmentTurn(flagOnly)).toBe(false);
|
|
898
|
+
const noVerdict = {
|
|
899
|
+
...revised,
|
|
877
900
|
diagnosis: {
|
|
878
901
|
rootCause: "",
|
|
902
|
+
summary: "Words.",
|
|
903
|
+
revisesAssessment: true,
|
|
879
904
|
report: "",
|
|
880
|
-
remediation: [],
|
|
881
|
-
evidence: [linkedItem],
|
|
905
|
+
remediation: ["x"],
|
|
882
906
|
},
|
|
883
907
|
};
|
|
884
|
-
expect(
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
investigationLiveCaseTurnIndex([assessment, cited, assessment], 2),
|
|
898
|
-
).toBe(2);
|
|
908
|
+
expect(investigationIsAssessmentTurn(noVerdict)).toBe(false);
|
|
909
|
+
});
|
|
910
|
+
it("always takes verifications and never apply, explanation or running turns", () => {
|
|
911
|
+
const verify = { ...assessment, question: "re-check", verify: true };
|
|
912
|
+
expect(
|
|
913
|
+
investigationAssessmentTurnIndexes([
|
|
914
|
+
assessment,
|
|
915
|
+
{ ...assessment, apply: true },
|
|
916
|
+
{ ...assessment, explainAssessment: 2 },
|
|
917
|
+
{ ...assessment, status: "running" as const },
|
|
918
|
+
verify,
|
|
919
|
+
]),
|
|
920
|
+
).toEqual([0, 4]);
|
|
899
921
|
});
|
|
900
922
|
});
|
|
901
923
|
|
|
@@ -1015,3 +1037,239 @@ describe("adverse evidence and the healthy-conflict banner", () => {
|
|
|
1015
1037
|
}
|
|
1016
1038
|
});
|
|
1017
1039
|
});
|
|
1040
|
+
|
|
1041
|
+
describe("investigationSettledAnswerTurnIndexes", () => {
|
|
1042
|
+
const assessment = {
|
|
1043
|
+
status: "done" as const,
|
|
1044
|
+
diagnosis: { rootCause: "x", report: "s", remediation: [], summary: "S." },
|
|
1045
|
+
};
|
|
1046
|
+
const answer = (revises?: boolean) => ({
|
|
1047
|
+
status: "done" as const,
|
|
1048
|
+
question: "q",
|
|
1049
|
+
diagnosis: {
|
|
1050
|
+
rootCause: "",
|
|
1051
|
+
report: "a",
|
|
1052
|
+
remediation: [],
|
|
1053
|
+
revisesAssessment: revises,
|
|
1054
|
+
},
|
|
1055
|
+
});
|
|
1056
|
+
it("settles non-revising answers under the story contract only", () => {
|
|
1057
|
+
expect(
|
|
1058
|
+
investigationSettledAnswerTurnIndexes(
|
|
1059
|
+
[
|
|
1060
|
+
assessment,
|
|
1061
|
+
answer(false),
|
|
1062
|
+
answer(true),
|
|
1063
|
+
{ ...answer(), verify: true },
|
|
1064
|
+
],
|
|
1065
|
+
0,
|
|
1066
|
+
),
|
|
1067
|
+
).toEqual(new Set([1]));
|
|
1068
|
+
const legacy = {
|
|
1069
|
+
...assessment,
|
|
1070
|
+
diagnosis: { ...assessment.diagnosis, summary: undefined },
|
|
1071
|
+
};
|
|
1072
|
+
expect(
|
|
1073
|
+
investigationSettledAnswerTurnIndexes([legacy, answer(false)], 0),
|
|
1074
|
+
).toEqual(new Set());
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
describe("investigationHealthSignals", () => {
|
|
1079
|
+
const adverse = (id: string, title: string) => ({
|
|
1080
|
+
id,
|
|
1081
|
+
identity: id,
|
|
1082
|
+
historical: false,
|
|
1083
|
+
kind: "issue",
|
|
1084
|
+
latest: {
|
|
1085
|
+
relevance: "target" as const,
|
|
1086
|
+
tier: "key" as const,
|
|
1087
|
+
tone: "warning",
|
|
1088
|
+
title,
|
|
1089
|
+
source: { turnIndex: 0, id: `src-${id}` },
|
|
1090
|
+
},
|
|
1091
|
+
});
|
|
1092
|
+
it("classifies each adverse card by the agent's position on it", () => {
|
|
1093
|
+
const projection = {
|
|
1094
|
+
groups: [
|
|
1095
|
+
adverse("a", "Readiness probe failing"),
|
|
1096
|
+
adverse("b", "Restarts"),
|
|
1097
|
+
adverse("c", "OOM"),
|
|
1098
|
+
adverse("d", "Evicted"),
|
|
1099
|
+
],
|
|
1100
|
+
};
|
|
1101
|
+
const items = [
|
|
1102
|
+
{
|
|
1103
|
+
role: "benign",
|
|
1104
|
+
placement: "card" as const,
|
|
1105
|
+
claim: "Timeouts never removed it from endpoints.",
|
|
1106
|
+
groupId: "a",
|
|
1107
|
+
source: { turnIndex: 0 },
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
role: "demoted",
|
|
1111
|
+
placement: "card" as const,
|
|
1112
|
+
claim: "Old restarts.",
|
|
1113
|
+
groupId: "b",
|
|
1114
|
+
source: { turnIndex: 0 },
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
role: "symptom",
|
|
1118
|
+
placement: "card" as const,
|
|
1119
|
+
claim: "",
|
|
1120
|
+
groupId: "c",
|
|
1121
|
+
source: { turnIndex: 0 },
|
|
1122
|
+
},
|
|
1123
|
+
];
|
|
1124
|
+
expect(
|
|
1125
|
+
investigationHealthSignals(projection, items).map((s) => [
|
|
1126
|
+
s.title,
|
|
1127
|
+
s.status,
|
|
1128
|
+
]),
|
|
1129
|
+
).toEqual([
|
|
1130
|
+
["Readiness probe failing", "explained"],
|
|
1131
|
+
["Restarts", "related"],
|
|
1132
|
+
["OOM", "contradiction"],
|
|
1133
|
+
["Evicted", "unaddressed"],
|
|
1134
|
+
]);
|
|
1135
|
+
});
|
|
1136
|
+
});
|
|
1137
|
+
|
|
1138
|
+
describe("investigationHealthSignals twins across scopes", () => {
|
|
1139
|
+
const warning = {
|
|
1140
|
+
reason: "Unhealthy",
|
|
1141
|
+
message:
|
|
1142
|
+
"Readiness probe failed: check failed http://localhost:9898/readyz",
|
|
1143
|
+
type: "Warning",
|
|
1144
|
+
};
|
|
1145
|
+
const eventsGroup = (
|
|
1146
|
+
id: string,
|
|
1147
|
+
identity: string,
|
|
1148
|
+
patch: {
|
|
1149
|
+
relevance?: "target" | "producer-related" | "broader";
|
|
1150
|
+
events?: (typeof warning)[];
|
|
1151
|
+
turnIndex?: number;
|
|
1152
|
+
} = {},
|
|
1153
|
+
) => ({
|
|
1154
|
+
id,
|
|
1155
|
+
identity,
|
|
1156
|
+
historical: false,
|
|
1157
|
+
kind: "events",
|
|
1158
|
+
latest: {
|
|
1159
|
+
relevance: patch.relevance ?? ("target" as const),
|
|
1160
|
+
tier: "key" as const,
|
|
1161
|
+
tone: "warning",
|
|
1162
|
+
title: "Kubernetes events",
|
|
1163
|
+
summary: `${warning.reason}: ${warning.message} · ${identity}`,
|
|
1164
|
+
data: { type: "events", events: patch.events ?? [warning] },
|
|
1165
|
+
source: { turnIndex: patch.turnIndex ?? 0, id },
|
|
1166
|
+
},
|
|
1167
|
+
});
|
|
1168
|
+
const benignOnPod = [
|
|
1169
|
+
{
|
|
1170
|
+
role: "benign",
|
|
1171
|
+
placement: "card" as const,
|
|
1172
|
+
claim:
|
|
1173
|
+
"Probe timeouts during a node stall; the pod has been Ready since.",
|
|
1174
|
+
groupId: "events-pod",
|
|
1175
|
+
source: { turnIndex: 0 },
|
|
1176
|
+
},
|
|
1177
|
+
];
|
|
1178
|
+
|
|
1179
|
+
it("lets a benign note on the Pod's copy of a warning explain the Deployment's copy", () => {
|
|
1180
|
+
const groups = [
|
|
1181
|
+
eventsGroup("events-deploy", "deployment demo/podinfo"),
|
|
1182
|
+
eventsGroup("events-pod", "pod demo/podinfo-676569b68b-6278c"),
|
|
1183
|
+
];
|
|
1184
|
+
expect(
|
|
1185
|
+
investigationHealthSignals({ groups }, benignOnPod).map((signal) => [
|
|
1186
|
+
signal.groupId,
|
|
1187
|
+
signal.status,
|
|
1188
|
+
]),
|
|
1189
|
+
).toEqual([
|
|
1190
|
+
["events-deploy", "explained"],
|
|
1191
|
+
["events-pod", "explained"],
|
|
1192
|
+
]);
|
|
1193
|
+
expect(
|
|
1194
|
+
investigationHealthConflictExplainedBy({ groups }, benignOnPod),
|
|
1195
|
+
).toEqual(["Kubernetes events", "Kubernetes events"]);
|
|
1196
|
+
});
|
|
1197
|
+
|
|
1198
|
+
it("does not let an earlier turn's note on the Pod explain the Deployment's copy captured later", () => {
|
|
1199
|
+
const groups = [
|
|
1200
|
+
eventsGroup("events-deploy", "deployment demo/podinfo", { turnIndex: 1 }),
|
|
1201
|
+
eventsGroup("events-pod", "pod demo/podinfo-676569b68b-6278c"),
|
|
1202
|
+
];
|
|
1203
|
+
expect(
|
|
1204
|
+
investigationHealthSignals({ groups }, benignOnPod).map((signal) => [
|
|
1205
|
+
signal.groupId,
|
|
1206
|
+
signal.status,
|
|
1207
|
+
]),
|
|
1208
|
+
).toEqual([
|
|
1209
|
+
["events-deploy", "unaddressed"],
|
|
1210
|
+
["events-pod", "explained"],
|
|
1211
|
+
]);
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
it("never twins a cluster-scoped card with a namespaced one", () => {
|
|
1215
|
+
const groups = [
|
|
1216
|
+
eventsGroup("events-node", "node worker-1"),
|
|
1217
|
+
eventsGroup("events-pod", "pod demo/podinfo-676569b68b-6278c"),
|
|
1218
|
+
];
|
|
1219
|
+
expect(
|
|
1220
|
+
investigationHealthSignals({ groups }, benignOnPod).map((signal) => [
|
|
1221
|
+
signal.groupId,
|
|
1222
|
+
signal.status,
|
|
1223
|
+
]),
|
|
1224
|
+
).toEqual([
|
|
1225
|
+
["events-node", "unaddressed"],
|
|
1226
|
+
["events-pod", "explained"],
|
|
1227
|
+
]);
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
it("does not let a card with one warning explain a card that carries that warning and another", () => {
|
|
1231
|
+
const extra = {
|
|
1232
|
+
reason: "BackOff",
|
|
1233
|
+
message: "Back-off restarting failed container",
|
|
1234
|
+
type: "Warning",
|
|
1235
|
+
};
|
|
1236
|
+
const groups = [
|
|
1237
|
+
eventsGroup("events-deploy", "deployment demo/podinfo", {
|
|
1238
|
+
events: [warning, extra],
|
|
1239
|
+
}),
|
|
1240
|
+
eventsGroup("events-pod", "pod demo/podinfo-676569b68b-6278c"),
|
|
1241
|
+
];
|
|
1242
|
+
expect(
|
|
1243
|
+
investigationHealthSignals({ groups }, benignOnPod).map((signal) => [
|
|
1244
|
+
signal.groupId,
|
|
1245
|
+
signal.status,
|
|
1246
|
+
]),
|
|
1247
|
+
).toEqual([
|
|
1248
|
+
["events-deploy", "unaddressed"],
|
|
1249
|
+
["events-pod", "explained"],
|
|
1250
|
+
]);
|
|
1251
|
+
});
|
|
1252
|
+
|
|
1253
|
+
it("keeps a different warning, another namespace, or a broader card as its own signal", () => {
|
|
1254
|
+
const groups = [
|
|
1255
|
+
eventsGroup("events-deploy", "deployment demo/podinfo", {
|
|
1256
|
+
events: [{ ...warning, message: "Liveness probe failed: timeout" }],
|
|
1257
|
+
}),
|
|
1258
|
+
eventsGroup("events-elsewhere", "deployment other/podinfo"),
|
|
1259
|
+
eventsGroup("events-broader", "deployment demo/frontend", {
|
|
1260
|
+
relevance: "broader",
|
|
1261
|
+
}),
|
|
1262
|
+
eventsGroup("events-pod", "pod demo/podinfo-676569b68b-6278c"),
|
|
1263
|
+
];
|
|
1264
|
+
expect(
|
|
1265
|
+
investigationHealthSignals({ groups }, benignOnPod).map((signal) => [
|
|
1266
|
+
signal.groupId,
|
|
1267
|
+
signal.status,
|
|
1268
|
+
]),
|
|
1269
|
+
).toEqual([
|
|
1270
|
+
["events-deploy", "unaddressed"],
|
|
1271
|
+
["events-elsewhere", "unaddressed"],
|
|
1272
|
+
["events-pod", "explained"],
|
|
1273
|
+
]);
|
|
1274
|
+
});
|
|
1275
|
+
});
|