Repository navigation
get_latch_stats moves reading guidance off tools/list (#3898) - #4119
Merged
Merged
Conversation
Darling served 1,027 chars and Lite served 1,372 for this tool; both now serve a 614-char head, with get_tool_guide serving the rest by name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QQh8LczP1HGLXQYAx4oTZC
…eanings follow Microsoft's docs (#3898) The head and the old description said high ACCESS_METHODS_DATASET_PARENT / FGCB_ADD_REMOVE latch waits mean TempDB allocation contention. Per Microsoft's sys.dm_os_latch_stats page, the first synchronizes child dataset access during parallel operations and the second covers filegroup add, drop, grow and shrink file operations. The corrected sentence replaces the old one in the Darling, Lite and Dashboard descriptions, and in the Dashboard's LATCH_EX next-tool hint. The head also names Darling's top and Lite's LATEST IS A TIME snapshot, and says not_collected means a non-SQL Server target. Served head 614 -> 549 on both products. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NUU29PuGg9TUFBsACgZg2K
erikdarlingdata
marked this pull request as ready for review
September 24, 2026 03:41
erikdarlingdata
enabled auto-merge (squash)
September 24, 2026 03:41
9 tasks done
erikdarlingdata
added a commit
that referenced
this pull request
Sep 24, 2026
* Add 48 buffered CHANGELOG entries in one splice Adds 48 entries and 48 link refs (#4057, #4077, #4079, #4081, #4082, #4083, #4084, #4085, #4086, #4087, #4088, #4089, #4090, #4091, #4092, #4093, #4095, #4096, #4099, #4100, #4101, #4103, #4105, #4106, #4107, #4108, #4109, #4110, #4111, #4113, #4114, #4115, #4116, #4117, #4118, #4119, #4120, #4121, #4122, #4123, #4124, #4125, #4126, #4127, #4131, #4133, #4136, #4141). Each PR's entry was buffered, and this lands every entry whose PR was merged on origin/dev when it ran. Entries found under a bare section line (none unless the old script ran again) move into the matching ### section, below the new entries. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QQh8LczP1HGLXQYAx4oTZC * Changelog splice: add #4137's entry, which merged before the splice but was missed #4137 (pg_plan_capture reads csvlog) merged at 05:57Z with a CHANGELOG entry section in its body. It was neither spliced nor listed as needing no entry. Its entry goes under Fixed, right after #4136's, and #4136's last sentence now points to it instead of saying plan capture is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NUU29PuGg9TUFBsACgZg2K --------- Co-authored-by: Claude Opus 5.5 (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.
Refs #3898.
Why
get_latch_statsserved 1,027 characters on Darling and 1,372 on Lite before a client asked its first question.This lane moves the reading guidance off
tools/list, into the per-tool guideget_tool_guideserves on demand.The guidance covers which fields are floors, which zeros are measurements, and which windows are fixed. Nothing is deleted.
What changes
Darling/PerformanceMonitor.Darling.Service/Mcp/DarlingMcpLatchSpinlockTools.cs:get_latch_stats'sDescription(...)now carries a terse head, the<<GUIDE>>marker, then the entire original descriptionverbatim as the tail.
Lite/Mcp/McpLatchSpinlockTools.cs: same split, with Lite's own original text as its tail. The head text isbyte-identical to Darling's (enforced by
McpToolGuideTests.EverySharedToolName_CarriesTheMarkerOnBothSkus_OrNeither_WithByteIdenticalHeads).Darling/Darling.Tests/McpToolGuideHeads.Latch.cs(McpToolGuideHeadsLatchTests) andLite.Tests/McpToolGuideHeads.Latch.cs(same class name,Lite.Testsnamespace).get_latch_statslines inDarling/Darling.Tests/McpToolsListBudget/DarlingMcpLatchSpinlockTools.txtand
Lite.Tests/McpToolsListBudget/McpLatchSpinlockTools.txt.get_spinlock_stats's lines in the same two filesare lane e5's, untouched here.
Darling and Lite genuinely differ in how this tool reads (D6). Darling sums each class's waits over the whole
hours_backwindow and ranks the top classes by that window total. Lite returns only the single newest snapshotfound within
hours_back, paged tolimitclasses, heaviest last-interval wait first. The shared head statesboth facts in one clause instead of picking one product's framing.
Darling-only fields (
severity,severity_banded_from) and Lite-only fields (truncated,captured_at,age_seconds) stay off the shared head. They live only in each product's own tail, the waylist_serversalready does this for its Darling-only fleet fields.
Served characters
Status routes (both products never return
status: "empty"for this tool)rows.Count == 0and the target's engine cannot producesys.dm_os_latch_stats(a non-SQL-Server target)rows.Count == 0and the engine can produce it, but nothing was collected in the requested windowCorrections
One sentence was wrong on all three products, and the lane had copied it into the head as "means TempDB allocation contention".
Microsoft's sys.dm_os_latch_stats page says ACCESS_METHODS_DATASET_PARENT is "Used to synchronize child dataset access to the parent dataset during parallel operations." It says FGCB_ADD_REMOVE is used "to synchronize access to filegroups for add, drop, grow, and shrink file operations." It also says BUFFER "covers all possible uses of page latches", so this DMV has no separate page-latch class. The product's own latch-class text in
install/47_create_reporting_views.sqlsays the same.LATCH_EXis a wait type, not a latch class, and this DMV reports no latch mode.The head no longer makes the claim. The tails now say:
The Dashboard's
LATCH_EXnext-tool hint also dropped its "(ACCESS_METHODS_DATASET_PARENT / FGCB_ADD_REMOVE point at TempDB allocation contention)" note. The dropped-sentence check now reportsmissing=1on each product: the corrected sentence, and nothing else.D4 removals
None. This tool's description carried no issue references and no anecdotes.
Re-pointed pins
None.
git grepforget_latch_statsacrossDarling/Darling.TestsandLite.Testsfound no test asserting aliteral substring of the old head text. Every hit reads the tool body or SQL, which this PR did not touch. The rest
read the whole
Descriptionattribute for a substring that still exists in the preserved tail(
McpLatestSnapshotStampTests,Lite.Tests/McpLatestSnapshotStampTests).The lane's own head-pin files changed in the coordinator pass. They follow the new head. A new test,
LatchClasses_KeepMicrosoftsMeaning_NotATempDbReading, checks that the TempDB reading is gone from the head and the tail on both products.D9 traps
Correct: No. Darling ranks by the SUM of waits across the whole hours_back window, not the latest interval.
Prevents it: "Darling sums waits over the whole hours_back window and returns the top classes by that total"
Correct: No. Lite returns only the single newest snapshot found within hours_back. The window only bounds the search for that snapshot.
Prevents it: "Lite: LATEST IS A TIME, only the newest snapshot within hours_back, paged to limit, heaviest last-interval wait first"
Correct: No. The page is ordered heaviest last-interval wait first, not by the cumulative total.
Prevents it: "Lite: LATEST IS A TIME, only the newest snapshot within hours_back, paged to limit, heaviest last-interval wait first"
hours_backis 20 hours old. Does the tool skip it as stale and return nothing?Correct: No. Lite returns the newest snapshot found within
hours_back, however old it is inside that window. LATEST IS A TIME: the snapshot is the moment it was captured, and the payload'scaptured_atsays when.Prevents it: "Lite: LATEST IS A TIME, only the newest snapshot within hours_back"
Correct: No. severity (Darling only) comes from the LATEST interval, the same single interval the per-second rates come from, never the window sum.
Prevents it: "interval_seconds, both per-second rates and (on Darling) severity come from the LATEST interval only"
Correct: No. The head marks severity "(on Darling)" specifically. Lite's payload has no severity or severity_banded_from field at all.
Prevents it: "(on Darling) severity come from the LATEST interval only"
Correct: No. When the interval is unknowable (a restart or first sample, stored as 0), the rates are null, never a real 0.
Prevents it: "on a restart or first sample (interval unknowable, stored 0) they are null, never 0 or LOW"
Correct: No. severity is also null on that row, never a LOW banded from an unmeasured zero.
Prevents it: "they are null, never 0 or LOW"
Correct: No. This tool never returns status empty. Zero rows is either not_collected or unavailable.
Prevents it: "Zero rows: not_collected on a non-SQL Server target, else unavailable, never empty"
Correct: No. not_collected here means the target's engine cannot produce this data at all, because it is not a SQL Server engine. A supported target with nothing collected yet answers unavailable instead.
Prevents it: "Zero rows: not_collected on a non-SQL Server target, else unavailable, never empty"
Correct: No. Darling's top bounds how many classes the window ranking returns. Lite's limit bounds how many classes the snapshot page returns.
Prevents it: "Darling sums waits over the whole hours_back window and returns the top classes by that total. Lite: LATEST IS A TIME, only the newest snapshot within hours_back, paged to limit"
Correct: Not necessarily. The window total (Darling only) and the per-second rates come from different sources: the whole window versus the latest interval only. A class can be high on one and unremarkable on the other.
Prevents it: "interval_seconds, both per-second rates and (on Darling) severity come from the LATEST interval only"
Test plan
dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Debug- Build succeeded, 0 Warning(s), 0 Error(s).dotnet build Lite.Tests/Lite.Tests.csproj -c Debug- Build succeeded, 0 Warning(s), 0 Error(s).McpPayloadContractCensus*, DarlingMcpLatchSpinlockTools*, McpLatestSnapshotStamp*, McpPageContract*,
DeltaFamilyUnknowableRowRead*): Darling 312 total, 0 failed. Lite 106 total, 0 failed.
McpToolGuideHeadsLatchTestsfail, restored it, reran green.dropcheck.py origin/dev HEAD get_latch_stats: Darlingsentences=6 missing=0, Litesentences=6 missing=0.git merge origin/dev(clean, no conflicts), then full suites once:it is not a failure, so it was not investigated further.
(
AnalysisPassTokenThreadingTests.TheReadLockWaitIsAbandonableWhileAWriterHoldsIt, a lock/threading testunrelated to MCP descriptions). Re-ran alone: passed. Treated as a timing flake, not filed.
(
**Q:**,**Correct:**,**Prevents it:**) and two exact-quoted head phrases in "Prevents it" fields, bothallowed by the brief.
Coordinator verification
origin/dev(90d6af4a) into the branch. No parameter description changed.LatchStatsTopNSqlsumsdelta_wait_time_msover the window and returnsLIMIT topclasses by that total. Rates,interval_secondsandseveritycome from each class's newest row, and a stored interval of 0 becomes NULL. Lite reads the one newest snapshot inside the window, ordered bydelta_wait_time_ms DESC, and pages it tolimit. Both products returnnot_collectedorunavailableon zero rows and neverempty. The latch_stats collector runs on every SQL Server edition, sonot_collectedonly happens on a non-SQL Server target.topor Lite's "LATEST IS A TIME" (lesson 5), and D9 readtopandlimitas the same bound. It now says Darling "returns the top classes by that total" and "Lite: LATEST IS A TIME, only the newest snapshot within hours_back". Trap Q4 asked about the false claim, so I replaced it with a trap on the Lite snapshot.topandlimit"bound the same thing"). Q10 gave the right answer for the wrong reason ("the collector is turned off").Handoff
None.
get_latch_statsis fully converted on both products, green.🤖 Generated with Claude Code
https://claude.ai/code/session_01QQh8LczP1HGLXQYAx4oTZC