Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Darling/Darling.Tests/AgentLevel2MuteRuleToolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public sealed class AgentLevel2ToolPolicyTests
private static readonly string[] ActionTools =
{
"create_mute_rule", "update_mute_rule", "delete_mute_rule", "set_mute_rule_enabled",
"create_custom_alert_rule", "update_custom_alert_rule", "delete_custom_alert_rule",
"create_custom_alert_rule", "update_custom_alert_rule", "delete_custom_alert_rule", "set_alert_threshold_override",
};

private static readonly DarlingMcpWritePolicy.Effective AgentArm = new(false, false, Investigations: true);
Expand All @@ -50,7 +50,7 @@ private static List<McpServerTool> AgentServed()
}

[Fact]
public void TheInvestigationsArm_ServesExactlyTheSevenActionTools_OfTheWrites()
public void TheInvestigationsArm_ServesExactlyTheEightActionTools_OfTheWrites()
{
var served = AgentServed().Select(t => t.ProtocolTool.Name).ToList();
var writes = served.Where(DarlingMcpWritePolicy.IsWrite).OrderBy(n => n, StringComparer.Ordinal).ToList();
Expand Down Expand Up @@ -89,15 +89,15 @@ public void TheServedActionTools_HaveNoParameter_ThatWritesAnAlertEnableFlagASel
}

[Fact]
public void TheInstructionsCensus_UnderTheInvestigationsArm_CountsTheSevenAsServed_AndStillSaysTheWritesAreOff()
public void TheInstructionsCensus_UnderTheInvestigationsArm_CountsTheEightAsServed_AndStillSaysTheWritesAreOff()
{
var catalog = DarlingMcpWritePolicy.ToolNames(McpToolsListBudgetTests.BuildServedTools().Tools);
var served = AgentServed().Select(t => t.ProtocolTool.Name).ToList();
var writes = catalog.Count(n => DarlingMcpWritePolicy.IsWrite(n) && !DarlingMcpWritePolicy.IsServerAdmin(n));
var admin = catalog.Count(DarlingMcpWritePolicy.IsServerAdmin);
var text = DarlingMcpInstructions.Build(DarlingPeerDirectory.Snapshot.Empty, catalog, served);
Assert.Contains($"the write tools are off, so the {writes + admin - 7} that change monitoring configuration are not served", text, StringComparison.Ordinal);
Assert.Contains("the 7 mute and custom-rule tools are served only to an agent with an `agent_action` at Level 2", text, StringComparison.Ordinal);
Assert.Contains($"the write tools are off, so the {writes + admin - 8} that change monitoring configuration are not served", text, StringComparison.Ordinal);
Assert.Contains("the 8 mute, custom-rule and threshold override tools are served only to an agent with an `agent_action` at Level 2", text, StringComparison.Ordinal);
}

[Fact]
Expand Down
9 changes: 7 additions & 2 deletions Darling/Darling.Tests/AlertReadFailureSurfaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -975,12 +975,16 @@ resolving it. */
arriving in a new member of this file cannot inherit clean status, because the totals stop
matching the moment its catch block is neither counted nor exempt. */
"LoadMuteRulesAsync",
/* #5916: the threshold-override reload, the mute-rule reload's twin: a control-plane read whose swallowed failure keeps the
overrides already in force, so a changed override waits unseen. COUNTED. */
"LoadThresholdOverridesAsync",
};

/* 12th since #5654: EvaluateExternalAlertsAsync's catch, the external-alert delivery count. */
/* 11th since #4215: ReadRejectedManagedConfSettingNamesAsync's catch — COUNTED,
not exempt, because a RejectedValue row is judgeable evidence for the alert, not context for its text. */
private const int WorkerCountedSites = 12;
/* 13th since #5916: LoadThresholdOverridesAsync's catch, the threshold-override reload. */
private const int WorkerCountedSites = 13;
/* 13th: the deadlock text repair pass's catch in SweepStoreSelfMetricsAsync, exempt like the re-mask pass beside it.
14th: the collection log hourly rollup's catch there (#5810), a maintenance write no alert is judged on.
15th: EvaluateComposeHoursStuckAsync's catch (#5867), the compose builder's failure record read for its self-alert, which
Expand Down Expand Up @@ -1037,8 +1041,9 @@ holds the standing alert on a failed read. */
/// read ("runnable queue top requests"), counted because it IS a store read the alert pass swallowed, though only
/// the card's request items go missing and the fire does not. And a FORTY-FIRST since #5640: the Client Timeouts window read ("client timeouts"), counted because a swallowed read neither fires nor clears the alert. And a FORTY-SECOND since #5654: the external-alert delivery self-alert's count of undelivered rows, counted because a
/// swallowed read leaves the standing alert unjudged (the worker holds it rather than resolving it). And a FORTY-THIRD since #5715 part B: the escalation-tier seed read ("escalation tier seed"), counted because a swallowed read leaves a Warning delivered before a restart unknown to the engine, so the Critical that follows waits out the cooldown instead of escalating; it seeds nothing, never blocks a fire, and is retried on the next sweep.</para>
/// And a FORTY-FOURTH since #5916: the threshold-override reload ("threshold-override reload"), counted because a swallowed read keeps the overrides already in force, so a nonzero count says a changed override has not yet taken effect.
/// </summary>
private const int CountedSites = 43;
private const int CountedSites = 44;

/// <summary>
/// Log-message fragments that identify a catch block DELIBERATELY not counted, each paired with the
Expand Down
6 changes: 3 additions & 3 deletions Darling/Darling.Tests/DarlingMcpAlertToolsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ public void ParamContract_MatchesContract(string toolName, string expectedCsv)
}

[Fact]
public void ParamContract_AlertSettings_TakesNoInputParameters()
public void ParamContract_AlertSettings_TakesOnlyTheOptionalServerName()
{
/* Only the injected NpgsqlDataSource, which is not [Description]-decorated — an empty input schema. */
Assert.Empty(McpParams("get_alert_settings"));
/* The injected NpgsqlDataSource is not [Description]-decorated; the one input is the optional server_name (#5916). */
Assert.Equal(new[] { "server_name" }, McpParams("get_alert_settings").Select(p => p.Name).ToArray());
}

[Fact]
Expand Down
4 changes: 2 additions & 2 deletions Darling/Darling.Tests/DarlingMcpInvestigationToolsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ public void Annotations_ClaimAndSubmit_AreNeitherReadOnlyNorDestructive_TheReads
Assert.False(byName[name].DestructiveHint);
}

/* #5915: the investigations arm serves exactly the seven Level 2 action tools of the writes, each through the gate. The
/* #5915, #5916: the investigations arm serves exactly the eight Level 2 action tools of the writes, each through the gate. The
literal is the behaviour pin: a write added to or dropped from the served set changes this list on purpose. */
var servedWrites = byName.Keys.Where(DarlingMcpWritePolicy.IsWrite).OrderBy(n => n, StringComparer.Ordinal).ToArray();
Assert.Equal(
new[]
{
"create_custom_alert_rule", "create_mute_rule", "delete_custom_alert_rule", "delete_mute_rule",
"set_mute_rule_enabled", "update_custom_alert_rule", "update_mute_rule",
"set_alert_threshold_override", "set_mute_rule_enabled", "update_custom_alert_rule", "update_mute_rule",
},
servedWrites);
/* Every other write stays unserved: alert settings, the finding mute, routes, Custom Views, server tags, server admin. */
Expand Down
2 changes: 1 addition & 1 deletion Darling/Darling.Tests/DarlingWebEndpointsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ mute_analysis_finding. wait_for_investigation_requests (#5822) is a long poll, n
"analyze_server", "assign_server_tag", "backtest_custom_alert_rule", "claim_investigation_request", "create_custom_alert_rule", "create_custom_view", "create_mute_rule", "create_server_tag", "delete_custom_alert_rule",
"delete_custom_view", "delete_mute_rule", "delete_notification_route", "delete_server_tag", "describe_custom_view_catalog", "edit_server", "get_custom_alert_rule", "get_custom_view", "get_tool_guide",
"list_custom_alert_rules", "list_custom_alert_templates", "list_custom_views", "mute_analysis_finding", "remove_server", "run_custom_view_panel",
"set_mute_rule_enabled", "set_notification_route_enabled", "submit_investigation_report", "test_custom_alert_rule", "unassign_server_tag", "update_alert_settings", "update_custom_alert_rule", "update_custom_view", "update_mute_rule", "update_server_tag", "validate_custom_alert_rule", "validate_custom_view",
"set_alert_threshold_override", "set_mute_rule_enabled", "set_notification_route_enabled", "submit_investigation_report", "test_custom_alert_rule", "unassign_server_tag", "update_alert_settings", "update_custom_alert_rule", "update_custom_view", "update_mute_rule", "update_server_tag", "validate_custom_alert_rule", "validate_custom_view",
"wait_for_investigation_requests",
},
DarlingWebEndpoints.ExcludedToolNames.OrderBy(n => n, StringComparer.Ordinal).ToArray());
Expand Down
10 changes: 8 additions & 2 deletions Darling/Darling.Tests/McpPayloadContractCensusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,15 @@ public sealed class McpPayloadContractCensusTests
/// in #3653's vocabulary lane, and the 30 PostgreSQL-side catches that called <c>McpHelpers.Status("error", …)</c>
/// directly — the retired second dialect — went through it under #3653 Q11. Kept as a roster rather than a
/// bare "zero" so a new ad-hoc return fails by name and a deliberate exception has somewhere to state its
/// reason.
/// reason. One exception since #5916: <c>set_alert_threshold_override</c> answers two store faults an operator can act on
/// with a status word rather than an error (<c>precondition</c> when the store role lacks the table grant, and a refusal
/// naming a server removed from the configuration), because a client that reads <c>status</c> must see "do this" and not
/// a failed call.
/// </summary>
public static readonly (string File, string Tool)[] AdHocErrorReturns = [];
public static readonly (string File, string Tool)[] AdHocErrorReturns =
[
("DarlingMcpThresholdOverrideTools.cs", "set_alert_threshold_override"),
];

/// <summary>
/// The floor under the one-helper count. 243 catch returns route through <c>FormatError</c> at the time of
Expand Down
5 changes: 3 additions & 2 deletions Darling/Darling.Tests/McpServiceParameterDiSeatCensusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ AddSingleton<InvestigationBriefComposer> overload (its reader behind it, AddSing
typed-generic AddSingleton<ReadAdmission> overload. InvestigationOpenSignal added by #5822: the long poll waits on
the process's one open signal, registered via the typed-generic AddSingleton<InvestigationOpenSignal> overload. InvestigationReadPolicy added by #5918: get_investigation_reports hides the case a live practice request replays under the investigations arm, so the tool takes the arm as a service parameter, registered via the typed-generic AddSingleton<InvestigationReadPolicy> overload.
DarlingAgentActionSeat added by #5915: the Level 2 mute and custom-rule tools read the served policy through it, registered
via the typed-generic AddSingleton<DarlingAgentActionSeat> overload. */
via the typed-generic AddSingleton<DarlingAgentActionSeat> overload.
DarlingMcpServedPolicy added by #5916: set_alert_threshold_override tells its two arms apart by the served policy, registered via the typed-generic AddSingleton<DarlingMcpServedPolicy> overload. */
Assert.Equal(
new List<string> { "AnalyzerConfig", "DarlingAgentActionSeat", "DarlingAnalysisService", "DarlingMcpAddServersPolicy", "ILogger", "InvestigationBriefComposer", "InvestigationOpenSignal", "InvestigationReadPolicy", "MonitoredServerRegistryState", "NpgsqlDataSource", "PostgresConfig", "ReadAdmission", "ReadLatencyRecorder", "StoreHostProfileCache" },
new List<string> { "AnalyzerConfig", "DarlingAgentActionSeat", "DarlingAnalysisService", "DarlingMcpAddServersPolicy", "DarlingMcpServedPolicy", "ILogger", "InvestigationBriefComposer", "InvestigationOpenSignal", "InvestigationReadPolicy", "MonitoredServerRegistryState", "NpgsqlDataSource", "PostgresConfig", "ReadAdmission", "ReadLatencyRecorder", "StoreHostProfileCache" },
serviceParameterTypeNames);
}

Expand Down
2 changes: 2 additions & 0 deletions Darling/Darling.Tests/ReadAdmissionCoverageCensusTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ public void TheDedicatedWebReadRoutes_Admit()
[WebFile + "GET \"/api/investigation-notes/pending\""] = "definition read: the notes agents proposed that nobody has decided (one small config table, capped at 200 rows; #5903)",
[WebFile + "PUT \"/api/investigation-notes/{id:long}/approve\""] = "write",
[WebFile + "PUT \"/api/investigation-notes/{id:long}/reject\""] = "write",
[WebFile + "GET \"/api/threshold-overrides\""] = "definition read: the threshold overrides, one small config table, plus the registry's names (#5916)",
[WebFile + "PUT \"/api/threshold-overrides\""] = "write",
[WebFile + "POST \"/api/server-tags\""] = "write",
[WebFile + "PATCH \"/api/server-tags/{id:int}\""] = "write",
[WebFile + "DELETE \"/api/server-tags/{id:int}\""] = "write",
Expand Down
Loading
Loading