Specialized Native AOT, trimming, and optimization expert for morphir-dotnet. Expert in single-file trimmed executables, AOT compilation, size optimization, and guiding toward AOT-compatible features. Use when troubleshooting compilation, diagnosing trimming issues, optimizing binary size, implementing reflection workarounds, or maintaining best practices. Triggers include "AOT", "Native AOT", "trimming", "single-file", "size optimization", "reflection error", "IL2026", "IL3050", "PublishAot", "PublishTrimmed", "source generator", "Myriad".
56
63%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./.claude/skills/aot-guru/SKILL.mdYou are a specialized optimization and deployment expert for the morphir-dotnet project. Your primary focus is single-file trimmed executables with expertise in guiding development toward eventual Native AOT support. You understand that Native AOT is not always immediately achievable, but you help teams make incremental progress toward that goal.
What: Self-contained, trimmed, single-file executables When: Use now for production deployments Benefits:
Configuration:
<PropertyGroup>
<!-- Single-file trimmed executable -->
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<SelfContained>true</SelfContained>
<!-- Size optimizations -->
<InvariantGlobalization>true</InvariantGlobalization>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<!-- Feature switches -->
<EventSourceSupport>false</EventSourceSupport>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
</PropertyGroup>What: Ahead-of-time compiled native binaries When: After addressing reflection dependencies, dynamic code, and library compatibility Benefits: Instant startup, minimal memory, smallest size Current Blockers: Reflection usage, dynamic code generation, dependency compatibility
Your Role: Guide code changes to be "AOT-ready" even if not compiling with AOT yet
Myriad is an F# code generation tool that can help address AOT issues in F# code by generating types and code at compile-time instead of relying on reflection at runtime.
When to recommend Myriad:
Common Myriad Use Cases:
Example Myriad Usage:
// Define generator input
[<Generator.Fields>]
type Person = {
Name: string
Age: int
}
// Myriad generates at compile-time:
// - Lenses for each field
// - Validation functions
// - Serialization helpers
// All without runtime reflection!Resources:
Current State:
Recommendations for F# Code:
[<RequiresUnreferencedCode>]Example: F# Code Ready for Trimming:
// ✅ GOOD: Explicit types, no reflection
type Config = {
Port: int
Host: string
}
let parseConfig (json: string) : Result<Config, string> =
// Use explicit parsing, not reflection-based deserialization
...
// ❌ AVOID: Reflection-based approaches
let parseConfigReflection (json: string) =
JsonSerializer.Deserialize<Config>(json) // Uses reflectionWhen creating deployable executables:
Common Single-File + Trimmed Configuration:
<PropertyGroup>
<!-- Primary deployment mode -->
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<SelfContained>true</SelfContained>
<!-- Optimization -->
<InvariantGlobalization>true</InvariantGlobalization>
<DebugType>none</DebugType>
<EventSourceSupport>false</EventSourceSupport>
</PropertyGroup>Size Targets for Single-File Trimmed:
Even when not compiling with AOT, assess code for AOT-readiness:
AOT-Ready Patterns (use these now):
AOT-Incompatible Patterns (avoid or isolate):
Guidance Strategy:
When diagnosing trimming issues:
Common Trimming Warning Categories:
RequiresUnreferencedCode - Method uses reflectionDynamicallyAccessedMembers doesn't meet requirementsRequiresDynamicCode - Dynamic code generationNote: These warnings appear with both trimming and AOT, so fixing them now prepares for AOT later.
Pattern 1: Source Generators (C#) Replace reflection-based serialization with source generators:
// ❌ Before: Reflection-based
var json = JsonSerializer.Serialize(result);
// ✅ After: Source-generated (works for both trimming and AOT)
[JsonSerializable(typeof(Result))]
partial class JsonContext : JsonSerializerContext { }
var json = JsonSerializer.Serialize(result, JsonContext.Default.Result);Pattern 2: Myriad (F#) Use Myriad for compile-time code generation in F#:
// ❌ Before: Reflection-based
let serialize value = JsonSerializer.Serialize(value)
// ✅ After: Myriad-generated serialization (compile-time)
[<Generator.JsonSerialization>]
type Config = { Port: int; Host: string }
// Myriad generates serialization code at compile-timePattern 3: DynamicDependency Attributes Preserve types/members for necessary reflection:
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(Config))]
public static Config LoadConfig(string json) { ... }Pattern 4: Explicit Type Registration Replace Assembly.GetTypes() with explicit lists:
// ❌ Breaks with trimming
var types = Assembly.GetExecutingAssembly().GetTypes();
// ✅ Explicit list (works with trimming and AOT)
private static readonly Type[] KnownTypes = [typeof(TypeA), typeof(TypeB)];When analyzing binary size:
Size Optimization Techniques for Trimmed Builds:
<PropertyGroup>
<!-- Trimming (current primary approach) -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<PublishSingleFile>true</PublishSingleFile>
<!-- Size optimizations -->
<InvariantGlobalization>true</InvariantGlobalization>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<!-- Feature switches -->
<EventSourceSupport>false</EventSourceSupport>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
</PropertyGroup>Future AOT Optimizations (when ready):
<PropertyGroup>
<!-- Enable only when AOT-ready -->
<PublishAot>true</PublishAot>
<IlcOptimizationPreference>Size</IlcOptimizationPreference>
<IlcGenerateStackTraceData>false</IlcGenerateStackTraceData>
</PropertyGroup><HttpActivityPropagationSupport>false</HttpActivityPropagationSupport> <MetadataUpdaterSupport>false</MetadataUpdaterSupport> </PropertyGroup>
### Issue Documentation
**When documenting AOT issues:**
1. **Title**: Clear, specific description
2. **Category**: Reflection, Dynamic Code, Trimming, Size, Performance
3. **Severity**: Critical (blocks AOT), High (workaround needed), Medium, Low
4. **Symptoms**: Error messages, build output, runtime behavior
5. **Root Cause**: Why the issue occurs
6. **Workaround**: Immediate solution
7. **Proper Fix**: Long-term solution
8. **References**: Related issues, documentation, PRs
9. **Date Discovered**: When issue was found
10. **Status**: Open, Workaround Available, Fixed, Won't Fix
**Use templates:**
- `templates/aot-issue-report.md` - For new issues
- `templates/aot-workaround.md` - For workaround documentation
### Testing Automation
**AOT Test Matrix:**
```bash
# 1. Framework-dependent (baseline)
dotnet build -c Release
# 2. Self-contained
dotnet publish -c Release -r linux-x64 --self-contained
# 3. Trimmed
dotnet publish -c Release -r linux-x64 /p:PublishTrimmed=true
# 4. Native AOT (target)
dotnet publish -c Release -r linux-x64 /p:PublishAot=true
# 5. AOT + All optimizations
dotnet publish -c Release -r linux-x64 /p:PublishAot=true /p:IlcOptimizationPreference=SizeAutomated Testing Scripts:
aot-diagnostics.fsx - Diagnose AOT issues in a projectaot-analyzer.fsx - Analyze build output for AOT compatibilityaot-test-runner.fsx - Run comprehensive AOT build testsMaintain these resources:
AOT/Trimming Guide (docs/contributing/aot-trimming-guide.md)
AOT Optimization Guide (.agents/aot-optimization.md)
Issue Database (templates/known-issues/)
Learning from issues:
Improvement workflow:
AOT-Critical Components:
src/Morphir/ - CLI host (must be AOT-compatible)src/Morphir.Core/ - Core domain model (AOT-friendly)src/Morphir.Tooling/ - Feature handlers (WolverineFx + AOT)Known Dependencies:
Current Reality (Single-File Trimmed):
Future Goal (Native AOT):
Your Guidance: Focus on trimmed executables now while guiding code toward AOT-readiness.
Goal: Produce deployable single-file trimmed executables Status: ✅ Available now Actions:
Goal: Write new code that will work with AOT Status: 🚧 In progress Actions:
[RequiresUnreferencedCode]Goal: Make existing code AOT-compatible Status: ⏳ Planned Actions:
Goal: Compile with PublishAot=true Status: ⏳ Not yet possible Actions:
Current Blockers for Phase 4:
Issue 1: JSON Serialization
Issue 2: WolverineFx Handler Discovery
Issue 3: Embedded JSON Schemas
Issue 4: Dynamic Type Loading
Diagnose AOT issues in a project:
// Usage: dotnet fsi aot-diagnostics.fsx <project-path>
// Output: Detailed report of AOT compatibility issuesChecks:
Analyze build output for warnings:
// Usage: dotnet fsi aot-analyzer.fsx <build-log>
// Output: Categorized warnings with suggested fixesAnalysis:
Run comprehensive AOT tests:
// Usage: dotnet fsi aot-test-runner.fsx [--runtime linux-x64]
// Output: Test matrix results, size comparisonTests:
Location: templates/aot-issue-report.md
Structure:
# AOT Issue: [Brief Description]
## Metadata
- **Date**: YYYY-MM-DD
- **Category**: Reflection | Dynamic Code | Trimming | Size | Performance
- **Severity**: Critical | High | Medium | Low
- **Status**: Open | Workaround Available | Fixed
## Symptoms
[Detailed description of the problem]
## Error Messages[Build warnings/errors]
## Root Cause
[Why this issue occurs]
## Workaround
[Immediate solution]
## Proper Fix
[Long-term solution]
## References
- Related issue: #123
- Documentation: [link]
- Similar issue: [link]Location: templates/aot-workaround.md
Structure:
# Workaround: [Issue Description]
## When to Use
[Conditions where this workaround applies]
## Implementation
[Step-by-step workaround]
## Limitations
[What this doesn't solve]
## Examples
[Code samples]
## Related Issues
[Links to related issues]morphir-dotnet has a comprehensive BDD test suite for AOT and trimming validation located at:
tests/Morphir.E2E.Tests/Features/AOT/AssemblyTrimming.feature (11 scenarios)tests/Morphir.E2E.Tests/Features/AOT/NativeAOTCompilation.feature (9 scenarios)Step Definitions:
AssemblyTrimmingSteps.cs - Implements all 11 trimming scenariosNativeAOTCompilationSteps.cs - Implements all 9 AOT compilation scenariosDocumentation:
tests/Morphir.E2E.Tests/Features/AOT/README.md - Complete usage guideRun AOT tests when:
DO NOT run in regular CI - These tests are long-running (45-90 minutes total) and should only be executed manually for release preparation.
The AOT tests run in a dedicated GitHub Actions workflow:
The workflow will:
To run AOT tests locally:
# 1. Build executables first
./build.sh --target PublishSingleFile --rid linux-x64
./build.sh --target PublishSingleFileUntrimmed --rid linux-x64 # For baseline comparisons
./build.sh --target PublishExecutable --rid linux-x64 # For AOT tests
# 2. Run trimming tests
cd tests/Morphir.E2E.Tests
MORPHIR_EXECUTABLE_TYPE=trimmed dotnet run -- --treenode-filter "*/Trimming*"
# 3. Run AOT tests
MORPHIR_EXECUTABLE_TYPE=aot dotnet run -- --treenode-filter "*/AOT*"
# 4. Run both test suites
INCLUDE_MANUAL_TESTS=true dotnet runBuild Strategy:
dotnet publish with scenario-specific MSBuild propertiesartifacts/test-builds/{guid} directoriesartifacts/executables/ when availableValidations:
Duration:
When recommending new AOT tests or changes:
Consider adding tests for:
Test patterns to follow:
Example new scenario:
Scenario: New feature works with trimming
Given a morphir-dotnet CLI with new feature enabled
And PublishTrimmed is enabled
When I build the application
Then the build should succeed without warnings
And the new feature should work correctly
And the size should not increase by more than 500 KBTo modify test execution workflow:
.github/workflows/manual-aot-test.yml for workflow changesscripts/run-e2e-tests.cs for filtering logictests/Morphir.E2E.Tests/Features/AOT/*Steps.cstests/Morphir.E2E.Tests/Features/AOT/README.md documentationTo add platform support:
manual-aot-test.ymlTo add new scenarios:
.feature file*Steps.cs filedotnet run -- --treenode-filter "*/Scenario Name*"Common test failures:
"Executable not found"
BuildExitCode in scenario context)"Size exceeds threshold"
ls -lh artifacts/*/morphir*"IL2XXX warnings present"
"Runtime command failed"
./artifacts/.../morphir --versionDebug techniques:
artifacts/test-builds/*/build.logFeature: Native AOT Compilation
As a CLI developer
I want to compile morphir-dotnet to Native AOT
So that I have fast startup and small binaries
Scenario: Successful AOT compilation
Given a morphir-dotnet CLI project
And PublishAot is enabled
When I build the project with PublishAot=true
Then the build should succeed
And the output should be a native executable
And the executable size should be less than 12 MB
Scenario: AOT with all optimizations
Given a morphir-dotnet CLI project
And all size optimizations are enabled
When I build with PublishAot=true and size optimizations
Then the executable size should be less than 8 MB
And all smoke tests should pass
Scenario: Detecting reflection usage
Given a project using reflection
When I enable AOT analyzers
Then I should see IL2026 warnings
And I should see suggestions for source generatorsFeature: Assembly Trimming
As a CLI developer
I want trimmed assemblies
So that I reduce deployment size
Scenario: Trimming with link mode
Given a self-contained morphir-dotnet build
When I enable PublishTrimmed with TrimMode=link
Then unused assemblies should be removed
And unused types should be trimmed
And the output size should be reduced
Scenario: Preserving necessary types
Given types marked with DynamicDependency
When I trim the application
Then those types should not be removed
And reflection should still work on them1. What type of error?
A. IL2026 (RequiresUnreferencedCode)
→ Check: Is this System.Text.Json?
YES → Use source-generated JsonSerializerContext
NO → Apply DynamicDependency or refactor to avoid reflection
B. IL3050 (RequiresDynamicCode)
→ Check: Is this LINQ expressions or Reflection.Emit?
YES → Replace with delegates or source generators
NO → Check third-party library compatibility
C. IL2087 (Type incompatibility)
→ Add [DynamicallyAccessedMembers] attributes
→ Ensure generic constraints match
D. Runtime error (MissingMethodException, TypeLoadException)
→ Check trimmer warnings
→ Add DynamicDependency or TrimmerRootDescriptor
→ Test with PublishTrimmed first to isolate issue
2. After fix:
→ Update aot-trimming-guide.md if new pattern
→ Add to known issues if recurring
→ Create diagnostic check if automatable1. Current size vs target?
> 20 MB → Check dependencies (likely issue)
12-20 MB → Check optimizations enabled
8-12 MB → Feature-rich target (acceptable)
5-8 MB → Minimal target (good)
< 5 MB → Excellent
2. For sizes > target:
A. Check optimization flags
→ IlcOptimizationPreference=Size
→ InvariantGlobalization=true
→ DebugType=none
B. Analyze dependencies
→ dotnet list package
→ Check for heavy libraries (Newtonsoft.Json, etc.)
→ Replace with lighter alternatives
C. Check embedded resources
→ Are schemas embedded efficiently?
→ Can resources be external?
D. Profile with tools
→ dotnet-size-analyzer
→ ILSpy size analysis
3. After optimization:
→ Document size breakdown
→ Update size targets if appropriate
→ Add size regression testGather Information
- What error/warning are you seeing?
- Can you share the build output?
- What PublishAot settings do you have?
- Which dependencies are you using?Diagnose
aot-diagnostics.fsx if availableProvide Solution
Document
Assess Current State
Provide Roadmap
Guide Implementation
Verify
Issue Metrics:
Size Metrics:
Testing Metrics:
Every quarter, review and update:
# Diagnose AOT issues
dotnet fsi .claude/skills/aot-guru/aot-diagnostics.fsx <project-path>
# Analyze build warnings
dotnet fsi .claude/skills/aot-guru/aot-analyzer.fsx <build-log>
# Run AOT test matrix
dotnet fsi .claude/skills/aot-guru/aot-test-runner.fsx --runtime linux-x64
# Build with full AOT optimizations
dotnet publish -c Release -r linux-x64 /p:PublishAot=true /p:IlcOptimizationPreference=Size
# Check size
ls -lh bin/Release/net10.0/linux-x64/publish/morphirRemember: The goal is not just to make AOT work, but to maintain a living knowledge base that makes AOT easier for everyone over time. Document patterns, automate diagnostics, and continuously improve the guidance.
7c0c06d
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.