Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Part XII: End-to-End Walkthrough

What We Build

This chapter builds an e-commerce platform from an empty directory to a deployed application. Every command. Every file. Every generated artifact. By the end, we will have:

  • 2 bounded contexts (Catalog, Ordering)
  • 3 aggregates (Product, Order, Customer)
  • 1 content type (BlogPost) with parts, blocks, and StreamField
  • 3 admin modules (Products, Orders, BlogPosts)
  • A page tree (Home, Catalog, Product Detail, Blog)
  • An editorial workflow on BlogPost (Draft, Review, Translation, Published)
  • 1 epic, 1 feature with 3 ACs, 1 specification interface, 1 domain service, 5 tests
  • Full quality gates: analyzers, coverage, fuzz testing

The comparison at the end: approximately 300 lines written by the developer, approximately 15,000 lines generated by the compiler.


Step 1: Create the Project

cmf new MyStore --template ecommerce
Creating MyStore from template 'ecommerce'...

  Created: MyStore.sln
  Created: Directory.Build.props
  Created: .editorconfig
  Created: src/MyStore.Requirements/
  Created: src/MyStore.SharedKernel/
  Created: src/MyStore.Specifications/
  Created: src/MyStore.Lib/
  Created: src/MyStore.Infrastructure.Postgres/
  Created: src/MyStore.Server/
  Created: src/MyStore.Client/
  Created: test/MyStore.Tests/
  Created: .github/workflows/build.yml

Done. Run 'dotnet build' to verify.

Project tree after Step 1:

MyStore/
├── MyStore.sln
├── Directory.Build.props
├── .editorconfig
├── src/
│   ├── MyStore.Requirements/
│   │   ├── MyStore.Requirements.csproj
│   │   ├── Epics/
│   │   └── Features/
│   ├── MyStore.SharedKernel/
│   │   ├── MyStore.SharedKernel.csproj
│   │   └── Result.cs
│   ├── MyStore.Specifications/
│   │   └── MyStore.Specifications.csproj
│   ├── MyStore.Lib/
│   │   ├── MyStore.Lib.csproj
│   │   ├── Catalog/
│   │   └── Ordering/
│   ├── MyStore.Infrastructure.Postgres/
│   │   └── MyStore.Infrastructure.Postgres.csproj
│   ├── MyStore.Server/
│   │   ├── MyStore.Server.csproj
│   │   └── Program.cs
│   └── MyStore.Client/
│       └── MyStore.Client.csproj
├── test/
│   └── MyStore.Tests/
│       └── MyStore.Tests.csproj
└── .github/
    └── workflows/
        └── build.yml

Step 2: Define Requirements

Create the Epic

cmf add feature OrderFulfillment --epic DomainModelingEpic

The template already created DomainModelingEpic. We write the feature by hand in src/MyStore.Requirements/Features/OrderFulfillmentFeature.cs:

namespace MyStore.Requirements.Features;

using MyStore.Requirements;
using MyStore.Requirements.Epics;

/// <summary>
/// Feature: Order Fulfillment
/// Customers can place orders, cancel orders, and view order totals.
/// </summary>
public abstract record OrderFulfillmentFeature
    : Feature<DomainModelingEpic>
{
    public override string Title => "Order fulfillment and lifecycle";
    public override RequirementPriority Priority
        => RequirementPriority.Critical;
    public override string Owner => "ordering-team";

    /// AC1: A customer can place an order with at least one line item
    public abstract AcceptanceCriterionResult OrderCanBePlaced(
        UserId customer, ProductId product, int quantity);

    /// AC2: An order can be cancelled if not yet shipped
    public abstract AcceptanceCriterionResult OrderCanBeCancelled(
        UserId customer, OrderId order);

    /// AC3: Order total equals sum of line totals
    public abstract AcceptanceCriterionResult OrderTotalIsCorrect(
        OrderId order, decimal expectedTotal);
}

Build check:

dotnet build
Build succeeded.

warning REQ100: OrderFulfillmentFeature has 3 acceptance criteria but no
                specification interface references it.
                → Create IOrderFulfillmentSpec with
                  [ForRequirement(typeof(OrderFulfillmentFeature))]

The build succeeds, but the analyzer immediately tells us: the feature exists, but nothing specifies it yet.


Step 3: Create Specifications

Create src/MyStore.Specifications/IOrderFulfillmentSpec.cs:

namespace MyStore.Specifications;

using MyStore.Requirements.Features;
using MyStore.SharedKernel;

[ForRequirement(typeof(OrderFulfillmentFeature))]
public interface IOrderFulfillmentSpec
{
    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBePlaced))]
    Result PlaceOrder(User customer, Product product, int quantity);

    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBeCancelled))]
    Result CancelOrder(User customer, Order order);

    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderTotalIsCorrect))]
    Result VerifyOrderTotal(Order order, decimal expectedTotal);
}

Build check:

dotnet build
Build succeeded.

info  REQ103: OrderFulfillmentFeature: all 3 ACs specified.
warning REQ200: IOrderFulfillmentSpec is not implemented by any class.
warning REQ300: OrderFulfillmentFeature has no test class.

Progress: REQ100 is gone (spec exists). Now REQ200 (no implementation) and REQ300 (no tests) appear.


Step 4: Model the Domain

Create Aggregates

cmf add aggregate Product --context Catalog
cmf add aggregate Order --context Ordering
cmf add aggregate Customer --context Identity

Define Properties and Compositions

Edit src/MyStore.Lib/Catalog/Product.cs:

namespace MyStore.Lib.Catalog;

[AggregateRoot("Product", BoundedContext = "Catalog")]
public partial class Product
{
    [EntityId]
    public partial ProductId Id { get; }

    [Property("Name", Required = true, MaxLength = 200)]
    public partial string Name { get; }

    [Property("Sku", Required = true, MaxLength = 50)]
    public partial string Sku { get; }

    [Property("Description", MaxLength = 2000)]
    public partial string? Description { get; }

    [Composition]
    public partial Money Price { get; }

    [Property("StockQuantity", Required = true)]
    public partial int StockQuantity { get; }

    [Invariant("Product price must be positive")]
    private Result PriceIsPositive()
        => Price.Amount > 0
            ? Result.Success()
            : Result.Failure("Product price must be positive");

    [Invariant("Stock cannot be negative")]
    private Result StockNotNegative()
        => StockQuantity >= 0
            ? Result.Success()
            : Result.Failure("Stock quantity cannot be negative");
}

Edit src/MyStore.Lib/Ordering/Order.cs:

namespace MyStore.Lib.Ordering;

[AggregateRoot("Order", BoundedContext = "Ordering")]
public partial class Order
{
    [EntityId]
    public partial OrderId Id { get; }

    [Property("OrderDate", Required = true)]
    public partial DateTime OrderDate { get; }

    [Property("Status", Required = true)]
    public partial OrderStatus Status { get; }

    [Composition]
    public partial IReadOnlyList<OrderLine> Lines { get; }

    [Composition]
    public partial ShippingAddress ShippingAddress { get; }

    [Association]
    public partial CustomerId CustomerId { get; }

    [Invariant("Order must have at least one line item")]
    private Result HasLines()
        => Lines.Count > 0
            ? Result.Success()
            : Result.Failure("Order must have at least one line item");

    [Invariant("Order total must be positive")]
    private Result TotalIsPositive()
    {
        var total = Lines.Sum(l => l.LineTotal.Amount);
        return total > 0
            ? Result.Success()
            : Result.Failure($"Order total ({total}) must be positive");
    }

    [Invariant("Cancelled orders cannot be modified")]
    private Result CancelledOrdersImmutable()
    {
        // This invariant is checked after any mutation
        // If status is Cancelled, no changes should have been made
        return Result.Success(); // Enforced by command handler guards
    }
}

[Entity("OrderLine")]
public partial class OrderLine
{
    [EntityId]
    public partial OrderLineId Id { get; }

    [Property("ProductName", Required = true, MaxLength = 200)]
    public partial string ProductName { get; }

    [Property("Quantity", Required = true)]
    public partial int Quantity { get; }

    [Composition]
    public partial Money UnitPrice { get; }

    [Composition]
    public partial Money LineTotal { get; }
}

[ValueObject("Money")]
public partial class Money
{
    [ValueComponent("Amount", "decimal", Required = true)]
    public partial decimal Amount { get; }

    [ValueComponent("Currency", "string", Required = true)]
    public partial string Currency { get; }
}

[ValueObject("ShippingAddress")]
public partial class ShippingAddress
{
    [ValueComponent("Street", "string", Required = true)]
    public partial string Street { get; }

    [ValueComponent("City", "string", Required = true)]
    public partial string City { get; }

    [ValueComponent("PostalCode", "string", Required = true)]
    public partial string PostalCode { get; }

    [ValueComponent("Country", "string", Required = true)]
    public partial string Country { get; }
}

public enum OrderStatus
{
    Draft, Placed, Paid, Shipped, Delivered, Cancelled
}

Step 5: Generate Code

dotnet build
[Stage 0] Metamodel Registration
  Registered 24 concepts across 6 DSLs

[Stage 1] DSL Validation & Collection
  Found: Product (Catalog), Order (Ordering), Customer (Identity)
  Validated: 0 errors, 0 warnings

[Stage 2] Core Generation
  Generated: Product.g.cs             (entity impl, backing fields)
  Generated: ProductBuilder.g.cs      (fluent builder)
  Generated: ProductConfiguration.g.cs (EF Core)
  Generated: IProductRepository.g.cs
  Generated: ProductRepository.g.cs
  Generated: Order.g.cs
  Generated: OrderBuilder.g.cs
  Generated: Order.Invariants.g.cs    (EnsureInvariants)
  Generated: OrderConfiguration.g.cs
  Generated: OrderLineConfiguration.g.cs
  Generated: IOrderRepository.g.cs
  Generated: OrderRepository.g.cs
  Generated: Customer.g.cs
  Generated: CustomerBuilder.g.cs
  Generated: CustomerConfiguration.g.cs
  Generated: ICustomerRepository.g.cs
  Generated: CustomerRepository.g.cs
  Generated: AppDbContext.g.cs        (3 DbSets)
  Generated: RequirementRegistry.g.cs (1 feature, 3 ACs)

[Stage 3] Cross-Cutting Generation
  Generated: ProductsController.g.cs  (REST API)
  Generated: OrdersController.g.cs
  Generated: CustomersController.g.cs

[Stage 4] Traceability & Diagnostics
  Generated: TraceabilityMatrix.g.cs

Build succeeded. 23 files generated.
  warning REQ200: IOrderFulfillmentSpec is not implemented.
  warning REQ300: OrderFulfillmentFeature has no test class.

Project tree after Step 5:

MyStore/
├── src/
│   ├── MyStore.Requirements/
│   │   ├── Epics/DomainModelingEpic.cs
│   │   └── Features/OrderFulfillmentFeature.cs        ← Written (12 lines)
│   ├── MyStore.SharedKernel/
│   │   └── Result.cs                                   ← Template (15 lines)
│   ├── MyStore.Specifications/
│   │   └── IOrderFulfillmentSpec.cs                    ← Written (18 lines)
│   ├── MyStore.Lib/
│   │   ├── Catalog/
│   │   │   ├── Product.cs                              ← Written (25 lines)
│   │   │   └── obj/generated/
│   │   │       ├── Product.g.cs                        ← Generated
│   │   │       ├── ProductBuilder.g.cs                 ← Generated
│   │   │       └── ProductConfiguration.g.cs           ← Generated
│   │   └── Ordering/
│   │       ├── Order.cs                                ← Written (70 lines)
│   │       └── obj/generated/
│   │           ├── Order.g.cs                          ← Generated
│   │           ├── Order.Invariants.g.cs               ← Generated
│   │           ├── OrderBuilder.g.cs                   ← Generated
│   │           ├── OrderConfiguration.g.cs             ← Generated
│   │           └── OrderLineConfiguration.g.cs         ← Generated
│   ├── MyStore.Infrastructure.Postgres/
│   │   └── obj/generated/
│   │       ├── AppDbContext.g.cs                        ← Generated
│   │       ├── IProductRepository.g.cs                 ← Generated
│   │       ├── ProductRepository.g.cs                  ← Generated
│   │       ├── IOrderRepository.g.cs                   ← Generated
│   │       └── OrderRepository.g.cs                    ← Generated
│   └── MyStore.Server/
│       └── obj/generated/
│           ├── ProductsController.g.cs                 ← Generated
│           ├── OrdersController.g.cs                   ← Generated
│           └── CustomersController.g.cs                ← Generated
└── test/
    └── MyStore.Tests/                                  ← Empty (warnings)

Step 6: Add Content Types

Create src/MyStore.Lib/Content/BlogPost.cs:

namespace MyStore.Lib.Content;

[AggregateRoot("BlogPost", BoundedContext = "Content")]
[HasPart(typeof(RoutablePart))]
[HasPart(typeof(SeoablePart))]
[HasPart(typeof(TaggablePart))]
public partial class BlogPost
{
    [EntityId]
    public partial BlogPostId Id { get; }

    [Property("Title", Required = true, MaxLength = 200)]
    public partial string Title { get; }

    [Property("Author", Required = true)]
    public partial string Author { get; }

    [Property("PublishedDate")]
    public partial DateTime? PublishedDate { get; }

    [StreamField("Body", AllowedBlocks = new[]
    {
        typeof(RichTextBlock),
        typeof(ImageBlock),
        typeof(CodeBlock),
        typeof(QuoteBlock),
        typeof(ProductCarouselBlock)
    })]
    public partial StreamFieldValue Body { get; }

    [Invariant("Published posts must have a title")]
    private Result PublishedHasTitle()
    {
        if (PublishedDate.HasValue && string.IsNullOrWhiteSpace(Title))
            return Result.Failure("Published blog post must have a title");
        return Result.Success();
    }
}

Create src/MyStore.Lib/Content/Blocks/ProductCarouselBlock.cs:

namespace MyStore.Lib.Content.Blocks;

[ContentBlock("ProductCarousel")]
public partial class ProductCarouselBlock
{
    [BlockField("Title", "string", MaxLength = 100)]
    public partial string Title { get; }

    [BlockField("ProductIds", "Guid[]")]
    public partial Guid[] ProductIds { get; }

    [BlockField("MaxItems", "int")]
    public partial int MaxItems { get; }
}

Build:

dotnet build
[Stage 2] Core Generation
  Generated: BlogPost.g.cs
  Generated: BlogPostBuilder.g.cs
  Generated: BlogPostConfiguration.g.cs (with part columns + JSON body)
  Generated: ProductCarouselBlock.g.cs

[Stage 3] Cross-Cutting Generation
  Generated: BlogPostsController.g.cs
  Generated: ProductCarouselWidget.g.razor (Blazor WASM component)

Build succeeded. 29 files generated.

Step 7: Build Admin Modules

Create src/MyStore.Lib/Admin/AdminModules.cs:

namespace MyStore.Lib.Admin;

using MyStore.Lib.Catalog;
using MyStore.Lib.Ordering;
using MyStore.Lib.Content;

[AdminModule("Products", Entity = typeof(Product),
    ListFields = new[] { "Name", "Sku", "Price.Amount", "StockQuantity" },
    FilterFields = new[] { "Name", "Sku" },
    SortDefault = "Name")]
public partial class ProductsAdmin { }

[AdminModule("Orders", Entity = typeof(Order),
    ListFields = new[] { "OrderDate", "Status", "CustomerId", "Lines.Count" },
    FilterFields = new[] { "Status", "OrderDate" },
    SortDefault = "-OrderDate")]
public partial class OrdersAdmin { }

[AdminModule("BlogPosts", Entity = typeof(BlogPost),
    ListFields = new[] { "Title", "Author", "PublishedDate", "Tags" },
    FilterFields = new[] { "Author", "Tags" },
    SortDefault = "-PublishedDate")]
public partial class BlogPostsAdmin { }

Build:

dotnet build
[Stage 3] Cross-Cutting Generation
  Generated: ProductsAdminList.g.razor
  Generated: ProductsAdminForm.g.razor
  Generated: ProductsAdminDetail.g.razor
  Generated: OrdersAdminList.g.razor
  Generated: OrdersAdminForm.g.razor
  Generated: OrdersAdminDetail.g.razor
  Generated: BlogPostsAdminList.g.razor
  Generated: BlogPostsAdminForm.g.razor (with StreamField editor)
  Generated: BlogPostsAdminDetail.g.razor
  Generated: AdminLayout.g.razor (sidebar with 3 modules)
  Generated: AdminRoutes.g.cs

Build succeeded. 40 files generated.

Step 8: Create Page Tree

Create src/MyStore.Lib/Pages/SitePages.cs:

namespace MyStore.Lib.Pages;

using MyStore.Lib.Catalog;
using MyStore.Lib.Content;

[Page("Home", Template = "home", IsRoot = true)]
[Zone("hero")]
[Zone("featured")]
[Zone("content")]
public partial class HomePage { }

[Page("Catalog", Template = "catalog", Parent = typeof(HomePage))]
[Zone("filters")]
[Zone("products")]
[BoundEntity(typeof(Product), UrlPattern = "/catalog/{Slug}")]
public partial class CatalogPage { }

[Page("Product Detail", Template = "product-detail",
    Parent = typeof(CatalogPage))]
[Zone("main")]
[Zone("related")]
public partial class ProductDetailPage { }

[Page("Blog", Template = "blog", Parent = typeof(HomePage))]
[Zone("posts")]
[Zone("sidebar")]
[BoundEntity(typeof(BlogPost), UrlPattern = "/blog/{Slug}")]
public partial class BlogPage { }

// Widget placements
[WidgetPlacement(Page = typeof(HomePage), Zone = "hero",
    Widget = typeof(HeroBannerWidget), Order = 1)]
[WidgetPlacement(Page = typeof(HomePage), Zone = "featured",
    Widget = typeof(ProductCarouselBlock), Order = 1)]
[WidgetPlacement(Page = typeof(BlogPage), Zone = "sidebar",
    Widget = typeof(TagCloudWidget), Order = 1)]
public partial class DefaultWidgetPlacements { }

Build:

dotnet build
[Stage 3] Cross-Cutting Generation
  Generated: HomePageComponent.g.razor
  Generated: CatalogPageComponent.g.razor
  Generated: ProductDetailPageComponent.g.razor
  Generated: BlogPageComponent.g.razor
  Generated: PageRouter.g.cs (materialized path routing)
  Generated: SitemapGenerator.g.cs

Build succeeded. 46 files generated.

Step 9: Set Up Workflow

Create src/MyStore.Lib/Workflows/EditorialWorkflow.cs:

namespace MyStore.Lib.Workflows;

using MyStore.Lib.Content;

[Workflow("Editorial", AttachedTo = typeof(BlogPost))]
[Stage("Draft", IsInitial = true)]
[Stage("Review")]
[Stage("Translation", ForEachLocale = true)]
[Stage("Published", IsFinal = true)]
[Transition("Draft", "Review",
    Gate = "RequiresRole('editor')")]
[Transition("Review", "Translation",
    Gate = "RequiresRole('reviewer')")]
[Transition("Translation", "Published",
    Gate = "AllLocalesComplete AND RequiresRole('publisher')")]
[Transition("Review", "Draft",
    Gate = "RequiresRole('reviewer')",
    Label = "Reject")]
public partial class EditorialWorkflow { }

Build:

dotnet build
[Stage 3] Cross-Cutting Generation
  Generated: EditorialWorkflowStateMachine.g.cs
  Generated: EditorialWorkflowGuards.g.cs
  Generated: BlogPostWorkflowService.g.cs

Build succeeded. 49 files generated.

Step 10: Implement Domain Service

Create src/MyStore.Lib/Ordering/Services/OrderFulfillmentService.cs:

namespace MyStore.Lib.Ordering.Services;

using MyStore.Specifications;
using MyStore.Requirements.Features;
using MyStore.SharedKernel;

[ForRequirement(typeof(OrderFulfillmentFeature))]
public class OrderFulfillmentService : IOrderFulfillmentSpec
{
    private readonly IOrderRepository _orders;
    private readonly IProductRepository _products;

    public OrderFulfillmentService(
        IOrderRepository orders,
        IProductRepository products)
    {
        _orders = orders;
        _products = products;
    }

    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBePlaced))]
    public Result PlaceOrder(User customer, Product product, int quantity)
    {
        if (quantity <= 0)
            return Result.Failure("Quantity must be positive");

        if (product.StockQuantity < quantity)
            return Result.Failure(
                $"Insufficient stock: {product.StockQuantity} available, " +
                $"{quantity} requested");

        var line = new OrderLineBuilder()
            .WithProductName(product.Name)
            .WithQuantity(quantity)
            .WithUnitPrice(product.Price)
            .WithLineTotal(new Money(
                product.Price.Amount * quantity,
                product.Price.Currency))
            .Build();

        var order = new OrderBuilder()
            .WithOrderDate(DateTime.UtcNow)
            .WithStatus(OrderStatus.Placed)
            .WithCustomer(customer.Id)
            .AddLine(line.Value)
            .Build();

        return order.IsSuccess
            ? Result.Success()
            : Result.Failure(order.Reason!);
    }

    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBeCancelled))]
    public Result CancelOrder(User customer, Order order)
    {
        if (order.Status == OrderStatus.Shipped)
            return Result.Failure("Cannot cancel a shipped order");

        if (order.Status == OrderStatus.Delivered)
            return Result.Failure("Cannot cancel a delivered order");

        if (order.Status == OrderStatus.Cancelled)
            return Result.Failure("Order is already cancelled");

        // Domain logic: update status
        return Result.Success();
    }

    [ForRequirement(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderTotalIsCorrect))]
    public Result VerifyOrderTotal(Order order, decimal expectedTotal)
    {
        var actualTotal = order.Lines.Sum(l => l.LineTotal.Amount);

        return actualTotal == expectedTotal
            ? Result.Success()
            : Result.Failure(
                $"Expected total {expectedTotal}, " +
                $"actual total {actualTotal}");
    }
}

Build:

dotnet build
Build succeeded. 49 files generated.

info  REQ203: IOrderFulfillmentSpec: fully implemented by
              OrderFulfillmentService with complete [ForRequirement] coverage.
warning REQ300: OrderFulfillmentFeature has no test class.

REQ200 is gone (implementation exists). REQ300 remains (no tests yet).


Step 11: Write Tests

Create test/MyStore.Tests/Ordering/OrderFulfillmentTests.cs:

namespace MyStore.Tests.Ordering;

using MyStore.Requirements.Features;
using MyStore.Lib.Ordering.Services;
using MyStore.Lib.Catalog;
using MyStore.SharedKernel;

[TestFixture]
[TestsFor(typeof(OrderFulfillmentFeature))]
public class OrderFulfillmentTests
{
    private OrderFulfillmentService _service;
    private User _customer;
    private Product _product;

    [SetUp]
    public void Setup()
    {
        _service = new OrderFulfillmentService(
            new InMemoryOrderRepository(),
            new InMemoryProductRepository());

        _customer = new User(
            new UserId(Guid.NewGuid(), "Alice", "Customer",
                new Email("alice@example.com")),
            "Alice",
            new HashSet<Role>());

        _product = new ProductBuilder()
            .WithName("Laptop")
            .WithSku("LAP-001")
            .WithPrice(new Money(999.99m, "USD"))
            .WithStockQuantity(10)
            .Build().Value;
    }

    [Test]
    [Verifies(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBePlaced))]
    public void Customer_can_place_order_with_valid_product()
    {
        var result = _service.PlaceOrder(_customer, _product, 2);
        Assert.That(result.IsSuccess, Is.True);
    }

    [Test]
    [Verifies(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBePlaced))]
    public void Cannot_place_order_with_zero_quantity()
    {
        var result = _service.PlaceOrder(_customer, _product, 0);
        Assert.That(result.IsSuccess, Is.False);
        Assert.That(result.Reason, Does.Contain("Quantity must be positive"));
    }

    [Test]
    [Verifies(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBeCancelled))]
    public void Can_cancel_placed_order()
    {
        var order = CreatePlacedOrder();
        var result = _service.CancelOrder(_customer, order);
        Assert.That(result.IsSuccess, Is.True);
    }

    [Test]
    [Verifies(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderCanBeCancelled))]
    public void Cannot_cancel_shipped_order()
    {
        var order = CreateShippedOrder();
        var result = _service.CancelOrder(_customer, order);
        Assert.That(result.IsSuccess, Is.False);
        Assert.That(result.Reason,
            Does.Contain("Cannot cancel a shipped order"));
    }

    [Test]
    [Verifies(typeof(OrderFulfillmentFeature),
        nameof(OrderFulfillmentFeature.OrderTotalIsCorrect))]
    public void Order_total_matches_line_totals()
    {
        var order = CreateOrderWithLines(
            new Money(10.00m, "USD"),
            new Money(20.00m, "USD"));
        var result = _service.VerifyOrderTotal(order, 30.00m);
        Assert.That(result.IsSuccess, Is.True);
    }

    // Helper methods
    private Order CreatePlacedOrder()
    {
        return new OrderBuilder()
            .WithOrderDate(DateTime.UtcNow)
            .WithStatus(OrderStatus.Placed)
            .WithCustomer(_customer.Id)
            .AddLine(new OrderLineBuilder()
                .WithProductName("Laptop")
                .WithQuantity(1)
                .WithUnitPrice(new Money(999.99m, "USD"))
                .WithLineTotal(new Money(999.99m, "USD"))
                .Build().Value)
            .Build().Value;
    }

    private Order CreateShippedOrder()
    {
        return new OrderBuilder()
            .WithOrderDate(DateTime.UtcNow)
            .WithStatus(OrderStatus.Shipped)
            .WithCustomer(_customer.Id)
            .AddLine(new OrderLineBuilder()
                .WithProductName("Laptop")
                .WithQuantity(1)
                .WithUnitPrice(new Money(999.99m, "USD"))
                .WithLineTotal(new Money(999.99m, "USD"))
                .Build().Value)
            .WithShippingAddress(new ShippingAddress(
                "123 Main St", "Springfield", "62704", "US"))
            .Build().Value;
    }

    private Order CreateOrderWithLines(params Money[] lineTotals)
    {
        var builder = new OrderBuilder()
            .WithOrderDate(DateTime.UtcNow)
            .WithStatus(OrderStatus.Placed)
            .WithCustomer(_customer.Id);

        foreach (var total in lineTotals)
        {
            builder.AddLine(new OrderLineBuilder()
                .WithProductName("Item")
                .WithQuantity(1)
                .WithUnitPrice(total)
                .WithLineTotal(total)
                .Build().Value);
        }

        return builder.Build().Value;
    }
}

Build:

dotnet build
Build succeeded. 49 files generated.

info  REQ103: OrderFulfillmentFeature: all 3 ACs specified.
info  REQ203: IOrderFulfillmentSpec: fully implemented.
info  REQ303: OrderFulfillmentFeature: all 3 ACs have [Verifies] tests.
              OrderCanBePlaced: 2 tests
              OrderCanBeCancelled: 2 tests
              OrderTotalIsCorrect: 1 test

0 errors, 0 warnings.

All REQ diagnostics are now green. Every AC is specified, implemented, and tested.


Step 12: Run Quality Gates

Run Tests

dotnet test --collect:"XPlat Code Coverage" --logger:trx \
    --results-directory TestResults
Test run for MyStore.Tests.dll (.NET 10.0)
Microsoft (R) Test Execution Engine
Starting test execution, please wait...

Passed!  - Failed:  0, Passed:  5, Skipped:  0, Total:  5
         Duration: 1.2 s

Results File: TestResults/MyStore.Tests_2026-03-19.trx
Attachments:
  TestResults/.../coverage.cobertura.xml

Run Quality Gates

dotnet quality-gates check \
    --trx TestResults/*.trx \
    --coverage TestResults/**/coverage.cobertura.xml \
    --min-pass-rate 100 \
    --min-coverage 80 \
    --max-duration 5000 \
    --fuzz-inputs 500
Quality Gates Report
====================

FEATURE: OrderFulfillmentFeature (3 ACs, 5 tests)

  [REQ400] Pass Rate
    OrderCanBePlaced:       2/2 passed                    PASS
    OrderCanBeCancelled:    2/2 passed                    PASS
    OrderTotalIsCorrect:    1/1 passed                    PASS

  [REQ401] AC Coverage
    OrderCanBePlaced:       covered                       PASS
    OrderCanBeCancelled:    covered                       PASS
    OrderTotalIsCorrect:    covered                       PASS

  [REQ402] Code Coverage
    OrderFulfillmentService.PlaceOrder:         92%       PASS (>= 80%)
    OrderFulfillmentService.CancelOrder:        88%       PASS (>= 80%)
    OrderFulfillmentService.VerifyOrderTotal:   100%      PASS (>= 80%)

  [REQ403] Duration
    Customer_can_place_order:                   18ms      PASS (< 5000ms)
    Cannot_place_order_zero_quantity:            4ms       PASS
    Can_cancel_placed_order:                    12ms      PASS
    Cannot_cancel_shipped_order:                 6ms      PASS
    Order_total_matches_line_totals:             8ms      PASS

  [REQ405] Fuzz Testing
    OrderCanBePlaced:       500 inputs, 0 crashes         PASS
      478 Result.Success, 22 Result.Failure (expected)
    OrderCanBeCancelled:    500 inputs, 0 crashes         PASS
      312 Result.Success, 188 Result.Failure (expected)
    OrderTotalIsCorrect:    500 inputs, 0 crashes         PASS
      500 Result.Success, 0 Result.Failure

Summary
-------
OrderFulfillmentFeature: 5/5 gates passed
Overall: PASS (exit code 0)

All gates pass. The chain is complete.


Step 13: Deploy

# Build production image
dotnet publish src/MyStore.Server -c Release -o publish

# Or Docker
docker build -t mystore:latest .
docker run -p 8080:8080 mystore:latest
MyStore.Server starting...

info: RequirementComplianceCheck[0]
      ── Requirement Compliance Report ──
info: RequirementComplianceCheck[0]
      Order fulfillment and lifecycle: 3/3 ACs covered
info: RequirementComplianceCheck[0]
      ── All requirements verified ──

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:8080

The startup compliance check confirms all requirements are covered before the application accepts traffic.


Step 14: Review What Was Generated

Lines Written vs Lines Generated

Developer-Written Code
======================
MyStore.Requirements/
  Epics/DomainModelingEpic.cs                   8 lines
  Features/OrderFulfillmentFeature.cs           18 lines

MyStore.SharedKernel/
  Result.cs                                     15 lines

MyStore.Specifications/
  IOrderFulfillmentSpec.cs                      20 lines

MyStore.Lib/
  Catalog/Product.cs                            28 lines
  Ordering/Order.cs                             75 lines
  Content/BlogPost.cs                           32 lines
  Content/Blocks/ProductCarouselBlock.cs        12 lines
  Admin/AdminModules.cs                         22 lines
  Pages/SitePages.cs                            30 lines
  Workflows/EditorialWorkflow.cs                14 lines
  Ordering/Services/OrderFulfillmentService.cs  55 lines

MyStore.Tests/
  Ordering/OrderFulfillmentTests.cs             95 lines
                                          ────────────
  TOTAL WRITTEN:                           ~324 lines

Generated Code (by dotnet build)
================================
Domain entities (backing fields, properties)    ~600 lines
Fluent builders                                 ~400 lines
EnsureInvariants() methods                       ~60 lines
EF Core configurations                          ~500 lines
EF Core DbContext                               ~100 lines
Repository interfaces                           ~120 lines
Repository implementations                     ~300 lines
REST API controllers                            ~600 lines
Blazor admin modules (list, form, detail)     ~3,000 lines
Blazor page components                          ~800 lines
Blazor content block widgets                    ~400 lines
Page router + sitemap                           ~200 lines
Workflow state machines + guards                ~300 lines
RequirementRegistry.g.cs                         ~50 lines
TraceabilityMatrix.g.cs                          ~80 lines
ForRequirement/Verifies/TestsFor attributes      ~40 lines
GraphQL schema types                            ~400 lines
OpenAPI enrichment                              ~200 lines
                                          ────────────
  TOTAL GENERATED:                        ~8,150 lines

Ratio: ~1:25 (324 written : 8,150 generated)

In a full-featured application with more aggregates, content types, and requirements, this ratio approaches 1:50. The developer writes the domain model and the requirements. The compiler writes everything else.

Generated Artifacts Flow

Diagram

Final Project Structure

Diagram

End-to-End Sequence

Diagram

Summary

This walkthrough demonstrated the full CMF lifecycle:

Step Action Lines Written Artifacts
1 cmf new 0 Solution scaffold
2 Define requirements 18 1 feature, 3 ACs
3 Create specifications 20 1 interface
4 Model domain 135 3 aggregates, entities, VOs
5 dotnet build 0 23 generated files
6 Add content types 44 BlogPost + blocks
7 Build admin 22 3 admin modules
8 Create pages 30 4 pages, widgets
9 Set up workflow 14 Editorial workflow
10 Implement service 55 OrderFulfillmentService
11 Write tests 95 5 type-linked tests
12 Quality gates 0 All gates pass
13 Deploy 0 Production binary
Total ~324 lines ~8,150 generated

The developer wrote the "what" (requirements, domain model, content types). The compiler wrote the "how" (entities, persistence, API, admin, pages, workflow engine, traceability). At every step, the analyzers guided the developer: missing specification, missing implementation, missing tests. The quality gates verified that tests pass, coverage meets thresholds, and fuzz testing found no crashes.

Three hundred and twenty-four lines of intent. Eight thousand one hundred and fifty lines of infrastructure. One compiler. Zero strings. The chain is complete.