Table of Contents

Guides

Each guide covers one task in depth, with compiled code, the real output it produced, and the edge cases you'll meet in production. New to RuleWright? Start with Get started or a tutorial.

Writing rules

Extending

Running in production

The facts these guides use

Every guide evaluates the same small model. Facts.Vip() is Aroha, a 34-year-old gold VIP in New Zealand with a three-line order. Facts.Newcomer() is Ben, 17, with no country on file and a single small order.

public sealed class Checkout
{
    public Customer Customer { get; set; } = new();
    public Order Order { get; set; } = new();
}

public sealed class Customer
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
    public string Tier { get; set; } = "standard";
    public bool IsVip { get; set; }
    public int LoyaltyYears { get; set; }
    public string? Country { get; set; }
    public string? Email { get; set; }
}

public sealed class Order
{
    public decimal Total { get; set; }
    public int ItemCount { get; set; }
    public decimal Weight { get; set; }
    public string? Coupon { get; set; }
    public DateTime PlacedOn { get; set; }
    public List<OrderLine> Lines { get; set; } = new();
    public List<string> Tags { get; set; } = new();
}

public sealed class OrderLine
{
    public string Sku { get; set; } = "";
    public string Category { get; set; } = "";
    public int Quantity { get; set; }
    public decimal Price { get; set; }
}
/// <summary>Ready-made facts, so each sample shows only the part it is about.</summary>
internal static class Facts
{
    /// <summary>A loyal adult VIP with a three-line order placed on a Saturday.</summary>
    public static Checkout Vip() => new()
    {
        Customer = new Customer { Name = "Aroha", Age = 34, Tier = "gold", IsVip = true, LoyaltyYears = 6, Country = "NZ", Email = "aroha@example.com" },
        Order = new Order
        {
            Total = 240m,
            ItemCount = 4,
            Weight = 2.5m,
            PlacedOn = new DateTime(2026, 9, 19, 10, 30, 0, DateTimeKind.Utc),
            Lines =
            {
                new OrderLine { Sku = "TEA-01", Category = "grocery", Quantity = 2, Price = 45m },
                new OrderLine { Sku = "WINE-12", Category = "alcohol", Quantity = 1, Price = 60m },
                new OrderLine { Sku = "MUG-07", Category = "homeware", Quantity = 1, Price = 90m },
            },
            Tags = { "gift", "priority" },
        },
    };

    /// <summary>A first-time teenage customer with one small order placed on a Tuesday.</summary>
    public static Checkout Newcomer() => new()
    {
        Customer = new Customer { Name = "Ben", Age = 17, Tier = "standard", LoyaltyYears = 0, Country = null, Email = "not-an-email" },
        Order = new Order
        {
            Total = 35m,
            ItemCount = 1,
            Weight = 0.4m,
            PlacedOn = new DateTime(2026, 9, 22, 14, 0, 0, DateTimeKind.Utc),
            Lines = { new OrderLine { Sku = "PEN-02", Category = "stationery", Quantity = 1, Price = 35m } },
        },
    };
}

Unless a guide says otherwise, engine is built as in Your first rule, with UseJsonReader(new SystemTextJsonReader()).