Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Sections dated before 2026-09-19 predate the cycle and stay as they are. Named m

## Unreleased

- learn(workflow skills): **a Jump has one fixed target, so one failure handler for N steps is a child workflow, not a shared node; plus three probed workflow errors (CE0117 on a `System.Workflow` argument means map `$WorkflowInstance`, CE1613 means the called workflow's parameter must be `$WorkflowContext`, and `returns` goes before `exposed as workflow action`).** `workflow-structure-rules.md` §1 and `learned-workflow-patterns.md` §9. The §9 rows were probed on mxcli v0.26.0 / Mendix 11.15.0 with native `mx check`. The third row corrects the reading that a called microflow cannot return a value. Upstream issues: mendixlabs/mxcli#1529 (CE0117), #1530 (CE1613, and `syntax workflow call-workflow` shows the failing form), #1531 (describe drops every call workflow mapping), #1533 (`returns` parse messages). Source: a five-app lab project (Mendix 11.15, mxcli v0.26.0) — five-app lab report, WF-1
- learn(fixture-seeding): **resetting workflow data: abort instances through the runtime (Workflow Commons admin or *Change workflow state*); if SQL is unavoidable, delete the link tables first (`system$workflow_currentactivity`, `system$workflow_workflowdefinition`, `system$workflowusertask_assignees`, `system$workflowusertask_targetusers`, `system$workflowusertask_targetgroups`, plus the `system$workflowendedusertask_*` equivalents; names read from a Mendix 11.15 database), and reset a context object only after its instances are gone.** A seed reset that deleted workflow rows by SQL failed on those links (WF-5). Text only, `ondemand` skill. — five-app lab report, WF-5
- fix(e2e/helpers): **`navTo` throws `navigation item "<title>" not found` instead of clicking nothing.** A missing menu item was a silent no-op, so when the target page was also the persona's home page the landing guard stayed green and a broken-control journey (a control that must FAIL) passed. The parent group stays soft (an open flyout needs no click); the item itself must be found. The message names the active user and the visible menu items, so the reader can tell a renamed item (fix the journey) from a role that cannot open the page (fix the grants). Callers: journey steps fail with the message, design-audit rung 7 records a fault, full-app-walkthrough records a failed `nav` step (the walk stops only when the step is `fatal`), monkey's `land` swallows the error and still checks `.mx-page`, so monkey is unchanged. `tests/wave2/test-navto-missing-item.sh` (stub page, no browser) fails on master (absent item resolves) and passes here. Field report: a five-app lab project (Mendix 11.15, mxcli v0.26.0), TK-012 — MendixMau
- learn(rest-between-mendix-apps): **new on-demand skill for two or more Mendix apps you build that read each other over REST (app-to-app, microservices).** The contract decisions to write down before the first script (pull vs push, versioned path, key + version rule, cursor paging, `since` with overlap, error shape incl. the runtime's 560, auth in the operation microflow as of mxcli v0.24 per BUG-152, fixed ports, one owner per fact), 17 publisher and consumer rules for honest "as of"/stale/"never read" states, and a six-rung cross-app test ladder with a per-change/slice/release cadence; a signal-stopped test run is BUG-157. The 26-row failure register behind it is `process/rest-between-mendix-apps-register-2026-10.md`. Routed ondemand for architect, mdl, test and review at stages 3–6. Field evidence: three demo apps, mxcli v0.24–v0.26, Mendix 11.15, 2026-10-07 to 2026-10-12, domain names generalised — MendixMau
- fix(docs-numbering): **the pre-commit doc numbering check no longer fails every merge commit.** A merge stages all the other side's files, so the check examined docs the merge never touched and tripped on the existing "15-step" prose in `skills/source-triage.md:240` (plus two siblings that fail `--all`), which sent agents to `--no-verify`. During a merge it now examines only files that differ from both parents. The doc prose is left alone (an anecdote, not a drift). `tests/wave2/test-docs-numbering.sh` T11 fails on master's script. — agent report of `--no-verify` merges
Expand Down
14 changes: 14 additions & 0 deletions skills/fixture-seeding.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,20 @@ the answer is "re-copy the Run Locally database", say that in the project's own
"re-run the seed script", the seed script has to be idempotent, which most hand-written ones are
not.

### Workflow data: abort through the runtime, link tables first if SQL

A seed reset that deletes workflow rows by SQL fails while the link tables still point at them.
On Mendix 11.15 (names read from a database, not from docs) they are
`system$workflow_currentactivity`, `system$workflow_workflowdefinition`,
`system$workflowusertask_assignees`, `system$workflowusertask_targetusers` and
`system$workflowusertask_targetgroups`. Finished tasks keep their own links, with rows:
`system$workflowendedusertask_assignees`, `_targetusers`, `_targetgroups`. There is no
`usertask_targets` table. List the real names first (`information_schema.tables`) rather than
trusting this list on another version. Abort instances through the runtime (Workflow Commons admin, or a microflow
with *Change workflow state*); if SQL is unavoidable (local database only), delete the link tables
first. Reset a context object only after its instances are gone: a deleted context object makes an
instance incompatible, and that cannot be resolved (Mendix docs, *Workflow versioning*).

## What seeding buys - set expectations

Journeys PASS / FAIL / INVALID on two public template apps, same set, empty vs seeded database:
Expand Down
3 changes: 3 additions & 0 deletions skills/learned-workflow-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,9 @@ varying **only** the suspected cause — see [[sandbox-ab-tool-defect-probe]].
| **CE0053 / MDL040** | `DECLARE $L List of Mod.Entity = empty;` | Use `$L = CREATE LIST OF Mod."Entity";` |
| **CE0108** | A `RETRIEVE` inside an `IF` shadows the named return variable, leaving it out of scope on the `ELSE` path | Use early `RETURN empty;` on failure branches so only the success path reaches the named-return retrieve |
| **MDL-WF04** | Standalone `ANNOTATION` in a workflow activity flow (produces an unloadable model) | Use a plain MDL comment |
| **CE0117** at a *Call microflow* whose microflow takes a `System.Workflow` parameter | You passed a variable the workflow does not have (`Workflow = $Workflow`). `check --references` passes it. Only native `mx check` refuses it (mxcli v0.26.0, Mendix 11.15.0, probed 2026-10-15; upstream mendixlabs/mxcli#1529) | Map it to `$WorkflowInstance`: `call microflow M.ACT_X(Workflow = $WorkflowInstance, Ctx = $WorkflowContext)`, which builds clean (same probe). Don't look the instance up through `System.Workflow_ParentWorkflow` instead. That lookup has to guess when more than one child is in progress |
| **CE1613** "The selected parameter '…' no longer exists" at a *Call workflow* | The called workflow's parameter is named something other than `$WorkflowContext` (`parameter $Task: …` with `(Task = …)`). `check --references` passes it. `describe workflow` drops every call workflow mapping, correct ones included (mendixlabs/mxcli#1531), and `mxcli syntax workflow call-workflow` still prints the failing form (`Request = $WorkflowContext`, v0.27.0; #1530), so do not copy that example (mxcli v0.26.0, probed 2026-10-15) | Every workflow that is called declares `parameter $WorkflowContext: …`, and the call maps `(WorkflowContext = …)`. Keep the `.mdl` file as the source; don't round-trip the call through `describe` |
| parse error on a workflow call microflow: `mismatched input 'returns' expecting BEGIN` (v0.26.0) or `mismatched input 'returns' expecting STRING_LITERAL` (v0.27.0, mendixlabs/mxcli#1533) | `exposed as workflow action …` written before `returns …` | Write `returns Boolean as $Ok` first, then `folder` and `exposed as workflow action`. A called microflow *can* return a value: a Boolean gives the activity `true`/`false` outcomes and an enumeration one outcome per value plus empty (Mendix docs, *Call microflow*). "Exposed call microflows return nothing" is a wrong reading of this parse error (probed 2026-10-15) |
| **MPR006** | Empty container — compiles, crashes at runtime | Give every container content, or drop it |
| **MPR010** | Widgets not wrapped in a `LAYOUTGRID` | Wrap them |
| Workflow stuck | No `complete_task` button for one of the task's outcomes | Add the missing outcome button |
Expand Down
21 changes: 21 additions & 0 deletions skills/workflow-structure-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ Two failures this prevents, both invisible to `mxcli check`:
The main flow is `Start → … → End`. New activities go after the start and before the end (or
before a *Jump*, when the main flow ends on one).

**A *Jump to* has one fixed target. It cannot return to whichever step sent it there.** So "every
failing step goes to one shared failure node, then retries the step that failed" is not a
workflow you can draw: the retry needs a different target for each step, and there is no
"return to caller". A five-app lab project (Mendix 11.15, mxcli v0.26.0) drew exactly that for
seven calls. The Stage 3 count (§12) refused it, and the redesign cost a resolution round plus a
resync of the blueprint and three BRDs. When one failure handler must serve N steps:

- put the step and its retry or attention loop in a **child workflow** that each step reaches
through *Call workflow*. The child holds one handler, and its backward jumps stay inside the
child, so every target is fixed;
- the child ends **normally** and writes its result on its own context (an outcome attribute).
The parent reads it in a decision after the call. A sub-workflow returns nothing, and if it
*fails* or is aborted, the parent fails too (Mendix docs, *Call workflow*). Failure must
therefore be data, never an error;
- a jump in the parent aborts a running child (same page). Keep jumps in the parent to the
points where no child is running.

The alternative, one copied tail per step, multiplied a 7-call parent to 21 calls and 43
decisions in that project's count. Count the child design and the copied-tail design (§12)
before you choose.

## 2. Boundary events — type decides the terminator

A boundary event hangs on one parent activity. Only these can carry one: *wait for
Expand Down
Loading