diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml
index f63b8ecd2..208875356 100644
--- a/.github/workflows/build-and-release.yml
+++ b/.github/workflows/build-and-release.yml
@@ -793,7 +793,7 @@ jobs:
- name: Read the toolchain versions from the metadata
run: |
- # The .NET SDK version. The format is '10.0.114 (commit 0427b9abbe)',
+ # The .NET SDK version. The format is '10.0.403 (commit 5a2162bea6)',
# so we extract the version number alone:
dotnet_sdk_version=$(sed -n '4p' metadata.txt | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
diff --git a/app/AGENTS.md b/app/AGENTS.md
index 70f1159f4..45254675e 100644
--- a/app/AGENTS.md
+++ b/app/AGENTS.md
@@ -28,7 +28,7 @@ Key structure:
## Important Development Notes
- **Naming conventions** - Constants, enum members, and `static readonly` fields use `UPPER_SNAKE_CASE` such as `MY_CONSTANT`.
-- **Extension members** - Declare extension methods in an `extension` block of their static class, one block per receiver, never with a `this` parameter: MWAIS0016 refuses the classic form. The `` of the receiver, and of a generic block its ``, belongs on the block, not on its members. The one exception is a method with a `params` parameter, which stays classic until the SDK in `metadata.txt` carries the fix for dotnet/roslyn#80024: for a member of an extension block, the compiler warns about every argument passed one by one to a `params` parameter (CS8620), see `JsRuntimeExtensions`.
+- **Extension members** - Declare extension methods in an `extension` block of their static class, one block per receiver, never with a `this` parameter: MWAIS0016 refuses the classic form. The `` of the receiver, and of a generic block its ``, belongs on the block, not on its members.
- **Message Bus** - Singleton event bus for cross-component communication inside the .NET app
- **Prompt injection reports** - The user hears once per action about what the filter removed, as soon as that action ends. Content which belongs to an action carries its scope from `PromptInjectionGuardService.BeginAction` down to where it is read or filtered; whatever is filtered without a scope is reported right away. Pass the scope as a parameter, never through a field or an `AsyncLocal`: the service serves the whole app, and the message bus delivers to other receivers in the execution context of whoever sends.
- **Paths in stored data** - A stored path to a file which AI Studio keeps below the data directory, such as a transcript or a tokenizer copy, is relative to that directory, so that a backup or a copy of the data directory works on another computer, under another user name, or on another OS. Mark such a property with `[JsonConverter(typeof(DataDirectoryRelativePathConverter))]`, for a positional record parameter with `[property: ...]`; in memory, the path stays absolute. Better still, derive the path from IDs and store none, as `VisualBriefingStore` does. Paths to files of the user stay absolute. Chats stored before v26.10.1 are migrated by a compatibility shim, see `documentation/compatibility-shims/2026-10-relative-data-paths.md`.
diff --git a/app/MindWork AI Studio/Tools/JsRuntimeExtensions.cs b/app/MindWork AI Studio/Tools/JsRuntimeExtensions.cs
index 118278d19..6715dc0d9 100644
--- a/app/MindWork AI Studio/Tools/JsRuntimeExtensions.cs
+++ b/app/MindWork AI Studio/Tools/JsRuntimeExtensions.cs
@@ -3,16 +3,11 @@ using AIStudio.Tools.Services;
namespace AIStudio.Tools;
-//
-// The methods with a params parameter stay classic extension methods instead of moving into the
-// extension block: for a member of an extension block, the compiler of the .NET 10.0.1xx SDK warns
-// about every argument passed one by one to a params parameter (CS8620, dotnet/roslyn#80024). Move
-// them once the SDK in metadata.txt carries the fix; MWAIS0016 makes the same exception until then.
-//
public static class JsRuntimeExtensions
{
private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(JsRuntimeExtensions));
+ /// The JS runtime to call.
extension(IJSRuntime jsRuntime)
{
public async Task GenerateAndShowDiff(string text1, string text2)
@@ -24,115 +19,115 @@ public static class JsRuntimeExtensions
{
await jsRuntime.InvokeVoidAsync("clearDiv", divId);
}
- }
- ///
- /// Calls a JavaScript function which returns nothing, and tolerates a circuit which is already gone.
- ///
- ///
- /// Blazor cannot issue JS interop calls once the browser connection of a circuit is gone. That happens
- /// during every reload and while a component gets disposed, so the failure is expected rather than
- /// exceptional. Discarding such a call is not an option, though: the discarded task keeps the fault
- /// until the finalizer reports it as an unobserved task exception, without any hint at its origin.
- /// This method is the one place which knows how to await such a call and what to do with its failure.
- ///
- /// The JS runtime to call.
- /// The name of the JavaScript function.
- /// The arguments for the JavaScript function.
- /// True when the browser ran the function. Callers which remember what they told the browser
- /// must check this: a call which never arrived leaves the browser in its previous state.
- public static async ValueTask TryInvokeVoidAsync(this IJSRuntime jsRuntime, string identifier, params object?[]? args)
- {
- try
+ ///
+ /// Calls a JavaScript function which returns nothing, and tolerates a circuit which is already gone.
+ ///
+ ///
+ /// Blazor cannot issue JS interop calls once the browser connection of a circuit is gone. That happens
+ /// during every reload and while a component gets disposed, so the failure is expected rather than
+ /// exceptional. Discarding such a call is not an option, though: the discarded task keeps the fault
+ /// until the finalizer reports it as an unobserved task exception, without any hint at its origin.
+ /// This method is the one place which knows how to await such a call and what to do with its failure.
+ ///
+ /// The name of the JavaScript function.
+ /// The arguments for the JavaScript function.
+ /// True when the browser ran the function. Callers which remember what they told the browser
+ /// must check this: a call which never arrived leaves the browser in its previous state.
+ public async ValueTask TryInvokeVoidAsync(string identifier, params object?[]? args)
{
- await jsRuntime.InvokeVoidAsync(identifier, args);
- return true;
+ try
+ {
+ await jsRuntime.InvokeVoidAsync(identifier, args);
+ return true;
+ }
+ catch (Exception exception)
+ {
+ LogInvocationFailure(exception, identifier);
+ return false;
+ }
}
- catch (Exception exception)
+
+ ///
+ /// Calls a JavaScript function which returns nothing, unless the circuit is known to be disconnected.
+ ///
+ ///
+ /// Prefer this over the variant without a circuit state wherever the caller knows its circuit. While a
+ /// browser connection is gone, every single call would otherwise throw, which is needless work for
+ /// something we already know cannot succeed — a component of a disconnected circuit which keeps
+ /// rendering would produce one such exception per render.
+ ///
+ /// The circuit of the caller.
+ /// The name of the JavaScript function.
+ /// The arguments for the JavaScript function.
+ /// True when the browser ran the function, false when it was skipped or failed.
+ public async ValueTask TryInvokeVoidAsync(CircuitStateService circuitState, string identifier, params object?[]? args)
{
- LogInvocationFailure(exception, identifier);
- return false;
+ if (!circuitState.IsConnected)
+ {
+ LOGGER.LogDebug("The JS call '{Identifier}' was skipped because the browser connection of the circuit '{CircuitId}' is down.", identifier, circuitState.CircuitId);
+ return false;
+ }
+
+ return await jsRuntime.TryInvokeVoidAsync(identifier, args);
+ }
+
+ ///
+ /// Calls a JavaScript function which returns a value, unless the circuit is known to be disconnected.
+ ///
+ ///
+ /// The two parts of the result answer two different questions, and callers must keep them apart.
+ /// Whether the browser ran the function at all comes first: a call which never arrived says nothing
+ /// about the page, so nobody may act on an answer they did not get. What the function returned is the
+ /// second question, and there a null is a legitimate answer -- it means the browser looked and found
+ /// nothing.
+ ///
+ /// The circuit of the caller.
+ /// The name of the JavaScript function.
+ /// The arguments for the JavaScript function.
+ /// Whether the browser ran the function, and what it returned.
+ public async ValueTask<(bool WasInvoked, TValue? Value)> TryInvokeAsync(CircuitStateService circuitState, string identifier, params object?[]? args)
+ {
+ if (!circuitState.IsConnected)
+ {
+ LOGGER.LogDebug("The JS call '{Identifier}' was skipped because the browser connection of the circuit '{CircuitId}' is down.", identifier, circuitState.CircuitId);
+ return (false, default);
+ }
+
+ try
+ {
+ return (true, await jsRuntime.InvokeAsync(identifier, args));
+ }
+ catch (Exception exception)
+ {
+ LogInvocationFailure(exception, identifier);
+ return (false, default);
+ }
}
}
- ///
- /// Calls a JavaScript function which returns nothing, unless the circuit is known to be disconnected.
- ///
- ///
- /// Prefer this over the variant without a circuit state wherever the caller knows its circuit. While a
- /// browser connection is gone, every single call would otherwise throw, which is needless work for
- /// something we already know cannot succeed — a component of a disconnected circuit which keeps
- /// rendering would produce one such exception per render.
- ///
- /// The JS runtime to call.
- /// The circuit of the caller.
- /// The name of the JavaScript function.
- /// The arguments for the JavaScript function.
- /// True when the browser ran the function, false when it was skipped or failed.
- public static async ValueTask TryInvokeVoidAsync(this IJSRuntime jsRuntime, CircuitStateService circuitState, string identifier, params object?[]? args)
- {
- if (!circuitState.IsConnected)
- {
- LOGGER.LogDebug("The JS call '{Identifier}' was skipped because the browser connection of the circuit '{CircuitId}' is down.", identifier, circuitState.CircuitId);
- return false;
- }
-
- return await jsRuntime.TryInvokeVoidAsync(identifier, args);
- }
-
- ///
- /// Calls a JavaScript function which returns a value, unless the circuit is known to be disconnected.
- ///
- ///
- /// The two parts of the result answer two different questions, and callers must keep them apart.
- /// Whether the browser ran the function at all comes first: a call which never arrived says nothing
- /// about the page, so nobody may act on an answer they did not get. What the function returned is the
- /// second question, and there a null is a legitimate answer -- it means the browser looked and found
- /// nothing.
- ///
- /// The JS runtime to call.
- /// The circuit of the caller.
- /// The name of the JavaScript function.
- /// The arguments for the JavaScript function.
- /// Whether the browser ran the function, and what it returned.
- public static async ValueTask<(bool WasInvoked, TValue? Value)> TryInvokeAsync(this IJSRuntime jsRuntime, CircuitStateService circuitState, string identifier, params object?[]? args)
- {
- if (!circuitState.IsConnected)
- {
- LOGGER.LogDebug("The JS call '{Identifier}' was skipped because the browser connection of the circuit '{CircuitId}' is down.", identifier, circuitState.CircuitId);
- return (false, default);
- }
-
- try
- {
- return (true, await jsRuntime.InvokeAsync(identifier, args));
- }
- catch (Exception exception)
- {
- LogInvocationFailure(exception, identifier);
- return (false, default);
- }
- }
-
- ///
- /// Calls a function of a JavaScript module which returns nothing, and tolerates a circuit which is
- /// already gone. See the remarks on the JS runtime variant of this method.
- ///
/// The JavaScript module to call.
- /// The name of the function inside the module.
- /// The arguments for the function.
- /// True when the browser ran the function, false when it failed.
- public static async ValueTask TryInvokeVoidAsync(this IJSObjectReference module, string identifier, params object?[]? args)
+ extension(IJSObjectReference module)
{
- try
+ ///
+ /// Calls a function of a JavaScript module which returns nothing, and tolerates a circuit which is
+ /// already gone. See the remarks on the JS runtime variant of this method.
+ ///
+ /// The name of the function inside the module.
+ /// The arguments for the function.
+ /// True when the browser ran the function, false when it failed.
+ public async ValueTask TryInvokeVoidAsync(string identifier, params object?[]? args)
{
- await module.InvokeVoidAsync(identifier, args);
- return true;
- }
- catch (Exception exception)
- {
- LogInvocationFailure(exception, identifier);
- return false;
+ try
+ {
+ await module.InvokeVoidAsync(identifier, args);
+ return true;
+ }
+ catch (Exception exception)
+ {
+ LogInvocationFailure(exception, identifier);
+ return false;
+ }
}
}
diff --git a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/Mailboxes/MailToolArguments.cs b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/Mailboxes/MailToolArguments.cs
index c5b30acd1..5fc767ee8 100644
--- a/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/Mailboxes/MailToolArguments.cs
+++ b/app/MindWork AI Studio/Tools/ToolCallingSystem/ToolCallingImplementations/Mailboxes/MailToolArguments.cs
@@ -49,32 +49,29 @@ internal static class MailToolArguments
private static readonly string[] SPECIAL_FOLDER_VALUES = [SPECIAL_FOLDER_SENT, SPECIAL_FOLDER_DRAFTS];
- ///
- /// Adds the conditions to the arguments a mail tool describes.
- ///
/// The schema of the tool.
- /// What the tool does with the mails, e.g., "search", completing "the mailboxes to ...".
- /// The ids of the mailboxes the tool offers, or none while no mailboxes are known.
- /// The schema, for further arguments.
- ///
- /// A classic extension method instead of a member of an extension block: for those, the compiler of
- /// the .NET 10.0.1xx SDK warns about every mailbox id passed one by one to the params parameter
- /// (CS8620, dotnet/roslyn#80024). Move it once the SDK in metadata.txt carries the fix; MWAIS0016 makes
- /// the same exception until then.
- ///
- public static ToolParameterSchemaBuilder AddMailConditions(this ToolParameterSchemaBuilder builder, string toolAction, params string[] mailboxIds) => builder
- .OptionalStringArray(MAILBOX_IDS_ARGUMENT, $"Optional IDs of the mailboxes to {toolAction}, out of those listed in the description of this tool. Leave it out to {toolAction} all of them.", mailboxIds)
- .OptionalString(FROM_ARGUMENT, $"Optional part of the address or the name of the sender, such as 'alice@example.org', 'example.org', or 'Alice'. At most {MAX_ADDRESS_CHARACTERS} characters.")
- .OptionalString(TO_ARGUMENT, $"Optional part of the address or the name of a recipient in To, Cc, or Bcc. At most {MAX_ADDRESS_CHARACTERS} characters.")
- .OptionalString(AFTER_ARGUMENT, "Optional: only mails received at this point in time or later. A date such as 2026-09-01 stands for the beginning of that day in the time zone of the user. A date with a time of day such as 2026-09-01T14:30 is read in that time zone as well, unless it ends with an offset such as +02:00 or with Z.")
- .OptionalString(BEFORE_ARGUMENT, "Optional: only mails received before this point in time, in the same forms as the argument after. A date stands for the beginning of that day, so before 2026-09-30 leaves that day out.")
- .OptionalBoolean(IS_UNREAD_ARGUMENT, "Optional: true for unread mails only, false for read ones only.")
- .OptionalBoolean(IS_FLAGGED_ARGUMENT, "Optional: true for flagged mails only, false for unflagged ones only.")
- .OptionalBoolean(IS_ENCRYPTED_ARGUMENT, "Optional: true for encrypted mails only, false for unencrypted ones only. AI Studio cannot read the content of encrypted mails, only their header.")
- .OptionalEnum(IMPORTANCE_ARGUMENT, "Optional importance the sender marked the mails with. Mails without such a mark count as normal.", IMPORTANCE_VALUES)
- .OptionalBoolean(HAS_ATTACHMENTS_ARGUMENT, "Optional: true for mails with attachments only, false for mails without any.")
- .OptionalString(FOLDER_ARGUMENT, $"Optional full path of the folder the mails lie in, exactly as results show it, such as 'INBOX' or 'Archive/2026'. Subfolders are not included. For the sent mails or the drafts, use {SPECIAL_FOLDER_ARGUMENT} instead.")
- .OptionalEnum(SPECIAL_FOLDER_ARGUMENT, $"Optional: only the mails the user sent, or only the drafts of the user, however the server names these folders. Cannot be combined with {FOLDER_ARGUMENT}.", SPECIAL_FOLDER_VALUES);
+ extension(ToolParameterSchemaBuilder builder)
+ {
+ ///
+ /// Adds the conditions to the arguments a mail tool describes.
+ ///
+ /// What the tool does with the mails, e.g., "search", completing "the mailboxes to ...".
+ /// The ids of the mailboxes the tool offers, or none while no mailboxes are known.
+ /// The schema, for further arguments.
+ public ToolParameterSchemaBuilder AddMailConditions(string toolAction, params string[] mailboxIds) => builder
+ .OptionalStringArray(MAILBOX_IDS_ARGUMENT, $"Optional IDs of the mailboxes to {toolAction}, out of those listed in the description of this tool. Leave it out to {toolAction} all of them.", mailboxIds)
+ .OptionalString(FROM_ARGUMENT, $"Optional part of the address or the name of the sender, such as 'alice@example.org', 'example.org', or 'Alice'. At most {MAX_ADDRESS_CHARACTERS} characters.")
+ .OptionalString(TO_ARGUMENT, $"Optional part of the address or the name of a recipient in To, Cc, or Bcc. At most {MAX_ADDRESS_CHARACTERS} characters.")
+ .OptionalString(AFTER_ARGUMENT, "Optional: only mails received at this point in time or later. A date such as 2026-09-01 stands for the beginning of that day in the time zone of the user. A date with a time of day such as 2026-09-01T14:30 is read in that time zone as well, unless it ends with an offset such as +02:00 or with Z.")
+ .OptionalString(BEFORE_ARGUMENT, "Optional: only mails received before this point in time, in the same forms as the argument after. A date stands for the beginning of that day, so before 2026-09-30 leaves that day out.")
+ .OptionalBoolean(IS_UNREAD_ARGUMENT, "Optional: true for unread mails only, false for read ones only.")
+ .OptionalBoolean(IS_FLAGGED_ARGUMENT, "Optional: true for flagged mails only, false for unflagged ones only.")
+ .OptionalBoolean(IS_ENCRYPTED_ARGUMENT, "Optional: true for encrypted mails only, false for unencrypted ones only. AI Studio cannot read the content of encrypted mails, only their header.")
+ .OptionalEnum(IMPORTANCE_ARGUMENT, "Optional importance the sender marked the mails with. Mails without such a mark count as normal.", IMPORTANCE_VALUES)
+ .OptionalBoolean(HAS_ATTACHMENTS_ARGUMENT, "Optional: true for mails with attachments only, false for mails without any.")
+ .OptionalString(FOLDER_ARGUMENT, $"Optional full path of the folder the mails lie in, exactly as results show it, such as 'INBOX' or 'Archive/2026'. Subfolders are not included. For the sent mails or the drafts, use {SPECIAL_FOLDER_ARGUMENT} instead.")
+ .OptionalEnum(SPECIAL_FOLDER_ARGUMENT, $"Optional: only the mails the user sent, or only the drafts of the user, however the server names these folders. Cannot be combined with {FOLDER_ARGUMENT}.", SPECIAL_FOLDER_VALUES);
+ }
///
/// The value of the importance argument which stands for the given importance.
diff --git a/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj b/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj
index 6e8c73ca5..f83e2da89 100644
--- a/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj
+++ b/app/SourceCodeRules/SourceCodeRules/SourceCodeRules.csproj
@@ -20,10 +20,12 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/app/SourceCodeRules/SourceCodeRules/StyleAnalyzers/ClassicExtensionMethodAnalyzer.cs b/app/SourceCodeRules/SourceCodeRules/StyleAnalyzers/ClassicExtensionMethodAnalyzer.cs
index fec369c29..6f83350f4 100644
--- a/app/SourceCodeRules/SourceCodeRules/StyleAnalyzers/ClassicExtensionMethodAnalyzer.cs
+++ b/app/SourceCodeRules/SourceCodeRules/StyleAnalyzers/ClassicExtensionMethodAnalyzer.cs
@@ -13,10 +13,7 @@ namespace SourceCodeRules.StyleAnalyzers;
///
///
/// AI Studio declares its extension members in extension blocks, one per receiver, so that all members of a
-/// receiver read alike and extension properties can join them. A method with a params parameter stays a
-/// classic one for now: for a member of an extension block, the compiler of the .NET 10.0.1xx SDK warns about
-/// every argument passed one by one to a params parameter (CS8620, dotnet/roslyn#80024). Drop that exception
-/// once the SDK in metadata.txt carries the fix.
+/// receiver read alike and extension properties can join them.
///
#pragma warning disable RS1038
[DiagnosticAnalyzer(LanguageNames.CSharp)]
@@ -29,7 +26,7 @@ public sealed class ClassicExtensionMethodAnalyzer : DiagnosticAnalyzer
private const string MESSAGE_FORMAT = "Declare '{0}' as a member of an extension block for its receiver instead of with a this parameter";
- private const string DESCRIPTION = "AI Studio declares its extension members in extension blocks, one per receiver. Only a method with a params parameter stays a classic extension method, until the SDK fixes dotnet/roslyn#80024.";
+ private const string DESCRIPTION = "AI Studio declares its extension members in extension blocks, one per receiver.";
private const string CATEGORY = "Style";
@@ -55,9 +52,6 @@ public sealed class ClassicExtensionMethodAnalyzer : DiagnosticAnalyzer
if (thisKeyword.IsKind(SyntaxKind.None))
return;
- if (parameters.Any(parameter => parameter.Modifiers.Any(SyntaxKind.ParamsKeyword)))
- return;
-
context.ReportDiagnostic(Diagnostic.Create(RULE, thisKeyword.GetLocation(), method.Identifier.Text));
}
}
diff --git a/app/SourceGeneratedMappings/SourceGeneratedMappings.csproj b/app/SourceGeneratedMappings/SourceGeneratedMappings.csproj
index 7d118d296..f83932100 100644
--- a/app/SourceGeneratedMappings/SourceGeneratedMappings.csproj
+++ b/app/SourceGeneratedMappings/SourceGeneratedMappings.csproj
@@ -21,10 +21,13 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/app/Tests/Analyzers/ClassicExtensionMethodAnalyzerTests.cs b/app/Tests/Analyzers/ClassicExtensionMethodAnalyzerTests.cs
index b8205e214..7c5f35e3e 100644
--- a/app/Tests/Analyzers/ClassicExtensionMethodAnalyzerTests.cs
+++ b/app/Tests/Analyzers/ClassicExtensionMethodAnalyzerTests.cs
@@ -11,9 +11,7 @@ namespace AIStudio.Tests.Analyzers;
///
///
/// AI Studio declares all its extension members in extension blocks, one per receiver. MWAIS0016 refuses the
-/// classic form while compiling, except for a method with a params parameter: for a member of an extension
-/// block, the compiler of the .NET 10.0.1xx SDK warns about every argument passed one by one to a params
-/// parameter (CS8620, dotnet/roslyn#80024).
+/// classic form while compiling.
///
[TestFixture]
public sealed class ClassicExtensionMethodAnalyzerTests
@@ -24,6 +22,7 @@ public sealed class ClassicExtensionMethodAnalyzerTests
[TestCase("public static T Echo(this T value) where T : class => value;", "Echo", TestName = "A generic extension method")]
[TestCase("public static void Bump(this ref int value) => value++;", "Bump", TestName = "An extension method with a ref receiver")]
[TestCase("public static System.Threading.Tasks.Task LabelAsync(this Meeting meeting) => System.Threading.Tasks.Task.FromResult(meeting.Name);", "LabelAsync", TestName = "An asynchronous extension method")]
+ [TestCase("public static string Label(this Meeting meeting, params string[] prefixes) => string.Concat(prefixes) + meeting.Name;", "Label", TestName = "An extension method with a params parameter")]
public async Task AClassicExtensionMethodIsRefused(string member, string name)
{
var reported = await AnalyzeAsync(member);
@@ -39,7 +38,6 @@ public sealed class ClassicExtensionMethodAnalyzerTests
[TestCase("extension(Meeting meeting) { public string Label() => meeting.Name; }", TestName = "A member of an extension block")]
[TestCase("extension(T value) where T : class { public T Echo() => value; }", TestName = "A member of a generic extension block")]
[TestCase("public static string Label(Meeting meeting) => meeting.Name;", TestName = "A static method without a this parameter")]
- [TestCase("public static string Label(this Meeting meeting, params string[] prefixes) => string.Concat(prefixes) + meeting.Name;", TestName = "An extension method with a params parameter")]
public async Task AnythingElseIsLeftAlone(string member)
{
var reported = await AnalyzeAsync(member);
diff --git a/app/Tests/Tests.csproj b/app/Tests/Tests.csproj
index ee96038d5..5c1c8d5d7 100644
--- a/app/Tests/Tests.csproj
+++ b/app/Tests/Tests.csproj
@@ -14,7 +14,8 @@
diff --git a/metadata.txt b/metadata.txt
index 0ac90de8f..f7443e537 100644
--- a/metadata.txt
+++ b/metadata.txt
@@ -1,7 +1,7 @@
26.10.1
2026-10-29 07:39:07 UTC
259
-10.0.114 (commit 0427b9abbe)
+10.0.403 (commit 5a2162bea6)
10.0.14 (commit 0427b9abbe)
1.99.1 (commit 58cf8f9c3)
9.12.0