Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2066d0f
docs: recover a merge whose base an older mxcli wrote (fix property-s…
claude Oct 28, 2026
5c66a8e
fix: a text box's KeyboardType survives describe → exec (ako/mxcli#1209)
claude Oct 28, 2026
2963b4a
fix: read and write page properties in Mendix 9.x/10.x's shape (ako/m…
claude Oct 28, 2026
0913b2d
docs: name version-shape lowering on the platform-CI pattern page
claude Oct 28, 2026
579547e
fix(pages): spell the workflow button actions so a rewrite keeps them…
claude Oct 28, 2026
c6cc983
docs(widgets): a rewrite keeps a widget's stored schema; update it wi…
claude Oct 28, 2026
dfd4134
fix(widgets): write and describe the action slots the built-in defini…
claude Oct 28, 2026
81756f3
fix(alter-page): `set (Action: …)` reaches a pluggable widget's click…
claude Oct 28, 2026
f3ad2b3
fix(widgets): write a pluggable widget's enumeration value as the key…
claude Oct 28, 2026
7cbc9ca
docs(changelog): entries for #1209, #832 and #1754
claude Oct 28, 2026
1bd1ad0
style: gofmt the version-shape test
claude Oct 28, 2026
5d48cf3
Merge pull request #1758 from ako/claude/optimistic-fermi-x62bln
ako Oct 28, 2026
c3bda29
Merge pull request #1759 from ako/claude/loving-clarke-qun7w5
ako Oct 28, 2026
1fe5505
fix(navigation): app title and app icon clauses for a navigation profile
claude Oct 28, 2026
c889109
docs(navigation): document app title and app icon
claude Oct 28, 2026
dba2d0c
chore(navigation): changelog entry and finding for app title and icon
claude Oct 28, 2026
2adfe9b
fix(navigation): refuse an app icon Mendix rejects (CE6859) (ako/mxcl…
claude Oct 28, 2026
281c020
fix(widgets): write, check and describe a combo box's custom content …
claude Oct 28, 2026
935d877
fix(widgets): refuse a combo box's custom-content type without the co…
claude Oct 28, 2026
2c40cca
docs(changelog): drop a stray blank line in the Unreleased list
claude Oct 28, 2026
b20ce85
fix: give a text box's "On enter key press" action an MDL property (a…
claude Oct 28, 2026
39dbd4f
fix: keep an input widget's On enter / On leave actions on describe -…
claude Oct 28, 2026
7cb0807
Merge pull request #1760 from ako/claude/loving-clarke-qun7w5
ako Oct 28, 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":"mdl/backend","date":"2026-10-28","symptom":"Found fixing ako/mxcli#1743: an input widget's Studio Pro 'On enter' / 'On leave' actions (focus in / out; OnEnterAction / OnLeaveAction on Forms$TextBox, TextArea, DatePicker, CheckBox, RadioButtonGroup, DropDown) had no MDL property and were deleted by describe -> exec of a Studio Pro page. Measured on 11.13.0: a page holding seven of them described with none, exec reported 'Replaced page', all seven were gone, mx check 0 errors","cause":"widgetToGen hard-coded SetOnEnterAction(noActionGen()) / SetOnLeaveAction(noActionGen()) on every input (only the text box's OnEnterAction read a model field, which no builder ever set), describe never read either slot, and the #721 L2 carry (carryNoActionExecution) copies DisabledDuringExecution between two NoActions only — a stored action meets a rebuilt NoAction and is skipped","file":"mdl/backend/modelsdk/widget_write.go (focusEventsToGen, every input case), widget_write_legacy_gaps.go (dropDownToGen); mdl/executor/input_event_actions.go (OnEnter / OnLeave rows, applyInputFocusEventsV3 called by all six input builders); mdl/executor/widget_native_props.go (inputReads); cmd_pages_describe_parse.go / cmd_pages_describe_output.go (extractFocusEventActions, appendFocusEventProps)","fix":"`OnEnter:` / `OnLeave:` (stored names `OnEnterAction:` / `OnLeaveAction:` accepted) on all six inputs, through the same table as `OnEnterKeyPress:`; written by focusEventsToGen, described back after OnChange. describe -> exec of the 7-action page: 'Unchanged page', mx check 0 errors","insight":"#721 L2 looked at these slots and fixed only the flag on the empty ones, because the stored population it measured was all NoActions — a slot that is empty in every fixture still needs a spelling if Studio Pro lets an author fill it, or the first page that does fill it is deleted by a rewrite. When a writer sets a slot to a constant, ask whether Studio Pro can put something else there, not whether the fixtures happen to. The cheapest control is the build before the fix run over a page written by the build after it: describe -> exec with the old binary showed the loss in one command, where a stored Studio Pro example would have had to be found first. 'On enter' is the focus event, not the Enter key, which is why the two spellings stay distinct (OnEnter vs OnEnterKeyPress)","refs":["ako/mxcli#1743","ako/mxcli#721"],"test":"TestInputFocusEvents_CheckAccepts, TestInputFocusEvents_BuilderWritesBoth, TestDescribeInputFocusEvents (mdl/executor/input_event_focus_test.go); TestWidgetToGen_InputWidgetsWriteFocusEvents (mdl/backend/modelsdk/widget_focus_events_write_test.go); mdl-examples/bug-tests/1743-input-focus-event-actions.mdl"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-10-28","symptom":"ako/mxcli#854 (follow-up of #842): an action on a data grid filter (`OnChange:` on textfilter / numberfilter / datefilter / dropdownfilter), a barcode scanner (`onDetect:`) or a combo box's onEnterEvent / onLeaveEvent / onChangeFilterInputEvent was refused under `mdl 1;` (4x MDL-WIDGET37, 4x MDL-WIDGET06 on one page) and dropped with MDL-V1-ACTIONSLOT / MDL-WIDGET06 warnings under mdl 0; describe printed no filter action, so a Studio Pro-authored one could not be restated, retargeted or removed. Third bullet: `alter page … set (Action: …) on <gallery>` was refused (\"has no on-click action — Action can only be set on a widget that has one\") while `set ('onClick': …)` wrote the same slot, and no ALTER spelling applied MDL-WIDGET36 — on an 11.13.0 app the quoted form under `mdl 1;` was written and mx check then failed: \"The item click action is ambiguous\" at Gallery 'gSingle', 1 error. Fourth bullet: an enumeration value of a pluggable widget was stored as written — `onClickTrigger: Double` / `triple` and a data grid's `pagination: 'Buttons'` all stored verbatim, mx check (11.13.0, with and without the widget update) 0 errors.","cause":"These widgets' definitions are hand-written and embedded (sdk/widgets/definitions), and a hand-written def beats the generator that maps every action slot of a generated widget. Theirs mapped none of these slots, so resolveMapping never read the action; describe's filter branch read no action and the known-type output branch printed no named slots. The combo box's onChangeDatabaseEvent named in the issue was already fixed by mendixlabs/mxcli#1583 (database mode, sourced from OnChange). ALTER's `Action` key went to SetWidgetAction, the built-in widget's click property (Action / OnClickAction / ClickAction), which a pluggable widget does not have; its click is the action-typed property its definition reads `onClick:` from. MDL-WIDGET36 lived only in the CREATE validator, which reads the statement's AST — an ALTER carries no widget. Neither the engine's primitive writes (mapping pass, explicit-property pass) nor ALTER's pluggable setter compared a value with the keys the widget's schema declares, and no check rule did for a top-level property (MDL-WIDGET08 covered object-list items only) — for generated and hand-written definitions alike.","file":"sdk/widgets/definitions/{text,number,date,dropdown}filter.def.json (onChange <- OnChange, in every mode of the dropdown filter), barcodescanner.def.json (onDetect named), combobox.def.json (onEnterEvent / onLeaveEvent / onChangeFilterInputEvent named, in all three modes) + modelsdk mirrors; mdl/executor/cmd_pages_describe_parse.go (filter OnChange, combo box NamedActions); cmd_pages_describe_output.go (known-type branch prints named slots, which no longer route a combo box into the generic branch); widget_named_action_slot.go (embeddedSourcedActionKeys: a slot a def sources from OnClick/OnChange under a key actionSourceForKey does not know — onChangeDatabaseEvent — is not also printed by key); mdl/executor/alter_set_click_action.go (setClickAction: Action / onClick reach a pluggable widget's click slot; checkGalleryClickAfterSet / storedGalleryClickAmbiguity judge the stored gallery after the SET); cmd_alter_page.go; validate_alter_set.go (checkGalleryClickSet on a probe copy); mdl/backend/pagemutator/pluggable_state.go (PluggableWidgetState capability); mdl/executor/widget_enum_value.go (enumerationValue in the engine, validatePluggableEnumValues for check -p, gateUndeclaredEnum, MDL-V1-WIDGETENUM in validate_widget_language.go); mdl/backend/widgetobj/builder.go (EnumerationKeys, read from the Type the build writes); widget_known_props_from_mpk.go (def.enumKeys from the installed .mpk); alter_set_pluggable_attribute.go + pagemutator/pluggable_attribute.go (PluggablePropertyScope.EnumKeys)","insight":"Test the hypothesis before fixing the half that may already be fixed: the 'filter onChange lost on rebuild' bullet already held on main through #832's per-property patch (statement and shadow build both wrote NoAction, so the stored action was kept) — proven by seeding a Studio Pro-shaped Forms$MicroflowAction into the filter's onChange, editing the filter via describe->exec, and stubbing patchStoredPluggable as the control (fails 'reset its onChange to Forms$NoAction'); a sibling edit needed patch AND passthrough stubbed to fail. What the mapping adds is that describe can SAY the action, so a statement can keep, retarget or remove it. The cheap audit for this class is mechanical: TestBuiltinDefsMapEveryActionSlot diffs each embedded def's action mappings against the action properties its .mpk declares (testdata), and requires a named slot in EVERY mode — selectMappings ignores top-level mappings of a def with modes. Spell new slots the way the generator would (actionSourceForKey): `onChange` -> `OnChange:`, anything else by its own key. A def-sourced slot under an unusual key (onChangeDatabaseEvent) must be excluded from describe's by-key list or it is printed twice. Real mx check (11.13.0, --no-update-widgets): all eight actions written, 0 errors, describe->exec 'Unchanged page'; fault variant: refused under mdl 1, 0 errors under mdl 0 with every action missing. For a whole-widget rule on ALTER, judge the STORED widget after the SET, not the SET: a gallery's ambiguity is three settings (Gallery editorConfig: `\"None\" !== itemSelection && onClick && \"single\" === onClickTrigger`), of which one SET may name one. Do it in exec (refuse before Save under mdl 1, warn under mdl 0) and in check on a Probe() copy with the whole op applied. A SET cannot write a Selection-typed property (columnValueField), so the advice for the selection route is `replace`. mx check is NOT the oracle for an enumeration value — it accepted Double, triple and Buttons at 0 errors; the widget's runtime bundle is (Gallery.mjs: `\"single\"===e.clickTrigger` / `\"double\"===e.clickTrigger`, so a stored Double makes the row click dead). Note the testdata .mpk files have their JS bundles stripped to 0 bytes; read the runtime code from an app's widgets/ folder. Split the fix by kind: a key in another case is a silent wrong write, normalised under both versions; a value with no key is a new rejection, gated (MDL-V1-WIDGETENUM -> MDL-WIDGET08). Check validates only with -p, from the installed package's keys — without a project it cannot know a newer widget's keys and stays silent rather than refuse. A def value-mapping authored by its own key (gallery onClickTrigger) is written twice, by the mapping pass and the explicit pass, so report it once.","refs":["ako/mxcli#854","ako/mxcli#842","ako/mxcli#832","mendixlabs/mxcli#1583","#956"],"rules":["MDL-WIDGET37","MDL-WIDGET06","MDL-V1-ACTIONSLOT","MDL-WIDGET36","MDL-V1-GALLERYCLICK","MDL-WIDGET08","MDL-V1-WIDGETENUM"],"test":"mdl/executor/issue854_action_slots_test.go (TestBuiltinDefsMapEveryActionSlot, TestIssue854_UnmappedActionSlotsAreWritten, TestIssue854_DescribedSlotsRoundTrip, TestIssue854_DatabaseComboBoxChangeSlotDescribedOnce, TestIssue854_SlotsPassValidation); mdl/executor/issue854_filter_onchange_test.go (TestIssue854_EditedFilterKeepsItsStoredOnChange, _SiblingEditKeepsTheFiltersStoredOnChange, _StoredFilterOnChangeIsDescribed, _StatementRetargetsAndRemovesTheFiltersOnChange); repro mdl-examples/bug-tests/854-pluggable-action-slots.mdl; mdl/executor/issue854_alter_gallery_click_test.go (TestIssue854_AlterSetActionOnGallery for Action / onClick / 'onClick', _AlterSetActionControls: button keeps SetWidgetAction, combo box still refused, _AlterSetGalleryClickAmbiguity mdl 1 refuses both spellings / mdl 0 writes and warns / Selection None control, _CheckAlterSetGalleryClickAmbiguity); mdl/executor/issue854_widget_enum_test.go (TestIssue854_EnumValueIsStoredAsItsKey under both headers, generated and hand-written def; _UndeclaredEnumValue mdl 1 refuses / mdl 0 writes and warns; _CheckUndeclaredEnumValue with -p, case-variant control; _AlterSetEnumValue)"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-10-28","symptom":"ako/mxcli#1744 (mendixlabs/mxcli#1663): a combo box's custom content could not be written — `combobox cbPerson (…) { optionssourceassociationcustomcontent cc { dynamictext … } }` was refused by check -p with MDL-WIDGET26 \"`optionssourceassociationcustomcontent` is not a container of `combobox`, which declares no containers\" although `widget describe combobox` listed it as a `widgets` property; the type that switches it on WAS written, so `optionsSourceAssociationCustomContentType: 'yes'` alone passed check and exec and mx check reported CE0642 \"Property 'Custom content' is required.\" at Widgets container 'Custom content' of combo box 'cbPerson'","cause":"The built-in combobox.def.json declared no child slots (the content keys were knownProperties). The content belongs to an option-source MODE (widget.xml binds it to that mode's datasource), and only the engine read a mode's childSlots: the unrouted-children rule, MDL-WIDGET26's parentDeclaresSlot, declaredContainers, containerKeyword, `widget describe` and the registry's MDLContainer lower-casing all read def.ChildSlots alone. Nothing tied the …CustomContentType enumeration to its slot","file":"sdk/widgets/definitions/combobox.def.json (+ modelsdk copy): mode childSlots with a `switch`; mdl/executor/widget_unrouted_children.go (selectedChildSlots, declaresChildSlots, otherModeSlot, mode-aware MDL-WIDGET30 message), widget_slot_switch.go (slotSwitchProblem = MDL-WIDGET53, switchedSlotsToTurnOn), widget_engine.go (ChildSlotMapping.Switch; explicit pass skips Widgets values), validate_widget_kind.go, validate_widgets.go (childSlotKeyword), widget_registry.go (lowerSlotContainers), cmd_pages_describe_combobox_content.go (comboBoxDescribedMode, comboBoxCustomContent), cmd_pages_describe_output.go, cmd_pages_pluggable_passthrough.go (undescribedContent), widget_describe.go (DescribedContainer.Mode)","insight":"**A mode-scoped slot is invisible to every reader of def.ChildSlots** — the engine already built mode slots (selectMappings), so adding them to the definition made the write work and left check refusing it, the container list empty and `widget describe` silent; grep `def.ChildSlots` (and `def.Modes`) when a slot is per mode, and route check and exec through one selectedChildSlots that mirrors selectMappings. **Measure the slot's switch before trusting the slot**: content under the type 'no' (also when the type is left out, since the template stores 'no') is CE0463 on 11.13.0, not a silent hide — one throwaway page per value settled 'yes' 0 errors, 'no' CE0463, the type alone CE0642. The fix is a def-declared `switch` (off/on/caption) that check and exec both read, not a combo box special case. **Describe must print the content only where it re-executes as the same thing**: in the mode exec reselects from the description, and only while the switch is on — a block under 'no' would re-execute as SHOWN content, so it stays in the NOT SHOWN note, and the #1648 refusal narrows to content the parsed description lacks (not a second mode test). **The reference check that changed nothing is the evidence**: `mxcli fix widgets` (mx update-widgets in place) left the written page's BSON identical (10505 ndsl lines, 0 diff). Measured on 11.13.0 with Combo box 2.5.0; the reporter's 2.10.0 was not available here. Not covered: a static-mode combo box's per-value staticDataSourceCustomContent — static values have no MDL spelling yet","refs":["ako/mxcli#1744","mendixlabs/mxcli#1663","ako/mxcli#1648","ako/mxcli#1563"],"ce":["CE0642","CE0463"],"rules":["MDL-WIDGET26","MDL-WIDGET30","MDL-WIDGET53","MDL-WIDGET27"],"test":"mdl/executor/widget_combobox_custom_content_1744_test.go, widget_combobox_custom_content_type_1744_test.go; mdl-examples/bug-tests/1744-combobox-custom-content.mdl, 1744-combobox-custom-content-type-without-content.fail.mdl"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-28", "symptom": "On Mendix 9.24 `describe page` printed no design properties, no text box placeholder, no data view `Editable: Never` and no data view `DataSource: $Param`, so describe → exec removed them (Home_Web: \"Replaced page\", bytes changed); writing any page with a data view was refused (`cannot store Forms$DataView.Editability (Mendix 10.7.0+); Forms$DesignPropertyValue.Value (Mendix 10.2.0+)`); `alter styling` on a stored 9.x design property reported \"Updated styling\" and changed nothing; a text box's KeyboardType was reset to Default on every rebuild, any version", "cause": "Five properties kept their meaning and changed storage shape at a version: DesignPropertyValue Type/StringValue/BooleanValue → Value (10.2), DataViewSource PageParameter/SnippetParameter → SourceVariable (10.0), DataView Editable → Editability (10.7), AttributeWidgetWithPlaceholder Placeholder → PlaceholderTemplate (10.11), DataSource.ForceFullObjects (10.8). Readers and writers knew only the newer shape. The floor refused the newer key where it saw it and missed the supertype-declared ones (PlaceholderTemplate, SourceVariable, ForceFullObjects). The mutator updated an entry with DSet(\"Value\"), a no-op on a missing key. KeyboardType had no MDL spelling and the writer hard-coded Default", "file": "`modelsdk/canon/versionshape.go` (LowerToProjectShape, run in `modelsdk/mpr/writer_property_sets.go` normalizePropertySetsFor before the floor), `mdl/executor/cmd_pages_describe_parse.go` (parseFlatDesignProperty, placeholder/editability fallbacks), `cmd_pages_describe_datasource.go` (sourceParameterNames), `mdl/backend/pagemutator/mutator.go` (setDesignPropertyMut rebuilds the entry), `mdl/executor/textbox_keyboard_type.go`", "insight": "**Lower at the one hook every write passes, not per writer**: normalizePropertySetsFor sees every unit (create, update, ALTER's raw mutators, pluggable templates) for the project's version, and runs before canon.Reconcile, so a lowered rewrite of a stored 9.x unit still elides as unchanged. Build in the current shape, lower on the way out, read both shapes — and refuse what the older shape cannot hold (Spacing/colour design properties, conditional editability, placeholder parameters, a data view fed by another widget) rather than drop it. **The floor cannot see a key declared on an abstract supertype** (#1163's blind spot), so the newer key of such a pair is never refused and the older one never written; the generated tables carry no inheritance, so name the declaring type in PropertyDeclared. **Seed the test with Studio Pro's bytes, not mxcli's**: the 9.24 starter app's Home_Web/Account_Overview hold the flat design-property shape; a `mxcli new … --version 9.24.30.51827 --theme none --layout none --skip-init` app is the cheapest source (needs libgdiplus + JDK 17). **The first fix exposed the next gap**: with design properties and editability lowered, mx check found CE6050 (data view source) — keep re-running the real check until it is clean. Measured: bug-test on a fresh 9.24.30 app → mx check 0 errors (main: MDL-WIDGET52 on KeyboardType; without it, the page write refused for Editability + DesignPropertyValue.Value); Home_Web round trip Unchanged/bytes-same (main: Replaced/bytes changed); alter styling on a Studio Pro entry stores the new value (main: unchanged). Tests: writer_version_shape_test.go, cmd_pages_describe_mendix9_shapes_1209_test.go, cmd_pages_textbox_keyboardtype_1209_test.go, TestSetDesignProperty_OverwritesAMendix9Entry; mdl-examples/bug-tests/1209-mendix9-page-shapes.mdl", "refs": ["#1209", "#1163"], "ce": ["CE6050"]}
Loading
Loading