Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3a31926
fix(executor): judge one-hop variable comparands in widget data sourc…
claude Oct 15, 2026
592ae00
fix(executor): MDL-WIDGET16 requires an association-mode combo box ca…
claude Oct 15, 2026
0a639d3
docs(skills): regenerate xpath-constraints' line index (mendixlabs/mx…
claude Oct 15, 2026
ccf533f
Merge pull request #1390 from ako/fix/1466-xpath-comparand-and-combob…
ako Oct 16, 2026
50ea77e
fix(executor): carry business event channel identity on create or mod…
claude Oct 16, 2026
81bd757
fix(backend): describe workflow keeps the call workflow parameter map…
claude Oct 16, 2026
9c0b2d5
fix(executor): check business event message attributes against inheri…
claude Oct 16, 2026
5f3332d
Merge branch 'mendixlabs:main' into main
ako Oct 16, 2026
979cb8f
fix(executor): describe keeps an untitled Data grid 2 actions column …
claude Oct 16, 2026
50b75bc
fix(executor): refuse a call workflow mapping not keyed WorkflowConte…
claude Oct 16, 2026
5c01fe9
fix(navigation): an omitted clause keeps the stored value (mendixlabs…
claude Oct 16, 2026
bdcdd11
Merge pull request #1416 from ako/fix/1520-describe-untitled-datagrid…
ako Oct 16, 2026
3026187
fix(widgets): drop-down filter keeps its attribute (mendixlabs/mxcli#…
claude Oct 16, 2026
91352c9
fix(executor): check the variables a workflow expression names (mendi…
claude Oct 16, 2026
507e57d
Merge pull request #1418 from ako/fix/1531-call-workflow-parameter-ma…
ako Oct 16, 2026
71a599f
fix(executor): an undefined glyph code is an error, MDL078 (mendixlab…
claude Oct 16, 2026
399083b
fix(pages): reset hidden column properties after an ALTER SET (mendix…
claude Oct 16, 2026
5fd72a0
Merge origin/main into fix/1529-workflow-expression-scope
claude Oct 16, 2026
2f42df6
fix(mdl/executor): judge an alter block's scope against the flow it w…
claude Oct 16, 2026
e411b54
fix(mdl/executor): name the deliberate rebuild in the loop-body refus…
claude Oct 16, 2026
6ab9bc1
fix(exprcheck): check built-in argument kinds, without a project too …
claude Oct 16, 2026
81be179
fix(run-local): boot with scheduled events running and say so (mendix…
claude Oct 16, 2026
77bc42c
Merge pull request #1421 from ako/fix/1522-undefined-glyph-is-an-error
ako Oct 16, 2026
976d4d7
fix(marketplace): run the widget and design-property repairs as part …
claude Oct 16, 2026
e3bb427
fix(visitor): hint a keyword used as a name and `returns` after optio…
claude Oct 16, 2026
cc4a252
fix(visitor): hint a routine header written without parameter parenth…
claude Oct 16, 2026
cd4c52e
fix(visitor): make the backslash-quote hint version-correct under mdl 0
claude Oct 16, 2026
966e94c
Merge pull request #1419 from ako/fix/1529-workflow-expression-scope
ako Oct 16, 2026
ead28cf
Merge pull request #1422 from ako/fix/1519-datagrid-filter-and-column…
ako Oct 16, 2026
a540ed2
fix(executor): note when an unstated localized keeps a stored not loc…
claude Oct 16, 2026
c54c616
Merge pull request #1424 from ako/fix/1515-builtin-argument-types
ako Oct 16, 2026
0070912
fix(check): refuse a list retrieved over an association used as an ob…
claude Oct 16, 2026
403d520
Merge pull request #1423 from ako/fix/1517-alter-microflow-scope-cons…
ako Oct 16, 2026
73c5ed8
fix(catalog): record every document a widget names, not the smallest …
claude Oct 16, 2026
5e3dda6
fix(settings): show the project id in describe/show settings (mendixl…
claude Oct 16, 2026
8e37111
Merge pull request #1425 from ako/fix/1516-retrieve-list-over-associa…
ako Oct 16, 2026
922b804
Merge pull request #1426 from ako/fix/1528-run-local-scheduled-events
ako Oct 16, 2026
99e3373
Merge pull request #1430 from ako/fix/1533-parse-hints-keyword-name-a…
ako Oct 16, 2026
0bbc838
Merge pull request #1429 from ako/fix/1526-show-project-id
ako Oct 16, 2026
5c81f36
Merge pull request #1428 from ako/fix/1521-datetime-localized-carry-n…
ako Oct 16, 2026
3a5c503
Merge pull request #1427 from ako/fix/1527-marketplace-install-fixes-…
ako Oct 16, 2026
a9fe433
Merge pull request #1431 from ako/fix/1513-catalog-widget-multiple-refs
ako Oct 16, 2026
faeb9a3
Merge pull request #1417 from ako/fix/1525-business-event-channel-ide…
ako Oct 16, 2026
8594d04
Merge origin/main into fix/1522-navigation-omitted-clause-keeps-stored
claude Oct 17, 2026
e8a6c79
Merge pull request #1420 from ako/fix/1522-navigation-omitted-clause-…
ako Oct 17, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-10-16", "symptom": "`mxcli marketplace install <id>` of a module or widget that ships pluggable widgets left the project failing CE0463 (41 units in the field run) until the user ran `mxcli fix widgets` by hand; install only printed it as a \"Next\" step", "cause": "`installModuleFromFile` (transplant path) and the widget paths (`installWidget`, `placeWidgetFile` via `printWidgetNext`) printed the `mxcli fix widgets` / `mxcli fix design-properties` commands instead of running them", "file": "`cmd/mxcli/marketplace_postinstall.go` (`runPostInstallRepairs`, seams `postInstallResolveMx` / `postInstallRunTool` / `postInstallMendixVersion`); `cmd/mxcli/cmd_marketplace_install.go` (`reportTransplantInstall`, `resyncInstalledWidget`)", "insight": "A step every install needs and only one tool can do belongs in the install, not in its output: a printed \"Next\" is skipped by agents and humans alike. The repair reuses `docker.RunToolPreservingFormat` (what `mxcli fix` calls), so MPR v2 survives; bare `mx update-widgets` would collapse it. Unresolvable mx (or an unreadable version) keeps the printed commands as a warning, never a failure, and a failing step names its own manual command while the next still runs. Measured on 11.6.6 with `install --file` of a widget: update-widgets ran, 369 .mxunit files before and after. Not changed: `marketplace update` (still prints the steps) and the --allow-format-change module-import path; dependency resolution is a separate concern", "refs": ["mendixlabs/mxcli#1527"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-10-16", "symptom": "`mxcli run --local` booted an app whose scheduled events never fired; the only trace was the runtime log line `Synchronizing scheduled events: None`, and nothing at start said so", "cause": "`runtimeConfigParams` builds the boot update_configuration payload without `ScheduledEventExecution`, so the runtime's own default NONE applies to every local run", "file": "`cmd/mxcli/docker/runlocal.go` (`withScheduledEventsDefault`, `scheduledEventsLine`, called in `RunLocal` after `buildRuntimeSettings`)", "insight": "A setting mxcli never names is a setting the runtime decides, silently. The default belongs in the RunLocal path, not in `runtimeConfigParams`: that payload is shared with the test runner (`StartLocalApp`), where a scheduled event firing mid-run would make tests nondeterministic, and a test pins that the shared payload stays without it. Explicit `--runtime-setting` still wins because the default is only added when the key is absent. Not booted; asserted on the payload map", "refs": ["mendixlabs/mxcli#1528"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-10-16", "symptom": "`alter page … set (ColumnWidth: manual, Size: 220) on dg column(Name)` then `set (ColumnWidth: autoFill) …` stored width=autoFill with size=220 and mx check reported CE0463 on the Data grid 2 (11.6.6 and 11.15.0, 1 error; the reporter's workaround was `autoFill` with `Size: 1`) (mendixlabs/mxcli#1519 item 3b)", "cause": "`setColumnPropertyMut` (mdl/backend/pagemutator/mutator.go) writes exactly the property named and leaves the properties the widget hides BECAUSE of it at whatever they held. Data grid 2 3.x hides `size` unless width is \"manual\", `minWidth` unless width is \"autoFit\", `minWidthLimit` unless minWidth is \"manual\"; a hidden property holding a non-default value is CE0463. The create path writes them at their default; ALTER never re-evaluated", "file": "`mdl/backend/pagemutator/column_hidden_reset.go` (`ResetHiddenColumnProperties`, `resetHiddenItemProps` — defaults from the STORED Type, iterated to a fixpoint for cascades), `mdl/backend/mutation.go` (optional `backend.ColumnHiddenPropertyResetter`), `mdl/executor/cmd_alter_page.go` (`applySetPropertyMutator` → `resetHiddenColumnProperties` with rules lifted from the installed .mpk), `mdl/executor/validate_alter_set.go` (check judges a column SET whole as well as per property)", "insight": "**A setter that changes one property must re-ask which OTHER properties are now hidden** — the dependency is the widget's (editorConfig `hidePropertyIn(…,\"columns\",o,\"size\")`, lifted as a nested item-scope rule), so take the rules from the installed package and the defaults from the stored Type rather than special-casing `size`. A hidden property the same statement names is refused rather than silently reset (`ColumnWidth: autoFill, Size: 220`); its default (`Size: 1`) is accepted. Check's per-property dry run had to stop applying the follow-up: judged alone, `Size: 220` of `ColumnWidth: manual, Size: 220` is hidden under the stored autoFill and was refused — the first measurement run caught that, the unit tests did not. Test the whole-statement probe as well as the per-property one.", "refs": ["mendixlabs/mxcli#1519", "ako/mxcli#1401", "mendixlabs/mxcli#891"], "ce": ["CE0463"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-10-16", "symptom": "`describe workflow M.WF_Parent` printed `call workflow M.WF_Child;` for a call stored with `(WorkflowContext = $WorkflowContext/M.Parent_Current/M.Item)`; re-executing the describe output reported \"Modified workflow\" and mx check went from 0 errors to CE0117 (mendixlabs/mxcli#1531).", "cause": "The gen->sdk reader's CallWorkflowActivity case copied Workflow, ParameterExpression and BoundaryEvents but never ParameterMappingsItems(); describe's workflowCallArguments prints mappings when populated, so it had nothing to print. On re-exec, autoBindCallWorkflow saw no mapping and wrote the default `$WorkflowContext` - the parent's context object, not the associated child object.", "file": "mdl/backend/modelsdk/workflow_read.go (workflowParamMappingsFromGen, twin of microflowParamMappingsFromGen, wired into the CallWorkflowActivity case)", "insight": "The call-microflow cases had the identical gap fixed earlier (FINDINGS #42) and the call-workflow case right below them was not touched - when one arm of a type switch gains a property read, diff it against its siblings. The describe tests build semantic structs directly, so the reader layer had no coverage; the test that catches this goes writer -> gen -> reader (roundTripWorkflowActivity). The silent part is the auto-bind default, not the drop: a missing mapping is re-filled with a plausible one. Measured on 11.15.0: pre-fix round trip CE0117, fixed round trip prints \"Unchanged workflow\" and 0 errors. Side measurement: `$WorkflowContext/M.Parent_Current` (no target entity) is CE0117 on 11.15.0 as on 11.6.6 - not a version difference, the path must name the target entity.", "refs": ["mdl/backend/modelsdk/workflow_callworkflow_read_test.go", "mdl-examples/bug-tests/1531-call-workflow-mapping-describe-roundtrip.mdl"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend/modelsdk", "date": "2026-10-16", "symptom": "`create or modify navigation Responsive { menu item … }` (a statement that states only a menu) passes check and exec, then the profile has no home page and mx check reports CE0527 \"Select a default home page for this profile\"; the role home pages, login page and not-found page are gone too", "cause": "navPatchWebProfile wrote HomePage, HomeItems, LoginPageSettings and NotFoundHomepage unconditionally from the spec — an empty spec field cleared the stored one — while Menu, OfflineEntityConfigs, ThrowPartialSyncError and ProgressiveWebAppSettings were already guarded (HasMenu/HasSync/pointer). navPatchNativeProfile rebuilt RoleBasedNativeHomePages the same way", "file": "`mdl/backend/modelsdk/navigation_write.go` (`navPatchWebProfile`, `navPatchNativeProfile`, new `navMergeRoleHomes`)", "insight": "Half of one writer was guard-don't-drop and half was not, and the docs said both ('fully replaces' and 'omitting the block leaves it alone'). describe -> exec could never show it because describe states every clause; only a hand-written partial statement does. Role homes are merged per role (stated role replaces, unmentioned role kept), so MDL can no longer REMOVE a role home page — there is no clearing syntax for home/login/not-found. Patchers now copy the bson.D first: navSetField writes in place, and a test that reused its input doc only passed because an appended field used to force a reallocation", "refs": ["mendixlabs/mxcli#1522", "ako/mxcli#1404"], "ce": ["CE0527"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-15", "symptom": "After MDL055 learned the two-hop form, three combo box shapes from mendixlabs/mxcli#1466 still passed `mxcli check` and `exec` and failed mxbuild: a one-hop comparand landing on another entity than the left side (`[Mod.District_Region = $currentObject/Mod.AreaPicker_City]`) and an unqualified comparand association (`$currentObject/AreaPicker_Region`), both CE0161 \"Error(s) in XPath constraint.\", and an association-mode combo box with no caption (the issue's actual script), CE0642 \"Property 'Caption' is required.\"", "cause": "No rule judged the TYPE of a one-hop variable comparand — MDL055 counts hops only, and MDL-XPATH01 ran over microflow retrieves only; MDL-WIDGET16 returned clean as soon as an association-mode combo box had a data source, never asking for the caption that mode requires", "file": "`mdl/executor/validate_datasource_xpath_comparand.go` (`ValidateDatasourceXPathComparands`, MDL-XPATH02 + the page arm of MDL-XPATH01, wired in `ValidateProgram`), `mdl/executor/validate_widgets.go` (`validateComboBoxCaption` under MDL-WIDGET16), `memberTypeIndex` now buildable from the script alone (`overlayScriptMembers`)", "insight": "**Give every page of a multi-page measurement project its own widget NAME.** mxbuild's message carries only the widget name (`at Combo box 'cb'`), so sixteen pages with a `cb` each gave eleven unattributable errors; naming each widget after its page made one `mx check` answer the whole matrix. Measured identically on fresh 11.13.0 and 11.14.0: a comparand landing on a specialization OR a generalization of the left side's entity builds clean (so the type rule compares generalization chains, and stays silent when a chain runs through an entity it does not hold), association-vs-attribute is CE0161 too, and the caption is whichever one the caption TYPE selects — `optionsSourceAssociationCaptionType: expression` with only `CaptionAttribute:` is CE0642, and so is an expression without the type; enumeration mode needs no caption. A data source alone selects association mode, so the `Attribute:` spelling of the association needs the caption as well — reading `Association:` first would have missed it. The type rule runs in the no-project tier from the script's declarations (the issue is one script declaring everything), with -p filling in the rest; putting it in the --references walk would have left `mxcli check script.mdl` silent on the reported shape. No language-version gate: each refused form already fails the build.", "refs": ["mendixlabs/mxcli#1466", "#831"], "ce": ["CE0161", "CE0642"], "rules": ["MDL-XPATH01", "MDL-XPATH02", "MDL-WIDGET16"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-16", "symptom": "mendixlabs/mxcli#1517 (ako#1399): three scope verdicts of one `alter microflow` block disagreed with the flow the block writes. (A2) a consistent rename — producer, log and return replaced in one block — was refused by check and exec: \"replace $Code = call microflow …: $Code is still used by: log …; return $Code\". (B2) `insert after X begin declare $Late … end; replace log … with begin …$Late… end;` was refused MDL090 \"the fragment uses $Late, which is not declared on the path\". (B3) `replace loop` whose body read an undefined $Nope passed check, exec said \"Altered microflow\", and mx check (11.6.6 and 11.15.0 alike) gave CE0109 \"Undefined variable 'Nope'\"", "cause": "applyTo ran checkOutputUnused per operation, in order, against the stored candidates, so readers a later operation replaces still counted, and an in-place return/condition edit never retired its stored reads; checkFragmentScope consulted own/inScope/removedByOps but not what earlier operations declared (unscopedRefs did, but unconditionally, without position); and it read a fragment's variables from formatActivity text, which renders a LoopedActivity as its header only, so nothing inside a loop body was ever scope-checked", "file": "mdl/executor/cmd_alter_flow.go (applyTo outputChecks, noteRewritten, declSite/declaredAt, declaredOnPath, fragmentReads, checkFragmentScope, unscopedRefs, checkOutputUnused)", "fix": "Output-in-use checks are deferred until every operation is applied, and a return value or condition set in place marks its node rewritten (its stored reads retire, the new text's reads count). Each declared variable records the operation and stored target that put it in; declaredOnPath credits it to a later operation only when that site is upstream of where the later one goes (insert after / replace t: t strictly upstream; insert before t: also t itself, unless the later op is another insert before t) — used by both the fragment scope check and the condition check. fragmentReads walks loop bodies recursively, with the iterator and the body's own outputs local to the body", "test": "mdl/executor/cmd_alter_flow_scope_pedapp_test.go TestAlterMicroflow_ScopeRenameAcrossTheBlock, TestAlterMicroflow_ScopeDeclaredByAnEarlierOperation, TestAlterMicroflow_ScopeReplaceLoopChecksTheBody — each asserts check (CheckFlowVerdicts) and exec agree, with controls (a reader the block leaves, a declaration downstream, two inserts after one node, a body using its iterator and own declare). Revert controls: A2 stub (checks run inline) -> rename refused \"$Code is still used by\"; B2 stub -> \"$Late … not declared on the path\" (and the rename test fails on $Code2); B3 stub -> exec accepts $Nope. mx check: B3 script old binary 'Altered' + CE0109 (1 error) on 11.6.6 and 11.15.0, fixed binary refuses, nothing written, 0 errors; the rename + late-declare script on the fixed binary: 0 errors on both versions", "insight": "A block of patch operations aimed at the stored flow still writes one flow, so every verdict about variables has to be taken against that final flow — per-operation checks are order-dependent and refuse consistent edits. The A2 repro also hit B2 (the reader replacement reads the new $Code2 that op 1 declared), so one bug masked the other. And a scope check that scans rendered text inherits the renderer's elisions: formatActivity prints a loop as its header, so the body was invisible to every check built on it", "refs": ["mendixlabs/mxcli#1517", "ako/mxcli#1399", "ako/mxcli#1106"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"date": "2026-10-16", "area": "mdl/executor", "symptom": "mendixlabs/mxcli#1516: `retrieve $L from $h/M.Line_Header` (from the TO entity Header, the \"one\" side) followed by `$L/Qty`, `change $L (…)` or `call microflow M.Sub(line = $L)` passed check --references and exec, then mx check reported CE0117 \"Error(s) in expression.\" / CE7247 \"Variable 'L' is of type List of M.Line, but should be of type Object.\"; MDL043 also told `declare $X M.SomeEnum = empty` it was an object declare even with -p.", "cause": "MDL-RETRIEVE03 (validate_microflow_retrieve_single.go) only seeded database retrieves, because list-vs-object over an association needs the association's type/owner and which end the start variable is; the builder decided it (cmd_microflows_builder_actions.go) but typed an object use leniently. MDL043 ran in the no-project validator only and never asked whether the bare name was an enumeration.", "file": "mdl/executor/validate_retrieve_association_list.go", "fix": "associationRetrieveYieldsList(refSet, ownerBoth, fromToSide), used by the builder and by a new --references pass (validateAssociationRetrieveListUse) that tracks each object variable's entity, resolves the start end via checkAssociationShapes + generalizationChain, and reports member path / change / object-parameter use of the list under MDL-RETRIEVE03 through the walk the no-project rule now shares (walkListObjectUses). MDL043 asks the flow-rule resolver (voidCodeActions.declaredTypeKindOf) and, for a known enumeration, warns with describe's `enum` spelling instead of refusing.", "test": "TestAssociationRetrieveListUsedAsObject, TestAssociationRetrieveYieldsList, TestMDL043_EnumerationNamedBare, TestMDL063_ConditionalCreateNamesTheIdiom; mdl-examples/bug-tests/1516-retrieve-list-over-association.mdl", "insight": "The issue's literal repro (bare list retrieve, unused) builds clean on 11.15.0 as on 11.6.6 — the build failure is only in the USE, so re-measure the reporter's version but expect the defect one statement later than the repro shows. Measured on both: owner Both from the TO side is one object (control), a ReferenceSet a list either way, and `retrieve … where [Assoc = $h] first` the working one-object form. The bare enum declare builds at 0 errors when the project has the enumeration (describe prints `enum`), so MDL043 there was a false error, not just a wording issue. Same name created in both if/else branches is CE0111 on 11.15.0 — Mendix does not allow it; the conditional-create idioms are one create with `if … then … else` values, or a sub-microflow returning per branch."}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"date": "2026-10-16", "area": "mdl/executor", "symptom": "`create or modify business event service` of an existing service wrote a new random ChannelName for every message on every run: three runs of an unchanged script gave three different channel names, each reported `Modified business event service`. On a deployed app the ChannelName is the Kafka topic, so every re-run moves every topic and disconnects subscribers in other apps; mx check and the build stay clean.", "cause": "createBusinessEventService rebuilt the definition from the AST and called generateChannelName() for each message unconditionally, with no read of the stored channels. The canon $ID transplant cannot help: ChannelName is a content string, not an $ID, and no codec FreshGUIDField registration exists for it, so TestFreshGUIDFieldsHaveAnIdentityDecision never saw it (the same blind spot as Workflows PersistentId, #949).", "file": "mdl/executor/cmd_businessevents.go (businessEventIdentityCarry)", "fix": "On a rewrite, carry the stored definition $ID and, per declared message matched by message name (case-insensitive), the stored channel's $ID and ChannelName, the message $ID, attribute $IDs (by attribute name) and the service-operation $ID; a new message gets a fresh channel name. A stored channel holding several messages (Studio Pro can; MDL writes one channel per message) is handed to the first message only, so no two channels share a topic (PR #533).", "test": "mdl/executor/cmd_businessevents_identity_test.go: TestCreateOrModifyBusinessEventService_CarriesChannelIdentity (MockBackend, Studio Pro-shaped IDs, reordered messages/attributes plus a new message and attribute), _SharedStoredChannelNotDuplicated, _RerunIsUnchanged (PedApp copy: run 2 writes no file, reports Unchanged, same ChannelNames). Revert control (carry fed nil): all three fail, the rerun with `re-run moved the channels` and the .mxunit + .mpr rewritten.", "insight": "An identity need not look like one: ChannelName is a plain string property, but something outside the model (the broker, other apps' subscriptions) remembers it, which is the definition canon.identityFields uses. Grep the executor for generate*/GenerateID calls on a CREATE OR MODIFY path — each is a candidate. Carry by name, not position, so reordering a script cannot swap topics; the end-to-end rerun test (files unchanged + Unchanged report) is what proves every other nested ID is also carried.", "refs": ["mendixlabs/mxcli#1525", "ako/mxcli#1407", "docs-wiki/bug-patterns/rewrite-drops-unauthored-state.md"]}
Loading
Loading