Skip to content

Multi-version pluggable widgets: resolve CE0463 generically, add widget describe, docs - #3

Merged
ako merged 27 commits into
mainfrom
claude/mxbuild-diagnostics-spike-emta6h
Jul 20, 2026
Merged

Multi-version pluggable widgets: resolve CE0463 generically, add widget describe, docs#3
ako merged 27 commits into
mainfrom
claude/mxbuild-diagnostics-spike-emta6h

Conversation

@ako

@ako ako commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

Makes mxcli's pluggable-widget generation version-correct across Mendix versions generically — no per-widget hardcoding and no dependency on mx update-widgets — closing the long-standing CE0463 "widget definition has changed" errors for the Data Widgets stack and ComboBox. Adds a mxcli widget describe command to inspect a widget's discovered format, plus user- and developer-facing docs.

Everything is driven off the widget's own package (.mpk XML + compiled editorConfig.js) and the generic Mendix metamodel defaults, so it scales to new widget versions without code changes.

What's included

Definition-side reconciliation (augment) — reconcile the emitted CustomWidgetType to the project's installed .mpk:

  • Per-ValueType scalar reconciliation (Type/Required/DefaultValue/AllowedTypes/IsList/ReturnType/Translations), enum option sets, per-property metadata (Category/Caption), and the generic AllowUpload envelope field.
  • PropertyType ordering now respects the .mpk's full declared order including inline <systemProperty> (Label/Visibility/Editability). DataGrid2/Gallery declare none inline (unaffected); ComboBox declares them mid-list, which was the dominant slice of its drift.
  • <returnType assignableTo="…"/> is now emitted (Type None with the reference), not dropped to null.
  • Result: DataGrid2 @ Data Widgets 3.10.0 / Mendix 11.12.0 and ComboBox on a fresh 11.12.x project both reach a byte-identical definition vs update-widgets → 0 CE0463.

Instance-side visibility (editorConfig extractor) — a static analyzer lifts the dominant getProperties idioms from each widget's compiled editorConfig.js into declarative WidgetVisibilityRules, so config-hidden textTemplate defaults are nulled exactly as Studio Pro does (the last-mile CE0463 cause). Covers all 9 Data Widgets and the filter build path; compound/object-list-nested guards are safely skipped rather than mis-lifted. Rules are also wired into check as a config-aware warning (MDL-WIDGET10).

mxcli widget describe <id> — inspects a widget's discovered format: available widgets, expected properties (keys/types/captions/categories/required/enums, from the reconciled definition), and the dynamic property (visibility) rules extracted from editorConfig.js. Supports --format json.

Docs — a docs-site guide for multi-version pluggable widget support and the widget describe command; an internals "Object-Lists and DataGrid2 Columns" section clarifying that DataGrid2 page-building already runs on the generic engine (the only hand-coded remnant is ALTER PAGE column insert/replace, a tracked follow-up); corrected stale buildDataGridV3 references; proposal updates recording the investigation.

Robustness — cleared a stale Image template default (CE0463) and broadened the dirty-template guard to catch image/page/action instance bindings.

Testing

  • go build ./... clean; full go test ./... passes except cmd/mxcli/docker TestServeIntegration, which is a live-mxbuild serve integration test that fails identically on main — a stale local fixture (test project v11.6.3 vs cached mxbuild v11.12.1), unrelated to these changes and untouched by this branch.
  • Widget scripts in mdl-examples/ verified via mx check on fresh 11.12.x projects: pluggable DataGrid2/Gallery/ComboBox scenarios report 0 CE0463.
  • New unit tests for the mpk declared-order parsing and the editorConfig extractor.

Notes

  • No sdk/mpr write imports added to the executor; new mutation goes through the backend abstraction.
  • Verified against Mendix 10.24 / 11.10 / 11.12.x with the bundled Data Widgets (no regression) and against marketplace Data Widgets 3.10.0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4


Generated by Claude Code

claude added 27 commits July 19, 2026 11:49
The prompt block used a triple-backtick ```text fence containing a nested
```bash fence. mdBook's parser treated the inner closing ``` as closing the
outer block, so everything after the curl example rendered as prose instead of
inside the prompt code block. Switch the outer fence to four backticks (the
pattern already used elsewhere in the site) so the nested fence is literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
CE0463 remediation in the synced skills told agents to run `mx update-widgets`
directly. On an MPRv2 project (an `mprcontents/`-folder project — everything
`mxcli new` creates) that command silently rewrites the project to single-file
v1 and deletes `mprcontents/`, corrupting a git working tree, breaking a running
`mxcli run --local` loop, and sometimes leaving Studio Pro unable to open the
project. This actually bit a warm-loop app-generation run (CE0463 on Image
widgets → agent ran `mx update-widgets` per the skill).

With PR mendixlabs#764 (issue mendixlabs#763) merged, `mxcli docker check`/`build` snapshot and
restore the v2 storage around the widget normalization, so they are the safe
remediation. Point every CE0463/update-widgets mention at those commands and
warn that bare `mx update-widgets` is only safe on a v1 project or a throwaway
diagnostic copy.

- create-page.md, custom-widgets.md, migrate-design-prototype.md,
  download-marketplace-content.md (user-synced): steer to docker check/build,
  warn about the v2->v1 deletion.
- debug-bson.md (dev): fix the "safety net"/"quick workaround" framing; add a
  "use a COPY" caution to the reference-extraction blocks.
- fix-issue.md: add a symptom-table row for the mprcontents/ data-loss class
  (issue mendixlabs#763 / PR mendixlabs#764).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Authoring an Image widget on any Mendix 11.7+ project and running `mx check`
(without `mx update-widgets`) reported CE0463 "the definition of this widget
has changed". The documented remedy — `mx update-widgets` — rewrites an MPRv2
project to v1 and deletes mprcontents/ (issue mendixlabs#763), so this stale default
quietly funnelled users into data loss.

Root cause (found by ruling out every other theory empirically): the embedded
image.json carried a spurious default value — a WidgetValue.Image pointing at
`Atlas_Core.Content.Mendix` (Atlas's Mendix logo), captured when the template
was extracted from a project that had it set. The installed 11.12 Image widget
expects that field empty, so MxBuild flags the definition as changed. It was
NOT a version stamp, Type $IDs, property order, or missing properties — those
were all disproven (a passing datagrid is reordered by update-widgets too, and
authoring with a "correct" extracted template + stableIds still failed).

Fix: clear the default to "" in both engine templates. Verified: the widget
now passes `mx check --no-update-widgets` with 0 errors on Mendix 11.12.1.

Adds a bug-test repro and a fix-issue.md symptom row documenting the
order-independent before/after-update-widgets diff method used to isolate it
(reusable for the rest of this CE0463 class, incl. DataGrid2 mendixlabs#600).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…n defaults

The dirty-template guard (from the ComboBox fix, 827bffd) only flagged
concrete entity/attribute/flow refs in a template's Object — which is exactly
why the Image dirty default (WidgetValue.Image = "Atlas_Core.Content.Mendix",
fixed in 549c44f) shipped and caused CE0463. Extend `dirtyBindings` to also
flag image-asset refs, page refs, and configured client actions
(Action != Forms$NoAction) on a WidgetValue — the broader dirty-default class
the tolerance spike identified.

- Scans BOTH engines' template sets (modelsdk embed + sdk sibling on disk),
  so a regression in either fails the build.
- Non-vacuous: detect-dirt cases for all four classes (entity/image/page/action)
  + a clean-is-clean case guarding against false positives (an empty DataSource
  slot on a data widget is legitimate and must not flag).
- Verified it catches the real Image regression (reintroducing the stale
  default fails the test; clean passes).

Kept WidgetValue-scoped (false-positive-free) rather than any-node: a broader
scan surfaces a configured delete Forms$ActionButton baked into datagrid.json,
but that nested-Forms-widget dirt is an unverified object-list-widget issue
(mendixlabs#600 / Open Question 1) — documented as a lead in the proposal, not flagged
here.

Updates PROPOSAL_multi_version_pluggable_widgets.md: Image recorded as the
second cleaned template (Phase 1), the guard marked built+broadened, the
before/after-update-widgets diagnosis method recorded, and the datagrid
ActionButton captured as a mendixlabs#600 lead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ery@10.24 schema drift

Verified pluggable-widget CE0463 directly against cached mxbuild 10.24.19 /
11.10.0 / 11.12.1:

- DataGrid2 is clean across all three versions (attribute columns — the exact
  mendixlabs#600 repro — plus custom content, filters, and selection). mendixlabs#600 was filed on
  v0.11.0 and is resolved on HEAD. Corrects an earlier note that claimed
  DataGrid2 custom-content still failed on 11.12.1; that was a test-syntax
  artifact (Content: showContentAs), not a defect.
- Gallery custom content fails CE0463 on 10.24 (clean on 11.10/11.12). The
  before/after-update-widgets subtree diff shows it is within-key PropertyType
  DEFINITION drift (pagingPosition enum values + default changed, a Category
  renamed, a Type/order shift), not a dirty default and not merely nested.
  augmentFromMPK reconciles key presence but not within-key definition changes.

Frames the fix (deeper augment reconciling full PropertyType from the .mpk vs
per-version templates) and notes this generalises — DataGrid2 will drift the
same way on a far-enough version, so the deeper-augment fix future-proofs it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…n mxcli-version bug

The latest mendixlabs#600 report (mxcli v0.16.0, Mendix 11.12.0, "still present") is
reproduced-by-diagnosis: the user updated Data Widgets from the marketplace
(bundled 3.4.0 → 3.10.0), and that newer schema drifts from the 11.6 template
exactly like Gallery@10.24 — within-key PropertyType definition changes that
augmentFromMPK's key-presence reconciliation misses.

Material facts established this session:
- mxcli widget code is IDENTICAL v0.16.0→HEAD (only Image fix + guard differ),
  so no mxcli upgrade fixes the reporter's CE0463.
- All BUNDLED Data Widgets versions (3.0.0@10.24, 3.4.0@11.10/11.12) reconcile
  and pass; a marketplace-updated newer widget is what drifts.

Corrects the prior "DataGrid2 is clean across all three versions" to "clean
with the bundled Data Widgets" and confirms the deeper-augment fix is the
reporter's actual bug, not a Gallery-only concern.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…E0463 drift)

augmentFromMPK reconciled property-KEY presence (add/remove) and enum OPTION SETS,
but not the rest of a matched PropertyType's definition. When a project's installed
widget is updated past the embedded 11.6 template (e.g. Data Widgets 3.4.0 → 3.10.0
from the marketplace — the mendixlabs#600 case), the schema drifts WITHIN existing keys:

  - DefaultValue goes stale: reconcileEnumValues rebuilds Gallery pagingPosition's
    options to {below,above} but the default stays "bottom" — a value the installed
    widget no longer defines, so the PropertyType is inconsistent → CE0463.
  - Category drifts (General::Pagination → General::Items across 5 Gallery props).
  - Caption drifts.

Add reconcilePropertyMetadata: for every PropertyType whose key the installed .mpk
defines, overwrite Category, Caption, and ValueType.DefaultValue from the .mpk (only
non-empty .mpk values, so a template value is never clobbered by a blank). The .mpk
is authoritative for a freshly-created instance — this is what update-widgets does.

Verified: after this pass, every Gallery@10.24 PropertyType matches update-widgets'
output exactly (was: Category + pagingPosition DefaultValue drift). Existing widget
tests green; DataGrid2 + Gallery still 0 errors on 11.12.0 (no regression).

This is the likely complete fix for the mendixlabs#600 DataGrid2-with-updated-Data-Widgets
case (that drift is PropertyType metadata). Gallery@10.24 additionally drifts in its
datasource structure (Forms$GridSortBar.SortItems, CustomWidgetXPathSource.
SourceVariable) — a separate codec-TypeDefaults axis, tracked in the proposal.

modelsdk (default) engine only; the legacy sdk engine lacks even reconcileEnumValues.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…fixed

Records the root-cause split from the key-indexed PropertyType diff: Axis 1
(within-key PropertyType metadata — Category/DefaultValue/Caption) fixed in
8b65f06 and verified to make every Gallery@10.24 PropertyType match
update-widgets; Axis 2 (datasource structure — GridSortBar.SortItems /
XPathSource.SourceVariable, a codec TypeDefaults gap) remaining. Notes Axis 1
alone likely closes the mendixlabs#600 DataGrid2 case, since DataGrid2 does not hit the
datasource axis that Gallery does.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
… PropertyType order

Two remaining axes of the object-list within-key drift (after the metadata fix
8b65f06), both needed to make Gallery@10.24 pass end-to-end without update-widgets:

1. Datasource structure (codec TypeDefaults, widget_write.go): a pluggable-widget
   XPath datasource always serializes SourceVariable as null when unbound, and its
   GridSortBar always emits an empty SortItems list (marker 2). An older embedded
   template omits both; a project whose installed widget expects them (Data Widgets
   updated past the 11.6 template) reports CE0463. Register the defaults for
   CustomWidgets$CustomWidgetXPathSource (NullFields: SourceVariable) and
   Forms$GridSortBar (MandatoryListMarkers: SortItems=2).

2. PropertyType order (augment.go): augment adds/removes/reconciles by KEY but kept
   the template's original order. When the installed widget reordered its properties
   across versions (Gallery 3.x moved pagingPosition ahead of showTotalCount), the
   emitted Type's PropertyType order != the installed widget -> CE0463. The
   WidgetType's PropertyType order IS checked (unlike the WidgetObject's Properties
   order, which Studio Pro tolerates). reorderPropertyTypes sorts the top-level
   PropertyTypes to the .mpk declaration order; Object<->Type refs are by $ID so
   reordering the Type list is safe.

Verified end-to-end: Gallery@10.24 (previously CE0463) now 0 errors with NO
update-widgets. Full regression clean — DataGrid2 (attribute + filter +
custom-content) and Gallery both 0 errors on 10.24 / 11.10 / 11.12.0 / 11.12.1.
Unit + executor + both widget-engine suites green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…10.24 green

Marks Axis 2 (datasource TypeDefaults + PropertyType order) fixed in 10b5bcf.
Gallery@10.24 now passes mx check with 0 errors and no update-widgets; full
regression clean across 10.24/11.10/11.12.0/11.12.1 for DataGrid2 and Gallery.
Remaining: fold into widget-version-matrix.sh as a gate; mendixlabs#600 DataGrid2
end-to-end validation awaits a Data Widgets 3.10.0 project.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ecessary but not sufficient

End-to-end validation against the reporter's exact stack (marketplace Data
Widgets 3.10.0 swapped into a Mendix 11.12.0 project): a DataGrid2 authored with
the fixed binary STILL reports CE0463. Isolated from the Atlas template pages,
the installed 3.10.0 schema differs from the 11.6-era template across far more
than the three fixed axes reconcile — AllowUpload (79), ValueType.Type (15),
Translations (14), DefaultValue (13), Required (7), EnumerationValues (7),
AllowedTypes (4), and more.

Corrects the earlier claim that Axis 1 alone would close mendixlabs#600: augment's
key-presence + metadata/enum/order reconciliation scales to a MODERATE drift
(Gallery@10.24, fully fixed) but not to a LARGE version jump (DataGrid2 11.6-era
-> 3.10.0). The Phase-1 "56=56 for ComboBox" measurement held only because that
was a small delta.

Records the two paths to close the large-drift case, both now testable against
real DW 3.10.0: (a) full-ValueType augment (overwrite the entire ValueType from
the .mpk; recommended), or (b) per-version templates (fallback). Notes
marketplace download now makes the version matrix a feasible standing gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…lope is mxbuild-only

End-to-end reproduction of the mendixlabs#600 stack (DW 3.10.0 over bundled 3.4.0 in an
11.12.0 project, DataGrid2 authored with mxcli, isolated from the Atlas template
pages) with an order-independent, ID-masked before/after-update-widgets subtree
diff proves the parser/template/augment approach is structurally capped below
large version jumps:

- Nested-column PropertyKey sets are already identical before/after (augment adds
  every new 3.10.0 key correctly).
- Residual drift is dominated by fields ABSENT from the widget XML source:
  AllowUpload (x105), DesignProperties, LabelTemplate, and a mxbuild-COMPUTED
  Required (XML declares 3 required="true"; mxbuild emits 54).
- update-widgets on the same copy takes the grid CE0463 -> 0.

Since these fields are not derivable from the .mpk, no augment (including the
proposed full-ValueType path a) can reproduce a version-faithful WidgetType. A
speculative reconcileValueTypeSchema was implemented and reverted (setting
Required from the XML attr would mis-set the 51 computed keys to false).

Revised path forward: delegate the envelope to mxbuild's own update-widgets made
v2-safe (adopt mendixlabs PR mendixlabs#764), keep the moderate-drift augment as-is. Records
the rejected approach inline in augment.go and updates the proposal Open Question #1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ly (mendixlabs#600)

update-widgets is fully generic — it has no per-widget knowledge, so everything
needed to reconcile a widget across a large version jump is derivable from the
widget package plus the generic metamodel defaults. This reworks augment to do
the same, closing the DEFINITION side of the DataGrid2@3.10.0 CE0463: the emitted
CustomWidgetType is now byte-identical (canonically) to mxbuild's update-widgets
output for the mendixlabs#600 reporter's exact stack (DW 3.10.0 on Mendix 11.12.0).

Parser (mpk):
- Required defaults to TRUE when the XML omits required= (Mendix pluggable-widget
  spec default; mxbuild emits Required=true for every property without the attr).
  Defaulting missing->false caused within-key drift on augment-added keys.
- Parse <returnType type=.../> (expression props) and <translations> (shipped
  caption localizations).
- Nested (object-list) child properties now inherit their propertyGroup caption
  chain as Category, matching how mxbuild derives nested categories.

Augment:
- reconcileValueTypesFromMPK: overwrite each matched PropertyType's ValueType
  scalars (Type, Required, DefaultValue, AllowedTypes, IsList, DataSourceProperty)
  from the .mpk; when a Type changes (wrong-typed exemplar clone), reset the
  matching Object WidgetValue so it stays schema-consistent; normalize the
  mutually-exclusive type-specific fields (EnumerationValues cleared on non-enum,
  ReturnType built only for Expression) so stale clone data cannot survive.
- reconcilePropertyMetadata also reconciles Description.
- completeValueTypeEnvelope emits the generic AllowUpload envelope default
  (mxbuild writes it on every ValueType; the 11.6-era template predates it).
- reorderPropertyTypes now recurses into nested ObjectTypes.

Verified end-to-end: definition diff vs update-widgets output = 0; no regression
on bundled Data Widgets (3.4.0/3.0.0) across 11.12.0 / 11.10.0 / 10.24. Note the
instance-side envelope (Forms$Appearance.DesignProperties, CustomWidget.
LabelTemplate, Object-side translations) is not yet emitted; see follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…jected, editor-logic boundary

Corrects the earlier (wrong) "only mxbuild can produce the envelope" conclusion:
the WidgetType IS generically reproducible and is now byte-identical to
update-widgets output (committed c7fe714). Records the instance-side investigation:

- The residual CE0463 (definition matching) is textTemplate default-template
  instantiation in the WidgetObject. Even a minimal DataGrid2 reproduces it.
- Which textTemplates get a default template is config-conditional applicability
  (aria labels always; clearSelectionButtonLabel/loadMoreButtonCaption/
  singleSelectionColumnLabel only when their feature is active) — a distinction
  mxbuild derives from the widget's editor code, NOT the declarative XML (the
  null-vs-populated property defs are structurally identical). always-populate
  closes 9->3, Required-gate 3->9; neither matches because the rule isn't declarative.
- The Object-from-definition rebuild was tried and REJECTED: it discards the
  byte-exact extracted template Object and regressed bundled DataGrid2 0->1 on
  both 11.12.0 and 10.24.

Path forward for the instance last-mile: v2-safe update-widgets (mendixlabs#764) on top of
mxcli's now-correct definition — the applicability logic lives in the widget's
compiled editor code, which mxbuild executes and mxcli cannot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…nce-default mechanism

Upgrades the instance last-mile finding from inference to confirmed, with the
concrete evidence: the widget .mpk ships Datagrid.editorConfig.js whose
getProperties() calls hidePropertyIn/hidePropertiesIn conditionally on the
instance's values. The verbatim hides for the three always-null properties are
present ("Multi"!==selection hides clearSelectionButtonLabel; "loadMore"!==
pagination hides loadMoreButtonCaption; singleSelectionColumnLabel conditional),
mapping 1:1 onto the measured null-vs-populated pattern. Always-populated props
(selectRowLabel, cancelExportLabel) appear 0x in editorConfig.js. A hidden
property does not get its default template instantiated — so the applicability
rule is imperative JS keyed on instance config, not declarative XML.

Adds path (d): execute editorConfig.js in-process via a Go JS engine (goja) as a
research spike for a no-mxbuild-dependency path; kept deferred behind the
recommended (c) v2-safe update-widgets (mendixlabs#764).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…d2 CE0463 (mendixlabs#574)

Automates what the hand-transcribed widgetVisibilityRules table did for
VideoPlayer/Timeline: a static extractor lifts a widget's compiled
editorConfig.js property-hide logic (hidePropertyIn/hidePropertiesIn) into
declarative WidgetVisibilityRules, which the builder's existing
ApplyPropertyVisibility consumes to null the TextTemplate of properties the
widget hides under the current config. This is the instance last-mile that the
definition reconciliation (c7fe714) could not reach — the applicability logic
lives in the widget's editor JS, not the declarative .mpk XML.

Extractor (mdl/executor/editorconfig_extract.go):
- Recognizes the dominant getProperties idioms: "V"===/!==ref && hide,
  ref && hide, ref || hide, ref ? hide : … — with scoped alias resolution
  (var r=e.selection) so minified single-letter identifiers don't leak across
  functions.
- Skips object-list-nested hides and compound/ternary-nested guards (boundary
  check), degrading safely to "not hidden" rather than emitting a partial rule.
- Reports coverage stats. On the real DW 3.10.0 Datagrid.editorConfig.js: 9/28
  hide calls lifted (12 nested, 7 complex) — including the three that drive mendixlabs#600.

Wiring: built-in widgets (DataGrid2/Gallery) skip .def.json generation, so rules
are resolved on the fly from the project's installed .mpk editorConfig at build
time (mpk.ReadEditorConfig + resolveWidgetVisibilityRules, cached), then applied.
Object-side textTemplate defaults are populated with the .mpk's shipped caption
translations (fixes CE4899 required-textTemplate) and the visibility pass nulls
the hidden ones afterward.

Result: minimal DataGrid2 on Mendix 11.12.0 + Data Widgets 3.10.0 (the mendixlabs#600
stack) → 0 errors (was CE0463). No regression on bundled Data Widgets across
11.12.0 / 11.10.0 / 10.24. Remaining: the full repro's nested textfilter widgets
(separate widget type) still show 1 CE0463 — same mechanism, follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ditions (mendixlabs#574)

A WidgetVisibilityRule keyed on a Selection-typed property (DataGrid2
itemSelection = None/Single/Multi) was evaluated against the wrong WidgetValue
field: currentPrimitiveValues read only PrimitiveValue, but a selection value
lives in the `Selection` field. The condition therefore saw "" and mis-fired —
e.g. singleSelectionColumnLabel was nulled even under Selection:Single, leaving
1 CE0463 on the full mendixlabs#600 repro (DataGrid2 with Selection:Single + column
textfilters) while the minimal case passed.

currentPrimitiveValues now reads the field appropriate to each property's
ValueType (Selection→`Selection`, else `PrimitiveValue`). Result: the full
DataGrid2 repro on Mendix 11.12.0 + Data Widgets 3.10.0 → 0 errors. Bundled DW
(11.12.0 / 10.24) minimal+full still 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
mendixlabs#574)

Piece 2 of the editorConfig visibility work.

Generation (2a): GenerateDefJSON now lifts propertyVisibility from the widget's
installed editorConfig.js (extractVisibilityRulesFromMPK) and writes it into the
generated .def.json, superseding the hand-transcribed widgetVisibilityRules
table for any widget whose editor config parses. Built-in widgets (DataGrid2/
Gallery) still resolve rules at build time from the installed .mpk.

Check (2b): a new MDL-WIDGET10 warning fires when a property the user set on a
pluggable widget is hidden under that widget's current configuration — the
editorConfig suppresses it, so Studio Pro ignores the value. Rules come from the
.def.json or are resolved on the fly from editorConfig for built-ins (registry
now carries the project path). Conservative: only warns when the property is
explicitly set AND the hiding condition's value is determinable from the MDL or a
mapping default, so it never guesses. Config-aware end-to-end: DataGrid2 with
Selection:None + ClearSelectionButtonLabel warns; Selection:Multi does not.

No regression: DataGrid2 3.10.0 minimal+repro and bundled DW still 0 CE0463.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…LVED via editorConfig extractor

Updates Open Question #1 to record the landed outcome (was still framing the
instance last-mile as needing v2-safe update-widgets / a goja spike):

- The static editorConfig.js extractor (4b8c4f5) + selection-value fix (666a65b)
  close the DataGrid2 CE0463 natively in mxcli — 0 errors on the mendixlabs#600 stack
  (11.12.0 + DW 3.10.0), minimal and full, no bundled regression. No mxbuild/
  update-widgets dependency needed for DataGrid2.
- Phase 2 (458c52a): extraction moved into .def.json generation; rules wired into
  check as the config-aware MDL-WIDGET10 warning.
- Marks paths (c) update-widgets and (d) goja as superseded (c kept as fallback
  for widgets the static extractor can't fully lift); records coverage (9/28
  DataGrid hide-calls) and the JS-AST / LLM-property-card follow-ups.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…lter build path (mendixlabs#574)

The Data Widgets 3.10.0 package ships 9 widgets (DataGrid2, Gallery, DropdownSort,
SelectionHelper, TreeNode/outline-tree, and 4 filters: Date/Dropdown/Number/Text),
all with editorConfig.js. The extractor recognized DataGrid only; the rest use guard
forms it skipped.

Extractor generalization:
- Strip ANY `<ident>.` namespace prefix (D./M./j./A.), not just `_.` — the minifier
  names it per widget.
- Strip a leading `return` keyword (getProperties' first statement is
  `return <cond> && hide…`, minified `return"none"===…`).
- Handle grouping parens `cond && ( hide, … )` for the first hide in a group.

Coverage now (was 0 for everything but DataGrid): DataGrid 9/28, Gallery 5/13,
TreeNode 4/7, DropdownFilter 5/13, DateFilter 3/5, Number/TextFilter 2-3, Selection
Helper 1/2. Remaining skips are grouped-subsequent and compound guards (safely
skipped, not mis-lifted); a real JS AST would lift those.

Filter build path: BuildFilterWidget went through a separate path that never applied
visibility, so a filter's hidden textTemplate stayed populated -> CE0463. Factored the
nulling into widgetobj.ApplyVisibilityRules (engine-agnostic), added VisibilityRules to
FilterWidgetSpec, and the executor now resolves+passes them.

Result: DataGrid2 3.10.0 (minimal+repro) and bundled DW still 0; Text/Number/Date
filters 0. The Dropdown filter still shows 1 CE0463 — a SEPARATE definition-drift
issue (its nested filter-options ObjectType drifts ~30 Type/28 ObjectType fields from
3.10.0), i.e. the DataGrid-class definition reconciliation applied to the dropdown
filter, not a visibility/extractor gap. Tracked as follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…Widgets + filter path

Records the filter/multi-widget work (da30bab): the DW 3.10.0 package ships 9
widgets (DataGrid2, Gallery, DropdownSort, SelectionHelper, TreeNode, 4 filters),
all with editorConfig; the extractor now handles all of them (coverage table)
after generalising namespace/return/grouping-paren guard forms. Filter build path
wired via widgetobj.ApplyVisibilityRules → Text/Number/Date filters at 0.

Adds the open items: the Dropdown filter's separate ~1529-line definition drift
(nested filter-options ObjectType — a definition-reconciliation follow-up, not a
visibility gap), and TreeNode's dynamic-structure guards that need a JS AST.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…x into definition-drift follow-up (mendixlabs#574)

Verified the pluggable-widget scripts in mdl-examples/ against mx check
on fresh 11.12.0 projects: 8 of 9 report 0 CE0463 via the generic
editorConfig visibility path. The 9th (112-combobox) is documented
version drift — the embedded 2.5.0 template restructures ~3351
definition lines from the newer installed ComboBox — same class as the
DropdownFilter ddf drift, now folded into the definition-reconciliation
follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…endixlabs#112 CE0463

A ComboBox created on a fresh 11.12.x project raised CE0463 even though the
project ships ComboBox 2.5.0 (the same version as mxcli's embedded template),
so it was never a version jump. Two generic definition-drift causes the augment
reconciliation didn't cover:

1. System-property order. ComboBox declares <systemProperty> Label/Visibility/
   Editability inline mid-list (Editability group mixes a systemProperty ahead of
   a regular property). mxbuild emits the WidgetType PropertyTypes in that declared
   order and CE0463 checks it, but the .mpk parser split system properties into a
   separate list and reorderPropertyTypes pushed them to the end. DataGrid2/Gallery
   declare no inline system properties, so they were unaffected — which is why they
   passed and ComboBox didn't. The parser now preserves the full declared order
   (regular + system interleaved) via WidgetDefinition.AllTopLevel, built from a
   document-ordered custom UnmarshalXML on propertyGroup; reorderPropertyTypes ranks
   by it.

2. <returnType assignableTo="../staticAttribute"/>. ComboBox's staticDataSourceValue
   expression derives its return type from another property. The parser read only
   <returnType type=...> and emitted a null ReturnType where mxbuild emits
   WidgetReturnType{Type:None, AssignableTo}. Now parsed and emitted.

Both fixes are generic (no ComboBox-specific code). After them the emitted
CustomWidgetType is byte-identical (ID-masked) to mx update-widgets output for the
mendixlabs#112 stack, and mx check reports 0 errors. No regression: DataGrid2/Gallery/filters
(incl. DropdownFilter) stay at 0 CE0463 on 11.12.1.

Adds mpk parser tests for the interleaved system-property order and the assignableTo
return type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…neric order + assignableTo fixes)

Corrects the earlier '~3351-line large version jump' framing (an ID-unmasked
diff artifact): ComboBox on a fresh 11.12.1 project ships 2.5.0 = the embedded
template version, so no version jump. Masked drift was 243 lines from two
generic causes (inline system-property order + returnType assignableTo), both
now fixed; emitted WidgetType is byte-identical to update-widgets. DropdownFilter
is also clean on bundled DW. Only the 3.10.0-marketplace nested object-list axis
remains open.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…overed format

Adds a CLI command that surfaces what mxcli knows about a pluggable widget: its
expected properties (key, type, caption, category, required, default, enum options,
nested object-list children) and its dynamic property rules (which properties the
widget's editor hides under which configuration), lifted from the widget package's
editorConfig.js.

- Resolve by MDL keyword (COMBOBOX, DATAGRID2, GALLERY, …) or full widget id.
- With -p, properties + rules come from the widget package installed in the project
  (widgets/*.mpk) — the version-accurate discovered format, including marketplace
  widgets mxcli has no built-in def for. Without -p, from the embedded template.
- --format json for machine consumption; text output groups by category and marks
  system properties, showing the declared order (so e.g. ComboBox's Label/Visibility/
  Editability appear at their real mid-list position).
- Reports editorConfig extraction coverage (recognized / total hide-rules).

Exports executor.WidgetVisibilityRules / ExtractWidgetVisibilityStats for the CLI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Adds docs-site guide 'Pluggable Widgets Across Versions' explaining how mxcli keeps
widget definitions version-correct (embedded template + reconcile against the project
.mpk + editorConfig dynamic rules, no update-widgets needed) and documents the
`mxcli widget list` / `mxcli widget describe` inspection commands with text and JSON
examples. Wires it into SUMMARY.md, cross-links the internals Widget Template System
page, and notes the command in the CLAUDE.md feature table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…gine routing

DataGrid2 page-building is already fully on the generic pluggable engine (columns
as an ObjectListMapping, per-column filters as item slots) — buildDataGridV3 was
removed in the v0.12.0 consolidation. Correct the comments that still implied a
hand-coded DataGrid builder:

- cmd_pages_builder_v3.go: DATAGRID has no switch case; it falls through to the
  registry + buildPluggable (generic engine), not a hand-coded builder.
- 189-datagrid2-column-textfilter.mdl: describe the actual filter-slot routing
  (generic engine ItemSlots on page build; buildColumnSpecFromAST/BuildFilterWidget
  on the ALTER PAGE path), not the removed buildDataGridV3.

Add an 'Object-Lists and DataGrid2 Columns' section to the Pluggable Widget Engine
internals page and note that the only remaining hand-coded DataGrid2 path is ALTER
PAGE column insert/replace (a tracked follow-up). No functional change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako pushed a commit that referenced this pull request Jul 27, 2026
A parameter name accepted bare by `call microflow M.Foo(Source = $x)`
was a parse error in a widget's OnClick/Action argument list:

  container r (OnClick: microflow M.Foo(Source: $x))
    -> no viable alternative at input 'OnClick'

The affected names — View, Source, Item, Page, Entity — are all lexer
keywords. The widget-argument name rule (microflowArgV3) accepted only
(IDENTIFIER | QUOTED_IDENTIFIER), while call-microflow's callArgument
used the permissive identifierOrKeyword. Same identifier, two grammars:
keyword-named params failed the widget rule but passed call-microflow.
The misattributed error also anchored on OnClick (a valid property)
rather than the offending token, which made it very hard to diagnose.

Widen microflowArgV3 to identifierOrKeyword (matching callArgument) and
read the name via identifierOrKeywordText in the visitor. Keyword-named
params now parse unquoted in widget action args, and the wrong-token
error position disappears for these names.

Reported from the RSS-reader build (findings #2 and #3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako pushed a commit that referenced this pull request Jul 29, 2026
…c sugar, ADD doc (FINDINGS #3/#5/#13/#14/#4)

Five surprising parser rejects / silent-wrong writes where quoting or a keyword
behaved inconsistently with the rest of MDL:

- #3 index name can't be quoted: indexDefinition accepted only IDENTIFIER for the
  name → `index "idx_x" (Col)` was a parse error. Accept QUOTED_IDENTIFIER too
  (the name is advisory and discarded, as before).
- #5 role-name quoting inconsistent: DESCRIBE USER ROLE required quotes, DROP USER
  ROLE rejected them. Both now accept bare and quoted names; visitors handle both.
- #13 `sort by` quoted attribute stored a nonsense reference: a quoted qualified
  attribute (`sort by "Mod"."Entity"."Code"`) kept the quotes and only failed on
  write ("attribute does not belong to entity"). buildSortColumnMicroflow now
  unquotes each segment (bare dotted form), matching the SORT() list-op path.
- #14 `DataSource: ASSOCIATION $currentObject/…` didn't parse (keyword + sugar were
  mutually exclusive). Added the combined grammar branch; the existing
  VARIABLE&&SLASH visitor branch already handles it correctly.
- #4 doc: MDL spec README showed `alter entity … add (Attr: type)`, which the
  parser rejects. Corrected to `add attribute Attr: type`.

Grammar regenerated (`make grammar`). Verified end to end: quoted index name,
quoted qualified sort stored as `M.Thing.Code`, describe/drop role in both forms,
and `ASSOCIATION $currentObject/…` all parse/store correctly. Tests added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants