feat(issues): incident_parent on the per-resource path (drawer + MCP get_resource/diagnose)#1057
Merged
Merged
Conversation
…resource/diagnose) RelatedIssues now runs the grouped-mode enrichment (mirroring the cluster path) so the symptom→root pointer is coverage-gated and populated for the resource drawer, get_resource, and diagnose — not just the cluster Issues view + MCP issues. Re-adds the drawer back-pointer render (removed in #1056 when the path didn't populate it).
…(codex) The per-resource RelatedIssues path now assigns incident_parent via a grouped-mode re-enrichment, so the gate + foldGroup comments no longer say it's unset there.
…ontract on the per-resource path Review follow-ups: - New TestRelatedIssues_IncidentParentCoverageGate: a root covering only 2 of 3 members of a grouped symptom must not attach the pointer (guards the grouped argument at the RelatedIssues enrichment call — mutation-verified). - New TestRelatedIssuesFrom_NoIncidentParentOnBarePair: a bare GroupIssues pair yields rows without the pointer; enrichment is the caller's responsibility (pins the GitOps insights resolver's divergence as a decision, not an accident). - Correct foldGroup's "Both paths" comment (the precomposed RelatedIssuesFrom path never assigns the pointer) + document the contract on RelatedIssuesFrom; reword the diagnostic_context gate comment so ?view=flat doesn't read as the only ungrouped caller. - Drawer: hoist issue.incident_parent to drop the non-null assertion.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the symptom→root cause-pointer feature (#1056) by extending the
incident_parentreverse pointer to the per-resource surfaces — the resource drawer's Operational Issues block, and the MCPget_resource/diagnosetools. #1056 shipped the pointer on the cluster Issues view + MCPissues; this closes the one remaining gap so every surface that shows an issue can show why it exists.What changed
The per-resource path (
RelatedIssues, behind/api/issues/resource/...,get_resource,diagnose) composed issues in flat/ungrouped mode, where the whole-row coverage gate can't be evaluated — soincident_parentwas deliberately left unset there (#1056 even removed the drawer back-pointer because nothing populated it).Now
RelatedIssuesruns the grouped-mode enrichment (enrichDiagnosticContext(grouped, flat, grouped, p)) after grouping — exactly mirroring the cluster path — so the grouped issues get the same coverage-gatedincident_parent. It's one extra enrichment pass (not a secondCompose); the link computation reuses the already-composed flat + grouped sets.RelatedIssues.ResourceIssuesSection("Caused by: ‹kind/name›", honest per-fact-type wording, clickable) — now that the path populates it.get_resource/diagnosecarryincident_parenton their related issues automatically.The coverage gate, best-parent rule, and direction allow-list are unchanged — the per-resource path now simply runs the same well-gated assignment.
Scope note — slightly broader than the pointer alone: the grouped-mode pass also recomputes
ChangeContexton the grouped rows and collapses blast-radiusrelated_issuesto grouped refs with counts, so the drawer/MCP payloads now match what the cluster Issues view shows (previously they carried the flat representative's uncollapsed context). This is the intended parity, not an accident. The GitOps insights resolver's precomposedRelatedIssuesFrompath deliberately skips the enrichment — it projects issues down toReason/Message/Category/Severity, so the pointer would be dropped anyway; the contract is documented onRelatedIssuesFromand pinned by test.Testing
go test ./internal/issues ./internal/mcp ./internal/server+pkg/issuesapi— green;make tscgreen.TestRelatedIssues_PopulatesIncidentParent: a PVC + a covered unschedulable pod →RelatedIssuesreturns the pod issue withincident_parent → PVC/data (high).TestRelatedIssues_IncidentParentCoverageGate(review follow-up): a root covering only 2 of 3 members of a grouped symptom must NOT attach the pointer — mutation-verified (passing the flat set as the grouped argument fails it).TestRelatedIssuesFrom_NoIncidentParentOnBarePair(review follow-up): pins that a bareGroupIssuespair yields rows without the pointer./api/issues/resource/Deployment/...returned theunschedulableissue withincident_parent → PVC/data (high), and the resource drawer's Operational Issues rendered "Caused by: PersistentVolumeClaim / data" (clickable, 0 console errors).Not included
MemoryPressure/DiskPressure/PIDPressurecondition requires actually exhausting the node's (host-shared) memory/disk on the single-node test cluster — too risky to do safely. The pointer + forward link are unit-tested; live verification waits for a disposable multi-node environment.Note
Medium Risk
Changes causal attribution on per-resource APIs and drawer UI; logic reuses existing coverage gates but wrong enrichment inputs could mis-parent grouped symptoms.
Overview
Extends coverage-gated
incident_parent(symptom → root) to per-resource issue surfaces by running grouped-modeenrichDiagnosticContextinsideRelatedIssuesafterGroupIssues, matching the cluster Issues path. MCPget_resource/diagnoseand/api/issues/resource/...pick this up without separate API changes.Contract:
RelatedIssuesFromstill only matches; callers that pass a bareGroupIssuespair (e.g. GitOps insights compose-once) do not getincident_parentunless they enrich themselves. Comments indiagnostic_context.go,grouping.go, and tests document that split.UI:
ResourceIssuesSectionshows the back-pointer (incidentParentLabel+ optional clickablekind / name) when the API populatesincident_parent.Tests: Happy path (PVC → unschedulable pod), whole-row coverage gate (partial fan-out → no pointer), and bare-pair vs enriched
RelatedIssuesbehavior.Reviewed by Cursor Bugbot for commit 197030a. Bugbot is set up for automated code reviews on this repo. Configure here.