diff --git a/fallout.slnx b/fallout.slnx
index f8b402d0f..e0a18d91a 100644
--- a/fallout.slnx
+++ b/fallout.slnx
@@ -43,6 +43,9 @@
+
+
+
diff --git a/tests/Consumers/Fallout.Consumer.Local/Build.cs b/tests/Consumers/Fallout.Consumer.Local/Build.cs
new file mode 100644
index 000000000..2506d313d
--- /dev/null
+++ b/tests/Consumers/Fallout.Consumer.Local/Build.cs
@@ -0,0 +1,25 @@
+// Copyright 2026 Maintainers of Fallout.
+// Originally based on NUKE by Matthias Koch and contributors.
+// Distributed under the MIT License.
+// https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE
+//
+// Fallout consumer against this repo's local source. Catches breakage of the
+// public Fallout surface in the current PR.
+
+using Fallout.Common;
+using Fallout.Common.IO;
+using Fallout.Common.ProjectModel;
+
+class Build : FalloutBuild
+{
+ public static int Main() => Execute(x => x.Default);
+
+ [Solution] readonly Solution Solution;
+
+ Target Default => _ => _
+ .Executes(() =>
+ {
+ Serilog.Log.Information("hello from fallout consumer (local source)");
+ Serilog.Log.Information("solution name: {Name}", Solution?.Name ?? "");
+ });
+}
diff --git a/tests/Consumers/Fallout.Consumer.Local/Fallout.Consumer.Local.csproj b/tests/Consumers/Fallout.Consumer.Local/Fallout.Consumer.Local.csproj
new file mode 100644
index 000000000..0ff56655b
--- /dev/null
+++ b/tests/Consumers/Fallout.Consumer.Local/Fallout.Consumer.Local.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net10.0
+ Exe
+ false
+ Fallout.Consumer.Local
+ $(NoWarn);CS0649
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Consumers/Fallout.Consumer.NuGet/Build.cs b/tests/Consumers/Fallout.Consumer.NuGet/Build.cs
new file mode 100644
index 000000000..3a7cd83f3
--- /dev/null
+++ b/tests/Consumers/Fallout.Consumer.NuGet/Build.cs
@@ -0,0 +1,26 @@
+// Copyright 2026 Maintainers of Fallout.
+// Originally based on NUKE by Matthias Koch and contributors.
+// Distributed under the MIT License.
+// https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE
+//
+// Fallout consumer against PUBLISHED Fallout.* packages (pinned in the csproj).
+// Validates that the most-recent release's surface is intact from a clean
+// consumer's perspective.
+
+using Fallout.Common;
+using Fallout.Common.IO;
+using Fallout.Common.ProjectModel;
+
+class Build : FalloutBuild
+{
+ public static int Main() => Execute(x => x.Default);
+
+ [Solution] readonly Solution Solution;
+
+ Target Default => _ => _
+ .Executes(() =>
+ {
+ Serilog.Log.Information("hello from fallout consumer (pinned nuget 11.0.8)");
+ Serilog.Log.Information("solution name: {Name}", Solution?.Name ?? "");
+ });
+}
diff --git a/tests/Consumers/Fallout.Consumer.NuGet/Fallout.Consumer.NuGet.csproj b/tests/Consumers/Fallout.Consumer.NuGet/Fallout.Consumer.NuGet.csproj
new file mode 100644
index 000000000..f753fbdf7
--- /dev/null
+++ b/tests/Consumers/Fallout.Consumer.NuGet/Fallout.Consumer.NuGet.csproj
@@ -0,0 +1,33 @@
+
+
+
+ net10.0
+ Exe
+ false
+ Fallout.Consumer.NuGet
+ $(NoWarn);CS0649
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/Consumers/Nuke.Consumer/Build.cs b/tests/Consumers/Nuke.Consumer/Build.cs
new file mode 100644
index 000000000..21c081670
--- /dev/null
+++ b/tests/Consumers/Nuke.Consumer/Build.cs
@@ -0,0 +1,35 @@
+// Copyright 2026 Maintainers of Fallout.
+// Originally based on NUKE by Matthias Koch and contributors.
+// Distributed under the MIT License.
+// https://github.com/ChrisonSimtian/Fallout/blob/main/LICENSE
+//
+// Pre-rename NUKE consumer pattern, compiled against the Nuke.Common /
+// Nuke.Components transition shims. If a typical NUKE 10.x Build.cs stops
+// compiling against the latest Fallout, this fails — protecting upgrading
+// users from silent breakage.
+
+using Nuke.Common;
+using Nuke.Common.IO;
+using Nuke.Common.ProjectModel;
+using Nuke.Components;
+
+// The shim generator skips delegates by C# language limitation (see SHIM002 —
+// can't subclass a delegate cross-assembly). `Target` is a delegate in
+// Fallout.Common, so NUKE-era code referencing `Target` needs either
+// `fallout-migrate` (which flips usings to Fallout.*) or this manual alias.
+// Including it here keeps the rest of the file NUKE-shape.
+using Target = Fallout.Common.Target;
+
+class Build : NukeBuild
+{
+ public static int Main() => Execute(x => x.Default);
+
+ [Solution] readonly Solution Solution;
+
+ Target Default => _ => _
+ .Executes(() =>
+ {
+ Serilog.Log.Information("hello from nuke consumer (via shim)");
+ Serilog.Log.Information("solution name: {Name}", Solution?.Name ?? "");
+ });
+}
diff --git a/tests/Consumers/Nuke.Consumer/Nuke.Consumer.csproj b/tests/Consumers/Nuke.Consumer/Nuke.Consumer.csproj
new file mode 100644
index 000000000..1a5744333
--- /dev/null
+++ b/tests/Consumers/Nuke.Consumer/Nuke.Consumer.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net10.0
+ Exe
+ false
+ Nuke.Consumer
+
+ $(NoWarn);CS0649
+
+
+
+
+
+
+
+
+
diff --git a/tests/Consumers/README.md b/tests/Consumers/README.md
new file mode 100644
index 000000000..f75febc7d
--- /dev/null
+++ b/tests/Consumers/README.md
@@ -0,0 +1,53 @@
+# Consumer compatibility tests
+
+Three small build-project consumers that exercise Fallout's public surface from the perspectives of real downstream users. If any of these stop **compiling**, we've broken something consumers depend on.
+
+## Projects
+
+| Project | What it exercises | Reference style |
+|---|---|---|
+| [`Nuke.Consumer`](Nuke.Consumer/) | A pre-rename NUKE consumer using `class Build : NukeBuild`, `[Solution]`, and `Target` via the `Nuke.Common` / `Nuke.Build` / `Nuke.Components` transition shims. Catches breakage of **shim coverage** — if a NUKE-shape symbol stops resolving, an upgrading NUKE user breaks. | `ProjectReference` to `src/Shims/Nuke.*/` |
+| [`Fallout.Consumer.Local`](Fallout.Consumer.Local/) | A Fallout consumer using `class Build : FalloutBuild`, `[Solution]`, `Target` against **this repo's current source**. Catches breakage of the public Fallout surface **in the current PR**. | Direct `ProjectReference` to the in-repo `Fallout.*` projects |
+| [`Fallout.Consumer.NuGet`](Fallout.Consumer.NuGet/) | A Fallout consumer against the **last published** `Fallout.*` packages (pinned in the csproj). Catches **packaging issues** (missing assemblies, wrong references) on the most-recent release, and catches upgrade-direction breakage when the pin is bumped after a release. | `PackageReference` to nuget.org with `false` and `false` so the smart-rewrite doesn't kick in |
+
+## How they're validated
+
+**Compile-time validation only.** All three projects are in `fallout.slnx`, so `dotnet build fallout.slnx` (the standard CI gate) compiles them. Any consumer-facing breaking change makes the build fail.
+
+### Why not runtime validation?
+
+A runtime smoke test layer was considered (spawn each consumer via `dotnet run`, assert exit code `0`). That hits a Fallout framework requirement: `FalloutBuild.cctor()` enumerates `Host` subclasses and reflects for a static `IsRunningHost` property — minimal consumers that don't pull in the full Fallout MSBuild props/targets (`Fallout.Common.props`, `Fallout.Common.targets`) trigger `System.ArgumentException: Host type 'Host' defines no property 'IsRunningHost'` at activation. Reproducing the full build-app environment for a smoke consumer is more setup than the test's marginal value justifies — compile-time already catches the bulk of breaking changes.
+
+If runtime validation becomes worth the cost: import `Fallout.Common.props` + `Fallout.Common.targets` from the consumer csprojs (the way `build/_build.csproj` does), provide a `FalloutRootDirectory`, and the framework should activate cleanly.
+
+## Catching breaking changes
+
+The intended flow:
+
+1. These consumer projects live on `main` and reflect the **current public consumer surface**. Any PR proposing a change to consumer-facing types/namespaces/attributes…
+2. …will conflict with the consumer code in those projects (rebase or merge will surface the breakage).
+3. Resolving the conflict means either: (a) the change isn't really breaking and the conflict is trivial, or (b) the consumer code needs updating to the new shape, **which is the migration path**. Update both, document the migration in `CHANGELOG.md` under `[Unreleased] — `, and you've simultaneously detected the breaking change AND demonstrated how consumers migrate.
+
+This works as designed only because the consumer code is **fixed to the current API shape**, not regenerated to match new code. Don't auto-update consumer Build.cs files to match a PR's renamed types — let them break, then fix them deliberately as part of the migration story.
+
+## Bumping the NuGet pin
+
+After a new `Fallout.*` release ships, edit `Fallout.Consumer.NuGet/Fallout.Consumer.NuGet.csproj` to bump the pinned version. If the consumer source still compiles, the upgrade is non-breaking. If it fails, the new release introduces a consumer-facing breaking change — record it in `CHANGELOG.md` and the migration path under `[Unreleased] — `.
+
+The `Nuke.Consumer` doesn't pin anything (it references the in-repo shim assemblies directly), so no bump cadence there — it always tracks HEAD's shim coverage.
+
+## What's deliberately tested
+
+- **NUKE-era `class Build : NukeBuild`** — basic class identity through the shim
+- **`[Solution] readonly Solution Solution`** — value-injection attribute + facade type via shim
+- **`Target Default => _ => _.Executes(...)`** — delegate type, default target lambda
+- **`static int Main() => Execute(x => x.Default)`** — framework entry point
+
+## What's NOT tested
+
+- Actual build *execution* (see above — runtime activation is fragile)
+- CI-host integration (GitHubActions, AzurePipelines, etc.) — covered by `tests/Fallout.Common.Tests/CI/`
+- Tool wrappers — covered by their own generated tests
+- Source generator behaviour — covered by `tests/Fallout.SourceGenerators.Tests/`
+
+These consumer projects are a **sentinel for shape changes**, not a place to demo features. Don't add consumer projects covering specific subsystems — those go in their own focused tests.
diff --git a/tests/Fallout.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#Solution.g.verified.cs b/tests/Fallout.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#Solution.g.verified.cs
index 92fb07118..b5cc90b84 100644
--- a/tests/Fallout.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#Solution.g.verified.cs
+++ b/tests/Fallout.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#Solution.g.verified.cs
@@ -17,6 +17,8 @@ internal class Solution(SolutionModel model, AbsolutePath path) : Fallout.Common
public Fallout.Common.ProjectModel.Project Fallout_Common => this.GetProject("Fallout.Common");
public Fallout.Common.ProjectModel.Project Fallout_Common_Tests => this.GetProject("Fallout.Common.Tests");
public Fallout.Common.ProjectModel.Project Fallout_Components => this.GetProject("Fallout.Components");
+ public Fallout.Common.ProjectModel.Project Fallout_Consumer_Local => this.GetProject("Fallout.Consumer.Local");
+ public Fallout.Common.ProjectModel.Project Fallout_Consumer_NuGet => this.GetProject("Fallout.Consumer.NuGet");
public Fallout.Common.ProjectModel.Project Fallout_Migrate => this.GetProject("Fallout.Migrate");
public Fallout.Common.ProjectModel.Project Fallout_Migrate_Analyzers => this.GetProject("Fallout.Migrate.Analyzers");
public Fallout.Common.ProjectModel.Project Fallout_Migrate_Analyzers_Tests => this.GetProject("Fallout.Migrate.Analyzers.Tests");
@@ -44,6 +46,7 @@ internal class Solution(SolutionModel model, AbsolutePath path) : Fallout.Common
public Fallout.Common.ProjectModel.Project Nuke_Common_Shim_Tests => this.GetProject("Nuke.Common.Shim.Tests");
public Fallout.Common.ProjectModel.Project Nuke_Components => this.GetProject("Nuke.Components");
public Fallout.Common.ProjectModel.Project Nuke_Components_Shim_Tests => this.GetProject("Nuke.Components.Shim.Tests");
+ public Fallout.Common.ProjectModel.Project Nuke_Consumer => this.GetProject("Nuke.Consumer");
public _misc misc => Unsafe.As<_misc>(this.GetSolutionFolder("misc"));