From 81938d60ab6e398e86dea82f561889ac7b1dfcea Mon Sep 17 00:00:00 2001 From: Chrison Simtian Date: Mon, 29 Jun 2026 14:53:59 +1200 Subject: [PATCH 1/2] Split the tool-execution contract into Application-layer leaves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pulls the pure tool-execution contract out of Fallout.Tooling into two cohesive, single-purpose Application-layer foundation leaves (onion: tools are an Application concern), each ns2.0;net10 and referencing nothing else in the repo: - Fallout.Application.Tooling.Execution — the process-execution contract: IProcess, Output, OutputType. - Fallout.Application.Tooling.Requirements — the tool-requirement markers: IRequireTool, IRequireToolWithVersion, IRequirePathTool, IRequireNuGetPackage, IRequireNpmPackage, IRequireAptGetPackage (extracted from ToolRequirement.cs; the *Requirement classes stay in Fallout.Tooling). First bottom-up step of the onion migration on main. All types keep their Fallout.Common.Tooling namespace, so no consumer code changes — Fallout.Tooling references both leaves and re-flows them transitively. They must be netstandard2.0 because the Roslyn source generator and net472 MSBuild tasks consume them; Fallout.Core stays netstandard2.1. Co-Authored-By: Claude Opus 4.8 (1M context) --- fallout.slnx | 2 ++ .../Fallout.Application.Tooling.Execution.csproj | 8 ++++++++ .../IProcess.cs | 0 .../Output.cs | 0 .../OutputType.cs | 0 .../Fallout.Application.Tooling.Requirements.csproj | 8 ++++++++ .../ToolRequirements.cs | 13 +++++++++++++ src/Fallout.Tooling/Fallout.Tooling.csproj | 2 ++ src/Fallout.Tooling/ToolRequirement.cs | 13 ------------- 9 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 src/Fallout.Application.Tooling.Execution/Fallout.Application.Tooling.Execution.csproj rename src/{Fallout.Tooling => Fallout.Application.Tooling.Execution}/IProcess.cs (100%) rename src/{Fallout.Tooling => Fallout.Application.Tooling.Execution}/Output.cs (100%) rename src/{Fallout.Tooling => Fallout.Application.Tooling.Execution}/OutputType.cs (100%) create mode 100644 src/Fallout.Application.Tooling.Requirements/Fallout.Application.Tooling.Requirements.csproj create mode 100644 src/Fallout.Application.Tooling.Requirements/ToolRequirements.cs diff --git a/fallout.slnx b/fallout.slnx index 927adef11..d6058e85d 100644 --- a/fallout.slnx +++ b/fallout.slnx @@ -26,6 +26,8 @@ + + diff --git a/src/Fallout.Application.Tooling.Execution/Fallout.Application.Tooling.Execution.csproj b/src/Fallout.Application.Tooling.Execution/Fallout.Application.Tooling.Execution.csproj new file mode 100644 index 000000000..3750545bf --- /dev/null +++ b/src/Fallout.Application.Tooling.Execution/Fallout.Application.Tooling.Execution.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.0;net10.0 + Application-layer process-execution contract for Fallout tools — the IProcess abstraction and its Output model. No I/O, no logging. Targets netstandard2.0 so the source-generator and MSBuild-task layers can consume it. + + + diff --git a/src/Fallout.Tooling/IProcess.cs b/src/Fallout.Application.Tooling.Execution/IProcess.cs similarity index 100% rename from src/Fallout.Tooling/IProcess.cs rename to src/Fallout.Application.Tooling.Execution/IProcess.cs diff --git a/src/Fallout.Tooling/Output.cs b/src/Fallout.Application.Tooling.Execution/Output.cs similarity index 100% rename from src/Fallout.Tooling/Output.cs rename to src/Fallout.Application.Tooling.Execution/Output.cs diff --git a/src/Fallout.Tooling/OutputType.cs b/src/Fallout.Application.Tooling.Execution/OutputType.cs similarity index 100% rename from src/Fallout.Tooling/OutputType.cs rename to src/Fallout.Application.Tooling.Execution/OutputType.cs diff --git a/src/Fallout.Application.Tooling.Requirements/Fallout.Application.Tooling.Requirements.csproj b/src/Fallout.Application.Tooling.Requirements/Fallout.Application.Tooling.Requirements.csproj new file mode 100644 index 000000000..7d7dd195e --- /dev/null +++ b/src/Fallout.Application.Tooling.Requirements/Fallout.Application.Tooling.Requirements.csproj @@ -0,0 +1,8 @@ + + + + netstandard2.0;net10.0 + Application-layer tool-requirement marker interfaces — how a target declares the tools/packages it needs present before it runs. No I/O, no logging. Targets netstandard2.0 so the source-generator and MSBuild-task layers can consume it. + + + diff --git a/src/Fallout.Application.Tooling.Requirements/ToolRequirements.cs b/src/Fallout.Application.Tooling.Requirements/ToolRequirements.cs new file mode 100644 index 000000000..7ecd57bd5 --- /dev/null +++ b/src/Fallout.Application.Tooling.Requirements/ToolRequirements.cs @@ -0,0 +1,13 @@ +namespace Fallout.Common.Tooling; + +public interface IRequireTool; +public interface IRequireToolWithVersion; + + +public interface IRequirePathTool : IRequireTool; + +public interface IRequireNuGetPackage : IRequireTool, IRequireToolWithVersion; + +public interface IRequireNpmPackage : IRequireTool, IRequireToolWithVersion; + +public interface IRequireAptGetPackage : IRequireTool; diff --git a/src/Fallout.Tooling/Fallout.Tooling.csproj b/src/Fallout.Tooling/Fallout.Tooling.csproj index 2200aa636..1e871d084 100644 --- a/src/Fallout.Tooling/Fallout.Tooling.csproj +++ b/src/Fallout.Tooling/Fallout.Tooling.csproj @@ -5,6 +5,8 @@ + + diff --git a/src/Fallout.Tooling/ToolRequirement.cs b/src/Fallout.Tooling/ToolRequirement.cs index 21e591c3e..70e5fe3ba 100644 --- a/src/Fallout.Tooling/ToolRequirement.cs +++ b/src/Fallout.Tooling/ToolRequirement.cs @@ -3,19 +3,6 @@ namespace Fallout.Common.Tooling; -public interface IRequireTool; -public interface IRequireToolWithVersion; - - -public interface IRequirePathTool : IRequireTool; - -public interface IRequireNuGetPackage : IRequireTool, IRequireToolWithVersion; - -public interface IRequireNpmPackage : IRequireTool, IRequireToolWithVersion; - -public interface IRequireAptGetPackage : IRequireTool; - - public class ToolRequirement; public class PathToolRequirement(string pathExecutable) : ToolRequirement From 8ae03da8224e402be41bd415b28f953444a76a42 Mon Sep 17 00:00:00 2001 From: Chrison Simtian Date: Mon, 29 Jun 2026 14:53:59 +1200 Subject: [PATCH 2/2] Govern the Application.Tooling contract leaves in the architecture suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit References both leaves from the architecture test project, registers them as governed runtime libraries, and asserts (via a Theory) that each is a foundation depending on nothing else in the repo. Their contract types keep the Fallout.Common.Tooling namespace, so they stay in the pre-existing namespace-drift baseline by full name — the ratchet stays green. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/architecture-tests.md | 2 +- .../Fallout.Architecture.Specs.csproj | 2 ++ .../Fallout.Architecture.Specs/FalloutArchitecture.cs | 6 ++++-- tests/Fallout.Architecture.Specs/LayeringSpecs.cs | 10 ++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/architecture-tests.md b/docs/architecture-tests.md index cf7c02f97..79dacbc4c 100644 --- a/docs/architecture-tests.md +++ b/docs/architecture-tests.md @@ -31,7 +31,7 @@ Current rules: | File | Rule(s) | |---|---| -| `LayeringSpecs` | `Core` / `Utilities` are foundations (no in-repo deps); utility satellites depend only on `Utilities`; `Tooling` / `ProjectModel` / `Build.Shared` don't reach upward; `Solution` is a thin facade; nothing depends on the `Cli` composition root; `Fallout.*` never depends on the `Nuke.*` shims. | +| `LayeringSpecs` | `Core` / `Utilities` and the `Application.Tooling.Execution` / `Application.Tooling.Requirements` contract leaves are foundations (no in-repo deps); utility satellites depend only on `Utilities`; `Tooling` / `ProjectModel` / `Build.Shared` don't reach upward; `Solution` is a thin facade; nothing depends on the `Cli` composition root; `Fallout.*` never depends on the `Nuke.*` shims. | | `PuritySpecs` | `Fallout.Core` takes no dependency on `System.IO`, `System.Diagnostics.Process`, `System.Console`, or Serilog (issue #88). | | `NamingSpecs` | A type's namespace should be rooted at its assembly name. The main debt-bearing rule. | diff --git a/tests/Fallout.Architecture.Specs/Fallout.Architecture.Specs.csproj b/tests/Fallout.Architecture.Specs/Fallout.Architecture.Specs.csproj index 64047c195..f554c9160 100644 --- a/tests/Fallout.Architecture.Specs/Fallout.Architecture.Specs.csproj +++ b/tests/Fallout.Architecture.Specs/Fallout.Architecture.Specs.csproj @@ -26,6 +26,8 @@ + + diff --git a/tests/Fallout.Architecture.Specs/FalloutArchitecture.cs b/tests/Fallout.Architecture.Specs/FalloutArchitecture.cs index 6b56baf55..773d7529a 100644 --- a/tests/Fallout.Architecture.Specs/FalloutArchitecture.cs +++ b/tests/Fallout.Architecture.Specs/FalloutArchitecture.cs @@ -26,6 +26,8 @@ internal static class FalloutArchitecture public const string UtilitiesTextJson = "Fallout.Utilities.Text.Json"; public const string UtilitiesTextYaml = "Fallout.Utilities.Text.Yaml"; public const string Solution = "Fallout.Solution"; + public const string ToolingExecution = "Fallout.Application.Tooling.Execution"; + public const string ToolingRequirements = "Fallout.Application.Tooling.Requirements"; public const string Tooling = "Fallout.Tooling"; public const string ProjectModel = "Fallout.ProjectModel"; public const string BuildShared = "Fallout.Build.Shared"; @@ -52,8 +54,8 @@ internal static class FalloutArchitecture public static readonly string[] RuntimeLibraries = [ Core, Utilities, UtilitiesIoCompression, UtilitiesIoGlobbing, UtilitiesNet, UtilitiesTextJson, - UtilitiesTextYaml, Solution, Tooling, ProjectModel, BuildShared, Build, Common, Components, Cli, - NukeCommon, NukeBuild, NukeComponents, + UtilitiesTextYaml, Solution, ToolingExecution, ToolingRequirements, Tooling, ProjectModel, BuildShared, + Build, Common, Components, Cli, NukeCommon, NukeBuild, NukeComponents, ]; private static readonly IReadOnlyDictionary Loaded = LoadProductionAssemblies(); diff --git a/tests/Fallout.Architecture.Specs/LayeringSpecs.cs b/tests/Fallout.Architecture.Specs/LayeringSpecs.cs index 29a7f414b..9e1ccd4e8 100644 --- a/tests/Fallout.Architecture.Specs/LayeringSpecs.cs +++ b/tests/Fallout.Architecture.Specs/LayeringSpecs.cs @@ -42,6 +42,16 @@ public void Utility_satellite_depends_only_on_Fallout_Utilities(string satellite $"{satellite} is a utility satellite and may depend only on Fallout.Utilities", KnownViolations.None); + [Theory] + [InlineData(Arch.ToolingExecution)] + [InlineData(Arch.ToolingRequirements)] + public void Tooling_contract_leaf_is_a_foundation(string leaf) => + Ratchet.Enforce( + Arch.TypesIn(leaf) + .Should().NotDependOnAny(Arch.TypesIn(Arch.AllAssembliesExcept(leaf))), + $"{leaf} is a pure Application-layer tooling-contract leaf and must reference no other Fallout/Nuke assembly", + KnownViolations.None); + [Fact] public void Tooling_does_not_depend_on_upper_layers() => Ratchet.Enforce(