e-naxosMAF COURSE / COURS
Français

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Demo320 — Durable Approval

After start: Waiting, zero rows. After approve: Completed, StoredItem and ItemId. After identical resume: same ItemId, exactly one row. Retain the waiting receipt to force real checkpoint replay.

Objectives

Prepare the program

No model, embeddings, container or secret required. Start at the root of the complete distribution. Preserve shared projects and configuration files. Some historical prompts and labels in Demo260–290 remain French in public code; commands and identifiers match this revision.

dotnet build BaseTechnique.slnx -m:1 -c Release
Required projects
ProjectRole
demos/Demo320_DurableApproval/Demo320.App.csprojApp
shared/Maf.Durable/Maf.Durable.csprojShared implementation

Commands from the root

$state = Join-Path $env:TEMP ('maf-demo320-' + [guid]::NewGuid().ToString('N'))
dotnet run --project demos/Demo320_DurableApproval/Demo320.App.csproj -c Release --no-build -- start $state
dotnet run --project demos/Demo320_DurableApproval/Demo320.App.csproj -c Release --no-build -- status $state
dotnet run --project demos/Demo320_DurableApproval/Demo320.App.csproj -c Release --no-build -- resume $state approve
dotnet run --project demos/Demo320_DurableApproval/Demo320.App.csproj -c Release --no-build -- resume $state approve
dotnet run --project demos/Demo320_DurableApproval/Demo320.App.csproj -c Release --no-build -- status $state

Procedures and variants

Run the sequence below then the refusal/replay exercise. Each command is a separate process and must reuse the same directory.

public ApprovalState Apply(ApprovalDecision decision)
{
    RecordDecision(decision);
    using var connection = Open();
    using var transaction = connection.BeginTransaction();
    using var command = connection.CreateCommand();
    command.Transaction = transaction;
    command.CommandText = """
        INSERT INTO ApprovedBacklogItems (OperationId,Draft,CreatedUtc)
        SELECT OperationId,Draft,$utc FROM Approvals WHERE OperationId=$id AND Status IN ('Approved','Completed')
        ON CONFLICT(OperationId) DO NOTHING;
        UPDATE Approvals SET Status='Completed' WHERE OperationId=$id AND Status='Approved';
        """;
    command.Parameters.AddWithValue("$id", decision.OperationId);
    command.Parameters.AddWithValue("$utc", DateTimeOffset.UtcNow.ToString("O"));
    command.ExecuteNonQuery();
    transaction.Commit();
    return Read(decision.OperationId);

shared/Maf.Durable/ApprovalStore.cs · L80–L97 · 9a895c94534c

Source code · Maf.Durable · Folder

What must be observable

After start: Waiting, zero rows. After approve: Completed, StoredItem and ItemId. After identical resume: same ItemId, exactly one row. Retain the waiting receipt to force real checkpoint replay.

These results are expected from the linked code. Checks actually rerun for this lot are distinguished in exercises and reception; no unmeasured live output is presented as observed.

Limits and retained state

Demo300 responds in the live process; Demo310 retains its manager in memory; only Demo320 stores file checkpoints for another-process recovery. SQLite exists in all three variants. Local row uniqueness, no distributed exactly-once. The CLI trusts its operator without reviewer authentication.

dotnet test tests/Maf.Durable.Tests/Maf.Durable.Tests.csproj -m:1 -c Release --no-build --no-restore

Contracts and prerequisites

Prerequisites

Continue reading

Complete demo folder · README

lot009-workflows-1 · 2026-10-24 · 9a895c94534cd5fc6f3da883e37e5f7856e588c1