Release v1.11.0#341
Merged
Merged
Conversation
Avoids GitHub's June 2, 2026 forced migration off Node 20: - actions/checkout v4 -> v5 - actions/setup-dotnet v4 -> v5 - actions/upload-artifact v4 -> v6 (first major to default to Node 24) - signpath/github-action-submit-signing-request v1 -> v2 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* switch the default grid GroupBy from "None" to "Query Hash" and don't open the first line by default * The Query Stores Overview feature has been implemented. Here's a summary of what was created: New Files: 1. QueryStoreOverviewModels.cs — Models for: • QueryStoreState enum (Off, ReadOnly, ReadWrite) • DatabaseQueryStoreState — state per database • DatabaseMetrics — aggregated metrics (total + avg) per database • DatabaseTimeSlice — time slice data tagged by database • DatabaseWaitCategoryTimeSlice — wait stats tagged by database 2. QueryStoreOverviewService.cs — Parallel data fetching with: • SemaphoreSlim throttling (default DOP=8) • ConcurrentBag<T> for thread-safe result collection • Methods: FetchAllStatesAsync(string, int, CancellationToken), FetchAllMetricsAsync(string, List<string>, DateTime, DateTime, int, CancellationToken), FetchAllTimeSlicesAsync(string, List<string>, int, int, CancellationToken), FetchAllWaitStatsAsync(string, List<string>, DateTime, DateTime, int, CancellationToken) 3. QueryStoreOverviewControl.axaml — Layout with 3 rows: • Row 1: Donut chart + consolidated time slicer + consolidated wait stats ribbon • Row 2: 7 bar chart cards (Total metrics) • Row 3: 7 bar chart cards (Avg metrics) 4. QueryStoreOverviewControl.axaml.cs — Code-behind with: • Donut chart (RW=light blue, RO=dark blue, OFF=grey, center shows active/total) • Consolidated time slicer (30-day, 24h default selection) • Consolidated wait stats ribbon (sum across databases) • Top-N bar cards with consistent database colors, adaptive font color, tooltips, and right-click "Drill Down to DB Query Store" context menu Modified Files: 5. QuerySessionControl.axaml — Added "QS Overview" button 6. QuerySessionControl.axaml.cs — Added QueryStoreOverview_Click(object?, RoutedEventArgs) handler that opens the overview tab and wires drill-down to open single-DB Query Store tabs * 1. Drill-down with time range: DrillDownRequested now passes a DrillDownEventArgs containing Database, StartUtc, and EndUtc. The session control calls grid.SetInitialTimeRange() before the grid auto-fetches, so the drilled-down Query Store tab starts with the same time range selected in the overview. 2. Progress bar: Added an indeterminate ProgressBar at the top of the overview. It shows during LoadAsync() (all 3 phases) and during RefreshMetricsAndWaitStatsAsync(CancellationToken) (when the slicer range changes), and hides when complete via try/finally. * improve the dashboard * fix issue about waits stats on the QS overview * fix null on WTR in sql * add evg ref line in waitstats chart * 1. Dead code removed — Deleted FetchDatabaseWaitStatsAsync and DatabaseWaitCategoryTimeSlice (no callers). 2. Bare catch blocks fixed — All 4 parallel fetch methods now use when (ex is not OperationCanceledException) or when (!ct.IsCancellationRequested) so cancellation propagates correctly. 3. Permission errors surfaced — Added QueryStoreState.Error enum value and ErrorMessage property to DatabaseQueryStoreState. The donut now shows a red "Error" segment, and clicking it lists databases with their error messages. 4. _cts leak fixed — Added _cts?.Dispose() before every reassignment in LoadAsync() and OnSlicerRangeChanged(object?, TimeRangeChangedEventArgs), plus a DetachedFromVisualTree handler that cancels and disposes on control teardown. 5. SizeChanged race fixed — DrawWaitStatsChart() now returns early if _dbColorMap is empty, preventing all bars from being bucketed into "Others" when a resize fires before DrawBarCards() has run. 6. Misnamed field renamed — WaitRatio → WaitAmountHours on DatabaseWaitAmountTimeSlice and all references in the service and control. --------- Co-authored-by: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com>
QueryStoreOverviewControl fixes:
- Replace #888888 with theme ForegroundMutedBrush (dim-text rule)
- Convert wait-stats error modal to inline warning badge with tooltip
- Drop dispose-while-in-flight on the OnSlicerRangeChanged CTS race
- Replace blanket catch{} with an inline RefreshErrorBadge so failed
refreshes surface their SqlException instead of silently blanking
Brand sweep ("SQL Performance Studio" -> "Performance Studio"):
User-visible surfaces only — issue templates, .csproj <Product>,
VSIX manifest, vsct ButtonText, VSPackage.resx, AssemblyInfo,
all SSMS dialog titles + error messages, install.cmd, installer
console banner. Internal IDs (pipe name, registry key) and
Program-Files paths kept; legacy spaced "SQL Performance Studio"
Program-Files paths kept as additional fallbacks so existing
installs still launch.
Version unification:
- New src/Directory.Build.props centralizes Version + identity
for all SDK-style projects under src/
- Removed duplicated <Version>/<Authors>/<Company>/<Product>/
<Copyright> from App, Core, Cli, Web, Installer csprojs
- PlanViewer.Ssms is legacy non-SDK and bumped manually:
AssemblyInfo.cs 1.0.0.0 -> 1.10.0.0, vsixmanifest 1.0.0 -> 1.10.0
- Tests/server projects are outside src/ and unaffected
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All flagged controls (QuerySessionControl, QueryStoreGridControl, QueryStoreOverviewControl, ConnectionDialog, QueryStoreHistoryWindow) take typed constructor dependencies and are instantiated directly in code-behind. They are never loaded via AvaloniaXamlLoader.Load() and the Avalonia IDE previewer isn't used in this project, so the warning flags scenarios that aren't load-bearing. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- setup-dotnet@v5 with cache: true persists ~/.nuget/packages between runs, keyed on **/*.csproj. Cold restore (~90s) becomes a tar extract on cache hit. - Replace five sequential dotnet restore + five sequential dotnet build invocations with one each against PlanViewer.sln. MSBuild builds the dependency graph in parallel internally, and we save four MSBuild startup cycles. - Tests still build via the solution build, then run with --no-build. PlanViewer.Ssms and PlanViewer.Ssms.Installer are intentionally not in PlanViewer.sln, so they remain excluded from CI as before. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Linux runners are ~2x faster than windows-latest on GitHub-hosted. None of the projects in PlanViewer.sln are Windows-only: - PlanViewer.Core, .App, .Cli are net8.0 cross-platform - PlanViewer.Web is Blazor WASM, builds on Linux with wasm-tools - PlanViewer.Core.Tests is xunit on net8.0 - PlanViewer.App already references SkiaSharp.NativeAssets.Linux PlanViewer.Ssms (legacy net472 + VSSDK) is not in the solution and is not built in CI; it stays Windows-only via its own workflow if one exists. If anything fails on Linux that's not flaggable as a small fix, revert this PR and we keep the cache + solution-build wins from #317. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR-only filter (push to main keeps building unconditionally). Skips
the workflow when every changed file matches one of:
- Documentation: **.md, LICENSE, CITATION.cff, llms.txt
- Repo config: .gitignore, .gitattributes, .github/ISSUE_TEMPLATE/**
- Non-CI artifacts: docs/, screenshots/, server/
- Projects intentionally excluded from PlanViewer.sln:
src/PlanViewer.Ssms/**
src/PlanViewer.Ssms.Installer/**
If any changed file falls outside the ignore list, the workflow runs
as before. Mirrors the path filter pattern already in deploy-web.yml.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both methods had no callers — only FetchAggregateHistoryAsync is wired up to QueryStoreHistoryWindow. Cleanup follows the execution_type_desc work in #321. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sys.query_store_plan.query_plan is already nvarchar(max), so the TRY_CONVERT was a no-op identity cast. It also broke the query on databases at compatibility level <110, where the parser doesn't recognize TRY_CONVERT and reports 'nvarchar' is not a recognized built-in function name. Three call sites in QueryStoreService.cs: FetchTopPlansAsync, FetchGroupedByQueryHashAsync, and FetchGroupedByModuleAsync. Verified against a compat-100 database. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds --execution-type to the CLI query-store command and execution_type to the get_query_store_top MCP tool, accepting regular/aborted/exception/ failed (= aborted + exception). Mirrors the desktop UI filter added in #321. Parsing logic is centralized in QueryStoreFilter.ParseExecutionType. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add "Powered by Performance Studio" line on landing page Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add Darling Data favicon to web app Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add Open Graph and Twitter Card meta tags for social sharing Uses the Darling Data barbell logo as hero image when shared on social media. Also adds meta description for SEO. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Clarify OG description: in-browser, nothing to install Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix Rule 3 severity: CouldNotGenerateValidParallelPlan is actionable This reason means something in the query blocks parallelism (scalar UDFs, table variable inserts, etc.) — that's worth a Warning, not Info. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Expand Rule 3 to cover all NonParallelPlanReason values Adds human-readable messages for all 25 known reasons. Severity: - Warning: actionable reasons (UDFs, cursors, table variables, remote queries, trace flags, hints, DML OUTPUT, writeback variables) - Info: passive/environmental (cost below threshold, edition limits, memory-optimized tables, upgrade mode, index build edge cases) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Split PlanViewerControl.axaml.cs into partial classes Move-only refactor; no behavior changes. PlanViewerControl.axaml.cs (4,497 lines) split into 7 partials: Rendering (550) - RenderStatement/Nodes/Edges + edge tooltips Properties (1860) - ShowPropertiesPanel + all property/runtime/wait panels Tooltips (278) - BuildNodeTooltipContent + helpers Interaction (327) - Node_Click, Select, zoom, pointer events, save Statements (222) - statements grid panel Minimap (502) - minimap render/drag/resize/navigation Schema (347) - context-menu schema lookup + index/column formatting Main file (PlanViewerControl.axaml.cs) now 504 lines — fields, brushes, constructor, public API (LoadPlan/Clear/NavigateToNode), connection state, and PlanConnect/PlanDatabase event handlers. Build clean: 0 errors, 0 warnings on PlanViewer.sln. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move-only refactor; no behavior changes. QuerySessionControl.axaml.cs
(2,251 lines) split into 8 partials:
Editor (286) - syntax highlighting, context menu, key/wheel, zoom
Schema (355) - ShowSchemaInfoAsync + Format{Indexes,Columns} + BuildWithOptions
Connection (120) - Connect_Click + Populate/Fetch* metadata
Execution (477) - Execute/EstimatedPlan/GetActualPlan + CaptureAndShowPlan
Plans (368) - plan tab add/close/rename/context-menu + Compare picker
QueryStore (267) - QueryStore_Click + Overview + OpenQueryStoreForDatabaseAsync
Advice ( 24) - Human/Robot advice click + ShowAdviceWindow
Format (124) - Format_Click + FormatOptions + CopyRepro
Main file now 177 lines — usings, ctor, fields, AXAML wiring.
Build clean: 0 errors, 0 warnings on PlanViewer.App.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add "Powered by Performance Studio" line on landing page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Darling Data favicon to web app
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Open Graph and Twitter Card meta tags for social sharing
Uses the Darling Data barbell logo as hero image when shared on
social media. Also adds meta description for SEO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Clarify OG description: in-browser, nothing to install
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix Rule 3 severity: CouldNotGenerateValidParallelPlan is actionable
This reason means something in the query blocks parallelism (scalar UDFs,
table variable inserts, etc.) — that's worth a Warning, not Info.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Expand Rule 3 to cover all NonParallelPlanReason values
Adds human-readable messages for all 25 known reasons. Severity:
- Warning: actionable reasons (UDFs, cursors, table variables, remote
queries, trace flags, hints, DML OUTPUT, writeback variables)
- Info: passive/environmental (cost below threshold, edition limits,
memory-optimized tables, upgrade mode, index build edge cases)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Split PlanAnalyzer.cs into partial classes
Move-only refactor; no behavior changes. PlanAnalyzer.cs (2,238 lines)
split into 5 partials:
Statement (439) - AnalyzeStatement (statement-level rules)
Node (777) - AnalyzeNodeTree + AnalyzeNode (operator rules)
Detection (248) - predicate/pattern helpers (HasNotIn, IsAntiSemi,
IsRowstoreScan, IsProbeOnly, DetectNonSargable,
IsOrExpansionChain, HasAdaptiveJoin, ...)
Timing (345) - operator CPU/elapsed helpers + ScanImpact + memory
Helpers (275) - severity overrides, wait labels, format, truncate
Main file now 115 lines — class declaration, regex constants, static
dictionaries (RuleWarningTypes/WarningTypeToRule), static ctor, the
public Analyze() entry point, and the ScanImpact record.
PlanViewer.Web.csproj updated to link the new partial files.
Build clean: 0 errors, 0 warnings on PlanViewer.sln.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move-only refactor; no behavior changes. QueryStoreGridControl.axaml.cs
(1,959 lines) split into 7 partials:
Fetch (452) - Fetch_Click + FetchPlans/WaitStats + grouping
Filters (256) - search type/value + column filter popup + ApplyFilters
GroupBy (161) - GroupBy + ReorderColumns + row expand/collapse
+ ResultsGrid_DoubleTapped + ToggleRowExpansion
Sort (245) - sorting + UpdateBarRatios + GetSortKey + status
Selection (134) - select/load/ViewHistory/context menu + copy
WaitStats (182) - wait fetch + category click + mode toggle
TimeRange ( 33) - OnTimeRangeChanged
Main file now 465 lines — fields, ctor, public API
(SetInitialTimeRange), DB picker, and static accessor dictionaries.
The standalone QueryStoreRow class at the bottom of the file is
untouched.
Build clean: 0 errors, 0 warnings on PlanViewer.App.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add "Powered by Performance Studio" line on landing page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Darling Data favicon to web app
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Open Graph and Twitter Card meta tags for social sharing
Uses the Darling Data barbell logo as hero image when shared on
social media. Also adds meta description for SEO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Clarify OG description: in-browser, nothing to install
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix Rule 3 severity: CouldNotGenerateValidParallelPlan is actionable
This reason means something in the query blocks parallelism (scalar UDFs,
table variable inserts, etc.) — that's worth a Warning, not Info.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Expand Rule 3 to cover all NonParallelPlanReason values
Adds human-readable messages for all 25 known reasons. Severity:
- Warning: actionable reasons (UDFs, cursors, table variables, remote
queries, trace flags, hints, DML OUTPUT, writeback variables)
- Info: passive/environmental (cost below threshold, edition limits,
memory-optimized tables, upgrade mode, index build edge cases)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Split ShowPlanParser.cs into partial classes
Move-only refactor; no behavior changes. ShowPlanParser.cs (1,844 lines)
split into 4 partials:
RelOp (789) - ParseRelOp (~760-line workhorse) +
GetOperatorElement + FindChildRelOps
Warnings (323) - ParseWarnings + ParseWarningsFromElement +
ParseMissingIndexes
Costs ( 25) - ComputeOperatorCosts + ComputeNodeCosts
Helpers ( 66) - CleanTempTableName, IsHexDigit, ScopedDescendants,
ParseColumnList, FormatColumnRef, ParseDouble/Long
Main file now 628 lines — class declaration, XML namespace, the public
Parse entry, ParseStatement{,AndChildren,Attributes},
ParseQueryPlanElements / ParseQueryPlanAsStatement.
PlanViewer.Web.csproj updated to link the new partial files.
Build clean: 0 errors, 0 warnings on PlanViewer.sln.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move-only refactor; no behavior changes. QueryStoreService.cs (1,403
lines) split into 3 partials:
Grouped (584) - FetchGroupedByQueryHashAsync +
FetchGroupedByModuleAsync
WaitStats (232) - IsWaitStatsCaptureEnabledAsync +
FetchGlobalWaitStatsAsync +
FetchPlanWaitStatsAsync +
FetchGlobalWaitStatsRibbonAsync +
BuildWaitProfile
Main file now 584 lines — top-of-pipe fetches: CheckEnabledAsync,
FetchTopPlansAsync, FetchAggregateHistoryAsync, FetchTimeSliceDataAsync.
Class made `static partial`.
Build clean: 0 errors, 0 warnings on PlanViewer.Core.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move-only refactor; no behavior changes. MainWindow.axaml.cs (1,380
lines) split into 4 partials:
FileOps (260) - File open/paste/drag-drop, LoadSqlFile,
LoadPlanFile, ValidatePlanXml, Save/RestoreOpenPlans
Tabs (209) - CreateTab, Close/Context menu, StartRename,
GetTabFilePath/Label, GetQueryTextFromPlan
PlanViewer (468) - CreatePlanTabContent, ShowAdviceWindow,
ShowCompareDialog, GetActualPlanFromFile,
ExtractDatabaseFromPlanXml
RecentPlans ( 78) - TrackRecentPlan, RebuildRecentPlansMenu,
RecentPlanItem_Click, ClearRecentPlans_Click
Main file now 342 lines — fields, ctor (drag-drop wiring, hotkeys,
command-line args, MCP start), StartPipeServer/StartMcpServer, OnClosed,
Exit_Click, About_Click, UpdateEmptyOverlay, ShowError,
CheckForUpdatesOnStartupAsync.
Build clean: 0 errors on PlanViewer.App (existing pre-existing CS0618
on DragEventArgs.Data is unchanged).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add "Powered by Performance Studio" line on landing page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Darling Data favicon to web app
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add Open Graph and Twitter Card meta tags for social sharing
Uses the Darling Data barbell logo as hero image when shared on
social media. Also adds meta description for SEO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Clarify OG description: in-browser, nothing to install
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix Rule 3 severity: CouldNotGenerateValidParallelPlan is actionable
This reason means something in the query blocks parallelism (scalar UDFs,
table variable inserts, etc.) — that's worth a Warning, not Info.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Expand Rule 3 to cover all NonParallelPlanReason values
Adds human-readable messages for all 25 known reasons. Severity:
- Warning: actionable reasons (UDFs, cursors, table variables, remote
queries, trace flags, hints, DML OUTPUT, writeback variables)
- Info: passive/environmental (cost below threshold, edition limits,
memory-optimized tables, upgrade mode, index build edge cases)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Split AdviceContentBuilder.cs into partial classes
Move-only refactor; no behavior changes. AdviceContentBuilder.cs (1,227
lines) split into 4 partials:
NodeLinks (243) - MakeNodeRefsClickable + ProcessInlines +
AddRunsWithNodeLinks + WireNodeClickHandler
Operators (251) - CreateOperatorLine/Group/TimingLine +
CreateWarningBlock
WaitStats (242) - CreateWaitStatLine + CreateMissingIndexImpactLine +
ParseWaitMs + GetWaitCategoryBrush +
CreateTriageSummaryCard
Sql ( 36) - BuildSqlHighlightedLine
Main file now 444 lines — brushes/fonts, PhysicalOperators &
SqlKeywords sets, regex constants, the 3 Build() overloads (entry
points), IsSubSectionLabel helper.
Class made `internal static partial`.
Build clean: 0 errors on PlanViewer.App.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both are pre-existing bugs surfaced during smoke-testing of the god-file split; neither was caused by the move-only refactor. 1. Run Repro from a file-loaded plan produced an actual-plan tab with schema lookups (Show Indexes / Show Table Definition) greyed out. The new PlanViewerControl wasn't given the connection used to run the repro. Now inherits ConnectionString + connection services + status, matching the query-editor Run Repro path. 2. QuerySessionControl toolbar overflowed off-screen on narrow windows — the Format / Format Options buttons were unreachable. Switched the toolbar from a single-row StackPanel to a WrapPanel so buttons wrap to a second row instead of being cut off. Build clean: 0 errors on PlanViewer.sln. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Corporate-proxy users were hitting "Check for Updates" failures because neither Velopack's downloader nor the HttpClient fallback was sending Windows credentials to the proxy. James (issue #314) confirmed his proxy is auto-discovered for most apps but SSMS 25 needed manual address + on-prem AD user/pass, so both paths are needed. * ProxySettings — "System" (default) sends Windows credentials to the auto-discovered proxy; "Manual" lets the user enter address + optional username/password. Password is held in the existing ICredentialService (Windows Credential Manager / macOS Keychain). * ProxyHttpHandlerFactory — single source of truth for proxy wiring on HttpClientHandler. Used by both UpdateChecker (GitHub API fallback) and ProxyAwareDownloader (Velopack's IFileDownloader override). * ProxyAwareDownloader subclasses Velopack.Sources.HttpClientFileDownloader and snapshots ProxySettings at construction so retries/redirects don't re-read DPAPI. * SettingsFile — merge-safe JSON read/update so the MCP and Proxy save paths don't stomp each other. * AboutWindow — proxy settings UI (radio + collapsed manual grid). The password field is intentionally not round-tripped through the UI; watermark says "(saved — leave blank to keep)". Status text now wraps. When the update check fails, a "Open the releases page in your browser" link is shown as a manual-download fallback. * If Velopack itself fails (the actual #314 symptom), its error is now surfaced alongside the API fallback error instead of being swallowed. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- TargetFramework: net8.0 -> net10.0 across all SDK-style projects (App, Core, Cli, Web, PlanShare, Tests). SSMS extension and its installer stay on net472 (VS extension constraint). - ModelContextProtocol/ModelContextProtocol.AspNetCore: 1.2.0 -> 1.3.0 - Microsoft.NET.Test.Sdk: 18.4.0 -> 18.5.1 - Microsoft.AspNetCore.Components.WebAssembly + DevServer: 8.0.12 -> 10.0.0 - CI workflows (ci, nightly, release, deploy-web): dotnet-version 8.0.x -> 10.0.x - Doc/comment refs to .NET 8 updated to .NET 10
* Fix sort issues on the QueryHistory * What changed 1. QueryStoreGridControl.Selection.cs — ViewHistory_Click now walks up the visual tree to find the parent QuerySessionControl and calls AddHistorySubTab(), placing the history as a sub-tab alongside "Query Store — DB" and "QS Overview" (instead of at the top-level MainTabControl). 2. QuerySessionControl.QueryStore.cs — Added two new methods: • AddHistorySubTab() — creates a closeable sub-tab with the history control, including long-press (~500ms) to detach into a free-floating window • DetachHistorySubTabToWindow() — pops the history content into a standalone non-modal window (movable to another screen). When that window is minimized or closed, the content automatically re-docks back as a sub-tab 3. MainWindow.Tabs.cs — Removed the now-unused AddHistoryTab() method since history tabs no longer live at the top level User flow • View History → opens as a sub-tab next to Query Store / QS Overview • Long-press the history sub-tab → detaches into a free window (can move to another screen) • Minimize or close the free window → content returns to the sub-tab * What was added 1. QueryStoreService.FetchPlanByHashAsync() — New method that fetches a plan XML from sys.query_store_plan by query_plan_hash. The oldest parameter controls whether it returns the first (smallest plan_id) or last (largest plan_id) plan. 2. Context menu on QueryStoreHistoryControl — Right-clicking on the DataGrid or chart shows: • "Load the First Plan" — fetches the oldest plan for the selected plan hash • "Load the Last Plan" — fetches the most recent plan for the selected plan hash The selected plan hash is determined from either the grid selection or chart selection. 3. PlanLoadRequested event — Raised when the user picks a plan from the context menu. The parent QuerySessionControl subscribes to this event and opens the plan XML as a new sub-tab (using the existing AddPlanTab mechanism). User flow • Select a row in the history grid (or a dot on the chart) • Right-click → "Load the First Plan" or "Load the Last Plan" • The plan opens as a new sub-tab (e.g., "QS 42 / 17") * Code review : Bugs Fixed 1. Shared ContextMenu — BuildContextMenu() now creates separate ContextMenu instances for DataGrid and Chart via CreatePlanContextMenu() 2. Silent catch — LoadPlanFromSelection now shows errors in StatusText with catch (Exception ex) 3. Wrong type check — Close_Click now checks is not PlanViewer.App.MainWindow instead of IClassicDesktopStyleApplicationLifetime 4. Event handler leak — AddHistorySubTab now unsubscribes before subscribing: -= OnHistoryPlanLoadRequested before += Improvements 5. Loading feedback — Shows "Loading plan…" / "Plan not found" / error in StatusText 6. Disable menu when no selection — Opening handler disables items when GetSelectedPlanHash() is null 7. IndexOf — Added clarifying comment (list is <500 items, no better API available) 8. ScrollIntoView — Moved after ItemsSource reset so the target row exists 9. Long-press duplication — Extracted TabHeaderLongPressBehavior helper, used in both MainWindow.Tabs.cs and QuerySessionControl.QueryStore.cs 10. HistoryPlanLoadEventArgs — Moved to its own file Nits 11. Removed unnecessary ?. on non-nullable orderBy parameter 12. Changed bare catch to catch (Exception) in tooltip handler 13. Changed bare catch to catch (Exception ex) in LoadPlanFromSelection * When the MainWindow closes, it now iterates all open windows via IClassicDesktopStyleApplicationLifetime.Windows and closes any that aren't the MainWindow itself. This ensures all detached free-floating windows (from tab detach, history detach, advice windows, etc.) are closed when the app's main window is closed. * Must-fix fixed * use pin/unpin button to fix ux-must-fix * fix error truncation to 80 chars : truncation removed * fix most remaining nice to have * add spinner and cancel for history fetches
- Replace deprecated DataGridRow.GetIndex() with the Index property - Remove dead _suppressGridSelectionEvent field; the suppression was only needed for the old ItemsSource-reset highlight path, which was refactored away Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #315 moved <Version> from App.csproj into src/Directory.Build.props but left four workflows still parsing the old path — every one of them would have silently produced an empty VERSION on the next release: - release.yml: would tag as "v" and break Velopack pack/upload - check-version-bump.yml: empty == empty would block legit bumps - nightly.yml: nightly tag becomes "-nightly.YYYYMMDD" - deploy-web.yml: also tried to write <Version> back into Web csproj, which no longer has one — drop the obsolete sync step entirely (both csprojs now inherit from Directory.Build.props automatically) Version bumps for 1.11.0: - src/Directory.Build.props 1.10.0 -> 1.11.0 - PlanViewer.Ssms/Properties/AssemblyInfo.cs 1.10.0.0 -> 1.11.0.0 - PlanViewer.Ssms/source.extension.vsixmanifest 1.10.0 -> 1.11.0 Also ignore untracked local tools/ helper directory. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 tasks
…s missing (#342) Bootstrap fix for the v1.10.0 -> v1.11.0 release PR (#341). PR #315 (the version-unification refactor that introduced Directory.Build.props) landed on dev AFTER v1.10.0 was tagged, so main has never seen Directory.Build.props — the main-side checkout step fails on Get-Content with "Cannot find path". Test-Path now prefers Directory.Build.props and falls back to the legacy App.csproj location. Becomes dead code after #341 lands on main, but harmless and self-documenting. Co-authored-by: Claude Opus 4.7 (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.
Summary
Cuts the v1.11.0 release. 26 commits since v1.10.0. Merging this PR triggers
release.yml, which tagsv1.11.0, builds all platforms, signs the Windows binary via SignPath (if configured), and publishes the GitHub release + Velopack channel.Highlights
Features
execution_type_desc, with CLI + MCP support (Allow filter by "execution_type_desc" on Query Store screen #321, Expose execution_type_desc filter to CLI and MCP #325)Platform
src/Directory.Build.props(QS Overview review followups, brand sweep, version unification #315)Code health
CI
Test plan
check-version-bumpsees1.11.0(dev) vs1.10.0(main) — passesrelease.ymlcreatesv1.11.0tag and release with auto-generated noteswinupdated with delta from v1.10.0::warning::ifSIGNPATH_API_TOKENis unset)deploy-web.ymlredeploys plans.erikdarling.com without the dropped sync step1.11.0as the base version🤖 Generated with Claude Code