Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
759a89e
chore: build against a locally packed @miragon/bpmnlint-plugin-rules
emaarco Oct 28, 2026
8a1cb5e
refactor!: run the Camunda 7/8 engine rules as bpmnlint rules
emaarco Oct 28, 2026
81d92f4
perf: lint the engine rules in one walk and read the namespaces once …
emaarco Oct 28, 2026
39ebf2f
refactor: run the engine rules through the plugin's compatRules and l…
emaarco Oct 28, 2026
7531e87
refactor: merge the Camunda 7 engine rules into six group rules with …
emaarco Oct 28, 2026
4629302
refactor: merge the Camunda 8 engine rules into six group rules and s…
emaarco Oct 28, 2026
55ed40a
refactor: gather the camunda-compat corrections in CompatVerdicts and…
emaarco Oct 28, 2026
066172d
docs: name the six Camunda 7 and six Camunda 8 rules and lower the ru…
emaarco Oct 28, 2026
ca345be
refactor: name every engine file after the class it exports
emaarco Oct 28, 2026
da29e79
docs: describe what each engine rule checks and why in its header
emaarco Oct 28, 2026
50004c3
fix: key camunda-compat's start-event rule by the bpmnlint/ name its …
emaarco Oct 28, 2026
2ffb41b
docs: name camunda-compat's start-event rule as bpmnlint reports it
emaarco Oct 28, 2026
5e328e9
refactor!: drop the engine findings a file bpmn-cli writes cannot have
emaarco Oct 28, 2026
4c1beab
refactor: group the engine codes by code and drop the hint branches n…
emaarco Oct 28, 2026
bcbfe2e
refactor: word the vendor-content findings in the rules that report them
emaarco Oct 28, 2026
0c82799
refactor: hand the core helpers to the engine rules through one RuleKit
emaarco Oct 28, 2026
63b0140
refactor: write the ext add, ext remove and rebuild hints through Set…
emaarco Oct 28, 2026
e9dfc34
refactor: write the FEEL parser densely and drop the stray characters…
emaarco Oct 28, 2026
dd17abd
refactor: inline the single-use engine rule helpers
emaarco Oct 28, 2026
aefa677
refactor: share the XML element name, the definitions lookup and the …
emaarco Oct 29, 2026
4fc41f3
refactor: write the link events and flow index densely and drop unuse…
emaarco Oct 29, 2026
4d51057
refactor: lower the rule chunk budgets to the smaller engine rules
emaarco Oct 29, 2026
6b9cd5a
refactor: sort the engine adapter into the run, the rules and their s…
emaarco Oct 29, 2026
f0ff978
refactor: turn the checks on bpmn-cli's own model into engine rules o…
emaarco Oct 29, 2026
cb6967b
docs: describe the base engine rules in their headers
emaarco Oct 29, 2026
8e1ca11
refactor: write the engine rules and the rebased tests in block style
emaarco Oct 29, 2026
59e373f
refactor: leave a second incoming flow after an event-based gateway t…
emaarco Oct 29, 2026
623476c
refactor: split the Camunda 7 engine rules into single-check rules
emaarco Oct 29, 2026
e2bf9c6
refactor: split the Camunda 8 engine rules into single-check rules
emaarco Oct 29, 2026
f37070f
refactor: declare one code and impact per engine rule
emaarco Oct 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 8 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ them on a private corpus without copying it into the repository, are described i
| `domain/commands/` | the commands a caller can ask for (`EditCommand`: `AddElement`, `PlaceShapes`, ...), the ops JSON of `apply` and its aliases |
| `domain/diagram/` | the drawing (BPMN DI): `di/` reads and writes planes, frames, groups and the checkpoint every engine shares, `layout/` holds the engines (`clean/` redraws with `FullLayout`, `incremental/` keeps a hand-made drawing), `DrawnDiagram` is the drawing the diagram commands change, `commands/` holds one handler per diagram command (`ShapePlacement`, `ShapeAlignment`, `SpaceInsertion`, ...) and `DiagramCommands`, which dispatches them; `BatchDrawing` is all a batch does to the drawing |
| `domain/editing/` | what changes the model, one folder per concern: `elements/` (add, remove, retype, move, order, placement, artifacts, pools, lanes), `connections/` (connect, associations, sequence flows, bridges, flow ids, split), `properties/` (set, value coercion, the set keys, nested slots, vendor elements, decision links), `events/` (triggers, event definitions, root elements, the event-gateway rule), `extensions/` (ext), `ids/` (id renames); a command is a class created with the `EditSession` (`new ElementCreation(edit).add(op)`, `new Connections(edit).connect(op)`, ...) |
| `domain/validation/` | structural validation (`StructuralValidator`, `FlowOrder`), the validator hook, the `FindingBaseline` a write compares with and the `FindingMatcher` that tells the same finding before and after an edit; `profiles/` holds the engine rules that load on demand |
| `domain/validation/` | structural validation (`StructuralValidator`, `FlowOrder`), the validator hook, the `FindingBaseline` a write compares with and the `FindingMatcher` that tells the same finding before and after an edit; `PlatformCheck` adds the Camunda 7 / 8 findings of the injected `EngineLint` |
| `domain/views/` | the read views (`show`, `find`, `--around`, `--context`) and `DrawableDoc`, a document ready to draw (one without a diagram laid out in memory) |
| `domain/batch/` | one batch of commands on a document in memory: `EditBatch` (guard, commands, validation, layout, kept text, result), `ModelCommands` hands each model command to its domain service and `BatchDrawing` (`domain/diagram/`) lays the drawing out between them; the top of the domain, nothing imports it back |
| `application/port/in/` | one contract per use case, the way in: an interface with its `Command` and `Result` (`EditDocumentUseCase`, `RelayoutDiagramUseCase`, `ValidateDocumentUseCase`, `ShowModelUseCase`, ...), also for a pure query that needs no outbound port |
| `application/port/out/` | what the application needs from outside, named after what it does: `DocumentPort` (load a document, resolve where a result goes, save it), `LoadProjectSettingsPort` (the `.bpmnlintrc`), `RenderDiagramPort` (a plane as SVG), `WriteImagePort` |
| `application/port/out/` | what the application needs from outside, named after what it does: `DocumentPort` (load a document, resolve where a result goes, save it), `LoadProjectSettingsPort` (the `.bpmnlintrc`), `RenderDiagramPort` (a plane as SVG), `EngineLintPort` (the Camunda 7 / 8 rules), `WriteImagePort` |
| `application/service/` | one service per use case that implements its contract (`EditDocumentService implements EditDocumentUseCase`): load, let the domain work, save, all through the outbound ports; a query asks the domain and returns its answer |
| `adapters/in/cli/` | the driving adapter: the `Cli` (commander, streams, exit codes, errors) and one class per command; it knows the use cases only by their contracts and reaches the domain only through them; from the domain it takes the command vocabulary to check its flags (errors, op rules, flag values) |
| `adapters/in/report/` | what a use case's result looks like to the one who asked: text and JSON reports (`MutationText`, `MutationReportBuilder`, `ValidationText`, ...), the views as text, and the reference the guide and `bpmn kinds` print; the CLI prints them and `index.ts` / `api.ts` return them |
| `adapters/out/bpmnlint/` | the injected bpmnlint as a validator of the domain, browser-safe: `BpmnlintConfigResolution` (the effective `.bpmnlintrc`), `BpmnlintValidator`, `IdConventionsReader` (the id conventions of `element-id-naming`) |
| `adapters/out/files/` | the driven adapters on disk, Node only: `FileDocumentStore`, `BpmnlintProjectSettings` (loads the `.bpmnlintrc` and its plugins for `adapters/out/bpmnlint/`), `FileImageWriter` (PNG via resvg) |
| `adapters/out/bpmnlint/` | the injected bpmnlint as a validator of the domain, browser-safe: `BpmnlintConfigResolution` (the effective `.bpmnlintrc`), `BpmnlintValidator`, `IdConventionsReader` (the id conventions of `element-id-naming`); `BpmnlintEngineLint`, the Camunda 7 / 8 rules (the `EngineLintPort`), which loads `engine/` on demand: camunda-compat's rules (`compatRules`) and bpmn-cli's own rules (seventy for Camunda 7, fifty for Camunda 8: `engine/rules/c7|c8/`, one rule per file and one check per rule, next to the `support/` helpers of that engine, the shared helpers in `engine/rules/support/`, the rule bases both engines share in `engine/rules/`; a rule is named after what must hold, the id `<engine>-<subject>-<requirement>` and the class `<Engine><Subject><Requirement>Rule` in a file of its name (`c7-message-needs-name`, `C7MessageNeedsNameRule.ts`), the requirement `needs-<part>` for what must be there, `no-<part>` for what must not, or `known`, `valid`, `unique`, `allowed`, `supported`, `placement`, `resolves` for a value, a name or a place the engine accepts; it declares one `code` and `impact` in `defineRule`, several rules may share a code; an abstract base without `defineRule` (`C7ExecutableRule`, `C8FeelRule`, ...) holds what two or more rules check alike; the rules on what a typed parse drops read the file as written through `WrittenModel`, written on `EngineRule` of `@miragon/bpmnlint-plugin-rules/engine` and run in one walk with its `lint`), mapped to `W_C7_*` / `W_C8_*` by the engine run in `engine/run/` (`EngineRun`, `EngineFindings`, `EngineCodes`, `EngineHint`; `CompatVerdicts` holds where bpmn-cli reads camunda-compat differently); `engine/` gets the core from `engine-kit.ts` (a rule chunk must not import the entry) |
| `adapters/out/files/` | the driven adapters on disk, Node only: `FileDocumentStore`, `BpmnlintProjectSettings` (loads the `.bpmnlintrc` and its plugins for `adapters/out/bpmnlint/`), `FileImageWriter` (PNG) |
| `adapters/out/document/` | `DocumentStore`, what the file store and the in-memory store share behind the `DocumentPort`: a source parsed into a `Doc`, the lossless check, the target of a write and whether to write; browser-safe |
| `adapters/out/render/` | the SVG renderer behind the `RenderDiagramPort`, browser-safe: `SvgRenderer` (the port), `DocRenderer` (one plane, start to end), `crop/` (which part of the plane), `paint/` (the shapes, connections and labels as SVG), `compose/` (frame, scale, badges, tiles) |
| `adapters/out/memory/` | the driven adapters of the in-memory API: `NoDocumentFiles`, `NoProjectSettings` |
Expand Down Expand Up @@ -119,9 +119,10 @@ them on a private corpus without copying it into the repository, are described i

`bpmn-moddle` (the semantic model; `moddle` for its types), `@resvg/resvg-wasm` (the PNG rasteriser of
`bpmn render`), `commander` (the CLI only), and `bpmnlint` (pinned to `11.15.0`) with
`@miragon/bpmnlint-plugin-rules` (pinned to `0.12.1`: bpmnlint's rules, camunda-compat and
Miragon's rules behind one resolver), loaded only when a `.bpmnlintrc` applies (see
[bpmnlint](docs/bpmnlint.md)). Both are pinned exactly: they decide which findings an agent sees,
`@miragon/bpmnlint-plugin-rules` (bpmnlint's rules, camunda-compat and Miragon's rules behind one
resolver). They run when a `.bpmnlintrc` applies (see [bpmnlint](docs/bpmnlint.md)), and the plugin's
`./camunda-7` and `./camunda-8` entries are the Camunda 7 / 8 rules of every check, loaded on demand
(see [Camunda 7 and Camunda 8](docs/camunda.md#where-the-checks-come-from)). Both are pinned exactly: they decide which findings an agent sees,
the tests pin those findings, and bpmn-cli uses bpmnlint's `Linter` beyond its documented API.

`camunda-bpmn-moddle` (pinned to `8.0.1`) is a development dependency: its Camunda 7 descriptor
Expand Down
5 changes: 5 additions & 0 deletions docs/bpmnlint.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ and `@miragon/rules` come with bpmn-cli and need no install.
Keep the `moddleExtensions` entry. Without it camunda-compat sees no `camunda:` or `zeebe:`
properties and reports them missing, as bpmnlint does in CI.

bpmn-cli runs camunda-compat and the Miragon engine layer for every Camunda 7 / 8 file anyway, as
its `W_C7_*` / `W_C8_*` findings ([Camunda 7 and Camunda 8](camunda.md#where-the-checks-come-from)).
Extend them in the `.bpmnlintrc` when CI runs `npx bpmnlint` too: the same findings are then listed
twice, once under their code and once under the rule name.

::: warning Untrusted repositories
A `.bpmnlintrc` can name plugins of the repository, and `bpmn validate` then runs their code, as
`npx bpmnlint` would. In a repository you do not trust, pass `--no-lint-config`. See
Expand Down
Loading
Loading