Pure decisions
Business rules stay as ordinary functions. No database, publisher, clock, or hidden I/O.
Pure functional DDD, declarative sagas, and versioned contracts—designed so the correct path is the one your code naturally takes.
dotnet add package Wyrd01 / THE PROBLEM
A duplicated message charges twice. A missing timeout waits forever. A failed compensation leaves stock reserved. It all compiles—and often passes the tests.
02 / THE MODEL
Wyrd draws a hard line between decisions and effects, then makes that line useful.
Business rules stay as ordinary functions. No database, publisher, clock, or hidden I/O.
Retries, timeouts, idempotency, compensation, and delivery belong to the framework.
Run, draw, inspect, simulate and replay one model, in memory or durable.
Roslyn analyzers catch broken public events while the change is still in your editor.
THE CHANGE IN PERSPECTIVE
DDD starts with understanding the business. Wyrd gives that understanding a more explicit shape in code.
An order can be cancelled. A payment can be declined. A reservation can expire. These are the decisions a product team needs to discuss, but their implementation often disappears inside handlers, transactions, and message plumbing.
Wyrd separates the rule from its execution: a command and current state produce a fact or a rejection. The state evolves from accepted facts. A process connects those local decisions into a business policy.
Your language, aggregate boundaries, and invariants still matter. The shift is that the decision no longer needs to know how a message is delivered or a state change is stored. You can review the rule on its own, test it from facts, and inspect the flow that connects it to the rest of the business.
03 / THE PROCESS
The process definition is immutable data. Steps are pure mappings from facts to intentions; Wyrd owns the messy mechanics around them.
public static Process OrderFulfillment => Process
.StartOn<OrderPlaced>(e => e.OrderId)
.Then(Stock.Reserve).Retry(5.Times).Undo(Stock.Release)
.Then(Payments.Charge).Retry(5.Times, Backoff.Exponential).Undo(Payments.Refund)
.Await<PaymentConfirmed>(e => e.OrderId).Within(15.Minutes)
.Then(Shipping.Ship).Retry(5.Times)
.OnCompensated(Orders.Cancel).Retry(5.Times);04 / THE THREE NORNS
In Norse myth, wyrd—fate—is woven by three Norns. The framework follows the same shape.
what will be
Run your scenario in hundreds of hostile futures, with faults, duplicates, and reordering, and replay any broken one by its seed.
what was
Capture a process instance, in memory or from the database, and replay its recorded replies and clock as a deterministic local test.
what is
Run the same module durable on EF Core (PostgreSQL, SQL Server): one transaction per message, integrations as the only I/O, explicit retention, operators, and RabbitMQ between services.
05 / PUBLIC CONTRACTS
Integration events are public APIs. Wyrd snapshots their shape and explains what changed, why it is unsafe, and how to fix it.
Breaking change: field Amount changed from decimal to double.
// An intention sent to exactly one owner
public sealed record ChargePayment(string OrderId, decimal Amount) : ICommand;
// An internal fact inside one bounded context
public sealed record PaymentCharged(string OrderId, decimal Amount) : IDomainEvent;
// A versioned public contract across boundaries
[IntegrationEvent("payments.payment-charged", Version = 1)]
public sealed record PaymentChargedV1(string OrderId, decimal Amount, string Currency)
: IIntegrationEvent;START WEAVING
Wyrd is pre-1.0: try the model in memory, run it durable, read the source, and help shape 1.0.