Authoring a case model
Orvanta’s CMMN editor is a canvas built on Svelte Flow, reached from the Case Models entry in the sidebar rather than from the Create flow modal — CMMN is its own modelling language, not a fourth flow authoring model.
The palette
Section titled “The palette”The left rail lists every element the editor can author:
| Group | Elements |
|---|---|
| Tasks | Task, Human Task, Process Task, Case Task, Decision Task |
| Structure | Case Plan Model, Stage, Plan Fragment, Milestone |
| Events | User Event Listener, Timer Event Listener |
| Criteria | Entry Criterion, Exit Criterion |
The palette is wider than the engine
Section titled “The palette is wider than the engine”This is the opposite of the BPMN editor’s rule, and the difference is deliberate.
BPMN’s palette is identical to its engine’s supported set — there is no palette entry for a construct the engine cannot execute. CMMN’s palette instead tracks what the model represents. An element is a palette entry when orvanta-cmmn models it faithfully, whether or not the engine runs it.
So Process Task, Case Task, Decision Task and Timer Event Listener are all in the palette and all refused by the engine. You can draw them, save them, export them and re-import them unchanged; a model containing one is refused at deploy, by name.
The reason is the round trip. The editor must carry an imported Flowable case model through byte-identically, including constructs it cannot execute — so the model has to represent them, and once the model represents them there is no honest reason to refuse to draw them.
Everything the parser only recognises and refuses — the generic <eventListener>, <serviceTask>, <httpServiceTask>, <casePageTask> — is not a palette entry. Those ride through the round trip verbatim as read-only unsupported nodes.
Connectors target criteria, not plan items
Section titled “Connectors target criteria, not plan items”CMMN’s connector model is not BPMN’s, and this is the thing to unlearn first:
A connector runs from a plan item to a criterion. Never from plan item to plan item.
The criterion is what a connector targets; the sentry behind it decides whether the criterion’s host becomes available. So the arity rules are asymmetric:
| Element | Incoming | Outgoing |
|---|---|---|
| Any plan item | None | Many — its complete/occur event can feed many sentries |
| Entry or exit criterion | Many — a sentry may have several on-parts, which is an AND | None — it is a terminus |
| Case Plan Model | None | None — it is the root scope, not something another element’s completion can trigger |
| Plan Fragment | None | None — it has no runtime existence, so it can carry neither sentries nor events |
The canvas reads this table during a drag, so an illegal connection reads as invalid while you are making it rather than becoming a deploy error later.
To express “start B when A completes”, you drop an entry criterion on B and connect A → that criterion. Several connectors into one criterion is an AND; several criteria on one plan item is an OR.
The inspector
Section titled “The inspector”The right-hand panel renders its property rows from the element catalogue, so each element type offers exactly the properties its definition can carry — an assignee and form key on a human task, a process reference on a process task, auto-complete on a stage, an if-part condition on a criterion.
Properties are written to the plan item definition element (the <humanTask>), not to the <planItem> that references it, and are namespace-qualified where they are Flowable execution extensions.
Nothing in the inspector ever writes a design: attribute. That namespace is Flowable Design’s modeller decoration and it shadows real execution attribute names — design:required against flowable:required, and the same for repetition, manual activation and completion-neutral. The editor treats design: as foreign content that rides through untouched.
Import and export
Section titled “Import and export”Import takes a .cmmn or .cmmn.xml file. Export writes one back out.
The fidelity guarantee is stronger than it usually is for a modelling tool, and it is worth stating precisely because it is tested over the whole conformance corpus:
save(open(x)) === x, byte for byte, across all 968 corpus documents. Not a fixed point — the actual identity. Open a file, save it without touching anything, and you get the same bytes.save(save(x)) === save(x)after a real canvas edit — the fixed-point property git-sync depends on.- Zero element or attribute loss in both directions, compared on prefix-stripped local names by an independent scanner rather than by the parser under test.
There is no known-loss table, because there is no normalisation pass that could make an entry in one legitimate.
For context on why this is called out: the equivalent BPMN test documents that 0 of 60 files survive a no-op save unchanged, and settles for a fixed point instead. The difference is that CMMN’s XML layer preserves text rather than round-tripping through an object model.
Canvas basics
Section titled “Canvas basics”The canvas snaps to a grid, supports undo and redo, and multi-select. Entering the editor collapses the sidebar rail automatically and restores it on leaving — unless you had already collapsed it yourself.
What you cannot do yet
Section titled “What you cannot do yet”| Save a case model to the workspace | The table and the API exist; this editor does not call them. It saves a local draft and a .cmmn file |
| Deploy a case model | Same reason — the deploy path is server-side and there is no Deploy control here |
| Start or run a case | Same reason. Nothing in this editor starts a case |
| Test a case model in-product | No test framework — see Coming from Flowable |
Import a .cmmn file via the CLI or git-sync | The cmmn_case kind is registered but the sync arm is not built; a cmmn_case payload is reported as an unsupported kind rather than silently dropped |
See also
Section titled “See also”- Supported CMMN elements — what parses versus what runs.
- Fundamentals 3: sentries — what the criteria you are drawing actually do.