diff --git a/CHANGELOG.md b/CHANGELOG.md
index 012d8c61..e8a28997 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -132,6 +132,11 @@ is not part of this repository.
about three thousand characters. `--json` is unchanged and still carries both whole lists. A snapshot
edited by hand into a trigger this program never writes - an empty one, or data without its type or
values - still shows the two whole lists for that entry.
+- A trigger of the kind the Windows SDK calls an aggregate trigger is named *Aggregate*, in
+ `bws show`, the window, a snapshot and `--json`. It used to be *Unknown* - `sc qtriggerinfo` names no
+ kind for it either - so a change from it to another kind nobody could name went unseen.
+ `trigger:aggregate` asks for it, and `trigger:unknown` no longer finds it. Compared with a snapshot
+ taken by an earlier version, where it is still *Unknown*, it does not show as a change.
### Fixed
diff --git a/src/Bws.Cli/Resources/cli.en.json b/src/Bws.Cli/Resources/cli.en.json
index 75f7e133..6da3ef62 100644
--- a/src/Bws.Cli/Resources/cli.en.json
+++ b/src/Bws.Cli/Resources/cli.en.json
@@ -310,6 +310,7 @@
"cli.cell.trigger.networkEndpoint": "Network endpoint",
"cli.cell.trigger.custom": "Custom",
"cli.cell.trigger.systemState": "System state",
+ "cli.cell.trigger.aggregate": "Aggregate",
"cli.cell.startDelayed": "{0} (delayed)",
"cli.cell.startDelayedUnknown": "{0} (delay unknown)",
"cli.cell.startTrigger": "{0}, on trigger",
diff --git a/src/Bws.Cli/TriggerWords.cs b/src/Bws.Cli/TriggerWords.cs
index 231cd93b..59a3a516 100644
--- a/src/Bws.Cli/TriggerWords.cs
+++ b/src/Bws.Cli/TriggerWords.cs
@@ -9,7 +9,8 @@ namespace Bws.Cli;
///
/// WRITTEN 2026-09-01 FOR BACKLOG 260, the third and last family with this fault - the
/// argument for all three is in and is not repeated here. Seven of the
-/// nine members read as two or three words jammed together: DeviceArrival,
+/// nine members of that day read as two or three words jammed together (Aggregate, the
+/// tenth, came on 2026-10-28 for backlog 627 and is one word): DeviceArrival,
/// IpAddress, DomainJoin, FirewallPort, GroupPolicy,
/// NetworkEndpoint and CustomSystemStateChange.
///
@@ -110,6 +111,7 @@ private static IEnumerable Items(TriggerDocument trigger) =>
TriggerKind.NetworkEndpoint => Texts.Of("cli.cell.trigger.networkEndpoint"),
TriggerKind.Custom => Texts.Of("cli.cell.trigger.custom"),
TriggerKind.CustomSystemStateChange => Texts.Of("cli.cell.trigger.systemState"),
+ TriggerKind.Aggregate => Texts.Of("cli.cell.trigger.aggregate"),
_ => Texts.Of("cli.cell.unknown")
};
}
diff --git a/src/Bws.Core/ManagerTerms.cs b/src/Bws.Core/ManagerTerms.cs
index 492870b0..4977a535 100644
--- a/src/Bws.Core/ManagerTerms.cs
+++ b/src/Bws.Core/ManagerTerms.cs
@@ -55,10 +55,16 @@ internal static class ManagerTerms
// Value seven, which this interop metadata does not name. Identified from the
// machine rather than from memory: sc qtriggerinfo calls every trigger that landed
// here "CUSTOM SYSTEM STATE CHANGE EVENT", and mapping it took the count of kinds
- // we could not name from 89 to 1 on a machine with 810 entries. The one left is a
- // kind sc.exe cannot name either - it prints the action and no type line at all.
+ // we could not name from 89 to 1 on a machine with 810 entries.
(SERVICE_TRIGGER_TYPE)7 => TriggerKind.CustomSystemStateChange,
+ // Value thirty, the one that was left. sc.exe cannot name it either - it prints the
+ // action and no type line at all - but winsvc.h of the Windows SDK 10.0.28000.0 does,
+ // as SERVICE_TRIGGER_TYPE_AGGREGATE, on the line after SERVICE_TRIGGER_TYPE_CUSTOM.
+ // Measured on 2026-10-28: CDPSvc's one trigger, and after it no kind on that machine
+ // comes back Unknown.
+ (SERVICE_TRIGGER_TYPE)30 => TriggerKind.Aggregate,
+
_ => TriggerKind.Unknown
};
diff --git a/src/Bws.Core/Querying/QueryValueNames.cs b/src/Bws.Core/Querying/QueryValueNames.cs
index e9426f27..7d1b3630 100644
--- a/src/Bws.Core/Querying/QueryValueNames.cs
+++ b/src/Bws.Core/Querying/QueryValueNames.cs
@@ -111,6 +111,7 @@ internal static class QueryValueNames
new QueryValueName("network", "networkendpoint"),
new QueryValueName("custom", "custom"),
new QueryValueName("state", "customsystemstatechange"),
+ new QueryValueName("aggregate", "aggregate"),
new QueryValueName("unknown", "unknown"),
// Not a kind but an action, and worth asking about on its own: a trigger
diff --git a/src/Bws.Core/ServiceTrigger.cs b/src/Bws.Core/ServiceTrigger.cs
index dbf58d60..73c1cefa 100644
--- a/src/Bws.Core/ServiceTrigger.cs
+++ b/src/Bws.Core/ServiceTrigger.cs
@@ -44,7 +44,19 @@ public enum TriggerKind
/// entries. Leaving it as Unknown would have made the second largest group on the
/// machine indistinguishable from anything else we cannot name.
///
- CustomSystemStateChange
+ CustomSystemStateChange,
+
+ ///
+ /// A trigger Windows assembles from others, identified by a subtype - kind thirty.
+ ///
+ /// The interop metadata has no name for this one either, and sc qtriggerinfo prints no kind for
+ /// it at all, but winsvc.h of the Windows SDK does: SERVICE_TRIGGER_TYPE_AGGREGATE. Measured on
+ /// 2026-10-28 it is one trigger on a machine with 252, the one CDPSvc has. Until then it was held
+ /// as Unknown, which made a change from it to some other kind nobody can name invisible to a
+ /// comparison. Named inside schema seven, before that schema was released, so a file older than
+ /// seven is the only one that can still say Unknown for it - see SnapshotDiff.
+ ///
+ Aggregate
}
/// What the trigger does when it fires.
diff --git a/src/Bws.Core/Snapshots/SnapshotDiff.Values.cs b/src/Bws.Core/Snapshots/SnapshotDiff.Values.cs
index a911ff97..bc487c46 100644
--- a/src/Bws.Core/Snapshots/SnapshotDiff.Values.cs
+++ b/src/Bws.Core/Snapshots/SnapshotDiff.Values.cs
@@ -101,12 +101,23 @@ .. triggers.Select(trigger => trigger is null
? null
: new JsonObject
{
- ["kind"] = trigger["kind"]?.DeepClone(),
+ ["kind"] = KindBeforeSeven(trigger["kind"]),
["action"] = trigger["action"]?.DeepClone()
})
]);
}
+ ///
+ /// A kind as a file older than schema seven holds it. Kind thirty was named Aggregate on 2026-10-28
+ /// (backlog 627), inside schema seven and before it was released, and every build until then wrote it
+ /// Unknown - so against an older file the new name would read as a change on a machine where nothing
+ /// changed. Both sides are folded, which costs nothing on the older one: it cannot hold the name.
+ ///
+ private static JsonNode? KindBeforeSeven(JsonNode? kind) =>
+ kind is JsonValue value && value.TryGetValue(out var text) && text == nameof(TriggerKind.Aggregate)
+ ? JsonValue.Create(nameof(TriggerKind.Unknown))
+ : kind?.DeepClone();
+
///
/// The triggers each side holds and the other does not, for the triggers field - null for any other.
///
diff --git a/src/Bws.Gui/Resources/gui.en.json b/src/Bws.Gui/Resources/gui.en.json
index 605121ff..30c4282c 100644
--- a/src/Bws.Gui/Resources/gui.en.json
+++ b/src/Bws.Gui/Resources/gui.en.json
@@ -747,6 +747,7 @@
"gui.cell.trigger.networkEndpoint": "Network endpoint",
"gui.cell.trigger.custom": "Custom",
"gui.cell.trigger.systemState": "System state",
+ "gui.cell.trigger.aggregate": "Aggregate",
"gui.trigger.head": "{0}/{1}",
"gui.trigger.withSubtype": "{0} {1}",
"gui.trigger.withData": "{0} {1}",
diff --git a/src/Bws.Gui/ViewModels/CellFaces.cs b/src/Bws.Gui/ViewModels/CellFaces.cs
index ace524dc..c1505105 100644
--- a/src/Bws.Gui/ViewModels/CellFaces.cs
+++ b/src/Bws.Gui/ViewModels/CellFaces.cs
@@ -463,6 +463,7 @@ public static string TriggerList(Reading> reading)
TriggerKind.NetworkEndpoint => Texts.Of("gui.cell.trigger.networkEndpoint"),
TriggerKind.Custom => Texts.Of("gui.cell.trigger.custom"),
TriggerKind.CustomSystemStateChange => Texts.Of("gui.cell.trigger.systemState"),
+ TriggerKind.Aggregate => Texts.Of("gui.cell.trigger.aggregate"),
_ => Texts.Of("gui.cell.unknown")
};
diff --git a/tests/Bws.Cli.Tests/TriggerWordsTests.cs b/tests/Bws.Cli.Tests/TriggerWordsTests.cs
new file mode 100644
index 00000000..2fecc559
--- /dev/null
+++ b/tests/Bws.Cli.Tests/TriggerWordsTests.cs
@@ -0,0 +1,43 @@
+using Bws.Core;
+
+namespace Bws.Cli.Tests;
+
+///
+/// Every trigger kind the core names has a word of its own in the terminal - its own word, not one it
+/// shares with another kind and not the word for a kind nobody can name.
+///
+/// Written 2026-10-28 for backlog 627, when the core named a tenth kind, Aggregate. The words are a
+/// switch with a fallback, so a kind added to the core and forgotten here prints "Unknown" - the very word
+/// the new name was added to replace - and nothing else would say so. The first version asked only that,
+/// and the review of PR #99 caught what it let through: Aggregate pointed at the word for Custom would have
+/// passed. Now the table below pins each word, and the guard after it asks that no two kinds share one, so
+/// a kind added later and missing from the table is still held. CellFaceTests asks the same of the window.
+///
+public sealed class TriggerWordsTests
+{
+ [Theory]
+ [InlineData(TriggerKind.DeviceArrival, "cli.cell.trigger.deviceArrival")]
+ [InlineData(TriggerKind.IpAddress, "cli.cell.trigger.ipAddress")]
+ [InlineData(TriggerKind.DomainJoin, "cli.cell.trigger.domainJoin")]
+ [InlineData(TriggerKind.FirewallPort, "cli.cell.trigger.firewallPort")]
+ [InlineData(TriggerKind.GroupPolicy, "cli.cell.trigger.groupPolicy")]
+ [InlineData(TriggerKind.NetworkEndpoint, "cli.cell.trigger.networkEndpoint")]
+ [InlineData(TriggerKind.Custom, "cli.cell.trigger.custom")]
+ [InlineData(TriggerKind.CustomSystemStateChange, "cli.cell.trigger.systemState")]
+ [InlineData(TriggerKind.Aggregate, "cli.cell.trigger.aggregate")]
+ [InlineData(TriggerKind.Unknown, "cli.cell.unknown")]
+ public void Each_kind_reads_as_its_word(TriggerKind kind, string key)
+ {
+ Assert.Equal(Texts.Of(key), TriggerWords.Of(kind));
+ }
+
+ [Fact]
+ public void Every_kind_the_core_names_has_a_word_of_its_own()
+ {
+ var named = Enum.GetValues().Where(kind => kind != TriggerKind.Unknown).ToList();
+ var words = named.Select(TriggerWords.Of).ToList();
+
+ Assert.DoesNotContain(Texts.Of("cli.cell.unknown"), words);
+ Assert.Equal(named.Count, words.Distinct(StringComparer.Ordinal).Count());
+ }
+}
diff --git a/tests/Bws.Core.Tests/TriggerChangeTests.cs b/tests/Bws.Core.Tests/TriggerChangeTests.cs
index 1f197bfe..769649b1 100644
--- a/tests/Bws.Core.Tests/TriggerChangeTests.cs
+++ b/tests/Bws.Core.Tests/TriggerChangeTests.cs
@@ -165,6 +165,41 @@ public void Against_an_older_file_a_line_holds_the_kind_and_the_action_alone()
Assert.Equal(new TriggerDocument("CustomSystemStateChange", "Start", null, null), Assert.Single(change.Added));
}
+ ///
+ /// Kind thirty was named Aggregate inside schema seven (backlog 627), and every file older than seven
+ /// holds it as Unknown - so against such a file the name is folded back, and a machine where nothing
+ /// changed shows nothing.
+ ///
+ [Fact]
+ public void Against_an_older_file_an_aggregate_trigger_held_there_as_unknown_is_the_same_trigger()
+ {
+ var before = Tree(Six);
+ Entry(before, "sppsvc")["triggers"]![1]!["kind"] = "Unknown";
+ var after = Tree(Seven);
+ Trigger(after, "sppsvc", 1)["kind"] = "Aggregate";
+
+ Assert.Empty(Diff(before, after).Changed);
+ }
+
+ ///
+ /// The fold is for a file older than seven alone. Two files of schema seven compare the kind as written,
+ /// so a file a build before backlog 627 wrote shows the change once - the price the owner accepted on
+ /// 2026-10-28 for naming it without a schema eight.
+ ///
+ [Fact]
+ public void Between_two_files_of_schema_seven_unknown_and_aggregate_are_two_kinds()
+ {
+ var before = Tree(Seven);
+ Trigger(before, "sppsvc", 1)["kind"] = "Unknown";
+ var after = Tree(Seven);
+ Trigger(after, "sppsvc", 1)["kind"] = "Aggregate";
+
+ var change = Assert.Single(Assert.Single(Diff(before, after).Changed).Differences).Triggers!;
+
+ Assert.Equal("Unknown", Assert.Single(change.Removed).Kind);
+ Assert.Equal("Aggregate", Assert.Single(change.Added).Kind);
+ }
+
/// Only the triggers field carries the lines - every other difference is its two values.
[Fact]
public void Only_the_triggers_field_carries_a_trigger_change()
diff --git a/tests/Bws.Core.Tests/TriggerKindTests.cs b/tests/Bws.Core.Tests/TriggerKindTests.cs
new file mode 100644
index 00000000..4f811096
--- /dev/null
+++ b/tests/Bws.Core.Tests/TriggerKindTests.cs
@@ -0,0 +1,38 @@
+using Windows.Win32.System.Services;
+
+namespace Bws.Core.Tests;
+
+///
+/// The manager's number for a trigger kind, in our words - above all the two numbers the interop
+/// metadata does not name.
+///
+/// Written 2026-10-28 for backlog 627, when kind thirty got the name winsvc.h of the Windows SDK
+/// gives it, SERVICE_TRIGGER_TYPE_AGGREGATE. Until then nothing held the mapping of an unnamed number:
+/// seven was read right on every real machine, and a change sending it back to Unknown would have
+/// passed every test.
+///
+public sealed class TriggerKindTests
+{
+ [Theory]
+ [InlineData(7u, TriggerKind.CustomSystemStateChange)]
+ [InlineData(30u, TriggerKind.Aggregate)]
+ public void A_kind_the_metadata_does_not_name_is_read_by_its_number(uint number, TriggerKind kind)
+ {
+ Assert.Equal(kind, ManagerTerms.Trigger((SERVICE_TRIGGER_TYPE)number));
+ }
+
+ ///
+ /// A number no header names stays Unknown rather than being folded into a neighbour - the numbers
+ /// right beside the named ones as winsvc.h lists them: before one, after seven, after twenty and
+ /// after thirty.
+ ///
+ [Theory]
+ [InlineData(0u)]
+ [InlineData(8u)]
+ [InlineData(21u)]
+ [InlineData(31u)]
+ public void A_number_no_header_names_stays_unknown(uint number)
+ {
+ Assert.Equal(TriggerKind.Unknown, ManagerTerms.Trigger((SERVICE_TRIGGER_TYPE)number));
+ }
+}
diff --git a/tests/Bws.Core.Tests/TriggerQueryTests.cs b/tests/Bws.Core.Tests/TriggerQueryTests.cs
index 15b7ed6b..7c0bff71 100644
--- a/tests/Bws.Core.Tests/TriggerQueryTests.cs
+++ b/tests/Bws.Core.Tests/TriggerQueryTests.cs
@@ -80,6 +80,24 @@ public void A_kind_can_be_asked_for_by_name()
Assert.Contains("sppsvc", Match("trigger:state"));
}
+ ///
+ /// Kind thirty, named on 2026-10-28 (backlog 627) after the name winsvc.h gives it. Until that day it
+ /// answered to trigger:unknown - now it answers to its own word, and no longer to that one.
+ ///
+ [Fact]
+ public void An_aggregate_trigger_is_asked_for_by_its_own_word()
+ {
+ var entry = Specimens.DelayedAutomaticNotRunning with
+ {
+ ServiceName = "CDPSvc",
+ Triggers = Reading>.Present(
+ [new ServiceTrigger(TriggerKind.Aggregate, TriggerAction.Start, new Guid("a086ff1e-d6dc-45f7-b3e4-6cd5c9fdd6d7"), [])])
+ };
+
+ Assert.True(QueryParser.Parse("trigger:aggregate").Query!.Match(entry).Matched);
+ Assert.False(QueryParser.Parse("trigger:unknown").Query!.Match(entry).Matched);
+ }
+
[Fact]
public void The_action_is_askable_next_to_the_kind()
{
diff --git a/tests/Bws.Gui.Tests/CellFaceTests.cs b/tests/Bws.Gui.Tests/CellFaceTests.cs
index 6130ca9c..cb2a56e5 100644
--- a/tests/Bws.Gui.Tests/CellFaceTests.cs
+++ b/tests/Bws.Gui.Tests/CellFaceTests.cs
@@ -72,6 +72,42 @@ public void The_shape_is_never_the_word()
}
}
+ ///
+ /// Each trigger kind reads as its own word in the window. Written 2026-10-28 for backlog 627, when the
+ /// core named Aggregate: the label is a switch with a fallback, so a kind forgotten here reads "Unknown"
+ /// in the column and the panel, and the review of PR #99 caught that a first version asking only that
+ /// would have let Aggregate point at the word for Custom. TriggerWordsTests asks the same of the terminal.
+ ///
+ [Theory]
+ [InlineData(TriggerKind.DeviceArrival, "gui.cell.trigger.deviceArrival")]
+ [InlineData(TriggerKind.IpAddress, "gui.cell.trigger.ipAddress")]
+ [InlineData(TriggerKind.DomainJoin, "gui.cell.trigger.domainJoin")]
+ [InlineData(TriggerKind.FirewallPort, "gui.cell.trigger.firewallPort")]
+ [InlineData(TriggerKind.GroupPolicy, "gui.cell.trigger.groupPolicy")]
+ [InlineData(TriggerKind.NetworkEndpoint, "gui.cell.trigger.networkEndpoint")]
+ [InlineData(TriggerKind.Custom, "gui.cell.trigger.custom")]
+ [InlineData(TriggerKind.CustomSystemStateChange, "gui.cell.trigger.systemState")]
+ [InlineData(TriggerKind.Aggregate, "gui.cell.trigger.aggregate")]
+ [InlineData(TriggerKind.Unknown, "gui.cell.unknown")]
+ public void Each_trigger_kind_reads_as_its_word(TriggerKind kind, string key)
+ {
+ Assert.Equal(Bws.Gui.Texts.Of(key), CellFaces.TriggerKindLabel(kind));
+ }
+
+ ///
+ /// The guard for a kind added to the core later and missing from the table above: none reads as the
+ /// word for an unnamed kind, and no two share a word.
+ ///
+ [Fact]
+ public void Every_trigger_kind_the_core_names_has_a_word_of_its_own()
+ {
+ var named = Enum.GetValues().Where(kind => kind != TriggerKind.Unknown).ToList();
+ var words = named.Select(CellFaces.TriggerKindLabel).ToList();
+
+ Assert.DoesNotContain(Bws.Gui.Texts.Of("gui.cell.unknown"), words);
+ Assert.Equal(named.Count, words.Distinct(StringComparer.Ordinal).Count());
+ }
+
[Fact]
public void The_start_type_carries_what_changes_its_meaning()
{
diff --git a/tests/mutation/entries.ps1 b/tests/mutation/entries.ps1
index fbd39853..2d3bd089 100644
--- a/tests/mutation/entries.ps1
+++ b/tests/mutation/entries.ps1
@@ -15065,6 +15065,70 @@ internal sealed class SizeValue(NumberOperator operation, long low, long high) :
To = 'private const string ItemSeparator = " / ";'
Test = 'TriggerPartsTests.The_items_of_one_trigger_are_joined_by_a_bar'
}
+ @{
+ # Backlog 627: kind thirty is read as Aggregate, the name winsvc.h gives it.
+ Name = 'triggers: kind thirty is read as aggregate'
+ File = 'src\Bws.Core\ManagerTerms.cs'
+ From = '(SERVICE_TRIGGER_TYPE)30 => TriggerKind.Aggregate,'
+ To = '(SERVICE_TRIGGER_TYPE)30 => TriggerKind.Unknown,'
+ Test = 'TriggerKindTests.A_kind_the_metadata_does_not_name_is_read_by_its_number'
+ }
+ @{
+ # Backlog 627: seven had no test of its own until the day thirty got one beside it.
+ Name = 'triggers: kind seven is read as a system state change'
+ File = 'src\Bws.Core\ManagerTerms.cs'
+ From = '(SERVICE_TRIGGER_TYPE)7 => TriggerKind.CustomSystemStateChange,'
+ To = '(SERVICE_TRIGGER_TYPE)7 => TriggerKind.Unknown,'
+ Test = 'TriggerKindTests.A_kind_the_metadata_does_not_name_is_read_by_its_number'
+ }
+ @{
+ # Backlog 627: against a file older than seven, Aggregate is folded back to the Unknown that file holds.
+ Name = 'diff: aggregate is folded to unknown against a file older than seven'
+ File = 'src\Bws.Core\Snapshots\SnapshotDiff.Values.cs'
+ From = '? JsonValue.Create(nameof(TriggerKind.Unknown))'
+ To = '? JsonValue.Create(nameof(TriggerKind.Aggregate))'
+ Test = 'TriggerChangeTests.Against_an_older_file_an_aggregate_trigger_held_there_as_unknown_is_the_same_trigger'
+ }
+ @{
+ # Backlog 627: trigger:aggregate is a word the query language accepts.
+ Name = 'query: trigger accepts aggregate'
+ File = 'src\Bws.Core\Querying\QueryValueNames.cs'
+ From = 'new QueryValueName("aggregate", "aggregate"),'
+ To = ''
+ Test = 'TriggerQueryTests.An_aggregate_trigger_is_asked_for_by_its_own_word'
+ }
+ @{
+ # Backlog 627: the terminal has a word for every kind the core names.
+ Name = 'cli words: aggregate has a word of its own'
+ File = 'src\Bws.Cli\TriggerWords.cs'
+ From = 'TriggerKind.Aggregate => Texts.Of("cli.cell.trigger.aggregate"),'
+ To = ''
+ Test = 'TriggerWordsTests.Every_kind_the_core_names_has_a_word_of_its_own'
+ }
+ @{
+ # Backlog 627: the window has a word for every kind the core names.
+ Name = 'cell faces: aggregate has a word of its own'
+ File = 'src\Bws.Gui\ViewModels\CellFaces.cs'
+ From = 'TriggerKind.Aggregate => Texts.Of("gui.cell.trigger.aggregate"),'
+ To = ''
+ Test = 'CellFaceTests.Every_trigger_kind_the_core_names_has_a_word_of_its_own'
+ }
+ @{
+ # Review of PR #99: a kind pointed at another kind's word is caught, not only a kind with no word.
+ Name = "cli words: aggregate does not borrow custom's word"
+ File = 'src\Bws.Cli\TriggerWords.cs'
+ From = 'TriggerKind.Aggregate => Texts.Of("cli.cell.trigger.aggregate"),'
+ To = 'TriggerKind.Aggregate => Texts.Of("cli.cell.trigger.custom"),'
+ Test = 'TriggerWordsTests.Every_kind_the_core_names_has_a_word_of_its_own'
+ }
+ @{
+ # Review of PR #99: the same in the window.
+ Name = "cell faces: aggregate does not borrow custom's word"
+ File = 'src\Bws.Gui\ViewModels\CellFaces.cs'
+ From = 'TriggerKind.Aggregate => Texts.Of("gui.cell.trigger.aggregate"),'
+ To = 'TriggerKind.Aggregate => Texts.Of("gui.cell.trigger.custom"),'
+ Test = 'CellFaceTests.Every_trigger_kind_the_core_names_has_a_word_of_its_own'
+ }
)
$mutations