Skip to content

v0.26.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 18:44
· 1882 commits to main since this release

[0.26.0] - 2026-10-11

Headline: Documents mxcli writes now survive Studio Pro's merge and diff: every element carries exactly the property names Studio Pro writes for the project's Mendix version. Before, a key mxcli left out, or wrote for a newer version, made a document unmergeable the first time Studio Pro saved it, although mx check, the build and the runtime stayed green. mxcli fix property-sets repairs projects an older mxcli wrote. Alongside it: a Claude Code companion mod with a Project pane, describe → exec round trips that keep loop back-edges, shared error handlers and page design properties, check -p resolving script sets and security references the way exec does, mxcli run --local as a background service, and a run of Windows fixes for the local dev loop. The language poster puts all of mxcli and MDL on one page.

Added

  • alter page / alter snippet add and drop parameters (#1234) — add parameters $Order: M.Order and drop parameters $Order, beside add variables / drop variables. Before, add parameters was a parse error ("mismatched input 'parameters' expecting VARIABLES_KW") and the only route was create or replace page, which rebuilds every widget and loses what describe does not round-trip. The declaration is CREATE's Params: rule, written by the same converters (so the 11.5+ IsRequired/DefaultValue gate holds). A page with a Url must name the new parameter in it — set (Url: …) in the same statement — or exec refuses with the URL to use (mxbuild CE5601, measured on 11.12.1); a snippet parameter must be an entity (MDL087, at check time too); a drop is refused while a data source or expression still uses the parameter.
  • mxcli git note — Studio Pro's commit metadata for commits made with git, and the teamserver-git skill (#1337) — Studio Pro attaches a note under refs/notes/mx_metadata to every commit (Mendix version, branch, and the model units the commit changed) and reads it to check a revision's version and show what it changed; a commit an agent made with git had none, Studio Pro 11.13 back-filled an "(unknown)" placeholder, and the user saw conflicts and changes the change pane did not show. mxcli git note -p app.mpr [--write] computes the note from the commit — the .mpr unit index and mprcontents at the commit and its parent — for the commits not yet pushed (or the ones named), keeps any note Studio Pro wrote (--force replaces it) and replaces placeholders. Measured against the 8 notes Studio Pro wrote on a Team Server repository's MPR v2 history: the header is identical on all 8 and the change list identical on every ordinary commit (Added/Modified/Deleted/Moved, a deleted module listed once, $ID-only re-serialisation not listed); on a version upgrade, which Studio Pro does and annotates itself, it lists more units than Studio Pro. The new teamserver-git skill teaches the workflow: commit from Studio Pro when it is open, create branches on the Team Server (a local-only branch crashes Studio Pro 11.13 on open), push refs/notes/mx_metadata with the branch before Studio Pro's background fetch discards it, and never merge, rebase or force-push model history with git.
  • languages() in Starlark lint rules — the languages enabled in the project (#1306) — a rule had no way to tell which languages are enabled: strings() has a row for every stored translation, and a fresh en_US-only app already carries nl_NL texts, so enabling a language changed nothing a rule could see, and languages() failed to load with undefined: languages. It returns one language per enabled language, from the project settings, with code, is_default and check_completeness, so a per-language check (every page title translated into each enabled language) can filter strings() to the enabled codes. It reads the project settings, not the catalog, so it needs no full catalog build; a failed settings read fails the rule instead of answering [].
  • A published REST service's authentication (#1331) — create [or modify] published rest service M.Api (…, Authentication: (basic, session, microflow M.Authenticate)) sets Studio Pro's Requires authentication and its methods: basic (username and password), session (active session), microflow M.F (custom); Authentication: none is "Requires authentication: No". The methods are stored in the order written, which is how Studio Pro stores the ones ticked, and describe prints them in the stored order (it omits none). Left out, create or modify and alter keep the stored setting, as before. alter published rest service M.Api set ( Key: value, … ) now takes create's property list (Path, Version, ServiceName, Authentication); set Key = '…' still works. The authentication microflow must return System.User and take only a System.HttpRequest and/or System.HttpResponse (Mendix: CE0334, CE0336, measured with mx check on 11.14.0); exec and check --references refuse anything else as MDL-REST04. Executing the describe output of each of ako/TestApp's Studio Pro services writes nothing.
  • send email — the built-in Send Email activity (Mendix 11.13+, beta) — send email ( From: …, To: …, Subject: 'Order {1}' with ({1} = …), Body: template '…', HtmlBody: template '…', Headers: ('X-Name': 'value'), Attachment: $Doc, Host: …, Port: …, SecurityType: ssl, CheckServerIdentity: true, ConnectionTimeout: 30000, Authentication: basic (Username: …, Password: …) ) [on error …]; creates a Microflows$SendEmailAction, which sends SMTP mail without the Email Connector module. The settings are one property list (ADR-0013), keyed by the metamodel's names; an unknown, repeated or misshapen key is an error, and so is a missing From, Host, Port or recipient (mxbuild: CE0166). describe microflow renders the activity instead of -- Unsupported action: Microflows$SendEmailAction, and the description re-executes to the same activity. check type-checks its expressions (E009: String addresses, host and credentials, Integer/Long port, String template parameters — what mxbuild reports as CE9528/CE0117), and warns on a server-identity check without SSL and on header names Studio Pro would refuse (MDL-EMAIL02/03). A 10.x–11.12 project is refused; a stored activity MDL cannot restate (authentication document, pre-11.13 message) still describes as unsupported rather than being rewritten smaller. mxcli syntax microflow.send-email. (#1315)
  • mxcli playwright check — a text verdict for pages of a running app, in one call — mxcli playwright check /p/a /p/b -p app.mpr loads each page in one headless browser and prints the verdict run --page-check prints (title, heading, rows, visible text, error banners, console errors) plus failed same-origin requests and the HTTP status, then OK n page(s) or FAIL k of n page(s). Exit status 0 all passed, 1 a page failed (HTTP error, sign-in form or a 401 instead of the page, an error banner or error dialog, a console error, a failed request, a failed assertion), 2 the check could not run. It signs in when needed — --user/--password, --role R (the project's demo user with that user role), or with only -p a demo user — saves the session under .mxcli/playwright-check/, reuses it on the next check and renews it when the runtime has restarted. --assert-text, --assert-count 'SELECTOR>=N', and --screenshot out.png, which prints the path and never the image. It replaces the hand-written playwright-cli login/goto/sleep/eval/screenshot sequences that were about a sixth of the tool calls in a measured app-building session, each ending in a PNG read; the test-app and verify-in-runtime skills and /mendix:test now route "check a page" to it.
  • mxcli run --local runs as a background service — --detach starts the warm loop in its own session and returns once the app serves (running: http://127.0.0.1:8080/ (pid N, watch, log .mxcli/run.log)), or prints the boot failure and the last log lines and exits 1. mxcli run status prints one line (URL, uptime, last build and how it was applied, a pending change; a dead pid is reported as stopped). mxcli run wait blocks until the model as it is now has been applied — applied: build #3 via reload in 1.4s — or failed, with the CE codes; it is race-free (a change already applied when it starts is reported at once), so mxcli exec x.mdl && mxcli run wait is one honest call; --ready waits for the boot. mxcli run stop shuts the run down and then sweeps its process session, so no orphaned runtimelauncher or mxbuild JVM is left, even from a run killed with -9. mxcli run restart stops and detaches again with the same arguments. Exit codes: 0 ok, 1 failed, 2 timeout, 3 not running, 4 starting. A second run for a project that already has one is refused. These replace the nohup / until grep / pkill loops that took about a quarter of all tool calls in measured agent sessions; the run-local and run-app skills and the generated CLAUDE.md now teach them.
  • mxcli diag session-report — where an agent session's calls and tokens went, from its Claude Code transcript — diag loop-report counts mxcli processes; this reads the transcript (~/.claude/projects/<project>/<session>.jsonl, subagent transcripts included) and reports model calls, tool calls by tool, cache-read / cache-write / output tokens and wall time; Bash calls split into mxcli verbs, playwright, build, git and other; every call in one category (orientation, write, validate, apply, verify, diagnosis, retry, delegate, other); the costliest results by re-read cost (size × the model calls after it, up to the next compaction); error → retry chains aggregated by normalised error; and repeated file reads and syntax/help/skill lookups. Several transcripts give one report each plus a combined one; --json, --top N. The output carries counts and short command/path/error snippets only, so it can be shared without the conversation. Rules: docs-site "Measuring Agent Sessions".
  • mxcli eval run and the BENCH-001 benchmark brief — runs Claude Code headless (claude -p, permissions bypassed, a known session id) on an eval test in a fresh project made by mxcli new (so the agent gets the CLAUDE.md and skills a user gets), copies the session transcript and its subagent transcripts into the run directory, writes diag session-report for it, then runs the test's checks. Variables a hosting Claude Code session sets for its children (CLAUDECODE, CLAUDE_CODE_*) are not passed on. docs/14-eval/eval-bench-001.md is the fixed brief for measuring the agent loop: four entities, three associations, overview and edit pages, a validated microflow, two module roles, navigation and a microflow test. New eval checks: association_exists, module_role_exists, file_exists, tests_pass (--skip-tests).
  • The mxcli companion: a Claude Code mod with a Project pane — /mxcli-project opens a pane showing the app's structure (from mxcli project-tree) and the selected document's MDL (from mxcli describe). The tree reloads when the agent changes the model. From 90 columns the tree and the source sit side by side. The first session in which it loads offers the pane once, in a band above the prompt. mxcli init installs it in .claude/skills/mxcli-companion/ and init --sync-skills keeps it current. project-tree now marks each node describable, derived from describe's own dispatch, so a client never offers a node describe cannot answer (a JavaScript action and the Navigation node could not be described before).
  • mxcli fix property-sets — complete the property names of units no write reaches (#1373) — every write now normalizes a unit's property names for the project's Mendix version (see Fixed), but only the units a statement rewrites. mxcli fix property-sets -p app.mpr [--dry-run] applies the same normalization to every stored unit and reports the keys added and stripped per unit. It goes through the ordinary guarded write path: no $ID or GUID changes, and a second run writes nothing. On Studio Pro-authored projects it reports 0 units.
  • DateTime not localized (#1373) — BirthDate: DateTime not localized sets Studio Pro's Localize off, which had no MDL spelling and was only carried on a rewrite. Bare localized switches it back on in modify attribute; unstated keeps what is stored. describe entity prints it when it is off. alter entity … modify attribute no longer resets a stored non-localized DateTime when the statement does not mention it. A view attribute follows its OQL source, and changing a source attribute's Localize now re-derives every view over it instead of leaving them CE6770 "out of sync".
  • Module documentation and the administrator's user name (#1314) — the doc comment before create [or modify] module is stored as the module's domain model documentation and printed back by describe module; alter app security ( AdminUserName: '…' ) renames the built-in administrator. Lint could already read both; MDL could write neither.
  • close page n closes n pages — the count was written to a field Mendix removed in 8.11, so close page 2 closed one page, and a Studio Pro "close 2 pages" described as close page;. The parser now accepts the count, and the writer and reader use the current field.
  • add $X to $Obj/Module.Assoc and remove $X from $Obj/Module.Assoc (#1288) — the Change object activity's add and remove on a reference set. change $Obj (Assoc = $X) was the only spelling and assigns the whole set, so appending in a loop kept only the last row, with no error from check, mx check or the runtime.
  • Param = nothing for a call argument left blank — Studio Pro stores a blank call microflow / call nanoflow argument as an empty mapping, and describe printed it as Param = ,, which did not parse. It now prints, and accepts, Param = nothing.
  • check --v1=warn|error — mirrors --deprecations: under error, every MDL-V1-* warning (a headerless script not ready for mdl 1;) fails the run. A script headed mdl 1; reports none.
  • mxcli test --db-type postgresql|hsqldb (#1274) — a --local suite can run on the file database, as run --local --db-type hsqldb already could, so a machine without PostgreSQL can run tests.
  • MPR007 flags a user role that cannot open its home page — a role none of whose module roles may open the home page it lands on passed lint and check --references, then failed the build with one CE2729 per widget, none naming the cause. The warning resolves each navigation profile's effective home page per role, and states CE2729 only where the project runs at Production security.
  • The language poster — all of mxcli and MDL on one page, interactive (zoom into any panel, or step through it as a 19-panel tour), shown at the top of the README and in the manual's Preface.

Changed

  • A page or snippet variable's default is written as a bare expression — Variables: ( $show: Boolean = true ), = if (3 < 4) then true else false, = 'Price' + ' list', = Module.Enum.Value, and the same in alter page … add variables. The old spelling, a string whose content is the expression (= 'true'), keeps its meaning under every language version and warns as MDL-DEPR086 (refused from mdl 2). fmt --upgrade rewrites it, and describe prints the bare form. A default that is itself a string ($s: String = '''abc''') or is empty keeps its current spelling and is not reported, since a bare 'abc' is the old spelling.
  • A published OData service's authentication is a property — create published odata service M.S ( …, Authentication: (basic, session, microflow M.Authenticate) ), in the order written, replaces the trailing authentication basic, session clause (R9). The property can also say Authentication: none, which the clause could not, and alter published odata service M.S set ( Authentication: … ) now changes authentication on an existing service — before, it could only be restated with the whole service. Left out, create or modify and alter keep the stored setting, as before. describe prints the property. Migrating a script: nothing breaks — the clause (MDL-DEPR139) still parses and builds the same service, check / exec warn, and mxcli fmt --upgrade moves it into the list (a clause naming a method MDL has no keyword for, e.g. authentication Custom, is reported and left alone). A stored setting MDL cannot state — a microflow stored without the Microflow method, or the reverse — is now a comment in describe rather than printed as Microflow M.F, which used to add the method when the output was executed. Executing the describe output of each of ako/TestApp's three Studio Pro OData services writes nothing.
  • call rest service takes its settings as one property list (ADR-0013) — the activity's dialog settings go in one ( Key: value, … ) list after the URL, keyed as the consumed REST service names the same concepts: $Html = call rest service get 'https://example.com' (Headers: ('Accept': 'text/html'), Authentication: basic (Username: $User, Password: $Password), Timeout: 300) returns String;. Body: is template '…' [with ({1} = …)], mapping M.EMM from $Var, binary <expr> or an expression. The method, URL, returns … and on error … stay words. An unknown or repeated key, or a value of the wrong shape, is an error. describe writes this form. Migrating a script: nothing breaks — the clauses header 'N' = v, auth basic $u password $p, body … and timeout n (MDL-DEPR720) still parse and store the same activity, check / exec warn, and mxcli fmt --upgrade rewrites them; a statement cannot mix the two forms. ADR-0013 makes this the rule for every new microflow activity and every activity with several settings.
  • run --local --page-check signs in with --screenshot-user without --screenshot, and checks all pages in one browser — the sign-in only ran when --screenshot was also given, so --page-check --screenshot-user U reported every secured page as the login page. The verdict also no longer counts a list view's "No items found" placeholder or a data grid's header as rows, ignores the demo-user switcher's "Select user" heading, and reports a failed same-origin request (HTTP 560 POST /xas/) instead of the duplicate "Failed to load resource" console line. The login script used by --screenshot-user falls back to /login.html when the app root does not show the sign-in form, and finds Playwright the way the page check does (no playwright CLI on PATH needed).
  • mxcli rename takes java-action and workflow — the subcommand offered eight of the ten targets RENAME accepts; Java actions and workflows could only be renamed from MDL. mxcli rename -p app.mpr java-action M.JA_Old JA_New also renames the .java source file, and both update docs/brain/ anchors like the other types. The type list is now held to the grammar by a test, so a new RENAME target cannot be left out of the subcommand again. mxcli syntax rename documents both forms. (follow-up to #1318)
  • An in-place edit inside a loop body is spliced, not refused (ako#1106) — under mdl 1;, re-running create or modify microflow with one changed expression inside a loop was refused with MDL-V1-REBUILD, so one script could not both provision and update a flow that loops. A body of the same shape (same statements in the same order) is now edited in place, nested loops included, and alter microflow accepts a one-for-one replace of an activity in a loop. Adding, removing or moving a node in a body keeps the refusal.
  • Agents are routed to mxcli syntax before a skill, and every skill has a section index — the generated CLAUDE.md points at mxcli syntax as the first stop for how to write any MDL, and each of the 74 skills starts with a generated, line-numbered section index, so an agent can read one section rather than the whole file. Reading whole skills was ~68% of a benchmarked session's re-read cost.
  • Faster on large projects, MPR v1 above all — on MPR v1 every typed listing read the contents of every unit before filtering by type; listings now filter on a type index first. check -p lists only the document kinds the script's statements can clash with, and reads the project settings only for a script that writes translations. describe microflow on a flow whose decisions call rules no longer runs for minutes (one rule lookup took 53 s on a 140 MB v1 app), and a hand-laid flow is analysed once per describe instead of once per layout round (#1301).
  • MDL-DEPR081 names the $currentObject form it means — the message said Visible: <expression> had the same meaning as Visible: [<expression>]. It does not: inside the brackets a bare attribute is rooted in $currentObject. A migration done by hand from the message silently rebound every such condition.
  • Re-running create or modify navigation reports Unchanged when nothing was written, instead of "Navigation profile 'X' updated." every time.

Fixed

  • check -p on create or modify of stored microflows is back to v0.24.0's speed (#1272) — the passes that predict exec's verdict and resolve references looked each flow up by name several times per statement, and every lookup re-read and fully decoded every microflow file in the project, so the cost per statement grew with the project. Each check pass now reads a unit file once, and a lookup by name or ID decodes only the flows it returns. On a blank 11.14 app with 200 microflows, re-declaring 25 / 100 / 200 of them: 3.5 / 11.7 / 23.7 s → 0.8 / 1.8 / 3.0 s (v0.24.0: 0.9 / 2.6 / 3.7 s). exec gains the same through its preflight and its own planning of each statement; an unchanged re-run of the 200 went from 40 s to 5 s. Nothing reported changes.
  • A navigation sub-menu no longer keeps the action of the page item it replaces (#1341) — turning menu item 'Work' into sub-menu 'Work' with create or replace navigation (or create or modify menu) paired the two by caption and carried the page item's Forms$FormAction onto the sub-menu, reporting it as an action "MDL cannot express"; mx check then failed with CE0548 "Items with subitems cannot have an action themselves." A sub-menu is now always written with no action (measured on 11.14.0).
  • mxcli test --attach and the dev loop's "already serving" detection see a live app on Windows (#1284) — both read a pid from a handshake file (.mxcli/test-endpoint.json, .mxcli/run-local.json) and tested it with Signal(0), which Go supports only as Kill on Windows, so every pid read as dead: test --attach always refused with "the app that published … is no longer running" while the app was up, and a command that looks for a dev loop already serving the project (the recompile warning, for one) never found it. Liveness is now internal/procalive.Alive, which uses OpenProcess and WaitForSingleObject on Windows (the check run --local already used for mxbuild) and Signal(0) elsewhere. No change on Linux or macOS.
  • run stop on Windows no longer reports a run that has shut down as still alive — it printed "failed: 1 process(es) of pid N's run are still alive" and exited 1 for a run that had stopped, because its liveness check counted any pid Windows could still open as alive, and an exited process stays openable while its parent holds a handle to it. It now uses the same check as test --attach (above), and reports "stopped: pid N".
  • retrieve $u from $obj/System.owner passed check and exec, then failed the build with CE0136 (#1358) — owner and changedBy are entity flags, not modelled associations: mxbuild resolves the name in a retrieve by association but derives no entity from it, [CE0136] "Retrieve object must specify the 'Entity' property.", with or without owner: AutoOwner (measured on 11.12.2, System.changedBy alike). check and exec now refuse it as MDL-RETRIEVE02 and name the form that builds: retrieve $u from System.User where [id = $obj/System.owner] first;.
  • run --local and test --local work on Windows without Developer Mode or admin rights (#1286) — the first run for a new Mendix version failed with linking runtime into mxbuild cache: symlink …: A required privilege is not held by the client. mxcli links the downloaded runtime into the mxbuild cache, and an ordinary Windows user may create a symbolic link only with Developer Mode or an elevated token. When Windows refuses the symlink, mxcli now makes a directory junction instead, which needs no privilege (the same link mklink /J makes; it needs cmd.exe, which every Windows has). The other link site, the PAD files docker build links into the mxbuild cache, gets the same fallback. A cache that was already linked by hand with New-Item -ItemType Junction is left as it is.
  • run --local --watch applies a domain model change on Windows (#1342) — page and microflow edits hot-reloaded, but adding an entity or an attribute failed every rebuild with "The process cannot access the file '…\deployment\web' because it is being used by another process", and the app then served 404 until run --local was restarted. A domain model change makes mxbuild recreate deployment/web, and the incremental web client bundler runs inside it, which Windows will not let anyone delete. On that failure the watch loop now stops the bundler, builds again, and starts a fresh bundler on the new web/; page edits keep the incremental path. Applies to Mendix versions whose deployment has web/rollup.config.mjs (reported on 11.12.4, reproduced on 11.13.0); 11.12.6 and 11.14+ bundle in mxbuild and were never affected.
  • run stop and run status find a detached run's processes on every machine — the guard against a reused session id rebuilt each process's start time from the kernel's boot time, which is whole seconds, and allowed only one second of slack. On a machine that booted late in a second, a run's own processes read as older than the run and were skipped, so run stop could report "was not running" for a live run. The slack is now two seconds. This was also the intermittent TestRunStop_* / TestSessionMembers_* failure on CI.
  • The catalog names a call's and a delete's target (#1305) — activities_for() and CATALOG.ACTIVITIES returned every microflow, nanoflow, Java action and JavaScript action call with action_ref="", and every delete with entity_ref="", although refs_from() had both targets; a loop-scoped lint rule could not follow a call out of the loop. action_ref / ActionRef is now the called document, entity_ref / EntityRef a delete's entity (when the flow types the variable: a parameter, a create or retrieve output, a loop iterator), and the new queue_ref / QueueRef the task queue a microflow or Java action call runs in, so a rule can skip a call that runs asynchronously. A nanoflow's JavaScript action call now has a refs_from() call row (target_type "JAVASCRIPT_ACTION"), so show callers sees it. The catalog schema is bumped to 23; a cached catalog rebuilds.
  • A DataGrid 2 column's Visible: expression is written — Visible: $showPrices, Visible: if … then … else …, visible: not(…) and Visible: [cond] on a column passed check and exec and were stored as true, so the column was always visible; only the old quoted Visible: '<expr>' was kept. alter page … set (Visible: <expression>) on grid column(…) was refused as "column property VisibleIf not found", and an inserted column dropped Visible: false too. describe now prints the bare expression. A column's visibility is evaluated once for the grid, with no row object, so $currentObject there is CE0117 at build; check refuses it as MDL-WIDGET43 (measured on 11.14.0). Use a page variable or parameter. Projects regenerate their widget definitions (generator version 18).
  • set $Param = … on a parameter is refused — a Change variable cannot target a parameter, and mxbuild rejects it with CE7247 "Parameter 'N' cannot be changed." (measured on 11.14.0 for Integer and String parameters in a microflow, a nanoflow and a rule). check and exec passed it. MDL-SET01 now refuses it for every parameter but a list (set on a list parameter is a Change list Replace, which builds), and exec enforces the rule. Copy the parameter into a variable first: declare $Value Integer = $N;.
  • check refuses a button that passes its own data container by widget name (#1324) — actionbutton btnOwn (Action: call microflow M.F(Gate = $dvGate)) directly inside data view dvGate passed check --references and exec, then mx check reported [CE0117] "Error(s) in expression." at Action button 'btnOwn'. A data container's name is a variable only for the containers nested below it; in its own context the object is $currentObject. Reported as MDL-BUTTON02 (error, so exec refuses it), for data views, list views, galleries and data grids alike, including attribute paths ($dvGate/Name) and a control bar inside the container. The rule covers every slot evaluated in that context, not only action arguments: a nested widget's microflow data-source arguments, Visible:, Editable: and DynamicClasses: (CE0117), and a nested list's XPath where (CE0161). A grid's own name from its control bar (the selection) and an enclosing container's name from a nested one are not flagged. The flagged set matches mxbuild 11.14.0's CE0117s widget for widget on a ten-button probe page.
  • set $Obj = … on an object variable is refused (#1323) — with both variables single objects (e.g. a Reference retrieved from its FROM entity), set $Cursor = $Next; passed check --references and exec and was written as a Change variable action, which mxbuild refuses with CE7247 "Variable 'Cursor' does not have a primitive type". Mendix has no action that reassigns an object variable, so check (MDL-SET01, for the objects it can see without a project), check --references and exec now refuse it and name the alternatives (a sub-microflow that returns the next object, change $Obj (…)). check --references now types a Reference retrieve from its FROM entity as the object it is. set on a list variable stays a Change list Replace (ako#949).
  • RENAME JAVA ACTION renames the Java class, not just the file — renaming M.JA_Old to JA_New moved the source to JA_New.java but left public class JA_Old, its constructor and its toString inside it, which javac rejects (class JA_Old is public, should be declared in a file named JA_Old.java). A full build hid it, because mxbuild regenerates the stub in its own copy; run --local --watch hot reload and IDEs compile the file on disk. Those three places now follow the rename exactly as mxbuild rewrites them; user code and extra code are left as written. Applies to mxcli rename java-action too.
  • run --local --watch starts on Mendix 10.24 and 11.6 — it waited the full web-client timeout (5 minutes) for a bundle that had finished in seconds, then failed with web client watcher timed out. The rollup runner those versions ship reports its status as {"code":"SUCCESS"} rather than the modern-web-bundler protocol mxcli was reading; both are now understood, including that runner's error reports.
  • run --local --watch no longer loses a change made while the app boots — the watch loop took its baseline after the boot, so a model written during the ~15 s boot was never built and the app kept serving the model from before it. The baseline is now the source time the boot build was made from, so that change is built on the first tick.
  • Documents mxcli writes are mergeable in Studio Pro (#1373, ako#1097) — Mendix's merge and diff engine compares an element's property names between two revisions and throws ("Objects with ID … do not have the same properties") instead of filling a default. A new element failed one Studio Pro save later, and mx check, the build and the runtime never noticed.
    • Every written element gets Studio Pro's full property set, from a table measured with mx convert on Mendix 10.24, 11.6 and 11.12–11.15. Keys a project's version does not declare are stripped (refused when they hold a value), and keys Mendix removed before it are dropped.
    • On Mendix 10 and 11.0–11.11 projects, mxcli no longer writes types and keys those versions lack: no Rest$JsonBody on Mendix 10 (Studio Pro could not load the project at all; the body is written as a string body), and no 11.12-only published member types or navigation sync flag.
    • Writer gaps fixed on the way: a loop's documentation was never written (a rebuild erased it), a tab container's default tab never landed, a date-only attribute had no Localize key, an expression-bound page flow argument had no Variable slot, inline REST value mappings carried IsDefaultType, and Response: none came back as json after Studio Pro's next save.
    • A user role written by an older mxcli has no GUID, which mxbuild then re-invents on every build. It is filled with the role's $ID, which kept the runtime's role rows and every user-to-role link (measured on 11.15 with PostgreSQL).
  • describe → exec of a Studio Pro microflow keeps its control flow — each of these described a flow that re-executed to a different one, found on real Marketplace modules:
    • a loop whose header sits in a branch, or is also the join of an if, lost its back-edge, so a pagination or poll loop ran once;
    • an error handler two activities share was printed as two empty handlers, and one that runs through a merge with a single way in was cut off at that merge;
    • an activity with no outgoing flow that ends a loop-body branch now ends in continue; instead of falling into the code after the branch;
    • a region two case arms share is printed once, a crossed merge is joined wherever a branch reaches it, and an interleaved if whose entries are merges is joined instead of nested as fall-through;
    • an empty decision caption (#1254), @excluded on an activity (#1328), a nanoflow's grant execute (#1345) and interior blank lines in a /** */ doc comment (#1300) are kept;
    • an unspaced minus after a name ($P/Offset-1, $I/OEE-$B/OEE) is subtraction, not part of a hyphenated name, so Studio Pro's stored expressions parse.
  • describe → exec of a Studio Pro page or navigation changes nothing — layout grid rows and columns keep their design properties, classes, styles and alignment, a text input keeps its submit behaviour and delay, a layout grid its width and a column its preview width, and a static open-link address and Widgets lists are written exactly as Studio Pro stores them. A menu caption with an apostrophe parses again (#1343), and a folder name containing / is escaped as \/ instead of being filed three folders deep (#1367).
  • check -p predicts what exec refuses, in more places:
    • a set of script files is checked against what the earlier files write, so a later file's reference to something an earlier one creates is no longer reported missing (#1355);
    • grant, revoke and user-role statements resolve the entities, documents, members and roles they name, and create module role its module (#1354); flow and page signatures resolve their entity types;
    • a retrieve constraint comparing an attribute with a variable of an incompatible type (#1325), and an operator inside an XPath function argument (MDL091, #1326), are refused before the build reports CE0161;
    • currentDateTime(), which is not a Mendix function, is refused (MDL044);
    • accepted, as Mendix accepts them: the parse functions' default-value argument (#1216), : as division in a comparison, $obj/Assoc/Module.Target as an object value (MDL049), the output name of a call to a void microflow or nanoflow, and a join inside a REST call's error handler (MDL-FLOW02). A stored void microflow's return value is a warning instead of an error, so exec re-applies Studio Pro-authored flows;
    • no false MDL-WIDGET07 for properties the builders do write (ShowFooter, a navigation tree's Menu, …; #1346), or for a pluggable widget named by id when there is no project;
    • clearer syntax errors for drop … M.F if exists (it is drop … if exists M.F) and for a hyphenated icon name (Atlas_Core.Atlas."add-circle"), and a syntax error instead of a crash for a non-string REST property value (#1331).
  • Page and model writes that passed check and failed later:
    • a button's Tooltip: is stored, described and alterable (#1307); alter page can insert a tab page into an existing tab container (#1215);
    • a flow argument on a button inserted into a snippet, or set with alter page … set (Action: …), binds the parameter instead of writing $P as text (#1317);
    • changedBy/Name and owner/… in a widget's attribute path resolve the System associations (CE1613, #1338), a bare association name in validation feedback is stored as an association, and a cross-module association published on an OData entity is published as an association end (CE1613);
    • adding (KEY) to a published OData member no longer carries its stored "can be empty" onto the key (CE0309);
    • a Boolean constant's default and override are stored as True / False, as Studio Pro reads them (#1321); an underscore-led enumeration value in XPath (M.E._True) is stored as Studio Pro stores it (CE0161); a restrict association's delete message is stored in the project's language instead of en_US (#1344); a Microflow-typed Java action argument followed by a line break resolves (#1282); consecutive XPath predicates (Entity[a][b]) parse (#1281).
  • Lint: CONV011 and MDL-PERF01 count create … commit and change … commit in a loop as a commit in a loop, and MDL-MAP04 checks import and REST activities already stored in the model, not only those in a script (#1319).
  • Tools:
    • mxcli describe Mod.Name finds documents when there is no catalog, and the describe subcommand accepts published REST services (#1347);
    • an implicit catalog rebuild no longer counts against the statement timeout, which on a large app cut it off at 5 minutes and repeated it on every call (#1329);
    • describe structure depth 2|3 lists each page's data widgets, which it never had;
    • mxcli new no longer exits 1 when the devcontainer's Linux binary cannot be downloaded after the project was made;
    • playwright check finds mxbuild 11.15's bundled node;
    • diag loop-report counts the wall time of runs that wrote no summary, which hid the app restarts;
    • three skill examples that failed mxcli check are fixed, and whole skill examples are now gated on it (#1357).

Full Changelog: v0.25.0...v0.26.0