Skip to content
Phero Lang
Menu

.cmmn

Case management

Cases, plans and sentry criteria

Backend

consumed byphero-backend-cmmn

CMMN 1.1 case models: case files, discretionary and required plan items, sentries, and decision tasks that invoke sibling decision services.

Why it exists

What .cmmn is for

A .cmmn file declares a case: the adaptive, event-and-condition-driven work coordinated around a domain — the CMMN 1.1 notion of case management, not a workflow and not a state machine. The plan declares the work that is available (tasks, service tasks, milestones, grouped into stages) and the criteria under which each item activates, without prescribing a sequence.

The division of responsibility is explicit: the domain owns the data and its invariants, the domain lifecycle (.ddd machines) owns an aggregate’s valid transitions, the case owns the work, and the engine executes. Sibling tasks are concurrent by default; ordering exists only where a criterion imposes it.

Vocabulary

What it models

The concepts .cmmn declares, and what each one means to the compiler.

case
The declaration. Plan items and case-file items share one namespace per case.
roles
role <name> as <Actor>: the .actor principals who fill the work.
case_file
Typed case-file items (Ticket[1..1] ticket), resolved against the imported domain.
stage
A grouping of plan items.
task
A human task. A discretionary task is available but not required; a plain task is required once activated.
service item
execute <service>.<operation>: automation bound to an operation the imported design declares.
decision item
invokes <DecisionModel>.<service> with inputs and outputs: the sibling .dmn decision service as case work.
milestone
A reachable goal state.
entry / exit criteria
on <item>.<event> when (<expr>): the sentries that activate or terminate an item.

Source

A working example

Quoted from the example this page's artifact was compiled from — not a snippet written for the website.

Lines 42–57 of examples/support/support.cmmn, reproduced byte for byte, read from the file at build time:

examples/support/support.cmmn · lines 42–57
        service AssessRefund {
            execute support.TicketService.raiseRefund;
            entry on ReviewTicket.complete when (decision == null);
            required;
        }
        /// The desk's decision layer: the sibling decision model
        /// (support.dmn) assesses the ticket once the service has run, and
        /// its assessment lands in the `decision` case-file item the case
        /// coordinates around.
        decision AssessAuthority {
            invokes RefundDecisions.AssessRefund;
            inputs { ticket }
            outputs { decision }
            entry on AssessRefund.complete when (decision == null);
            required;
        }

The automated half of the assessment stage: a `service` item bound to a designed operation, a `decision` item invoking the sibling decision model’s `AssessRefund` service, and the discretionary finance approval.

The whole file is CI-tested: pherolang check examples/ checks every surface in the tree, and the example harness compiles each one on every run. What you see above is the input to the artifact below.

Neighbours

How it relates to the other surfaces

A case coordinates work over the other surfaces: .mox types the case file, .actor names the role principals, .ddd supplies the operations a service item executes, .dmn supplies the decision service a decision item invokes, and .evt stays the wider integration vocabulary — the case reacts to case-file transitions, not to events. The CMMN backend lowers the artifact to the engine’s CaseDefinition JSON.

Read alongside

Commands

How to compile and validate

Three commands, one file. They run from the repository root against the example on this page.

bash
pherolang check examples/support/support.cmmn
pherolang ir examples/support/support.cmmn -o site/data/artifacts/cmmn.json
pherolang artifact check site/data/artifacts/cmmn.json

check parses, resolves, validates and type-checks the file and printsOK examples/support/support.cmmn. ir writes the artifact and prints nothing on success. artifact check then validates the serialized JSON on its own — no model, no import resolution, no compiler — and prints OK site/data/artifacts/cmmn.json.

Directories work too: pherolang check examples/ enters project mode and checks every supported surface under the tree, each file's imports resolving from the snapshot.

Artifact

What it produces

One versioned JSON artifact, emitted by the compiler and consumed by whatever reads this surface.

One CmmnModel: cases with their roles, case file, plan items and sentries — the shape the CMMN backend lowers into a CaseDefinition.

The artifact is site/data/artifacts/cmmn.json, and it is committed here exactly as the released pherolang binary emits it. Its top-level shape:

  • cases1 entry

Jump to the compiled artifact

Provenance

formatVersion = 2
The compatibility gate. A reader accepts this number or refuses the file.
pheroVersion — not present
This standalone surface artifact is versioned on its ownformatVersion; only the domain model artifact carries the compiler-version stamp.
6,526 bytes
255 lines, two-space indented, in the file's own key order.

The compiled artifact

The first 56 of 255 lines, verbatim — the exact bytes pherolang ir writes, not a hand-written sample. The slice stops at a JSON boundary; the ellipsis marker is outside the JSON, and the full file is site/data/artifacts/cmmn.json.

artifacts/cmmn.json · lines 1–56
{
  "formatVersion": 2,
  "cases": [
    {
      "name": "RefundDesk",
      "description": "A refund-desk case: the work coordinated around one support ticket\nthat needs money back.",
      "roles": [
        {
          "name": "triage",
          "actor": "Agent"
        },
        {
          "name": "finance",
          "actor": "Finance"
        },
        {
          "name": "escalation",
          "actor": "Manager"
        }
      ],
      "caseFile": [
        {
          "name": "ticket",
          "description": "The ticket under triage.",
          "type": {
            "type": "class",
            "value": {
              "package": "nz.example.support",
              "name": "Ticket"
            }
          },
          "multiplicity": {
            "lower": 1,
            "upper": {
              "finite": 1
            }
          }
        },
        {
          "name": "decision",
          "description": "The refund decision, once assessed.",
          "type": {
            "type": "class",
            "value": {
              "package": "nz.example.support",
              "name": "RefundDecision"
            }
          },
          "multiplicity": {
            "lower": 0,
            "upper": {
              "finite": 1
            }
          }
        }
      ],

… 199 more lines in site/data/artifacts/cmmn.json

Regenerate it from the repository root — the second command validates the serialized bytes with no compiler in the loop:

bash
pherolang ir examples/support/support.cmmn -o site/data/artifacts/cmmn.json
pherolang artifact check site/data/artifacts/cmmn.json

The whole data directory is regenerated by node scripts/sync-model.mjs (run from site/) with the released binary; CI fails on a one-byte difference.

Reference

Documentation

The normative reference for this surface, rendered from the repository's own documentation.