WS4: missing-index CREATE statements as copy-paste on Recommendations cards#1084
Merged
Merged
Conversation
…ndations cards A MISSING_INDEX finding's drill-down carries the SQL Server-suggested CREATE INDEX statement(s), but the drill-down is ephemeral (not persisted / not read back), so the Recommendations reader never saw them -- the card showed advice + Ask-AI but no way to copy the suggested index. This carries the CREATE statements on the persisted RemediationAction (FactKey MISSING_INDEX) through the read-back, exactly like the autogrowth / server-config advisories already do, so the reader can render them. COPY-ONLY by design: there is deliberately no handler for MISSING_INDEX (creating an index is a judgement call -- over-indexing, write + storage cost), so the card shows 'Copy fix' but no Apply button. It stays an incident, keeping Open-in-Active-Queries / Ask-AI; a new IsMissingIndexAdvisory flag gates only ShowCopyFix. Shared: - RemediationAction: + MissingIndexTarget record + MissingIndexTargets field - FactRemediation: + BuildMissingIndexAction / ExtractMissingIndexTargets (reads the missing_indexes drill-down: table / impact / create_statement) - AlertContext: + MissingIndexTargetDto + ToDto/FromDto round-trip (backward-compatible) Dashboard: - AnalysisService: + BuildMissingIndexAction in the build chain - RecommendationsReader: render the CREATEs as CopyPasteSql, leave Remediation null (no Apply) - RecommendationItem / RecommendationsViewModel: IsMissingIndexAdvisory -> ShowCopyFix Tests: + MissingIndexAdvisoryTests (builder / extractor / serializer round-trip / reader copy-only mapping / card affordances) and a MISSING_INDEX copy-only case in the golden-sample (drill-down -> builder drift guard: non-null + targets + NOT registry-dispatchable). Dashboard.Tests 476/0, Lite.Tests 406/0. Lite + the read-only surfaces (email/webhook/MCP) render copy-paste via the shared FactRemediation.GenerateForFinding, which does not yet handle MISSING_INDEX -- Lite parity is a follow-up (one switch case), out of scope for this Dashboard-card PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Surfaces the SQL Server-suggested CREATE INDEX statement(s) on a MISSING_INDEX Recommendations card as "Copy fix". Previously the card showed advice + Ask-AI but no way to copy the suggested index.
Why it needed shared-library work (not just a reader tweak)
The
missing_indexesdrill-down (wherecreate_statementlives) is ephemeral —config.analysis_findingshas no drill-down column andReadFindingonly rehydrates the builtRemediationAction. So the reader never saw the CREATE text. This carries it on the persisted action (FactKeyMISSING_INDEX) through the round-trip — exactly the pattern the autogrowth / server-config-memory advisories already use.Copy-only by design
There is deliberately no handler for
MISSING_INDEX— creating an index is a judgement call (over-indexing, write + storage cost), matching the rebuild plan's "advise, over-indexing caveats" stance. So:Remediationnull →ShowApplystays false)IsMissingIndexAdvisoryflag gates onlyShowCopyFix, so the card isn't reclassified.Changes
Shared (
PerformanceMonitor.Analysis/.Notifications)RemediationAction: +MissingIndexTargetrecord +MissingIndexTargetsfieldFactRemediation: +BuildMissingIndexAction/ExtractMissingIndexTargets(readsmissing_indexes:table/impact/create_statement)AlertContext: +MissingIndexTargetDto+ToDto/FromDtoround-trip (trailing-optional → backward-compatible)Dashboard
AnalysisService: +BuildMissingIndexActionin the build chainRecommendationsReader: render the CREATEs asCopyPasteSql, leaveRemediationnullRecommendationItem/RecommendationsViewModel:IsMissingIndexAdvisory→ShowCopyFixTests
MissingIndexAdvisoryTests(builder, extractor skip/cap, serializer round-trip, reader copy-only mapping, card affordances) + a MISSING_INDEX copy-only case inRemediationGoldenSampleTests(drill-down → builder drift guard: non-null + targets + not registry-dispatchable). Dashboard.Tests 476 / 0, Lite.Tests 406 / 0.Scope notes
FactRemediation.GenerateForFinding, which doesn't yet handle MISSING_INDEX — Lite parity is a one-switch-case follow-up, out of scope for this Dashboard-card PR.🤖 Generated with Claude Code