agentsclimarketplace

Bpmn workflow

Skill rynhardt-potgieter/sprint_workflow/plugins/sprint-workflow/skills/bpmn-workflow

A portable Claude Code plugin system for orchestrating software development through parallel specialist agents, enforced engineering standards, and automated quality gates. One command to plan. Parallel agents to build. Automated gates to ship.

Install
npx -y skills add rynhardt-potgieter/sprint_workflow --skill bpmn-workflow

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

BPMN 2.0 workflow engine standards — process modeling, gateway patterns (exclusive/parallel/inclusive), human tasks, timer events, error handling, compensation, state machines, and workflow persistence. Use this skill when implementing workflow engine features, designing process definitions, building gateway logic, implementing human task flows, or working with the workflow builder.

SKILL.md

8.4 KB, as published. Nobody here has run it

BPMN 2.0 & Workflow Engine Standards

This skill defines patterns for workflow engine implementation following BPMN 2.0 standards.

BPMN 2.0 Core Concepts

Element Types

BPMN ElementOur ImplementationShape
Start EventTrigger node (Manual, Cron, Webhook)Circle
End EventEnd nodeCircle (thick border)
TaskAction node (HTTP, DB, Email, etc.)Rounded rectangle
User TaskHuman Task nodeRounded rectangle with person icon
Exclusive GatewayDecision node — ONE path takenDiamond
Parallel GatewaySplit & Wait — ALL paths, no conditionsDiamond
Inclusive GatewayMatch node — MATCHING paths takenDiamond
Timer EventDelay nodeCircle with clock
Sub-ProcessFor Each (loop) nodeRounded rectangle with scope zone

Gateway Semantics (CRITICAL)

Exclusive Gateway (Decision — XOR)

  • Evaluates conditions on outgoing edges in order
  • Takes the first matching path
  • Must have a default path (fallback)
  • Conditions live on edges, not the gateway node
  • Gateway ConfigPanel shows: question label + outgoing path summary
  • User clicks an edge to open the ConditionBuilder

Parallel Gateway (Split & Wait — AND)

  • Splits: ALL outgoing paths fire unconditionally
  • Joins: Waits for ALL incoming paths before continuing
  • NO conditions — ever. ConditionBuilder must NEVER appear for parallel edges
  • Use for concurrent operations (e.g., "send email AND update inventory AND notify Slack")

Inclusive Gateway (Match — OR)

  • Evaluates conditions on all outgoing edges
  • Takes ALL matching paths (not just the first)
  • Must have a default path for when nothing matches
  • Join waits only for the paths that were actually taken

Anti-Patterns

  • Conditions on parallel gateway edges (BPMN violation)
  • Missing default paths on exclusive/inclusive gateways (creates dead-end workflows)
  • Deeply nested gateways (>3 levels) — refactor into sub-processes
  • Gateway nodes trying to hold business logic — gateways ROUTE, they don't COMPUTE

Workflow Engine Architecture

Instance Lifecycle

Created → Running → [Suspended | WaitingForHuman | Completed | Failed]
                         ↓                ↓
                      Running          Running (on resume)

State Machine Rules

public enum WorkflowStatus
{
    Pending,            // Created but not started
    Running,            // Currently executing
    Suspended,          // Waiting on timer/retry
    WaitingForHuman,    // Human task pending
    Completed,          // Successfully finished
    Failed              // Unrecoverable error
}

Valid transitions:

  • Pending → Running (trigger fires)
  • Running → Completed (reached end node)
  • Running → Failed (unrecoverable error)
  • Running → Suspended (delay, retry backoff)
  • Running → WaitingForHuman (human task created)
  • Suspended → Running (timer/retry fires)
  • WaitingForHuman → Running (human approves/rejects)

Execution Model

public async Task ExecuteInstanceAsync(WorkflowInstance instance, CancellationToken ct)
{
    instance.Status = WorkflowStatus.Running;
    instance.ErrorCode = null;      // Clear stale errors from retry
    instance.ErrorMessage = null;

    while (instance.CurrentNodeId != null)
    {
        var node = graph.GetNode(instance.CurrentNodeId);
        var executor = _registry.Resolve(node.Type);

        var result = await executor.ExecuteAsync(context);

        // Handle result: advance to next node, suspend, complete, or fail
    }
}

Node System

Node Contract

Every node type has:

  1. Descriptor (backend): Declares params, default outputs, category
  2. Executor (backend): Implements ExecuteAsync, produces output DataBag
  3. Definition (frontend): Mirrors descriptor — params, outputs, display info

Output Contract

// Descriptor declares what the executor produces
public OutputFieldDef[] DefaultOutputs => new[]
{
    new OutputFieldDef("order_id", "Order ID", OutputType.String),
    new OutputFieldDef("total", "Total Amount", OutputType.Number),
};

// Executor MUST set exactly these keys
output.Set("order_id", orderId);
output.Set("total", totalAmount);

CRITICAL: DefaultOutputs keys must EXACTLY match executor DataBag keys AND frontend nodeDefinitions.ts keys. All three locations must stay in sync.

Expression Evaluation

  • Nodes reference upstream outputs via {{ nodes.node_1.field_name }}
  • Expression evaluator resolves at runtime from WorkflowVariables
  • After JSON round-trip (suspend/resume), values are JsonElement — evaluator handles both CLR types and JsonElement

Test Mode

public async Task ExecuteAsync(NodeContext ctx)
{
    if (ctx.IsTest)
    {
        ctx.Output.Set("result", "[TEST] Simulated output");
        return;
    }
    // Real execution...
}

Side-effecting executors MUST check ctx.IsTest. Read-only executors don't need guards.

Human Tasks

Flow

  1. Workflow reaches Human Task node → status becomes WaitingForHuman
  2. Task appears in user's task list (SSE notification sent)
  3. User reviews data, makes decision (approve/reject/custom)
  4. POST /api/workflows/{id}/resume with decision payload
  5. Engine resumes, stores payload under vars["__resume"] (namespaced)
  6. Downstream nodes access via {{ __resume.decision }}

Resume Payload Safety

CRITICAL: Never merge resume payloads into top-level workflow variables. Namespace under __resume to prevent variable collision with downstream node configs.

Timer & Scheduling

Delay Node

// Suspend instance with ResumeAfter timestamp
instance.Status = WorkflowStatus.Suspended;
instance.ResumeAfter = DateTimeOffset.UtcNow.Add(delay);

Cron Triggers

  • Use Cronos library for cron expression evaluation
  • Scheduler polls every 30s for due triggers
  • Track _lastFired per definition to prevent double-firing

Retry with Backoff

instance.Status = WorkflowStatus.Suspended;
instance.ErrorCode = "TRANSIENT_FAILURE";  // MUST set for scheduler to distinguish retry from delay
instance.ResumeAfter = DateTimeOffset.UtcNow.AddSeconds(Math.Pow(2, instance.RetryCount));

Error Handling

Transient vs Permanent Errors

TypeExampleAction
TransientHTTP 503, timeout, connection refusedRetry with backoff (max 3 attempts)
Permanent404, validation failure, business ruleFail immediately with clear error message
CompensationPartial completion of multi-stepRun compensation handlers

Error Propagation

try
{
    await executor.ExecuteAsync(context);
}
catch (TransientException ex)
{
    instance.RetryCount++;
    if (instance.RetryCount >= MaxRetries)
    {
        instance.Status = WorkflowStatus.Failed;
        instance.ErrorMessage = $"Max retries exceeded: {ex.Message}";
    }
    else
    {
        instance.Status = WorkflowStatus.Suspended;
        instance.ErrorCode = "TRANSIENT_FAILURE";
        instance.ResumeAfter = CalculateBackoff(instance.RetryCount);
    }
}
catch (Exception ex)
{
    instance.Status = WorkflowStatus.Failed;
    instance.ErrorMessage = ex.Message;
}

Graph Persistence

  • Workflow definitions stored as JSON graph in database
  • Graph deserialization MUST use JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower) to match global config
  • Node positions, connections, and configs all serialized
  • On load: advance nextNodeId past all existing IDs to prevent collisions

UX Principles (The Non-Technical User Test)

"Can a non-technical user who uses basic office tools daily but has never written a formula, build this workflow in under 5 minutes without help?"

  • Zero syntax — no brackets, dots, or template expressions visible to users
  • Human-readable labels — "Split & Wait" not "Parallel Split"
  • Click-to-configure — data pills for expressions, not text input
  • Conditions on edges — not in gateway config panels
  • Visual scope zones — For Each loops show a tinted region

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.