Fundamentals 2: tasks and plan items
This page covers the two things a CMMN author works with most: the plan item, and the lifecycle it moves through.
The plan item / definition split
Section titled “The plan item / definition split”CMMN separates what a thing is from where it sits in the case:
- A plan item definition (
<humanTask>,<stage>,<milestone>, …) declares the work. It lives in a stage’s definition list. - A plan item (
<planItem>) is a use of a definition at one place in the plan, via@definitionRef. It carries the id the rest of the model refers to, its own name, its item control, and its entry and exit criteria.
<casePlanModel id="cpm"> <planItem id="pi_review" definitionRef="def_review"> <entryCriterion id="ec_1" sentryRef="sentry_1" /> <itemControl> <requiredRule /> </itemControl> </planItem>
<humanTask id="def_review" name="Review the claim" flowable:assignee="${initiator}" /></casePlanModel>Two consequences worth internalising:
- Sentries reference plan items, not definitions. An on-part’s
@sourceRefpoints at a<planItem>id. The same definition used twice is two plan items with two independent lifecycles, and a sentry watches one of them. - Item control lives in two places. A definition may carry a
<defaultControl>; a plan item may carry an<itemControl>that overrides it. Orvanta models both.
@id is optional, and that matters
Section titled “@id is optional, and that matters”CMMN’s schema marks @id as optional on every element. 161 of the 968 Flowable corpus documents rely on this, omitting 249 ids between them. Orvanta’s parser synthesises the missing ids, flags each one, and counts them — rather than treating an absent id as a malformed document.
This is worth knowing if you hand-write CMMN: your file will import even without ids, but the ids the model refers to are then generated, so add them explicitly to anything a sentry needs to point at.
The task types
Section titled “The task types”CMMN defines several plan item definitions that represent work. Here is every one Orvanta’s parser models, and what the engine does with it:
| Definition | What it is | Orvanta’s engine |
|---|---|---|
<task> | The generic task | Executes. isBlocking="false" completes on start; isBlocking="true" parks for an external complete. |
<humanTask> | Work for a person | Executes. Parks in active, completes on an external trigger. |
<milestone> | An achievement marker | Executes. See Fundamentals 1. |
<stage> | A phase | Executes. |
<planFragment> | Visual grouping | Flattened — no runtime existence. |
<userEventListener> | A thing a person can trigger | Executes. Parks in available, occurs on an external trigger. |
<processTask> | Calls a BPMN process | Refused at deploy. |
<caseTask> | Calls another case | Refused at deploy. |
<decisionTask> | Calls a DMN decision | Refused at deploy. |
<timerEventListener> | Fires on a schedule | Refused at deploy. |
<eventListener> (generic) | Flowable’s flowable:eventType-discriminated listener | Refused at parse. 78 corpus files. |
“Refused” means refused at deploy time, with the element id and a named reason — never a silent approximation. A processTask that deployed and behaved as a pass-through would complete the case without ever running the process, which is worse than refusing it. The full list and the reasoning is on Supported CMMN elements.
Note that the editor’s palette does include Process Task, Case Task, Decision Task and Timer Event Listener, because the model represents them faithfully and they must survive a round trip. The palette tracks what the model can carry; the engine table tracks what runs. See Authoring a case model.
humanTask specifics
Section titled “humanTask specifics”<humanTask> is the most common definition in the corpus by a distance — 638 of 968 files. Orvanta’s parser captures @performerRef, @isBlocking, flowable:assignee, flowable:formKey, flowable:candidateStarterGroups and the whole <extensionElements> listener tree.
The engine parks in active and completes on an external trigger, and that is all: there is no form model, no assignee resolution and no task list. The attributes survive the round trip; nothing consumes them yet.
<planningTable> on a human task — CMMN’s discretionary-planning subsystem — is refused by name rather than ignored. It has zero corpus usage.
The lifecycle: twelve states
Section titled “The lifecycle: twelve states”Every plan item instance sits in exactly one of twelve states, transcribed from Flowable’s PlanItemInstanceState:
| State | Meaning | Orvanta |
|---|---|---|
available | Created, waiting on entry criteria | Reachable |
unavailable | An event listener held back by an available-condition | Reachable |
enabled | Manual activation is on; waiting for a human to start it | Reachable |
disabled | A human declined it; re-enterable | Reachable |
active | Running | Reachable |
completed | Terminal — finished normally | Reachable |
terminated | Terminal — ended by an exit | Reachable |
wait_repetition | A further repetition, waiting for its sentry again | Reachable |
failed | Terminal — faulted | Modelled only. No behaviour raises a fault yet. |
suspended | Paused | Reachable — a case-level suspend, or a suspend on one plan item. resume restores the state recorded at suspend time, not available, so a resumed stage does not re-instantiate its children. |
async-active | Async transaction boundary, entering | Modelled only. Requires flowable:async, which is refused. |
async-active-leave | Async transaction boundary, leaving | Modelled only. Requires flowable:asyncLeave, which is refused. |
The engine’s own groupings matter when reasoning about completion:
- Terminal states —
completed,terminated,failed. - End states — the terminal three, plus
unavailable,disabled,wait_repetition. - States in which entry criteria are re-evaluated —
availableandwait_repetition, and only those.
That last one is the reason a completed task does not restart when its sentry fires again: the engine only looks at entry criteria for instances sitting in available or wait_repetition.
The transitions
Section titled “The transitions”CMMN names 21 transitions. Orvanta executes seventeen of them:
Executed: create, start, enable, disable, reenable, manualStart, complete, occur, exit, initiate, dismiss, the internal repetition spawn (also a create), and the operator-driven set — suspend, resume, parentSuspend, parentResume, terminate and close.
terminate and exit are worth telling apart: an operator terminating the case or one plan item emits terminate and cascades to the sub-tree, where an exit criterion emits exit. A sentry watching one does not see the other.
Modelled only — the model carries them, nothing drives them: fault (no behaviour runs user code, so nothing can fault), reactivate (case reactivation is refused), async-activate and async-leave-active (flowable:async is refused).
initiate and dismiss are the pair that moves an event listener between unavailable and available as its flowable:availableConditionExpression turns true or false.
Manual activation: enabled → disabled → re-enable
Section titled “Manual activation: enabled → disabled → re-enable”By default a plan item whose entry criteria are satisfied goes straight to active. A <manualActivationRule> (114 corpus files) changes that: the item stops at enabled and waits for a person.
From enabled, three things can happen:
manualStart— a person starts it. It goesactive.disable— a person declines it. It goesdisabled, which is an end state but not a terminal one.reenable— a person changes their mind about adisableditem. It goes back toenabled.
Orvanta executes all four transitions. This three-way is what makes CMMN’s “optional work” idiom possible, and it combines with autocomplete in a specific way that has its own section on the completion page.
A <manualActivationRule> may carry a <condition>; if it does, the condition must be inside Orvanta’s decidable expression subset or the model is refused at deploy rather than defaulted to true. See Sentries.
Fundamentals 3: sentries — the guards that drive all of this.