Optima.Net.Decisioning 1.0.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Optima.Net.Decisioning --version 1.0.0
                    
NuGet\Install-Package Optima.Net.Decisioning -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Optima.Net.Decisioning" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Optima.Net.Decisioning" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Optima.Net.Decisioning" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Optima.Net.Decisioning --version 1.0.0
                    
#r "nuget: Optima.Net.Decisioning, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Optima.Net.Decisioning@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Optima.Net.Decisioning&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Optima.Net.Decisioning&version=1.0.0
                    
Install as a Cake Tool

Optima.Net.Decisioning

Optima.Net.Decisioning is a minimal, immutable, framework‑agnostic representation of what a system decided and why — independent of how the decision was reached. It serves as the authoritative record of a decision outcome, not as an execution engine, workflow system, or evaluation framework.

Principles

Decisioning is built on these core tenets:

  • Outcome‑centric, not process‑centric.
  • Immutable facts — once created, decisions cannot be changed.
  • Framework‑agnostic — no dependency on domain, infrastructure, or orchestration systems.
  • Semantic clarity — decisions record meaning, not control flow.
  • Audit‑friendly — explicit metadata and evidence for traceability.

Key Concepts

Decision<TIntent, TResult>

Represents a completed decision, capturing:

  • Intent — what was attempted.
  • Outcome — what was decided.
  • Result — produced value, if any.
  • Evidence — optional diagnostics or context.
  • Metadata — audit information (timestamp, actor, correlation).
  • Negotiation — optional negotiated outcome.

DecisionOutcome

Semantic classification of the decision result:

public enum DecisionOutcome
{
    Approved,
    Rejected,
    CounterProposed,
    Deferred,
    Escalated,
    Indeterminate
}

DecisionMetadata

Contextual information that accompanies every decision:

public sealed record DecisionMetadata
{
    public DateTimeOffset Timestamp { get; init; } = DateTimeOffset.UtcNow;
    public Optional<string> CorrelationId { get; init; }
    public Optional<string> Actor { get; init; }
    public Optional<string> Source { get; init; }
}

INegotiationOutcome

Used to record the result of a negotiation without performing it:

public interface INegotiationOutcome
{
    NegotiationDisposition Disposition { get; }
    Optional<object> Proposal { get; }
    IReadOnlyCollection<object> Evidence { get; }
}

Example Domain Types

These classes are domain examples used to demonstrate how Decisioning can model real problems. These belong to your application layer, not the Decisioning library itself.

Intent

public sealed record InsuranceClaimIntent(
    string ClaimId,
    string PolicyNumber,
    decimal ClaimedAmount,
    string Reason);

Result / Proposal

public sealed record ClaimSettlementProposal(
    string ClaimId,
    decimal ApprovedAmount,
    string SettlementNotes);

Negotiation Outcome Implementation

public sealed class NegotiationOutcome : INegotiationOutcome
{
    public NegotiationDisposition Disposition { get; }
    public Optional<object> Proposal { get; }
    public IReadOnlyCollection<object> Evidence { get; }

    public NegotiationOutcome(
        NegotiationDisposition disposition,
        Optional<object> proposal,
        IReadOnlyCollection<object> evidence)
    {
        Disposition = disposition;
        Proposal = proposal;
        Evidence = evidence;
    }
}

Handling Decisions — Example Handler

This handler shows how you might produce a Decision<TIntent, TResult> in an application flow. It evaluates incoming intents, applies domain logic, and returns immutable decisions.

public static class InsuranceClaimDecisionHandler
{
    public static Decision<InsuranceClaimIntent, ClaimSettlementProposal> Handle(
        InsuranceClaimIntent intent)
    {
        var metadata = new DecisionMetadata
        {
            Actor = Optional<string>.Some("Claims.Adjudicator.System"),
            Source = Optional<string>.Some("Optima.Net.Decisioning.Handler"),
            CorrelationId = Optional<string>.Some(Guid.NewGuid().ToString())
        };

        // Negotiation example
        if (intent.ClaimedAmount == 12000m &&
            intent.Reason.Contains("hail", StringComparison.OrdinalIgnoreCase))
        {
            var counterProposal = new ClaimSettlementProposal(
                intent.ClaimId,
                9000m,
                "Partial approval under hail coverage clause #HAIL-2025.");

            var negotiation = Optional<INegotiationOutcome>.Some(
                new NegotiationOutcome(
                    NegotiationDisposition.Modified,
                    Optional<object>.Some(counterProposal),
                    new List<object>
                    {
                        "Customer initially requested $12,000 for full roof replacement.",
                        "Coverage capped at $9,000 under policy tier Silver.",
                        "Customer accepted counterproposal."
                    }));

            var evidence = Optional<IReadOnlyCollection<object>>.Some(
                new List<object> { "Negotiation concluded with partial payout agreement." });

            return new Decision<InsuranceClaimIntent, ClaimSettlementProposal>(
                intent,
                DecisionOutcome.CounterProposed,
                Optional<ClaimSettlementProposal>.Some(counterProposal),
                evidence,
                metadata,
                negotiation);
        }

        // Deferred: high-value claim
        if (intent.ClaimedAmount > 10000m)
        {
            var evidence = Optional<IReadOnlyCollection<object>>.Some(new List<object>
            {
                "Claim amount exceeds auto-approval threshold ($10,000).",
                "Manual review required under risk policy #RC-2025.",
                "No prior authorization found for high-value claim."
            });

            return new Decision<InsuranceClaimIntent, ClaimSettlementProposal>(
                intent,
                DecisionOutcome.Deferred,
                Optional<ClaimSettlementProposal>.None(),
                evidence,
                metadata,
                Optional<INegotiationOutcome>.None());
        }

        // Rejected: flood exclusion
        if (intent.Reason.Contains("flood", StringComparison.OrdinalIgnoreCase))
        {
            var evidence = Optional<IReadOnlyCollection<object>>.Some(new List<object>
            {
                "Flood damage not covered under current policy tier.",
                "Refer to exclusion clause #17B."
            });

            return new Decision<InsuranceClaimIntent, ClaimSettlementProposal>(
                intent,
                DecisionOutcome.Rejected,
                Optional<ClaimSettlementProposal>.None(),
                evidence,
                metadata,
                Optional<INegotiationOutcome>.None());
        }

        // Approved
        var settlement = new ClaimSettlementProposal(
            intent.ClaimId,
            intent.ClaimedAmount * 0.9m,
            "Approved under standard coverage terms.");

        return new Decision<InsuranceClaimIntent, ClaimSettlementProposal>(
            intent,
            DecisionOutcome.Approved,
            Optional<ClaimSettlementProposal>.Some(settlement),
            Optional<IReadOnlyCollection<object>>.None(),
            metadata,
            Optional<INegotiationOutcome>.None());
    }
}

Usage Summary

  1. Construct an intent object from your application logic.
  2. Invoke your handler to produce a Decision.
  3. The Decision object is immutable, semantically meaningful, and suitable for:
    • Auditing
    • Logging
    • Persistence
    • Event publication
    • Analytical inspection

Decisioning does not execute business logic — that belongs in your domain or application layer.


This project embodies a clear separation of concerns: your system decides — Decisioning records the outcome.
Optional fields explicitly represent presence or absence using Optional<T> from Optima.Net.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 120 1/8/2026
1.0.0 122 1/4/2026

RELEASENOTES.md