diff --git a/.github/workflows/test-tools.yml b/.github/workflows/test-tools.yml
index c792dc7..6b675c3 100644
--- a/.github/workflows/test-tools.yml
+++ b/.github/workflows/test-tools.yml
@@ -6,18 +6,26 @@
# all: PR #131 reported zero. That left every runner regression test inert, including the
# one added in #131 to stop the System.Drawing.Common reference being dropped as unused.
#
-# Two jobs, deliberately separate.
+# Two jobs and two ComplianceRunner test projects, deliberately separate.
#
# dotnet-tests Hermetic. Checkout, SDK, run. No network beyond NuGet, no BHoM.
+# SerialiserRunner, VersioningRunner and Compliance.Unit.Tests.
# compliance-tests Resolves the Test_Toolkit dependency graph first, so Compliance.Tests
# can compile and its entry-point tests can run.
#
+# Why the ComplianceRunner suite is split across two projects. Compliance.Unit.Tests compiles
+# Annotation.cs, ArgParser.cs, FileFilter.cs and SarifBuilder.cs directly instead of
+# project-referencing Compliance.Shared, so it pulls in no BHoM assembly and runs in the
+# hermetic job with nothing installed. Compliance.Tests holds everything that cannot: the three
+# unit files that take a BHoM type as a parameter, and the integration files that invoke the
+# built runner executables.
+#
# Why Compliance.Tests needs the second job. Compliance.Shared HintPaths five assemblies out
# of C:\ProgramData\BHoM\Assemblies. Measured on a machine carrying the BHoM installer, four
# resolve and only CodeComplianceTest_oM.dll is missing, because it is built by
# BHoM/Test_Toolkit (CodeCompliance_oM/CodeComplianceTest_oM.csproj) rather than shipped in
# the installer payload. AnnotationConvert.cs then fails CS0234 on BH.oM.Test.CodeCompliance
-# and takes the whole project down, which is why all nine of its test files were inert.
+# and takes the whole project down.
#
# resolve-dependencies in mode: seeds with seed BHoM/Test_Toolkit is exactly what ci-compliance
# already does before prepare-runner publishes ComplianceRunner, and ComplianceRunner.csproj
@@ -58,10 +66,14 @@ jobs:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ # Two versions: the Serialiser and Versioning suites target net8.0-windows, matching
+ # their runners; Compliance.Unit.Tests targets net10.0, matching ComplianceRunner.
- name: Set up .NET
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5
with:
- dotnet-version: '8.0'
+ dotnet-version: |
+ 8.0
+ 10.x
- name: SerialiserRunner tests
run: dotnet test tools/SerialiserRunner/src/SerialiserRunner.Tests --nologo
@@ -69,6 +81,9 @@ jobs:
- name: VersioningRunner tests
run: dotnet test tools/VersioningRunner/src/VersioningRunner.Tests --nologo
+ - name: ComplianceRunner unit tests (BHoM-free)
+ run: dotnet test tools/ComplianceRunner/tests/Compliance.Unit.Tests --nologo
+
# ComplianceRunner's own suite, including the entry-point characterisation tests. Needs
# CodeComplianceTest_oM.dll, so it builds the Test_Toolkit graph first. See the header.
compliance-tests:
diff --git a/tools/ComplianceRunner/Platform.slnx b/tools/ComplianceRunner/Platform.slnx
index da5e1f2..2470a6a 100644
--- a/tools/ComplianceRunner/Platform.slnx
+++ b/tools/ComplianceRunner/Platform.slnx
@@ -3,4 +3,5 @@
+
diff --git a/tools/ComplianceRunner/tests/Compliance.Tests/Compliance.Tests.csproj b/tools/ComplianceRunner/tests/Compliance.Tests/Compliance.Tests.csproj
index ca84fae..a5bd949 100644
--- a/tools/ComplianceRunner/tests/Compliance.Tests/Compliance.Tests.csproj
+++ b/tools/ComplianceRunner/tests/Compliance.Tests/Compliance.Tests.csproj
@@ -20,11 +20,30 @@
+
+
$(ProgramData)\BHoM\Assemblies\BHoM.dll
diff --git a/tools/ComplianceRunner/tests/Compliance.Tests/Integration/PathspecFilterPairingTests.cs b/tools/ComplianceRunner/tests/Compliance.Tests/Integration/PathspecFilterPairingTests.cs
index d27bd03..a96dc1d 100644
--- a/tools/ComplianceRunner/tests/Compliance.Tests/Integration/PathspecFilterPairingTests.cs
+++ b/tools/ComplianceRunner/tests/Compliance.Tests/Integration/PathspecFilterPairingTests.cs
@@ -11,7 +11,8 @@
/// 2. ComplianceRunner then asks FileFilter.IsRelevantFile of every file it was handed.
///
/// Each half has tests. `.github/scripts/tests/test-changed-file-patterns.sh` asserts the
-/// pathspec behaviour against real git, and FileFilterTests asserts the predicate. Neither
+/// pathspec behaviour against real git, and FileFilterTests, which lives in the sibling
+/// Compliance.Unit.Tests project, asserts the predicate. Neither
/// asserts that the two agree, and they do not: the pathspec token `*AssemblyInfo.cs` selects
/// any file whose name ENDS with that string, while FileFilter.cs:24 requires the name to
/// EQUAL it. A file in between is selected, counted into the skip decision, handed to the
@@ -20,9 +21,9 @@
/// These tests are written to PASS against today's behaviour. They record the disagreement so
/// it is visible in the suite. Whether the fix narrows the pathspec or widens the filter is
/// open: BHoMBot used EndsWith("AssemblyInfo.cs") (ProjectCompliance.cs:33), so widening the
-/// filter restores the older semantics, and FileFilterTests.cs:20 currently asserts the
-/// narrower one deliberately. Where an assertion would change under one of those two answers,
-/// the comment says what it should become and under which answer.
+/// filter restores the older semantics, and line 20 of that same FileFilterTests file asserts
+/// the narrower one deliberately. Where an assertion would change under one of those two
+/// answers, the comment says what it should become and under which answer.
///
[TestFixture]
[Category("Integration")]
diff --git a/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Compliance.Unit.Tests.csproj b/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Compliance.Unit.Tests.csproj
new file mode 100644
index 0000000..d40cb78
--- /dev/null
+++ b/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Compliance.Unit.Tests.csproj
@@ -0,0 +1,57 @@
+
+
+
+
+
+ net10.0
+ enable
+ enable
+ false
+ Compliance.Tests
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/ComplianceRunner/tests/Compliance.Tests/Unit/ArgParserTests.cs b/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/ArgParserTests.cs
similarity index 100%
rename from tools/ComplianceRunner/tests/Compliance.Tests/Unit/ArgParserTests.cs
rename to tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/ArgParserTests.cs
diff --git a/tools/ComplianceRunner/tests/Compliance.Tests/Unit/FileFilterTests.cs b/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/FileFilterTests.cs
similarity index 100%
rename from tools/ComplianceRunner/tests/Compliance.Tests/Unit/FileFilterTests.cs
rename to tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/FileFilterTests.cs
diff --git a/tools/ComplianceRunner/tests/Compliance.Tests/Unit/SarifBuilderTests.cs b/tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/SarifBuilderTests.cs
similarity index 100%
rename from tools/ComplianceRunner/tests/Compliance.Tests/Unit/SarifBuilderTests.cs
rename to tools/ComplianceRunner/tests/Compliance.Unit.Tests/Unit/SarifBuilderTests.cs