git:20260509.cee0d36 to git:20261026.f263dd9

182 added, 267 removed. Audit A to A.

---
name: bpmn-xml-generator
description: >
- Generate well-formed, valid BPMN 2.0 XML files compatible with BPMN 2.0-compliant process engines.
- Use this skill whenever the user asks to create, write, design, model, or define a business process,
- workflow, or BPMN diagram — even if they just describe a flow in plain language ("I need a process
- that does X then Y..."). Also use it when asked to convert YAML/JSON process definitions to BPMN,
- or to edit/fix an existing BPMN file. The skill guides information gathering when the request is
- incomplete, produces schema-valid XML, and enforces schema and compatibility constraints.
+ Generate well-formed, schema-valid BPMN 2.0 XML for a target process engine (Stateway, Camunda 8 /
+ Zeebe, or Flowable). Use this skill whenever the user asks to create, write, design, model, or define
+ a business process, workflow, or BPMN diagram — even if they just describe a flow in plain language
+ ("I need a process that does X then Y..."). Also use it when asked to convert YAML/JSON process
+ definitions to BPMN, to migrate a BPMN file between engines, or to edit/fix/validate an existing BPMN
+ file. The skill gathers missing requirements first, writes engine-agnostic BPMN 2.0, applies the
+ engine profile, and verifies the result with an executable validator (bpmn-moddle, OMG XSD, bpmnlint).
---
- # BPMN Authoring
+ # BPMN XML Generator
- Produces valid BPMN 2.0 XML parseable by `bpmn-moddle` and executable by BPMN 2.0-compliant process engines.
+ Produces BPMN 2.0 XML that is valid against the OMG specification **and** executable on the engine
+ the user targets.
---
- ## 0. Orientation: what you are building
+ ## 0. Orientation: two layers
- This skill targets engines that parse BPMN via **`bpmn-moddle`** (the bpmn-io library), such as Camunda and Flowable-compatible engines.
- Key facts that govern every file you generate:
+ | Layer | Files | Responsibility |
+ |---|---|---|
+ | **Core** (this file + `references/`) | `elements.md`, `patterns.md`, `examples.md`, `validation-errors.md` | OMG BPMN 2.0 only: elements, structure, child order, modeling rules. Never emits engine extensions. |
+ | **Profile** (`profiles/`) | `stateway.md`, `camunda8.md`, `flowable.md` | One engine: namespace, expression language, extension elements, support matrix, deployment. |
+ | **Tooling** (`scripts/`) | `validate.mjs`, `layout.mjs` | Executable checks and diagram layout. |
- | Fact | Detail |
- |---|---|
- | Root namespace | `xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"` |
- | Root element | `<definitions>` with mandatory `id` and `targetNamespace` (any valid URI; not read by the engine — it is required by the BPMN 2.0 XML schema only) |
- | Each process | `<process id="..." isExecutable="true">` |
- | Conditions on flows | `<conditionExpression>{{expression}}</conditionExpression>` (engine-specific; verify with your engine — FEEL is the BPMN-standard alternative) |
- | Assignees / dynamic values | `{{variables.fieldName}}` inside string attributes |
- | DMN integration | `<businessRuleTask camunda:decisionRef="decision-id">` — `decisionRef` must match the `id` of a DMN definition already registered in the engine |
- | IDs | All elements **must** have a unique `id` attribute. Convention: `snake_case` or `PascalCase_N` |
- | `isExecutable` | Always `true` for processes intended for execution |
+ Workflow: **gather requirements → model in core BPMN → apply the profile → validate → lay out → deliver.**
+ Read only what you need: this file always; `profiles/<engine>.md` once the engine is known;
+ `references/*` when a construct needs detail.
+
---
## 1. Information gathering — ask before writing
- **Never generate a BPMN file from an incomplete description.** If the user's prompt is missing any of the items below, ask them before proceeding. Ask all missing items in a single response (not one at a time).
+ **Never generate a BPMN file from an incomplete description.** Ask every missing item in **one** message.
### 1.1 Always required
-
- - [ ] **Process key** — the logical identifier (e.g., `order-approval`). Must be URL-safe, lowercase, hyphen-separated.
+ - [ ] **Target engine profile** — Stateway, Camunda 8 (which 8.x version?), or Flowable.
+ If the user only wants a diagram for documentation, use the `core` profile (no extensions).
+ - [ ] **Process key** — lowercase kebab-case, starts with a letter (e.g. `order-approval`).
- [ ] **Process name** — human-readable label.
- - [ ] **Happy-path steps** — the sequence of activities from start to end (at least one activity).
- - [ ] **Human tasks** — which steps require human action? Who is the assignee or candidateGroup?
- - [ ] **Service tasks** — which steps call external systems? What is the `implementation` type? (`webhook` or `http`)
- - [ ] **Gateways** — are there any conditional branches? What are the conditions?
+ - [ ] **Happy path** — the sequence of steps from start to end (at least one activity).
+ - [ ] **Human steps** — which steps are done by people, and who (user, group, expression)?
+ - [ ] **Automated steps** — which steps call systems, and how (HTTP endpoint, job worker, decision, sub-process …)?
+ - [ ] **Decisions** — every branch point and the condition of each outgoing path, plus the default path.
### 1.2 Ask when relevant
+ - [ ] **Waits** — timers (ISO 8601 durations, dates, cycles), messages (name, correlation), signals.
+ - [ ] **Exceptions** — deadlines on tasks, error handling, cancellation, compensation (undo).
+ - [ ] **Parallel or repeated work** — parallel branches, one task per item of a list (multi-instance), loops.
+ - [ ] **Sub-processes** — embedded sub-flows, reusable processes (call activity), event sub-processes.
+ - [ ] **Data** — variable names used in conditions/mappings; what each human task may see and must write.
+ - [ ] **Diagram layout** — needed by bpmn.io / Modeler / Operate. Offer it by default (§6).
- - [ ] **Timer events** — any steps that wait for a time or duration? (ISO 8601: `PT1H`, `2026-12-01T09:00:00Z`, `R3/PT24H`)
- - [ ] **Message / Signal events** — any steps that wait for or emit an external message?
- - [ ] **Error / boundary events** — any error handling on tasks?
- - [ ] **Sub-processes** — any embedded sub-flows?
- - [ ] **DMN decisions** — does any step evaluate a decision table? If so, what is the `id` of the DMN definition that must already exist in the engine? (That `id` goes in `camunda:decisionRef`.)
- - [ ] **Variable names** — what process variables are used? (needed for expressions and `dataInputAssociation`)
- - [ ] **Data visibility** — for each `userTask`, which variables should the frontend see? (maps to `dataInput`/`dataOutput` in `ioSpecification`)
- - [ ] **Process-level variables** — are there default/initial variable values?
- - [ ] **Diagram layout** — do you want the output to include a visual layout (`BPMNDiagram` section), required by tools like bpmn.io? If yes, `bpmn-auto-layout` will be run automatically after saving (requires Node.js ≥ 18 and internet access for `npx`).
+ ### 1.3 Profile questions
+ Add the questions listed in section 6 of the selected `profiles/<engine>.md` (e.g. URL and sync/async
+ mode for Stateway HTTP tasks, job types for Camunda 8, delegate kind for Flowable).
- ### 1.3 Clarify ambiguity
+ ### 1.4 Clarify ambiguity
+ "Approve or reject" → confirm: exclusive choice? what ends each path? what is the condition and the default?
+ "Notify A and/or B" → inclusive vs parallel. "Wait for X or timeout" → event-based gateway or boundary timer
+ (check the profile's support matrix — e.g. Stateway does not execute event-based gateways).
- If the user describes a flow like "approve or reject", confirm:
- - Is this an `exclusiveGateway` (XOR — one path only)?
- - Are both outcomes leading to different end states?
- - What is the condition expression for each outgoing flow?
+ ### 1.5 Drafting with assumptions
+ Only if the user explicitly says to proceed with defaults: generate, and list every assumption
+ (names, conditions, assignees, endpoints) right after the file so they can be corrected.
---
- ## 2. Supported BPMN elements
-
- Read `references/elements.md` for the full attribute list of each element.
- Below is the complete list of supported types — do not use any element not on this list.
-
- ### Events
- | XML element | Type | Notes |
- |---|---|---|
- | `<startEvent>` | `startEvent` | None, Timer, Message, Signal, Conditional |
- | `<endEvent>` | `endEvent` | None, Terminate, Message, Signal, Error, Escalation |
- | `<intermediateCatchEvent>` | `intermediateCatchEvent` | Timer, Message, Signal, Conditional |
- | `<intermediateThrowEvent>` | `intermediateThrowEvent` | Message, Signal, Escalation |
- | `<boundaryEvent>` | `boundaryEvent` | Timer (interrupting/non), Error, Message, Signal, Escalation |
-
- ### Activities
- | XML element | Type | Notes |
- |---|---|---|
- | `<task>` | generic task | passes through immediately |
- | `<userTask>` | `userTask` | `assignee`, `candidateGroups`, `formKey`, `dueDate` |
- | `<serviceTask>` | `serviceTask` | `implementation="webhook"` or `"http"` |
- | `<scriptTask>` | `scriptTask` | expression evaluated against `variables` |
- | `<sendTask>` | `sendTask` | dispatches message/webhook |
- | `<receiveTask>` | `receiveTask` | waits for correlated message |
- | `<businessRuleTask>` | `businessRuleTask` | `camunda:decisionRef` must contain the `id` of a previously registered DMN definition |
- | `<callActivity>` | `callActivity` | calls another process definition |
- | `<subProcess>` | `subProcess` | embedded sub-flow |
+ ## 2. Supported BPMN constructs (core)
- ### Gateways
- | XML element | Behavior |
- |---|---|
- | `<exclusiveGateway>` | XOR — exactly one outgoing flow taken |
- | `<parallelGateway>` | AND — all flows activated (join requires all tokens) |
- | `<inclusiveGateway>` | OR — one or more flows based on conditions |
- | `<eventBasedGateway>` | race — first event wins |
+ Full attributes and child order: `references/elements.md`. Advanced patterns: `references/patterns.md`.
+ **Every construct must also be allowed by the profile's support matrix** (section 4 of the profile);
+ if it is `unsupported` there, use the listed alternative; if `parse-only`/`unverified`, warn the user.
- ### Connectors
- | XML element | Notes |
+ | Category | Elements |
|---|---|
- | `<sequenceFlow>` | `sourceRef`, `targetRef`, optional `<conditionExpression>` |
+ | Events | `startEvent`, `endEvent`, `intermediateCatchEvent`, `intermediateThrowEvent`, `boundaryEvent` |
+ | Event definitions | timer, message, signal, error, escalation, conditional, link, compensate, cancel, terminate |
+ | Activities | `task`, `userTask`, `manualTask`, `serviceTask`, `sendTask`, `receiveTask`, `scriptTask`, `businessRuleTask`, `callActivity` |
+ | Sub-processes | `subProcess` (embedded, event sub-process `triggeredByEvent`), `transaction`, `adHocSubProcess` |
+ | Loops | `multiInstanceLoopCharacteristics` (parallel/sequential), `standardLoopCharacteristics` |
+ | Gateways | `exclusiveGateway`, `inclusiveGateway`, `parallelGateway`, `eventBasedGateway`, `complexGateway` (discouraged) |
+ | Flows | `sequenceFlow` (+ `conditionExpression`, gateway/activity `default`) |
+ | Data | `dataObject`, `dataObjectReference`, `dataStoreReference`, `property`, `ioSpecification`, data associations, `itemDefinition` |
+ | Artifacts | `documentation`, `textAnnotation`, `association`, `group` (+ `category`) |
+ | Root elements | `process`, `message`, `signal`, `error`, `escalation`, `itemDefinition`, `dataStore`, `category` |
- ### Not commonly supported by BPMN process engines
- CMMN, Choreography, Conversation, DataStore, Association (rendered only).
+ **Out of scope (for now):** collaborations, pools (`participant`), lanes, message flows, choreographies,
+ conversations, CMMN. If asked for pools/lanes, say so and model the single executable process.
---
## 3. XML structure template
- ```xml
+ Start from the profile's *Definitions header* (section 2 of the profile). The core skeleton is:
+
+ ```xml profile=core
<?xml version="1.0" encoding="UTF-8"?>
- <definitions
- xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
- xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
- xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
- xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
- http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd"
- id="Definitions_{process-key}"
- targetNamespace="http://bpmn.io/schema/bpmn" <!-- any valid URI; this value is not used by the engine -->
- exporter="bpmn-xml-generator"
- exporterVersion="1.0">
+ <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
+ xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
+ xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
+ id="Definitions_process-key"
+ targetNamespace="http://bpmn.io/schema/bpmn"
+ exporter="bpmn-xml-generator"
+ exporterVersion="2.0">
- <process id="{process-key}" name="{Process Name}" isExecutable="true">
+ <!-- root elements used by the process: message, signal, error, escalation … -->
+ <process id="process-key" name="Process Name" isExecutable="true">
+
<!-- ═══ START ═══ -->
<startEvent id="start" name="Start">
- <outgoing>flow_start_to_first</outgoing>
+ <outgoing>flow_start_to_first_task</outgoing>
</startEvent>
<!-- ═══ ACTIVITIES ═══ -->
- <!-- ... -->
+ <task id="first_task" name="First Task">
+ <incoming>flow_start_to_first_task</incoming>
+ <outgoing>flow_first_task_to_end</outgoing>
+ </task>
<!-- ═══ GATEWAYS ═══ -->
- <!-- ... -->
<!-- ═══ END ═══ -->
- <endEvent id="end" name="End"/>
+ <endEvent id="end" name="End">
+ <incoming>flow_first_task_to_end</incoming>
+ </endEvent>
<!-- ═══ SEQUENCE FLOWS ═══ -->
- <!-- List ALL flows at the bottom for readability -->
- <sequenceFlow id="flow_start_to_first" sourceRef="start" targetRef="..."/>
+ <sequenceFlow id="flow_start_to_first_task" sourceRef="start" targetRef="first_task"/>
+ <sequenceFlow id="flow_first_task_to_end" sourceRef="first_task" targetRef="end"/>
</process>
</definitions>
```
+ - `targetNamespace` is required by the XSD; any URI works (keep the existing one when editing).
+ - Never put comments inside a start tag.
+ - Add the profile's namespace declaration(s) to `<definitions>` — and no other engine's.
+
---
- ## 4. Element patterns — copy-paste ready
+ ## 4. Authoring rules
- ### userTask with assignee and data visibility
- ```xml
- <userTask id="review_task" name="Review Request"
- camunda:assignee="{{variables.manager}}"
- camunda:candidateGroups="approvers">
- <extensionElements>
- <camunda:formData>
- <camunda:formField id="approved" label="Approved?" type="boolean"/>
- <camunda:formField id="comment" label="Comment" type="string"/>
- </camunda:formData>
- </extensionElements>
- <ioSpecification>
- <dataInput id="in_amount" name="amount"/>
- <dataInput id="in_reason" name="reason"/>
- <dataOutput id="out_approved" name="approved"/>
- <dataOutput id="out_comment" name="comment"/>
- </ioSpecification>
- <incoming>flow_to_review</incoming>
- <outgoing>flow_from_review</outgoing>
- </userTask>
- ```
+ ### 4.1 Child element order (XSD — enforced by the validator)
+ `documentation` → `extensionElements` → `incoming` → `outgoing` → type-specific children:
+ - activities: `ioSpecification` → `property` → `dataInputAssociation` → `dataOutputAssociation` → `loopCharacteristics` (last);
+ - catch events: … → event definition (last); throw events: `dataInputAssociation` → event definition (last);
+ - `ioSpecification`: `dataInput*` → `dataOutput*` → `inputSet` → `outputSet` (both sets **mandatory**).
- ### serviceTask (webhook)
- ```xml
- <serviceTask id="notify_erp" name="Notify ERP"
- implementation="webService">
- <extensionElements>
- <camunda:connector>
- <camunda:connectorId>webhook</camunda:connectorId>
- </camunda:connector>
- </extensionElements>
- <incoming>flow_to_notify</incoming>
- <outgoing>flow_from_notify</outgoing>
- </serviceTask>
- ```
+ ### 4.2 Structure
+ - Unique `id` on every element; ids are XML NCNames (start with a letter/underscore, no spaces).
+ - `<incoming>`/`<outgoing>` children must mirror the `sourceRef`/`targetRef` of the sequence flows.
+ - `message`, `signal`, `error`, `escalation` are siblings of `<process>`, never inside it.
+ - All `<sequenceFlow>` elements at the bottom of their container, after the nodes.
+ - Every task, event, splitting gateway and conditional/default flow has a `name`.
- ### exclusiveGateway with conditions
- ```xml
- <exclusiveGateway id="gw_approval" name="Approved?">
- <incoming>flow_to_gw</incoming>
- <outgoing>flow_approved</outgoing>
- <outgoing>flow_rejected</outgoing>
- </exclusiveGateway>
+ ### 4.3 Flow logic
+ - Exclusive/inclusive splits: every outgoing flow has a `conditionExpression` except the one in `default`.
+ - Never split and merge in one gateway; merge alternative paths with an exclusive gateway and
+ synchronize parallel paths with a parallel gateway (never several flows straight into a task).
+ - A parallel join must receive a token from every branch: a branch that can exit early (end event,
+ interrupting boundary) must end in a **terminate** end event or be restructured (ERR-022).
+ - Boundary events have `<outgoing>` but never `<incoming>`.
+ - Event-based gateway targets: only intermediate catch events / receive tasks.
- <sequenceFlow id="flow_approved" sourceRef="gw_approval" targetRef="notify_approved">
- <conditionExpression xsi:type="tFormalExpression">{{variables.approved == true}}</conditionExpression>
- </sequenceFlow>
+ ### 4.4 Expressions and data
+ - The expression language comes from the profile: `{{…}}` Stateway, `=FEEL` Camunda 8, `${…}` Flowable.
+ - Escape `&` → `&amp;`, `<` → `&lt;` (so `&&` → `&amp;&amp;`); `"` → `&quot;` inside attributes.
+ - Timers: ISO 8601 (`PT1H`, `2026-12-31T09:00:00Z`, `R3/PT1H`); cron/expressions only if the profile allows them.
+ - Data associations reference **ids** of item-aware elements, never variable names; prefer the profile's
+ variable-mapping mechanism (Stateway/Zeebe `ioMapping`, Flowable variables) for execution data.
- <sequenceFlow id="flow_rejected" sourceRef="gw_approval" targetRef="end_rejected">
- <conditionExpression xsi:type="tFormalExpression">{{variables.approved == false}}</conditionExpression>
- </sequenceFlow>
- ```
+ ### 4.5 Naming conventions
+ Process `kebab-case`; tasks `verb_noun`; gateways `gw_{purpose}`; flows `flow_{source}_to_{target}`;
+ boundary events `{type}_boundary_{activity}`; messages/signals/errors/escalations `msg_`/`sig_`/`err_`/`esc_`.
+ Full table: `references/validation-errors.md` §5.
- ### timerEvent (intermediate catch — wait N hours)
- ```xml
- <intermediateCatchEvent id="wait_24h" name="Wait 24h">
- <incoming>flow_to_timer</incoming>
- <outgoing>flow_from_timer</outgoing>
- <timerEventDefinition>
- <timeDuration xsi:type="tFormalExpression">PT24H</timeDuration>
- </timerEventDefinition>
- </intermediateCatchEvent>
- ```
+ ---
- ### boundaryEvent (timer, interrupting)
- ```xml
- <boundaryEvent id="timeout_boundary" name="Timeout"
- attachedToRef="review_task"
- cancelActivity="true">
- <outgoing>flow_timeout</outgoing>
- <timerEventDefinition>
- <timeDuration xsi:type="tFormalExpression">PT48H</timeDuration>
- </timerEventDefinition>
- </boundaryEvent>
- ```
+ ## 5. Validate — mandatory before delivering
- ### businessRuleTask (DMN decision)
- ```xml
- <!-- 'credit-score-decision' must be the id of a DMN definition already registered in the engine -->
- <businessRuleTask id="credit_check" name="Credit Score Check"
- camunda:decisionRef="credit-score-decision">
- <extensionElements>
- <camunda:in variables="all"/>
- <camunda:out variables="all"/>
- </extensionElements>
- <incoming>flow_to_credit</incoming>
- <outgoing>flow_from_credit</outgoing>
- </businessRuleTask>
- ```
+ Write the XML to a `.bpmn` file, then run the validator from this skill's directory
+ (the folder that contains this `SKILL.md`):
- ### messageStartEvent / messageCatchEvent
- ```xml
- <!-- Start on external message -->
- <startEvent id="start_on_message" name="Payment Received">
- <messageEventDefinition messageRef="msg_payment"/>
- </startEvent>
- <message id="msg_payment" name="payment_received"/>
+ ```sh
+ # once per machine (Node.js ≥ 20; needs network access the first time)
+ npm ci --prefix <skill-dir>/scripts
- <!-- Intermediate wait for message -->
- <intermediateCatchEvent id="wait_payment" name="Wait for Payment">
- <incoming>flow_to_wait</incoming>
- <outgoing>flow_after_payment</outgoing>
- <messageEventDefinition messageRef="msg_payment"/>
- </intermediateCatchEvent>
+ node <skill-dir>/scripts/validate.mjs <file.bpmn> --profile <stateway|camunda8|flowable|core> [--engine-version 8.10]
```
+ It checks: allowed namespaces → `bpmn-moddle` parse (unknown elements, unresolved references) →
+ OMG XSD via `xmllint` (child order, mandatory children) → bpmnlint (`recommended` + the profile's support
+ matrix, expression syntax and configuration; `camunda-compat` for Camunda 8).
+
+ - **Fix every error and re-run until there are 0 errors.** Look codes up in `references/validation-errors.md`
+ and the profile's section 8.
+ - Warnings: fix them, or tell the user why one stays (e.g. a construct that is `unverified` on the engine).
+ - If Node.js is unavailable, say so explicitly and walk the checklist in §7 manually.
+ If `xmllint` is missing the validator skips the XSD layer and prints a notice — apply §4.1 carefully.
+
---
- ## 5. Expression syntax
+ ## 6. Diagram layout
- This skill uses `{{expression}}` as the default condition syntax — **not** FEEL (`#{}`) and **not** UEL (`${}`). Expression syntax is engine-dependent; verify with your engine.
+ Engines run files without a diagram, but bpmn.io, the Camunda/Flowable modelers and monitoring tools
+ need the `bpmndi:BPMNDiagram` section. Unless the user declines:
- ```
- {{variables.amount > 1000}} → boolean condition
- {{variables.status == 'approved'}} → string equality
- {{variables.items.length > 0}} → array check
- {{variables.manager || 'default@company.com'}} → fallback
- {{variables.score >= 700 && variables.debt < 5000}} → compound
+ ```sh
+ node <skill-dir>/scripts/layout.mjs <file.bpmn> # in place; replaces any existing DI
+ node <skill-dir>/scripts/validate.mjs <file.bpmn> --profile <p> # re-validate (DI is now checked too)
```
- Use in:
- - `<conditionExpression>` on sequence flows
- - `camunda:assignee` attribute on `userTask`
- - Timer expressions **only use ISO 8601** (no `{{}}` in timer values)
-
---
- ## 6. Validation checklist
-
- Before outputting the final XML, verify every item:
+ ## 7. Manual checklist (fallback when the validator cannot run)
- - [ ] Every element has a unique `id`
- - [ ] Every `<sequenceFlow>` has `sourceRef` and `targetRef` pointing to existing element IDs
- - [ ] Every element except end events has at least one `<outgoing>` child
- - [ ] Every element except start events has at least one `<incoming>` child
- - [ ] `<exclusiveGateway>` outgoing flows all have `<conditionExpression>` (except a default flow if `default` attribute is set)
- - [ ] `<parallelGateway>` used for both split AND join — the join must have multiple `<incoming>` matching the split's `<outgoing>`
- - [ ] `<boundaryEvent>` has `attachedToRef` pointing to a valid activity
- - [ ] Timer expressions are valid ISO 8601: durations start with `P`, dates are full UTC timestamps
- - [ ] `isExecutable="true"` on `<process>`
- - [ ] `targetNamespace` is set on `<definitions>`
- - [ ] No CMMN, Choreography, or DataStore elements (rarely supported by BPMN process engines)
+ - [ ] Only the profile's namespace; no `camunda:`/`zeebe:`/`flowable:`/`stateway:` from another engine
+ - [ ] Unique, NCName ids; `targetNamespace` set; `isExecutable="true"` on executable processes
+ - [ ] Child order per §4.1; `ioSpecification` has `inputSet` and `outputSet`
+ - [ ] Every flow's `sourceRef`/`targetRef` exists and matches `<incoming>`/`<outgoing>`
+ - [ ] Every node is reachable and reaches an end; no implicit splits/joins
+ - [ ] Exclusive/inclusive splits: conditions on all non-default flows; a default where no condition may hold
+ - [ ] Parallel joins cannot deadlock; boundary events reference an activity and have no incoming
+ - [ ] Root elements (`message`, `signal`, `error`, `escalation`) declared and referenced
+ - [ ] Timers valid for the profile; conditions in the profile's expression language
+ - [ ] Every construct is `supported` in the profile's matrix (or the user was warned)
---
- ## 7. Output format
+ ## 8. Output format
- 1. Always output the complete XML (never truncate with `<!-- ... rest of process -->`)
- 2. Use consistent 2-space indentation
- 3. Group flows at the **end** of the process element, after all nodes
- 4. Add a brief inline comment above each logical section (START, ACTIVITIES, GATEWAYS, END, FLOWS)
- 5. If the file is longer than ~150 lines, offer to also write a summary table of elements and flows
- 6. After outputting the XML, remind the user to validate and upload it according to their engine's API.
- 7. **If the user requested a diagram layout**, after writing the BPMN file apply layout via the reusable runner at `/tmp/bpmn-layout-runner/layout.mjs`:
- ```
- node /tmp/bpmn-layout-runner/layout.mjs <output-file> <output-file>
- ```
- If `/tmp/bpmn-layout-runner/` does not exist yet, set it up first:
- ```
- mkdir -p /tmp/bpmn-layout-runner && \
- cd /tmp/bpmn-layout-runner && \
- npm init -y > /dev/null && \
- npm install bpmn-auto-layout && \
- node -e "
- import { readFileSync, writeFileSync } from 'fs';
- import { layoutProcess } from 'bpmn-auto-layout';
- const [,,i,o] = process.argv;
- writeFileSync(o||i, await layoutProcess(readFileSync(i,'utf8')), 'utf8');
- console.log('Layout applied.');
- " > layout.mjs
- ```
- Actually: write `layout.mjs` with the Write tool (see below), then run `npm install bpmn-auto-layout` inside `/tmp/bpmn-layout-runner/`.
+ 1. Write the complete XML to a file (default name `{process-key}.bpmn`; never truncate with `<!-- … -->`).
+ 2. 2-space indentation; section comments START / ACTIVITIES / GATEWAYS / END / SEQUENCE FLOWS.
+ 3. Validate (§5) and lay out (§6). Report the validator result (errors/warnings) to the user.
+ 4. Summarize: engine profile, elements used, assumptions, anything `parse-only`/`unverified`.
+ For files over ~150 lines, offer a table of elements and flows.
+ 5. Point to the profile's *Deployment* section (e.g. `POST /v1/definitions` for Stateway).
- **layout.mjs content:**
- ```js
- import { readFileSync, writeFileSync } from 'fs';
- import { layoutProcess } from 'bpmn-auto-layout';
- const [,, input, output] = process.argv;
- const xml = readFileSync(input, 'utf8');
- const layouted = await layoutProcess(xml);
- writeFileSync(output || input, layouted, 'utf8');
- console.log('Layout applied successfully.');
- ```
+ ---
- This overwrites the file in-place, adding a `<bpmndi:BPMNDiagram>` section with auto-computed shapes and edges. Confirm to the user that layout was applied and the file is ready for bpmn.io.
+ ## 9. Editing or migrating an existing file
- ---
+ - Read the whole file first; detect the engine from its namespaces (`stateway:`, `zeebe:`, `flowable:`,
+ `camunda:` = Camunda 7, out of scope — ask which supported profile to migrate to).
+ - Validate it **before** changing it, so pre-existing problems are reported separately from yours.
+ - Preserve ids, names, `targetNamespace`, extension data you do not touch, and the order of existing elements.
+ - Keep `<incoming>`/`<outgoing>` in sync with every flow you add, remove or reconnect.
+ - If the file has a diagram and the graph changed, re-run `layout.mjs` (it regenerates the whole DI —
+ tell the user manual positions are lost) or ask whether to keep the old DI and place new shapes manually.
+ - Migration between engines: translate extensions with the mapping tables in the target profile
+ (section 5), rewrite expressions, then validate with the target profile.
- ## 8. Reference files
+ ---
- Read these when you need deeper detail — do not load them all at once:
+ ## 10. Reference files
- | File | When to read |
+ | File | Read when |
|---|---|
- | `references/elements.md` | Full attribute reference for each element type |
- | `references/examples.md` | 4 complete end-to-end BPMN examples (approval, onboarding, timer escalation, message correlation) |
- | `references/validation-errors.md` | Common bpmn-moddle parse errors and how to fix them |
+ | `profiles/stateway.md` / `camunda8.md` / `flowable.md` | As soon as the engine is known (header, expressions, support matrix, extensions, examples) |
+ | `profiles/_contract.md` | Adding or changing a profile |
+ | `references/elements.md` | Attributes, child order and semantics of any core element |
+ | `references/patterns.md` | Multi-instance, loops, event sub-processes, errors/escalations, transactions, compensation, links, conditional events, ad-hoc, data and artifacts |
+ | `references/examples.md` | Complete engine-agnostic examples to adapt |
+ | `references/validation-errors.md` | Interpreting validator output; ID naming conventions |