Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ three commits past it), and a bug report can name a release instead of a sha nob
Sections dated before 2026-09-19 predate the cycle and stay as they are.

## Unreleased
- learn(skills/learned-microflow-patterns.md): **expression functions take positional arguments only — `toString(from: $X)` is not a syntax error, it's a silent misparse.** MDL's expression grammar has no named-argument form for function calls; `label: value` parses as `label` (a bare unresolved identifier) COLON-divided by `value` — COLON being the OQL division operator. Verified on mxcli v0.24.0 / Mendix 11.12.1, scratch copy of a PoC model: `toString(from: $Temperature)` and `formatDateTime($D, pattern: 'yyyy-MM-dd')` both pass `mxcli check --references` silently (exit 0) because the collapsed argument count still matches the function's arity; `substring(from: $S, index: 0, length: 3)` fails, but with a misleading `E006` ("expects 2 to 3 argument(s), got 1") that never names labelled arguments as the cause. The likely source: labelled-colon syntax is genuine MDL elsewhere (page `Attribute:`/`Action: MICROFLOW Name(Param: val)`, `@anchor(from: bottom, to: top)`) — just never inside an expression — workshop feedback, Sep 2026
- learn(skills/learned-file-upload-widget.md): **a file upload mxcli can author, with proof that it uploads.** The Mendix File Uploader 2.5.0 bound to a `System.FileDocument` specialisation: the MDL shape (entities, grants, create/delete microflows, advanced formats), which upload widgets mxcli cannot author (classic FileManager, PDS uploader), the two traps with workarounds (a simple-mode `allowedfileformat` passes exec and fails `mx check` with CE0463; an uploader DESCRIBE will not re-exec, `exposes 2 datasources`), and the six-step upload instrument. Field run on stock v0.24.0: the section-4 MDL taken verbatim from the skill gave `mx check` 0 errors, 2/2 files stored, 2/2 downloads sha256-equal, `.csv` rejected with 0 rows; both traps reproduce unchanged on v0.24.0 — a Mendix app-rebuild project
- new(skills/mendix-best-practices-index.md): **one row per Mendix best-practice area: the Mendix docs page, the bundled `assess-quality` section, the toolkit skill that applies it before the write, and the `mxcli lint` rule that catches it after exec.** An index, not a copy — the practice text stays on the Mendix pages (17 URLs verified HTTP 200 on 2026-09-25) and in the mxcli-bundled skill; Mendix's own Best Practice Recommender rules (MXP001–016) anchor the performance rows, and four rows say out loud that no lint rule exists and the preflight checklist is the only check. Routed `all` agents, stages 3/5/6, group reference — Maurits Visser
- learn(skills/microflow-preflight.md, agents/mdl-agent.md): **a microflow now gets a tier before any MDL — Simple, Guided or Split-first — and Split-first means a posted split plan (thin orchestrator + one `SUB_` per responsibility, with signatures) that the user confirms first.** Prompted by a colleague's session refusing a long microflow as "too difficult" while the same task went through on a stronger model: the piece was too big, not the task. mdl-agent gains two rules — never hand back "too difficult", hand back the split plan; escalate one failing `SUB_` by name after one retry, never the whole script. Also records the mxcli team's answer on positioning: a standalone `mxcli layout` command — which on v0.24.0 and upstream main (2026-09-25) arranges domain models only (`--dry-run` on a scratch copy of a PoC model: 10 entity moves, no microflow), so the no-`@position` rule and the if-branch workaround stand until a microflow mode ships; noted in the bug ledger and `learned-microflow-patterns.md` — Maurits Visser
Expand Down
30 changes: 30 additions & 0 deletions skills/learned-microflow-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,36 @@ This applies anywhere an enum value flows into a String context: concatenation,

---

## Expression Functions Take Positional Arguments Only — Never `name: value`

**Bug (verbatim, from field feedback):**

```mdl
set $JSON = $JSON + ',"temperature":' + toString(from: $Temperature);
```

**Rule:** every built-in Mendix expression function — `toString($X)`, `formatDateTime($D, 'yyyy-MM-dd')`, `substring($S, 0, 3)`, `length()`, `contains()`, etc. — takes **positional arguments only**. There is no `name: value` form inside an expression. That labelled-colon shape is real MDL syntax elsewhere — page properties (`Attribute: Name`), page actions (`Action: MICROFLOW Mod.Flow(Param: val)`), and annotations (`@anchor(from: bottom, to: top)`) all use it — which is almost certainly where the habit leaks in from. Inside an *expression*, a bare `name:` is not a label at all: `mxcli`'s expression grammar has no named-argument production for function calls (`argumentList: expression (COMMA expression)*`), so it parses `label: value` as `label` (an unresolved bare identifier) **`:`-divided by** `value` — COLON is the OQL division operator — one silently wrong expression, not an error.

**This is not reliably caught by `mxcli check`, including `--references`.** Verified on mxcli v0.24.0 / Mendix 11.12.1:

| Written | `mxcli check --references` |
|---|---|
| `toString(from: $Temperature)` | **Passes silently** (exit 0, "✓ All references valid" / "Check passed!") — parsed as `toString(from : $Temperature)`, one bogus division argument, argument count still matches `toString`'s arity of 1 |
| `formatDateTime($D, pattern: 'yyyy-MM-dd')` | **Passes silently** — same mechanism, second argument's label/value pair still counts as one argument, matching `formatDateTime`'s arity of 2 |
| `substring(from: $S, index: 0, length: 3)` (or any label, e.g. `src:` — not keyword-specific) | **Fails**, but with a misleading message that never names the real cause: `substring() expects 2 to 3 argument(s), got 1. [E006]` |

A labelled call that happens to land on the function's normal arity round-trips through `mxcli check`/`describe microflow` clean and reaches real `mx check`/Studio Pro/mxbuild before anyone notices — where the bare identifier (`from`, `pattern`, …) fails as an undefined rule/constant reference. Only a call whose label count doesn't match the arity gets a (misleadingly worded) error from `mxcli check` itself. Treat any `name:` inside a function call's parentheses as a STOP regardless of whether `mxcli check` complained — grep the expression for `[A-Za-z]\w*:\s` before trusting a clean check.

```mdl
-- WRONG — silently misparsed, not a syntax error:
set $JSON = $JSON + ',"temperature":' + toString(from: $Temperature);

-- CORRECT:
set $JSON = $JSON + ',"temperature":' + toString($Temperature);
```

---

## CHANGE activity: clear a String attribute — use `empty` not `''`

Setting a String attribute to empty string via `''` in a CHANGE activity causes CE0117:
Expand Down
Loading