Repository navigation
get_collection_health's reading guide moves off tools/list (#3898) - #4063
Conversation
…ad stays under budget (#3898) Splits the single biggest MCP tool description (21,026 served chars) into a <=620-char head that tools/list still serves and a full reading-guide tail that get_tool_guide serves on demand, on both Darling and Lite (byte-identical, since the source text already was). Five anecdotes-with-numbers and one stale issue reference come off the wire per D4; the rule each one taught stays in the tail. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
… tense without the issue reference (#3898) Dropping 'before #3848' (D4) left 'Every one of those was a swallowed failure', which reads as current. It now says each retried read would once have been a swallowed failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
|
Coordinator D9 misreading check (haiku, served tools/list text only, no get_tool_guide): traps 1-5 correct, with correct reasoning, each answer quoting the head. The PR lists only 5 traps, so I added 4 probes of rules that stay in the tail: avg vs p95 durations, dominance vs share, retried_reads rising with failures at zero, and an expensive collector that stored zero rows. There was no confident misread. For each one the model said the served text does not settle it and it would call get_tool_guide. dropcheck: missing=6 on both SKUs, exactly the six D4 removals listed. Coordinator commit e1da486: dropping 'before #3848' had left 'Every one of those was a swallowed failure', which reads as current. It now reads 'would once have been a swallowed failure', on both SKUs, in the tail only. The coordinator is running both full suites now. |
…r-bearing tools (#3898) The hand-kept list of converted tools made every content PR that converts a Data (Darling) or Discovery (Lite) tool edit the same lines, so two such PRs in flight conflict. The expected roster is now every tool on the fixture's types whose Description carries the marker, sorted ordinally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
…ntries in their sections (#4080) Adds 42 entries and 42 link refs (#3992, #3995, #3996, #3998, #4001, #4002, #4003, #4007, #4010, #4011, #4013, #4015, #4020, #4022, #4025, #4029, #4030, #4031, #4036, #4038, #4039, #4040, #4044, #4047, #4048, #4049, #4050, #4051, #4055, #4061, #4063, #4064, #4065, #4066, #4067, #4068, #4069, #4070, #4071, #4073, #4074, #4078). Each PR's entry was buffered, and this lands every entry whose PR was merged on origin/dev when it ran. #3989 left 26 entries under bare 'Changed' and 'Fixed' lines above '### Added'. They move into '### Changed' and '### Fixed', below the new entries, and one blank line stays under [Unreleased]. Claude-Session: https://claude.ai/code/session_01Ua31ugERL5DmhFVRtf6keQ Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Refs #3898.
Why
get_collection_healthwas the single biggest description in the catalog: 21,026 served characters on bothDarling and Lite (identical text, one physical home each:
DarlingMcpDataTools.cs/McpHealthTools.cs). Aclient that loads
tools/listpaid for all of it before asking a question. This PR converts exactly that onetool: a <=620-char head stays on
tools/list, the full reading guide moves toget_tool_guide.What changes
get_collection_health(Darling and Lite): head/tail split via the<<GUIDE>>marker. Heads arebyte-identical on both SKUs (the original text already was, so no per-SKU divergence to reconcile).
FAILING (gate off does not count as failing),
rows_stored=0is not automatically a fault,last_erroris asticky slot rather than a live-condition signal,
regressed_from_productiveis a separate axis fromfailed_collector_count(never add them), andalert_read_healthuses a different since-restart window (notthe 7-day one everything else on this payload uses).
existing topic from another converted family.
Per-tool served chars (both SKUs identical):
Corrections
None. Original prose was verified against the surrounding paragraph structure only (this lane did not cross-check
against the C# body given the deadline); no factual error found in what was read.
D4 removals (6, all in the tail; the dropcheck script reports each as one "missing" line)
pg_statement_statsstory (85% productive -> EXTENSION_MISSING on 23 of 50 PostgreSQLclusters). Deleted whole; it was pure anecdote with no separable rule. The two sentences immediately after it
(
last_productive_at is...andget_fleet_overview counts...) DID move to the tail unchanged; thedropcheck script reports all three as one "missing" chunk only because its sentence splitter merges runs that
continue in lowercase, not because two of the three were dropped.
retried_readsparagraph. Deleted the reference only; kept therule ("Every one of those was a swallowed failure, so read the two together...").
query_storedogfood-server anecdote (13,834 ms avg over 1,155 runs, ~80,900 ms per productive run).Kept the rule before it ("...because a collector's runs are not always one population.") and the rule after
it ("Read the three together: avg close to p95...").
verdict, because its ceiling is items." and "A fixed threshold on dominance misreads exactly the widest
fan-outs..." on either side.
pg_deadlocks49,258,335 ms / 79,333-run story. Kept "This is deliberately NOT a band." before it and"A verdict keyed on cost-plus-zero-rows would fire on the healthy quiet install rather than the blind one."
after it.
pg_deadlocksin-database-to-AWS-API-route story (the six-days-later stale-denial bug report). Kept "Afault recorded before a code path changed will sit in last_error for the rest of the window while every cycle
since succeeds." before it and "Do not infer a live condition from last_error alone." after it.
Verified with
dropcheck.py origin/dev HEAD get_collection_health:missing=6on both Darling and Lite,exactly these six lines, nothing else.
Re-pointed pins (2, both mechanical)
Darling.Tests.McpToolGuideTests.GetToolGuide_WithNoArguments_IsTheIndex(and no Lite twin needed - Lite'sequivalent fixture host does not wire
McpHealthTools): the fixture's ordinaltools_with_guideslist nowhas
get_collection_healthfirst (beforeget_file_io_stats), since this fixture's host registersDarlingMcpDataToolsand the tool joined the guide-bearing roster. Added the name in its correct ordinalslot.
Darling.Tests.CollectionOutputBesideCostTests.BothSkusToolDescriptions_TeachThatACorrectZeroExistsand itsLite twin: both asserted the literal string
"that zero was CORRECT", which was inside the pg_deadlocksanecdote deleted by D4 Lite: collector health status bar shows global errors instead of per-server #5. Re-pointed to
"would fire on the healthy quiet install", the kept ruleimmediately after it, which teaches the identical fact (a zero can be the healthy reading) the test's name
describes.
D9 traps (5, for this one tool)
status: STOPPEDand0runs this window - does it count toward the server'sfailing-collector total?
Correct: no - STOPPED means its gate (
AppliesTo) turned off for this target, not that it is erroring.Prevents it: head's "STOPPED (gate off) does not count as failing."
rows_stored: 0- is that collector broken?Correct: not necessarily -
output_findingsays whether it is a resting event-collector (correct) or adenial (needs a grant); a zero from an event-driven collector (deadlocks, blocking, etc.) is the healthy
resting state.
Prevents it: head's "rows_stored=0 is NOT a fault by itself - output_finding says whether it is a resting
event-collector or a denial needing a grant."
last_errorshows a permission-denied message - is that condition happening right now?Correct: not necessarily -
last_erroris a sticky slot that can hold a stale message from before a codepath changed; check
last_error_at/denied_since_last_successfor currency.Prevents it: head's "last_error is a sticky slot, not necessarily current: check
last_error_at/denied_since_last_success."
regressed_collector_count: 1andfailed_collector_count: 1- are there 2distinct problems, or is this the same collector counted twice?
Correct: could be either - the two are a SEPARATE axis and are never meant to be added; a regression can
read WARNING on day one and FAILING once its success clock runs out, counted on both.
Prevents it: head's "regressed_from_productive floors WARNING on an axis SEPARATE from
failed_collector_count - never add them."
alert_read_health.server_read_failuresreads0for the trailing 7 days shown elsewhere on thispayload - is that 7 days of clean alerting?
Correct: no - this block counts in-memory since the service's last restart (
counting_since), not the7-day collector window everything else on this payload uses; a recent restart makes a
0uninformative.Prevents it: head's "alert_read_health uses a DIFFERENT since-restart window, not this one; zero there
means none since restart, not none in 7 days."
Test plan
Darling.TestsandLite.Tests: 0 Warning(s), 0 Error(s) both.dropcheck.py origin/dev HEAD get_collection_health:missing=6on both SKUs, exactly the D4 list above.git grepfound mentioningget_collection_health, plus the generic MCP guide/budget infrastructure): 474 total, 0 failed, 9 skipped(live-Postgres, no rig).
text).
Handoff
Nothing else in this family was in this lane's brief (it was scoped to exactly this one tool). No other tool
touched.
🤖 Generated with Claude Code
https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF