diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..1ba4e4d
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,19 @@
+root = true
+
+[*]
+max_line_length = 120
+indent_style = tab
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+file_header_template = Copyright (c) The Geekeey Authors\nSPDX-License-Identifier: EUPL-1.2
+
+[*.md]
+indent_style = space
+trim_trailing_whitespace = false
+
+[*.yml]
+indent_style = space
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a9a1271
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+artifacts/
+node_modules/
+*.DotSettings.user
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..f98619b
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,23 @@
+
+
+ $(MSBuildThisFileDirectory)artifacts
+
+
+
+ enable
+ enable
+
+
+
+ Recommended
+ latest
+ true
+ nullable
+ true
+
+
+
+ moderate
+ all
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..8c119d5
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,2 @@
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..b8e7e93
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,7 @@
+
+
+ true
+
+
+
+
diff --git a/arcade.slnx b/arcade.slnx
new file mode 100644
index 0000000..c9b62ee
--- /dev/null
+++ b/arcade.slnx
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..76286dc
--- /dev/null
+++ b/global.json
@@ -0,0 +1,11 @@
+{
+ "$schema": "https://www.schemastore.org/global.json",
+ "sdk": {
+ "version": "10.0.0",
+ "rollForward": "latestMinor"
+ },
+ "msbuild-sdks": {},
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
+ }
+}
diff --git a/src/sdk/Geekeey.Arcade.NET.Sdk.Test.csproj b/src/sdk/Geekeey.Arcade.NET.Sdk.Test.csproj
new file mode 100644
index 0000000..47b2019
--- /dev/null
+++ b/src/sdk/Geekeey.Arcade.NET.Sdk.Test.csproj
@@ -0,0 +1,17 @@
+
+
+ netstandard2.0
+ true
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/Geekeey.Arcade.NET.Sdk.Web.csproj b/src/sdk/Geekeey.Arcade.NET.Sdk.Web.csproj
new file mode 100644
index 0000000..175dc82
--- /dev/null
+++ b/src/sdk/Geekeey.Arcade.NET.Sdk.Web.csproj
@@ -0,0 +1,17 @@
+
+
+ netstandard2.0
+ true
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/Geekeey.Arcade.NET.Sdk.csproj b/src/sdk/Geekeey.Arcade.NET.Sdk.csproj
new file mode 100644
index 0000000..2f76c29
--- /dev/null
+++ b/src/sdk/Geekeey.Arcade.NET.Sdk.csproj
@@ -0,0 +1,17 @@
+
+
+ netstandard2.0
+ true
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/README.md b/src/sdk/README.md
new file mode 100644
index 0000000..cd9c5ac
--- /dev/null
+++ b/src/sdk/README.md
@@ -0,0 +1 @@
+# Geekeey.Arcade.Sdk
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Geekeey.Arcade.NET.Sdk.Test.editorconfig b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Geekeey.Arcade.NET.Sdk.Test.editorconfig
new file mode 100644
index 0000000..6847850
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Geekeey.Arcade.NET.Sdk.Test.editorconfig
@@ -0,0 +1,3 @@
+# global_level must be higher than the base editorconfig files
+is_global = true
+global_level = 1
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.props b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.props
new file mode 100644
index 0000000..2e198cf
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.props
@@ -0,0 +1,16 @@
+
+
+ true
+
+ $(CustomBeforeDirectoryBuildProps);$(MSBuildThisFileDirectory)../common/Common.props
+ $(BeforeMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)/../common/Common.targets
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.targets b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.targets
new file mode 100644
index 0000000..acc1558
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Test/Sdk.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Geekeey.Arcade.NET.Sdk.Web.editorconfig b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Geekeey.Arcade.NET.Sdk.Web.editorconfig
new file mode 100644
index 0000000..6847850
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Geekeey.Arcade.NET.Sdk.Web.editorconfig
@@ -0,0 +1,3 @@
+# global_level must be higher than the base editorconfig files
+is_global = true
+global_level = 1
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.props b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.props
new file mode 100644
index 0000000..af3d0a9
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.props
@@ -0,0 +1,16 @@
+
+
+ true
+
+ $(CustomBeforeDirectoryBuildProps);$(MSBuildThisFileDirectory)../common/Common.props
+ $(BeforeMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)/../common/Common.targets
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.targets b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.targets
new file mode 100644
index 0000000..8bb4915
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk.Web/Sdk.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Geekeey.Arcade.NET.Sdk.editorconfig b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Geekeey.Arcade.NET.Sdk.editorconfig
new file mode 100644
index 0000000..6847850
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Geekeey.Arcade.NET.Sdk.editorconfig
@@ -0,0 +1,3 @@
+# global_level must be higher than the base editorconfig files
+is_global = true
+global_level = 1
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.props b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.props
new file mode 100644
index 0000000..f42b153
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.props
@@ -0,0 +1,16 @@
+
+
+ true
+
+ $(CustomBeforeDirectoryBuildProps);$(MSBuildThisFileDirectory)../common/Common.props
+ $(BeforeMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)/../common/Common.targets
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.targets b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.targets
new file mode 100644
index 0000000..acc1558
--- /dev/null
+++ b/src/sdk/Sdk/Geekeey.Arcade.NET.Sdk/Sdk.targets
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/sdk/common/Common.props b/src/sdk/common/Common.props
new file mode 100644
index 0000000..8caf818
--- /dev/null
+++ b/src/sdk/common/Common.props
@@ -0,0 +1,78 @@
+
+
+ true
+
+
+
+ true
+
+
+
+ enable
+ enable
+
+
+
+
+ true
+
+
+
+ The Geekeey Team
+ Copyright (c) The Geekeey Team
+ true
+ true
+ snupkg
+
+
+
+ Recommended
+ latest
+ true
+ nullable
+ true
+ true
+
+
+
+
+ false
+
+
+ true
+ low
+ all
+ $(WarningsNotAsErrors);NU1900;NU1901;NU1902;NU1903;NU1904;NU1905
+
+
+
+
+ true
+ true
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
diff --git a/src/sdk/common/Common.targets b/src/sdk/common/Common.targets
new file mode 100644
index 0000000..0222c0d
--- /dev/null
+++ b/src/sdk/common/Common.targets
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.BannedApiAnalyzers.editorconfig b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.BannedApiAnalyzers.editorconfig
new file mode 100644
index 0000000..ad2f3d3
--- /dev/null
+++ b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.BannedApiAnalyzers.editorconfig
@@ -0,0 +1,19 @@
+# global_level must be higher than the NET Analyzer files
+is_global = true
+global_level = 0
+
+dotnet_banned_api_analyzer.exclude_generated_code = true
+
+# RS0030: Do not use banned APIs
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0030.severity = warning
+
+# RS0031: The list of banned symbols contains a duplicate
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0031.severity = warning
+
+# RS0035: External access to internal symbols outside the restricted namespace(s) is prohibited
+# Enabled: True, Severity: error
+dotnet_diagnostic.RS0035.severity = error
diff --git a/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.NetAnalyzers.editorconfig b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.NetAnalyzers.editorconfig
new file mode 100644
index 0000000..942853a
--- /dev/null
+++ b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.NetAnalyzers.editorconfig
@@ -0,0 +1,3 @@
+# global_level must be higher than the NET Analyzer files
+is_global = true
+global_level = 0
diff --git a/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.PublicApiAnalyzers.editorconfig b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.PublicApiAnalyzers.editorconfig
new file mode 100644
index 0000000..1391c5a
--- /dev/null
+++ b/src/sdk/configuration/Analyzer.Microsoft.CodeAnalysis.PublicApiAnalyzers.editorconfig
@@ -0,0 +1,113 @@
+# global_level must be higher than the NET Analyzer files
+is_global = true
+global_level = 0
+
+# Bail out silently for projects that do not have public API files. Projects opt in to
+# public API tracking by adding PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt.
+dotnet_public_api_analyzer.require_api_files = true
+
+# RS0016: Add public types and members to the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0016.severity = warning
+
+# RS0017: Remove deleted types and members from the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0017.severity = warning
+
+# RS0022: Constructor make noninheritable base class inheritable
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0022.severity = warning
+
+# RS0024: The contents of the public API files are invalid
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0024.severity = warning
+
+# RS0025: Do not duplicate symbols in public API files
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0025.severity = warning
+
+# RS0026: Do not add multiple public overloads with optional parameters
+# Help link: https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0026.severity = warning
+
+# RS0027: API with optional parameter(s) should have the most parameters amongst its public overloads
+# Help link: https://github.com/dotnet/roslyn/blob/main/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0027.severity = warning
+
+# RS0036: Annotate nullability of public types and members in the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0036.severity = warning
+
+# RS0037: Enable tracking of nullability of reference types in the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0037.severity = warning
+
+# RS0041: Public members should not use oblivious types
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0041.severity = warning
+
+# RS0048: Missing shipped or unshipped public API file
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0048.severity = warning
+
+# RS0050: API is marked as removed but it exists in source code
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: True, Severity: warning
+dotnet_diagnostic.RS0050.severity = warning
+
+# ---------------------------------------------------------------------------
+# Internal API tracking (InternalAPI.Shipped.txt / InternalAPI.Unshipped.txt)
+# These rules are disabled by default. Projects opt in to internal API tracking
+# by adding the InternalAPI.*.txt files, so the defaults are kept here.
+# ---------------------------------------------------------------------------
+
+# RS0051: Add internal types and members to the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0051.severity = none
+
+# RS0052: Remove deleted types and members from the declared internal API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0052.severity = none
+
+# RS0053: The contents of the internal API files are invalid
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0053.severity = none
+
+# RS0054: Do not duplicate symbols in internal API files
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0054.severity = none
+
+# RS0055: Annotate nullability of internal types and members in the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0055.severity = none
+
+# RS0056: Enable tracking of nullability of reference types in the declared API
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0056.severity = none
+
+# RS0057: Internal members should not use oblivious types
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0057.severity = none
+
+# RS0058: Missing shipped or unshipped internal API file
+# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/PublicApiAnalyzers/PublicApiAnalyzers.Help.md
+# Enabled: False, Severity: warning
+dotnet_diagnostic.RS0058.severity = none
diff --git a/src/sdk/configuration/BannedSymbols.NewtonsoftJson.txt b/src/sdk/configuration/BannedSymbols.NewtonsoftJson.txt
new file mode 100644
index 0000000..2e12391
--- /dev/null
+++ b/src/sdk/configuration/BannedSymbols.NewtonsoftJson.txt
@@ -0,0 +1,9 @@
+N:Newtonsoft
+N:Newtonsoft.Json
+N:Newtonsoft.Json.Bson
+N:Newtonsoft.Json.Converters
+N:Newtonsoft.Json.Linq
+N:Newtonsoft.Json.Linq.JsonPath
+N:Newtonsoft.Json.Schema
+N:Newtonsoft.Json.Serialization
+N:Newtonsoft.Json.Utilities
diff --git a/src/sdk/configuration/BannedSymbols.txt b/src/sdk/configuration/BannedSymbols.txt
new file mode 100644
index 0000000..e85b6b1
--- /dev/null
+++ b/src/sdk/configuration/BannedSymbols.txt
@@ -0,0 +1,50 @@
+T:System.Collections.ArrayList;Use System.Collections.Generic.List instead
+M:System.Reflection.Assembly.GetAssembly(System.Type);Use Type.Assembly instead
+
+P:System.DateTime.Now;Use System.DateTime.UtcNow instead
+P:System.DateTimeOffset.Now;Use System.DateTimeOffset.UtcNow instead
+
+P:System.IO.FileSystemInfo.CreationTime;Use CreationTimeUtc instead
+P:System.IO.FileSystemInfo.LastAccessTime;Use LastAccessTimeUtc instead
+P:System.IO.FileSystemInfo.LastWriteTime;Use LastWriteTimeUtc instead
+
+M:System.IO.File.GetCreationTime(System.String);Use GetCreationTimeUtc instead
+M:System.IO.File.GetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle);Use GetCreationTimeUtc instead
+M:System.IO.File.GetLastAccessTime(System.String);Use GetLastAccessTimeUtc instead
+M:System.IO.File.GetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle);Use GetLastAccessTimeUtc instead
+M:System.IO.File.GetLastWriteTime(System.String);Use GetLastWriteTimeUtc instead
+M:System.IO.File.GetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle);Use GetLastWriteTimeUtc instead
+M:System.IO.File.SetCreationTime(System.String,System.DateTime);Use SetCreationTimeUtc instead
+M:System.IO.File.SetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle,System.DateTime);Use SetCreationTimeUtc instead
+M:System.IO.File.SetLastAccessTime(System.String,System.DateTime);Use SetLastAccessTimeUtc instead
+M:System.IO.File.SetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle,System.DateTime);Use SetLastAccessTimeUtc instead
+M:System.IO.File.SetLastWriteTime(System.String,System.DateTime);Use SetLastWriteTimeUtc instead
+M:System.IO.File.SetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle,System.DateTime);Use SetLastWriteTimeUtc instead
+
+M:System.IO.Directory.GetCreationTime(System.String);Use GetCreationTimeUtc instead
+M:System.IO.Directory.GetLastWriteTime(System.String);Use GetLastWriteTimeUtc instead
+M:System.IO.Directory.GetLastAccessTime(System.String);Use GetLastAccessTimeUtc instead
+M:System.IO.Directory.SetCreationTime(System.String,System.DateTime);Use SetCreationTimeUtc instead
+M:System.IO.Directory.SetLastAccessTime(System.String,System.DateTime);Use SetLastAccessTimeUtc instead
+M:System.IO.Directory.SetLastWriteTime(System.String,System.DateTime);Use SetLastWriteTimeUtc instead
+
+F:System.StringComparison.InvariantCulture;Do you mean Ordinal?
+F:System.StringComparison.InvariantCultureIgnoreCase;Do you mean OrdinalIgnoreCase?
+P:System.StringComparer.InvariantCulture;Do you mean Ordinal?
+P:System.StringComparer.InvariantCultureIgnoreCase;Do you mean OrdinalIgnoreCase?
+
+M:System.Enum.TryParse(System.Type,System.String,System.Object);Use an overload with a ignoreCase argument
+M:System.Enum.TryParse(System.Type,System.ReadOnlySpan{System.Char},System.Object);Use an overload with a ignoreCase argument
+M:System.Enum.TryParse``1(System.String,``0@);Use an overload with a ignoreCase argument
+M:System.Enum.TryParse``1(System.ReadOnlySpan{System.Char},``0@);Use an overload with a ignoreCase argument
+
+M:System.Globalization.CultureInfo.#ctor(System.String);Use CultureInfo.GetCultureInfo
+
+T:System.Tuple`1;Use System.ValueTuple`1
+T:System.Tuple`2;Use System.ValueTuple`2
+T:System.Tuple`3;Use System.ValueTuple`3
+T:System.Tuple`4;Use System.ValueTuple`4
+T:System.Tuple`5;Use System.ValueTuple`5
+T:System.Tuple`6;Use System.ValueTuple`6
+T:System.Tuple`7;Use System.ValueTuple`7
+T:System.Tuple`8;Use System.ValueTuple`8
diff --git a/src/sdk/configuration/Geekeey.Arcade.NET.FileBasedProgram.editorconfig b/src/sdk/configuration/Geekeey.Arcade.NET.FileBasedProgram.editorconfig
new file mode 100644
index 0000000..71193b9
--- /dev/null
+++ b/src/sdk/configuration/Geekeey.Arcade.NET.FileBasedProgram.editorconfig
@@ -0,0 +1,6 @@
+# global_level must be higher than the base editorconfig files
+is_global = true
+global_level = 1
+
+# CA1050: Declare types in namespaces
+dotnet_diagnostic.CA1050.severity = none
diff --git a/src/sdk/configuration/Geekeey.CodingStyle.editorconfig b/src/sdk/configuration/Geekeey.CodingStyle.editorconfig
new file mode 100644
index 0000000..4e33058
--- /dev/null
+++ b/src/sdk/configuration/Geekeey.CodingStyle.editorconfig
@@ -0,0 +1,598 @@
+# global_level must be higher than the NET Analyzer files
+is_global = true
+global_level = 0
+
+# https://learn.microsoft.com/en-us/visualstudio/ide/reference/code-styles-refactoring-options
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+
+# Require file header (IDE0073)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0073
+dotnet_diagnostic.IDE0073.severity = warning
+
+# Remove unnecessary using directives (IDE0005)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005
+dotnet_diagnostic.IDE0005.severity = none
+
+# 'using' directive placement (IDE0065)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0065
+dotnet_diagnostic.IDE0065.severity = warning
+csharp_using_directive_placement = outside_namespace
+
+# Add braces (IDE0011)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0011
+dotnet_diagnostic.IDE0011.severity = warning
+csharp_prefer_braces = true
+
+# Use simple 'using' statement (IDE0063)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0063
+dotnet_diagnostic.IDE0063.severity = warning
+csharp_prefer_simple_using_statement = true
+
+# Namespace declaration preferences (IDE0160 and IDE0161)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0160-ide0161
+dotnet_diagnostic.IDE0160.severity = warning
+dotnet_diagnostic.IDE0161.severity = warning
+csharp_style_namespace_declarations = file_scoped
+
+# Remove unnecessary lambda expression (IDE0200)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0200
+dotnet_diagnostic.IDE0200.severity = warning
+csharp_style_prefer_method_group_conversion = true
+
+# Convert to top-level statements (IDE0210)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0210
+# Convert to 'Program.Main' style program (IDE0211)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0211
+dotnet_diagnostic.IDE0210.severity = none
+dotnet_diagnostic.IDE0211.severity = none
+csharp_style_prefer_top_level_statements = false
+
+# Use primary constructor (IDE0290)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0290
+dotnet_diagnostic.IDE0290.severity = none
+csharp_style_prefer_primary_constructors = false
+
+# Prefer 'System.Threading.Lock' (IDE0330)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0330
+dotnet_diagnostic.IDE0330.severity = warning
+csharp_prefer_system_threading_lock = true
+
+# Use labeled jump statement (IDE0410)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0410
+dotnet_diagnostic.IDE0410.severity = warning
+csharp_style_prefer_labeled_jump_statements = true
+
+# Use expression body for constructors (IDE0021)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0021
+dotnet_diagnostic.IDE0021.severity = warning
+csharp_style_expression_bodied_constructors = true
+
+# Use expression body for methods (IDE0022)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0022
+dotnet_diagnostic.IDE0022.severity = warning
+csharp_style_expression_bodied_methods = true
+
+# Use expression body for operators (IDE0023, IDE0024)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0023-ide0024
+dotnet_diagnostic.IDE0023.severity = warning
+dotnet_diagnostic.IDE0024.severity = warning
+csharp_style_expression_bodied_operators = true
+
+# Use expression body for properties (IDE0025)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0025
+dotnet_diagnostic.IDE0025.severity = warning
+csharp_style_expression_bodied_properties = true
+
+# Use expression body for indexers (IDE0026)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0026
+dotnet_diagnostic.IDE0026.severity = warning
+csharp_style_expression_bodied_indexers = true
+
+# Use expression body for accessors (IDE0027)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0027
+dotnet_diagnostic.IDE0027.severity = warning
+csharp_style_expression_bodied_accessors = true
+
+# Use expression body for lambdas (IDE0053)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0053
+dotnet_diagnostic.IDE0053.severity = warning
+csharp_style_expression_bodied_lambdas = true
+
+# Use expression body for local functions (IDE0061)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0061
+dotnet_diagnostic.IDE0061.severity = warning
+csharp_style_expression_bodied_local_functions = true
+
+# Simplify name (IDE0001)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0001
+dotnet_diagnostic.IDE0001.severity = warning
+
+# Simplify member access (IDE0002)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0002
+dotnet_diagnostic.IDE0002.severity = warning
+
+# Remove unnecessary cast (IDE0004)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0004
+dotnet_diagnostic.IDE0004.severity = warning
+
+# Add missing cases to switch statement (IDE0010)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0010
+dotnet_diagnostic.IDE0010.severity = warning
+
+# Use object initializers (IDE0017)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0017
+dotnet_diagnostic.IDE0017.severity = warning
+dotnet_style_object_initializer = true
+
+# Use collection initializers or expressions (IDE0028)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0028
+# Use collection expression for array (IDE0300)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0300
+# Use collection expression for empty (IDE0301)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0301
+# Use collection expression for stackalloc (IDE0302)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0302
+# Use collection expression for Create() (IDE0303)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0303
+# Use collection expression for builder (IDE0304)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0304
+# Use collection expression for fluent (IDE0305)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0305
+# Use collection expression for new (IDE0306)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0306
+dotnet_diagnostic.IDE0028.severity = warning
+dotnet_diagnostic.IDE0300.severity = warning
+dotnet_diagnostic.IDE0301.severity = warning
+dotnet_diagnostic.IDE0302.severity = warning
+dotnet_diagnostic.IDE0303.severity = warning
+dotnet_diagnostic.IDE0304.severity = warning
+dotnet_diagnostic.IDE0305.severity = warning
+dotnet_diagnostic.IDE0306.severity = warning
+dotnet_style_collection_initializer = true
+dotnet_style_prefer_collection_expression = when_types_loosely_match
+
+# Null check can be simplified (IDE0029, IDE0030, and IDE0270)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0029-ide0030-ide0270
+dotnet_diagnostic.IDE0029.severity = warning
+dotnet_diagnostic.IDE0030.severity = warning
+dotnet_diagnostic.IDE0270.severity = warning
+dotnet_style_coalesce_expression = true
+
+# Use null propagation (IDE0031)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0031
+dotnet_diagnostic.IDE0031.severity = warning
+dotnet_style_null_propagation = true
+
+# Use auto-implemented property (IDE0032)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0032
+dotnet_diagnostic.IDE0032.severity = warning
+dotnet_style_prefer_auto_properties = true
+
+# Use explicitly provided tuple name (IDE0033)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0033
+dotnet_diagnostic.IDE0033.severity = warning
+dotnet_style_explicit_tuple_names = true
+
+# Remove unreachable code (IDE0035)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0035
+dotnet_diagnostic.IDE0035.severity = warning
+
+# Use inferred member names (IDE0037)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0037
+dotnet_diagnostic.IDE0037.severity = warning
+dotnet_style_prefer_inferred_tuple_names = true
+dotnet_style_prefer_inferred_anonymous_type_member_names = true
+
+# Use 'is null' check (IDE0041)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0041
+dotnet_diagnostic.IDE0041.severity = warning
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true
+
+# Use conditional expression for assignment (IDE0045)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0045
+dotnet_diagnostic.IDE0045.severity = warning
+dotnet_style_prefer_conditional_expression_over_assignment = true
+
+# Use conditional expression for return (IDE0046)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0046
+dotnet_diagnostic.IDE0046.severity = warning
+dotnet_style_prefer_conditional_expression_over_return = true
+
+# Convert anonymous type to tuple (IDE0050)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0050
+dotnet_diagnostic.IDE0050.severity = warning
+
+# Remove unused private member (IDE0051)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0051
+dotnet_diagnostic.IDE0051.severity = warning
+
+# Remove unread private member (IDE0052)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0052
+dotnet_diagnostic.IDE0052.severity = warning
+
+# Use compound assignment (IDE0054 and IDE0074)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0054-ide0074
+dotnet_diagnostic.IDE0054.severity = warning
+dotnet_diagnostic.IDE0074.severity = warning
+dotnet_style_prefer_compound_assignment = true
+
+# Remove unnecessary expression value (IDE0058)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0058
+dotnet_diagnostic.IDE0058.severity = warning
+csharp_style_unused_value_expression_statement_preference = discard_variable
+
+# Remove unnecessary value assignment (IDE0059)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0059
+dotnet_diagnostic.IDE0059.severity = warning
+csharp_style_unused_value_assignment_preference = discard_variable
+
+# Use 'System.HashCode.Combine' (IDE0070)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0070
+dotnet_diagnostic.IDE0070.severity = warning
+dotnet_prefer_system_hash_code = true
+
+# Simplify interpolation (IDE0071)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0071
+dotnet_diagnostic.IDE0071.severity = warning
+dotnet_style_prefer_simplified_interpolation = true
+
+# Simplify conditional expression (IDE0075)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0075
+dotnet_diagnostic.IDE0075.severity = warning
+dotnet_style_prefer_simplified_boolean_expressions = true
+
+# Convert typeof to nameof (IDE0082)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0082
+dotnet_diagnostic.IDE0082.severity = warning
+
+# Remove unnecessary equality operator (IDE0100)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0100
+dotnet_diagnostic.IDE0100.severity = warning
+
+# Simplify LINQ expression (IDE0120)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0120
+dotnet_diagnostic.IDE0120.severity = warning
+
+# Simplify LINQ type check and cast (IDE0121)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0121
+dotnet_diagnostic.IDE0121.severity = warning
+
+# Namespace does not match folder structure (IDE0130)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0130
+dotnet_diagnostic.IDE0130.severity = warning
+dotnet_style_namespace_match_folder = false
+
+# Use throw expression (IDE0016)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0016
+dotnet_diagnostic.IDE0016.severity = warning
+csharp_style_throw_expression = true
+
+# Inline variable declaration (IDE0018)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0018
+dotnet_diagnostic.IDE0018.severity = warning
+csharp_style_inlined_variable_declaration = true
+
+# Simplify 'default' expression (IDE0034)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0034
+dotnet_diagnostic.IDE0034.severity = warning
+csharp_prefer_simple_default_expression = true
+
+# Use local function instead of lambda (IDE0039)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0039
+dotnet_diagnostic.IDE0039.severity = warning
+csharp_style_prefer_local_over_anonymous_function = true
+
+# Deconstruct variable declaration (IDE0042)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0042
+dotnet_diagnostic.IDE0042.severity = warning
+csharp_style_deconstructed_variable_declaration = true
+
+# Invalid format string (IDE0043)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0043
+dotnet_diagnostic.IDE0043.severity = warning
+
+# Use index operator (IDE0056)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0056
+dotnet_diagnostic.IDE0056.severity = warning
+csharp_style_prefer_index_operator = true
+
+# Use range operator (IDE0057)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0057
+dotnet_diagnostic.IDE0057.severity = warning
+csharp_style_prefer_range_operator = true
+
+# Add missing cases to switch expression (IDE0072)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0072
+dotnet_diagnostic.IDE0072.severity = warning
+
+# Remove unnecessary suppression operator (IDE0080)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0080
+dotnet_diagnostic.IDE0080.severity = warning
+
+# Simplify new expression (IDE0090)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0090
+dotnet_diagnostic.IDE0090.severity = warning
+csharp_style_implicit_object_creation_when_type_is_apparent = true
+
+# Remove unnecessary discard (IDE0110)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0110
+dotnet_diagnostic.IDE0110.severity = warning
+
+# Prefer 'null' check over type check (IDE0150)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0150
+dotnet_diagnostic.IDE0150.severity = warning
+csharp_style_prefer_null_check_over_type_check = true
+
+# Use tuple to swap values (IDE0180)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0180
+dotnet_diagnostic.IDE0180.severity = warning
+csharp_style_prefer_tuple_swap = true
+
+# Add explicit cast in foreach loop (IDE0220)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0220
+dotnet_diagnostic.IDE0220.severity = warning
+dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
+
+# Add explicit cast (IDE0221)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0221
+dotnet_diagnostic.IDE0221.severity = warning
+dotnet_style_prefer_non_hidden_explicit_cast_in_source = true
+
+# Use UTF-8 string literal (IDE0230)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0230
+dotnet_diagnostic.IDE0230.severity = warning
+csharp_style_prefer_utf8_string_literals = true
+
+# Nullable directive is redundant (IDE0240)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0240
+dotnet_diagnostic.IDE0240.severity = warning
+
+# Nullable directive is unnecessary (IDE0241)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0241
+dotnet_diagnostic.IDE0241.severity = warning
+
+# Use unbound generic type (IDE0340)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0340
+dotnet_diagnostic.IDE0340.severity = warning
+csharp_style_prefer_unbound_generic_type_in_nameof = true
+
+# Use implicitly typed lambda (IDE0350)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0350
+dotnet_diagnostic.IDE0350.severity = warning
+csharp_style_prefer_implicitly_typed_lambda_expression = true
+
+# Simplify property accessor (IDE0360)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0360
+dotnet_diagnostic.IDE0360.severity = warning
+csharp_style_prefer_simple_property_accessors = true
+
+# The name does not exist in the current context (IDE1007)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide1007
+dotnet_diagnostic.IDE1007.severity = warning
+
+# Add readonly modifier (IDE0044)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0044
+dotnet_diagnostic.IDE0044.severity = warning
+dotnet_style_readonly_field = true
+
+# Use language keywords instead of framework type names for type references (IDE0049)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0049
+dotnet_diagnostic.IDE0049.severity = warning
+dotnet_style_predefined_type_for_locals_parameters_members = true
+dotnet_style_predefined_type_for_member_access = true
+
+# Order modifiers (IDE0036)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0036
+dotnet_diagnostic.IDE0036.severity = warning
+csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
+
+# Add accessibility modifiers (IDE0040)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0040
+dotnet_diagnostic.IDE0040.severity = warning
+dotnet_style_require_accessibility_modifiers = for_non_interface_members
+
+# Make local function static (IDE0062)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0062
+dotnet_diagnostic.IDE0062.severity = warning
+csharp_prefer_static_local_function = true
+
+# Make struct fields writable (IDE0064)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0064
+dotnet_diagnostic.IDE0064.severity = warning
+
+# Struct can be made 'readonly' (IDE0250)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0250
+dotnet_diagnostic.IDE0250.severity = warning
+csharp_style_prefer_readonly_struct = true
+
+# Member can be made 'readonly' (IDE0251)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0251
+dotnet_diagnostic.IDE0251.severity = warning
+csharp_style_prefer_readonly_struct_member = true
+
+# Make anonymous function static (IDE0320)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0320
+dotnet_diagnostic.IDE0320.severity = warning
+csharp_prefer_static_anonymous_function = true
+
+# Remove unnecessary unsafe modifier (IDE0380)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0380
+dotnet_diagnostic.IDE0380.severity = warning
+
+# Make method synchronous (IDE0390 and IDE0391)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0390-ide0391
+dotnet_diagnostic.IDE0390.severity = warning
+dotnet_diagnostic.IDE0391.severity = warning
+
+# Avoid multiple blank lines (IDE2000)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2000
+dotnet_diagnostic.IDE2000.severity = warning
+dotnet_style_allow_multiple_blank_lines_experimental = false
+
+# Embedded statements must be on their own line (IDE2001)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2001
+dotnet_diagnostic.IDE2001.severity = warning
+csharp_style_allow_embedded_statements_on_same_line_experimental = false
+
+# Consecutive braces must not have blank line between them (IDE2002)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2002
+dotnet_diagnostic.IDE2002.severity = warning
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
+
+# Blank line required between block and subsequent statement (IDE2003)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2003
+dotnet_diagnostic.IDE2003.severity = warning
+dotnet_style_allow_statement_immediately_after_block_experimental = false
+
+# Blank line not allowed after constructor initializer colon (IDE2004)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2004
+dotnet_diagnostic.IDE2004.severity = warning
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
+
+# Blank line not allowed after conditional expression token (IDE2005)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2005
+dotnet_diagnostic.IDE2005.severity = warning
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
+
+# Blank line not allowed after arrow expression clause token (IDE2006)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide2006
+dotnet_diagnostic.IDE2006.severity = warning
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
+
+# Use conditional delegate call (IDE1005)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide1005
+dotnet_diagnostic.IDE1005.severity = warning
+csharp_style_conditional_delegate_call = true
+
+# Remove unused parameter (IDE0060)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0060
+dotnet_diagnostic.IDE0060.severity = warning
+dotnet_code_quality_unused_parameters = non_public
+
+# Use 'nameof' (IDE0280)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0280
+dotnet_diagnostic.IDE0280.severity = warning
+
+# Parentheses preferences (IDE0047 and IDE0048)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047-ide0048
+dotnet_diagnostic.IDE0047.severity = warning
+dotnet_diagnostic.IDE0048.severity = warning
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary
+
+# Use pattern matching to avoid 'is' check followed by a cast (IDE0020 and IDE0038)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0020-ide0038
+dotnet_diagnostic.IDE0020.severity = warning
+dotnet_diagnostic.IDE0038.severity = warning
+csharp_style_pattern_matching_over_is_with_cast_check = true
+
+# Use switch expression (IDE0066)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0066
+dotnet_diagnostic.IDE0066.severity = warning
+csharp_style_prefer_switch_expression = true
+
+# Use pattern matching to avoid 'as' followed by a 'null' check (IDE0019)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0019
+# Use pattern matching (IDE0078 and IDE0260)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0078-ide0260
+dotnet_diagnostic.IDE0019.severity = warning
+dotnet_diagnostic.IDE0078.severity = warning
+dotnet_diagnostic.IDE0260.severity = warning
+csharp_style_prefer_pattern_matching = true
+csharp_style_pattern_matching_over_as_with_null_check = true
+
+# Use pattern matching (not operator) (IDE0083)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0083
+dotnet_diagnostic.IDE0083.severity = warning
+csharp_style_prefer_not_pattern = true
+
+# Simplify property pattern (IDE0170)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0170
+dotnet_diagnostic.IDE0170.severity = warning
+csharp_style_prefer_extended_property_pattern = true
+
+# Remove unnecessary suppression (IDE0079)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0079
+dotnet_diagnostic.IDE0079.severity = warning
+dotnet_remove_unnecessary_suppression_exclusions = none
+
+# Remove unnecessary suppression (IDE0370)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0370
+dotnet_diagnostic.IDE0370.severity = warning
+
+# Member-access qualification preferences (IDE0003 and IDE0009)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0003-ide0009
+dotnet_diagnostic.IDE0003.severity = warning
+dotnet_diagnostic.IDE0009.severity = warning
+dotnet_style_qualification_for_field = false
+dotnet_style_qualification_for_property = false
+dotnet_style_qualification_for_method = false
+dotnet_style_qualification_for_event = false
+
+# 'var' preferences (IDE0007 and IDE0008)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0007-ide0008
+dotnet_diagnostic.IDE0007.severity = warning
+dotnet_diagnostic.IDE0008.severity = warning
+csharp_style_var_for_built_in_types = true
+csharp_style_var_when_type_is_apparent = true
+csharp_style_var_elsewhere = true
+
+# Formatting rule (IDE0055)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055
+dotnet_diagnostic.IDE0055.severity = warning
+
+## .NET formatting options
+## https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/dotnet-formatting-options
+
+dotnet_sort_system_directives_first = true
+dotnet_separate_import_directive_groups = false
+
+## C# formatting options
+## https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options
+
+### New-line options
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+### Indentation options
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = one_less_than_current
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+
+### Spacing options
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_between_parentheses = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_after_comma = true
+csharp_space_before_comma = false
+csharp_space_after_dot = false
+csharp_space_before_dot = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+
+### Wrap options
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = false
diff --git a/src/sdk/configuration/Geekeey.NamingConvention.editorconfig b/src/sdk/configuration/Geekeey.NamingConvention.editorconfig
new file mode 100644
index 0000000..dfd3d98
--- /dev/null
+++ b/src/sdk/configuration/Geekeey.NamingConvention.editorconfig
@@ -0,0 +1,215 @@
+# global_level must be higher than the NET Analyzer files
+is_global = true
+global_level = 0
+
+# IDE1006 (Naming rule violation)
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide1006
+dotnet_diagnostic.IDE1006.severity = warning
+
+# types and namespaces should be PascalCase
+dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces
+dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
+dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types_and_namespaces.required_modifiers =
+
+# interfaces should be PascalCase with I prefix
+dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion
+dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces
+dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase
+
+dotnet_naming_symbols.interfaces.applicable_kinds = interface
+dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interfaces.required_modifiers =
+
+# enums should be PascalCase
+dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
+dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.enums.applicable_kinds = enum
+dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.enums.required_modifiers =
+
+# type parameters should be PascalCase with T prefix
+dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion
+dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters
+dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase
+
+dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
+dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
+dotnet_naming_symbols.type_parameters.required_modifiers =
+
+# methods should be PascalCase
+dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods
+dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.methods.applicable_kinds = method
+dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.methods.required_modifiers =
+
+# parameters should be camelCase
+dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
+dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
+dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
+
+dotnet_naming_symbols.parameters.applicable_kinds = parameter
+dotnet_naming_symbols.parameters.applicable_accessibilities = *
+dotnet_naming_symbols.parameters.required_modifiers =
+
+# properties should be PascalCase
+dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties
+dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.properties.applicable_kinds = property
+dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.properties.required_modifiers =
+
+# events should be PascalCase
+dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.events_should_be_pascalcase.symbols = events
+dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.events.applicable_kinds = event
+dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.events.required_modifiers =
+
+# local
+
+dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
+dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
+dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
+
+dotnet_naming_symbols.local_variables.applicable_kinds = local
+dotnet_naming_symbols.local_variables.applicable_accessibilities = local
+dotnet_naming_symbols.local_variables.required_modifiers =
+
+
+dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
+dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.local_functions.applicable_kinds = local_function
+dotnet_naming_symbols.local_functions.applicable_accessibilities = *
+dotnet_naming_symbols.local_functions.required_modifiers =
+
+
+dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
+dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
+dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
+
+dotnet_naming_symbols.local_constants.applicable_kinds = local
+dotnet_naming_symbols.local_constants.applicable_accessibilities = local
+dotnet_naming_symbols.local_constants.required_modifiers = const
+
+# private
+
+dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion
+dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields
+dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase
+
+dotnet_naming_symbols.private_fields.applicable_kinds = field
+dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
+dotnet_naming_symbols.private_fields.required_modifiers =
+
+
+dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
+dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
+dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
+
+dotnet_naming_symbols.private_static_fields.applicable_kinds = field
+dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
+dotnet_naming_symbols.private_static_fields.required_modifiers = static
+
+
+dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
+dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
+dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
+dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
+
+
+dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
+dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
+dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
+dotnet_naming_symbols.private_constant_fields.required_modifiers = const
+
+# public
+
+dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
+dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.public_fields.applicable_kinds = field
+dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
+dotnet_naming_symbols.public_fields.required_modifiers =
+
+
+dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
+dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
+dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
+dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
+
+
+dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
+dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
+dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
+dotnet_naming_symbols.public_constant_fields.required_modifiers = const
+
+# others
+
+dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+
+# Naming styles
+
+dotnet_naming_style.pascalcase.required_prefix =
+dotnet_naming_style.pascalcase.required_suffix =
+dotnet_naming_style.pascalcase.word_separator =
+dotnet_naming_style.pascalcase.capitalization = pascal_case
+
+dotnet_naming_style.ipascalcase.required_prefix = I
+dotnet_naming_style.ipascalcase.required_suffix =
+dotnet_naming_style.ipascalcase.word_separator =
+dotnet_naming_style.ipascalcase.capitalization = pascal_case
+
+dotnet_naming_style.tpascalcase.required_prefix = T
+dotnet_naming_style.tpascalcase.required_suffix =
+dotnet_naming_style.tpascalcase.word_separator =
+dotnet_naming_style.tpascalcase.capitalization = pascal_case
+
+dotnet_naming_style._camelcase.required_prefix = _
+dotnet_naming_style._camelcase.required_suffix =
+dotnet_naming_style._camelcase.word_separator =
+dotnet_naming_style._camelcase.capitalization = camel_case
+
+dotnet_naming_style.camelcase.required_prefix =
+dotnet_naming_style.camelcase.required_suffix =
+dotnet_naming_style.camelcase.word_separator =
+dotnet_naming_style.camelcase.capitalization = camel_case
+
+dotnet_naming_style.s_camelcase.required_prefix = s_
+dotnet_naming_style.s_camelcase.required_suffix =
+dotnet_naming_style.s_camelcase.word_separator =
+dotnet_naming_style.s_camelcase.capitalization = camel_case