The centerpiece of the whole "no domain reload" claim, now proven empirically rather than argued on paper: 200 load/unload cycles against a real plugin (sandbox.echo), each one checked with a WeakReference that the collectible ALC actually collected — docs/kernel-contract.md §4's leak test, previously Skip-marked since the very first scaffold, now runs and passes (stable across repeated runs). New pieces, minimal by design: - PluginLoadContext: the collectible ALC a plugin's implementation loads into. Load() defers to whatever's already in the Default ALC (Engine.Kernel, the plugin's own Contracts assembly) before consulting AssemblyDependencyResolver for genuinely private dependencies — the standard .NET plugin pattern, needed so component types stay identical across the plugin boundary instead of loading as two distinct, incompatible copies. - PluginHost: reads plugin.json, loads Contracts into the Default ALC (once — verified directly, not just inferred from the leak test), loads the implementation into a fresh PluginLoadContext, finds the IPlugin type via reflection, calls Configure(). Unload() calls Shutdown() first, then .Unload()s the ALC and hands back a WeakReference for the caller to check. - Schedule, ServiceRegistry, NullEventBus, ConsoleLogger: minimal real implementations of the remaining IPluginContext pieces — no stage execution or parallelism in Schedule yet, that's separate Scheduler work. Schedule.RemoveAllFrom is the one piece that has to be correct now, not later: it's what lets a plugin's Shutdown() actually drop the delegate reference into its own collectible ALC, which is exactly what the leak test is checking end to end. Explicitly out of scope for this pass: resolving a project's or plugin's dependsOn graph to order loading across multiple plugins. Nothing to test that against yet — sandbox.echo is deliberately the only, dependency-free fixture. Noted as a TODO on PluginHost rather than built speculatively. Sandbox.Echo.csproj gets <EnableDynamicLoading>true</EnableDynamicLoading> (future plugins with real dependencies will need the deps.json this generates). Engine.ConformanceHarness.csproj now copies plugin.json and both built DLLs into one flat directory under its own output, matching the layout PluginHost.Load(directory) expects — via $(Configuration)/ $(TargetFramework)-aware CopyToOutputDirectory items, correct in Release too, not just Debug. 17 tests total now (13 in Engine.Kernel.Tests, 4 in Engine.ConformanceHarness), all passing on a clean build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N1qPfzq8TDCUMFMV3UwV5N
52 lines
2.3 KiB
XML
52 lines
2.3 KiB
XML
<Project Sdk="Microsoft.NET.Sdk">
|
|
|
|
<PropertyGroup>
|
|
<IsPackable>false</IsPackable>
|
|
</PropertyGroup>
|
|
|
|
<ItemGroup>
|
|
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
|
<PackageReference Include="xunit" Version="2.9.2" />
|
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<Using Include="Xunit" />
|
|
</ItemGroup>
|
|
|
|
<ItemGroup>
|
|
<ProjectReference Include="..\..\src\Engine.Kernel\Engine.Kernel.csproj" />
|
|
|
|
<!-- Build-order only: the harness must load this plugin the same way
|
|
PluginHost does at runtime, into its own collectible ALC by file
|
|
path. A normal ProjectReference would link its types straight into
|
|
the harness's Default ALC, which defeats the point of a leak test. -->
|
|
<ProjectReference Include="..\..\plugins\sandbox.echo\Sandbox.Echo\Sandbox.Echo.csproj"
|
|
ReferenceOutputAssembly="false" />
|
|
</ItemGroup>
|
|
|
|
<!-- Flatten plugin.json + both built DLLs into one directory under this
|
|
project's own output — plugins/sandbox.echo/ — matching the flat
|
|
layout PluginHost.Load(directory) expects. The ProjectReference
|
|
above guarantees these DLLs exist by the time this runs (transitive
|
|
build order also covers Sandbox.Echo.Contracts, which Sandbox.Echo
|
|
itself references). $(Configuration)/$(TargetFramework) keep this
|
|
correct in Release, not just Debug. -->
|
|
<ItemGroup>
|
|
<None Include="..\..\plugins\sandbox.echo\plugin.json">
|
|
<Link>plugins\sandbox.echo\plugin.json</Link>
|
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
</None>
|
|
<None Include="..\..\plugins\sandbox.echo\Sandbox.Echo.Contracts\bin\$(Configuration)\$(TargetFramework)\Sandbox.Echo.Contracts.dll">
|
|
<Link>plugins\sandbox.echo\Sandbox.Echo.Contracts.dll</Link>
|
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
</None>
|
|
<None Include="..\..\plugins\sandbox.echo\Sandbox.Echo\bin\$(Configuration)\$(TargetFramework)\Sandbox.Echo.dll">
|
|
<Link>plugins\sandbox.echo\Sandbox.Echo.dll</Link>
|
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
</None>
|
|
</ItemGroup>
|
|
|
|
</Project>
|