Repository navigation
get_alert_history/set_mute_rule_enabled/create_mute_rule/set_notification_route_enabled move reading guidance off tools/list (#3898) - #4077
Merged
Conversation
…tion_route_enabled move reading guidance off tools/list (#3898) Refs #3898. Converts the remaining alerting-family MCP tool descriptions to the two-tier head/tail shape: tools/list serves a short guardrail head plus a pointer, and get_tool_guide serves the full original prose as the tail. get_alert_history converts on both Darling and Lite with a byte-identical head (D6); the three mute-rule/route write tools are Darling-only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
Refs #3898. Extends McpToolGuideHeads.Alerting.cs on both products with get_alert_history, set_mute_rule_enabled, create_mute_rule and set_notification_route_enabled: the roster used by the shared under-620-chars/pointer check, plus per-tool head and tail assertions following the file's existing pattern. No existing method edited. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M7r1CXmEcBmsrTV34CCLfF
erikdarlingdata
marked this pull request as ready for review
September 23, 2026 21:22
erikdarlingdata
enabled auto-merge (squash)
September 23, 2026 21:22
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
Darling's
tools/listanswer carries long reading guidance inside four alerting-family tool descriptions. Under#3898, that guidance moves offtools/listinto each tool'sget_tool_guidetail. Nothing is deleted. A shorthead stays on the wire with the facts a model needs to pick the right tool. The full original text becomes
available on request, so a model can still read it before it acts on the answer.
What changes
Converts four tools to the two-tier head/tail shape:
get_alert_history: a twin tool, converted on both Darling and Lite with a byte-identical head (D6).set_notification_route_enabled,create_mute_rule,set_mute_rule_enabled: Darling only (Lite has nomute-rule or notification-route write tools).
Each head states what the tool returns or changes, plus the empty, zero and null semantics a caller needs. For
the three write tools, it also states what changes for everyone. It names any confirm step, and what is
reversible or easy to get wrong.
Before/after served characters
get_alert_historyget_alert_historyset_notification_route_enabledcreate_mute_ruleset_mute_rule_enabledget_alert_history'sinclude_dismissedparameter also dropped, per D2 (see below).Corrections
None. The four tools' original prose was checked against their implementations (field names, default values,
branch conditions) and nothing was found to be wrong.
D4 removals (issue references stripped from the wire)
get_alert_history(Darling tail): removed(#3712)(two occurrences) and(#3598)(one occurrence). Thesentences that carried them are unchanged otherwise.
get_alert_history(Lite tail): removed(#3712)(two occurrences).D2: parameter over 200 characters
get_alert_history'sinclude_dismissedparameter was 360 characters on Darling and 357 on Lite. On eachproduct, the guardrail sentence (what the parameter does, and its default) stays on the parameter, at 114
(Darling) and 111 (Lite) characters. The rest of the original sentence moved, verbatim, to that tool's own tail
(
Dismissal is an acknowledgement, not a verdict...), rather than being duplicated.Re-pointed pins
None needed. Every existing test class that mentions one of these four tools was run and passed unchanged. On
Darling that is
DarlingMcpAlertToolsTests,DarlingPgOperationalAlertTests,DarlingSelfAlertTests,DarlingWebEndpointsTests,McpPageContractTests, andNotificationRoutesRungTests. On Lite that isCrossAppMcpToolInventoryPinTests,McpPageContractTests, andToolRecommendationsTests. None of them asserteda specific head or tail substring for these four tools.
NotificationRoutesRungTestsdoes pin substrings, butfor
get_notification_routes, which this PR does not touch.New pins were added instead, in the existing
McpToolGuideHeads.Alerting.cson both products. The four toolnames were added to the file's own
AlertingToolsroster, which the file's existing, uneditedEveryAlertingHead_StaysAtOrUnder620Characters_AndPointsToTheGuidetest already loops over. One new head testand one new tail test were added per tool, plus one shared tail test for
get_alert_history's Lite-only facts.No existing test method was edited.
D9 traps
Each trap below names a question the served head text above, not the tail, must answer correctly.
Q: Does a row in
get_alert_historymean the alert was delivered (emailed or paged)?Correct: No. A row means the alert FIRED.
notification_typeis the separate field that says whether it wasdelivered.
Prevents it: "notification_type says whether it was DELIVERED, a separate question from DISMISSED"
Q:
get_alert_historyreturns fewer rows than thehours_backwindow covers. Does raisinghours_backhelp?Correct: No. The page is bounded by
limit, nothours_back. Raiselimit, or narrowhours_backiftruncatedis true.Prevents it: "THE PAGE IS BOUNDED BY limit, NOT hours_back"
Q: Does an empty
get_alert_historypage always mean no alerts fired in the window?Correct: No. It can also mean every alert in the window was dismissed by the default filter.
Prevents it: "An EMPTY page can mean no alerts fired, or that every alert here was dismissed"
Q: Are dismissed alerts included in
get_alert_historyby default?Correct: No. Dismissed rows are excluded unless
include_dismissed = true.Prevents it: "DISMISSED (UI-acknowledged), excluded by default"
Q: If a row's
send_erroris null, does that prove the alert delivered successfully?Correct: No. A null
send_errorproves nothing about delivery either way.Prevents it: "A null send_error proves nothing about delivery."
Q: Does
set_notification_route_enableddelete the route when disabling it?Correct: No. It disables the route WITHOUT deleting it, and re-enabling restores it exactly.
Prevents it: "Reversible: re-enabling restores it exactly."
Q: Does calling
set_notification_route_enabledtwice with the sameenabledvalue write twice?Correct: No. The second call returns
unchangedand is safe to retry.Prevents it: "unchanged (already that value, safe to retry)"
Q: Can
set_notification_route_enabledre-point a route to a new destination?Correct: No. It can only enable or disable an existing route. Authoring or re-pointing a route happens only
in the Settings window.
Prevents it: "Cannot author or re-point a route; that is Settings-window only."
Q: If
create_mute_ruleis called with no scope or pattern fields at all, what happens?Correct: It creates a rule that mutes EVERY alert across the whole fleet. That is a whole-fleet silence, not
a no-op.
Prevents it: "a rule with NO fields set matches and mutes EVERY alert across the whole fleet"
Q: Does a muted alert stop being logged in
get_alert_history?Correct: No. Matching alerts made by
create_mute_ruleare still logged, just not delivered.Prevents it: "matching alerts are still logged, just not delivered"
Q: Is there a confirmation step before a new mute rule from
create_mute_ruletakes effect?Correct: No. There is no confirm step. It takes effect on the running service's next collection sweep.
Prevents it: "No confirm step: the rule takes effect on the running service's next collection sweep."
Q: Is
delete_mute_rulefollowed bycreate_mute_rulean equally good way to temporarily silence a rule asset_mute_rule_enabled?Correct: No. Delete-then-create loses the rule's id and resets the Stale Mute Rules age clock.
set_mute_rule_enabledkeeps both.Prevents it: "unlike delete+create, which loses those and resets the Stale Mute Rules age clock"
Q: Does disabling a mute rule with
set_mute_rule_enabledclear its scope, reason, or creation date?Correct: No. It keeps the rule's id, scope, reason and creation date. Only the enabled flag changes.
Prevents it: "keeps its id, scope, reason and creation date"
Test plan
Darling/Darling.Tests/Darling.Tests.csprojbuilds with 0 warnings.Lite.Tests/Lite.Tests.csprojbuilds with 0 warnings.McpToolGuide*,McpDescription*,McpZeroIsAMeasurement*,McpPayloadContractCensus*, plus every class that mentions one of the four tools. 498 total, 0 failed, 7skipped (live-Postgres, no rig).
then 6 total. 0 failed in either.
get_alert_history's head (each row FIRED->each row XFIRED). WatchedGetAlertHistoryHead_StatesFiredVsDeliveredVsDismissedAndThePageBoundfail with the expected message.Restored it and confirmed green again.
dropcheck.py) againstorigin/dev, for all four tools.missing=0on everyproduct.
origin/dev(clean, no conflicts) and rebuilt both projects (0 warnings each).(
McpToolsListBudgetTests.EveryServedDescription_AndEveryParameterDescription_MatchesItsCeiling).Re-ran it alone on the same build right after. It passed. This test measures a pure function of the files
on disk, cached once per process in a static field. That measurement does not depend on my wording. This
reads as a pre-existing flake in the full run's test order or parallelism, not a defect in this change.
The lane rule says a failure that passes alone, on a freshly merged base, is not mine to file. This goes to
the coordinator's flake census instead of a new issue.
pr-body-alerting-c.md: 39 hit(s), doc mode. Every real hit wasfixed. The 39 remaining are all
**Q:**/**Correct:**/**Prevents it:**bold lead-ins, the D9 labelformat the brief allows.
Coordinator verification
Handoff
All four assigned tools are converted and green. Nothing was deferred from this lane's list.
The one open item is the Lite full-suite-only flake noted above in the test plan. It is not specific to this
PR's content. The coordinator can fold it into the next flake census if it recurs on other lanes.