Skip to content

Pluggable widget generation, warm local dev loop, ALTER PAGE INSERT INTO, and widget-authoring fixes#774

Merged
ako merged 42 commits into
mendixlabs:mainfrom
ako:main
Jul 22, 2026
Merged

Pluggable widget generation, warm local dev loop, ALTER PAGE INSERT INTO, and widget-authoring fixes#774
ako merged 42 commits into
mendixlabs:mainfrom
ako:main

Conversation

@ako

@ako ako commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary
This bundles six merged PRs from ako/mxcli into upstream. Together they make pluggable-widget generation version-correct without mx update-widgets, add a Docker-free warm dev loop, extend ALTER PAGE with INSERT INTO, and close a batch of widget-authoring gaps found while authoring real marketplace widgets against MPR v2 projects.
Every change was verified on Mendix 11.12.1 with mx check (0 errors, MPR v2 preserved), and the widget fixes each ship a runnable repro under mdl-examples/bug-tests/.
What’s included

  1. Warm local dev loop — mxcli run --local (proposal + implementation)
    A Docker-free, ~1s edit→test loop for Mendix apps plus the provisioning that makes a fresh/reaped web session testable.
    • Long-lived mxbuild --serve (warm ~1s builds vs ~30–60s one-shot), restartRequired-driven hot reload_model vs restart+DDL.
    • Standalone JVM runtime boot (no Docker), web-client rollup bundling (the serve Deploy target skips web/dist), --watch incremental bundler, Playwright screenshots (deep-link + authenticated).
    • --ensure-db provisions local Postgres + app DB; --setup non-blocking bring-up wired into a Claude Code SessionStart hook by mxcli init; empty-repo bootstrap prompt.
  2. Multi-version pluggable widgets — resolve CE0463 generically + widget describe
    Makes pluggable-widget generation version-correct across Mendix versions with no per-widget hardcoding and no dependency on mx update-widgets.
    • Definition-side reconciliation against the installed .mpk (per-ValueType scalars, enum option sets, per-property metadata, AllowUpload envelope), full declared PropertyType ordering including inline system properties.
    • editorConfig.js static extractor lifts getProperties visibility idioms into declarative rules so config-hidden textTemplate defaults are nulled exactly as Studio Pro does.
    • DataGrid2 @ Data Widgets 3.10.0 / Mendix 11.12 and ComboBox reach byte-identical definitions vs update-widgets → 0 CE0463.
    • New mxcli widget describe inspects a widget’s discovered format (properties, types, enums, dynamic visibility rules); --format json.
  3. Widget-authoring fixes (textTemplate / child slots / Charts CE0463 in v2 / multi-hop XPath / TimeSeries)
    • textTemplate content persisted for generated-def widgets (Badge value, TreeNode headerCaption, Timeline title/description/timeIndication were silently dropped).
    • Container-wrapped child slots routed by name (container children { … }, container customTitle { … }).
    • Visibility fallback merged, not overwritten (extracted wins, hand-authored fallback fills gaps).
    • Generated-widget definitions reconciled — Charts (no embedded template) now emit declared system props in order + run the same .mpk reconciliation; Pie/Column/Line/Bar/Area build byte-identical to update-widgets, no v2→v1 downgrade.
    • Multi-hop association XPath expanded to include the intermediate entity (Assoc1/Entity/Assoc2) → avoids CE1613.
    • Hidden chart-series textTemplates nulled (TimeSeries markerColor/fillColor honor item-level editorConfig gates).
  4. ColumnChart runtime JSON.parse fix
    Unset chart-series String properties were emitted as a single space " " instead of "". The chart client feeds customSeriesOptions/customLayout/customConfigurations to JSON.parse behind a value !== "" ? value : "{}" guard; a lone space slips the guard and throws JSON.parse(" "). Now emits "" (schema default), matching Studio Pro. Passed mx check before but failed at runtime.
  5. ALTER PAGE — INSERT INTO container
    ALTER PAGE … { insert into { … } } appends widgets as a container’s children — the only way to fill an empty container or add a child without an existing sibling to anchor to.
    • Full-stack: grammar → AST/visitor (Position = "INTO") → executor (children take the target’s own entity context, e.g. a dataview’s entity) → both the MPR-file pagemutator and live-Studio-Pro mcp mutator.
    • Empty containers omit the Widgets list, so it’s created with the Mendix widget-list marker and the grown bson.D written back into its parent.
    • Scope: simple containers (DivContainer, Container, DataView, GroupBox, ScrollContainerRegion, Section). LayoutGrid/TabContainer return a clear error pointing to INSERT BEFORE/AFTER.
    Testing
    • go build ./... clean; go test ./... green except cmd/mxcli/docker TestServeIntegration, a live-mxbuild serve integration test that fails identically on the base branch (stale local fixture: test project v11.6.3 vs cached mxbuild v11.12.1), unrelated to and untouched by these changes.
    • Each widget fix verified on a fresh Mendix 11.12.1 project via mx check (0 errors, mprcontents/ intact); charts and the XPath fix reproduced from real project scripts.
    • Repro scripts under mdl-examples/bug-tests/; doctype example for INSERT INTO; unit tests for mpk declared-order parsing, the editorConfig extractor, and the mutator INTO path.
    • Docs: docs-site pages, MDL_QUICK_REFERENCE.md, alter-page skill, and mxcli syntax help (page + snippet) updated.
    Notes
    • No sdk/mpr write imports added to the executor; new mutation goes through the backend abstraction.
    • Generated ANTLR parser files are not committed (regenerated by make).
    🤖 Generated with Claude Code

claude and others added 30 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
[email protected] 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 <[email protected]>
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 [email protected] — 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 ([email protected], [email protected]/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 <[email protected]>
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 [email protected] 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). [email protected] 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 <[email protected]>
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 [email protected] 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 <[email protected]>
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 [email protected] 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: [email protected] (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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…10.24 green

Marks Axis 2 (datasource TypeDefaults + PropertyType order) fixed in 10b5bcf.
[email protected] 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 <[email protected]>
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
([email protected], 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 <[email protected]>
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 <[email protected]>
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 [email protected] 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
Badge `value`, TreeNode `headerCaption`, and Timeline
`title`/`description`/`timeIndication` (all textTemplate properties) were
silently dropped by the page writer (MDL-WIDGET01): GenerateDefJSON emitted a
texttemplate PropertyMapping only when a friendly MDL alias was hand-registered
(PieChart/HeatMap only), so every other top-level textTemplate had no mapping and
its caption was discarded.

Emit a texttemplate mapping for every top-level textTemplate property, keyed by
its own name so it's authorable as `value:`/`title:`/`headerCaption:`. The
engine now skips the texttemplate write when the value is unset, so emitting the
mapping never nulls a widget's default caption — it only enables authoring.
Registered aliases (PieChart seriesName) are still carried. Bump
WidgetDefGeneratorVersion 10->11 so existing projects regenerate their defs.

Verified on Mendix 11.12.1: Badge/TreeNode/Timeline captions persist, no
MDL-WIDGET01, mx check 0 errors, MPR v2 preserved.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
A pluggable widget child slot authored as `container <slotName> { ... }`
(e.g. TreeNode `container children`, Timeline `container customTitle`) was
silently dropped: applyChildSlots matched a child block to a slot by the child's
Type ("container") against the slot keyword, so it never matched the slot named
after the container and fell through to the discarded default widgets. Only the
bare-keyword form (`children { ... }`) matched.

Route a `container <slotName>` to the slot whose keyword matches the container's
NAME (mirroring the object-list item-slot matcher); the bare-keyword form still
matches by Type. Verified: TreeNode `children` slot content persists, mx check
0 errors, MPR v2 preserved.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
claude and others added 12 commits July 21, 2026 14:33
…rules

The editorConfig visibility extractor skips compound/ternary guards (e.g.
Timeline's `customVisualization ? hidePropertiesIn([title,description,
timeIndication])`), and RefreshWidgetDefinitions overwrote the hand-authored
fallback table with the (incomplete) extracted rules. So Timeline title/
description/timeIndication lost their visibility rules and their hidden
textTemplates were emitted as empty ClientTemplates instead of null → CE0463 on
custom-visualization timelines.

Merge instead of overwrite: extracted rules win on conflict (version-specific),
hand-authored rules fill the keys the extractor misses. Bump generator version
11->12 to regenerate existing defs. Verified: Timeline customVisualization=true
now nulls the hidden captions (mx check 0 errors), and customVisualization=false
still keeps them visible.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…E0463 in v2

Charts (Pie/Column/Line/Bar/Area) have no embedded template, so they are built by
GenerateFromMPK. That path drifted from mxbuild's WidgetType in three ways, all
checked by CE0463, so every chart instance failed mx check in an MPR v2 project
(only mx update-widgets cleared it, downgrading v2->v1):

1. It omitted the widget's declared <systemProperty> entries (Name, TabIndex,
   Visibility). Now emitted in their declared document position as System-typed
   PropertyTypes (via the .mpk's AllTopLevel order), with no Object WidgetProperty.
2. It left each ValueType's schema-derived fields empty (enum option sets,
   expression returnType, selectionTypes, multiline). GenerateFromMPK now runs the
   same .mpk reconciliation augment applies to template-based widgets.
3. The .mpk parser read helpUrl/studioCategory as XML attributes; Mendix declares
   them as elements. Also parse the multiline attr and <selectionType> elements.

Result: the emitted WidgetType is byte-identical to update-widgets output for
Pie/Column/Line/Bar/Area on Mendix 11.12.1 — 0 CE0463, MPR v2 preserved. No
regression on template-based widgets (ComboBox, DataGrid2) or the reconcile path.

Known remaining: TimeSeries has a nested-series textTemplate that serializes as an
empty ClientTemplate instead of null (object-side, same class as the Timeline
visibility nulling but nested in an object-list item) — separate follow-up.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
A datasource constrained two associations away with the natural shorthand
  database from Travel.Activity where [Travel.Day_Activity/Travel.Trip_Day = $Trip]
failed with CE1613 'The selected entity Travel.Trip_Day no longer exists': Mendix
XPath requires the intermediate entity between two association hops
(Assoc1/Entity/Assoc2), and mxcli stored the shorthand verbatim so mxbuild read
the second association as an entity.

buildDataSourceV3 now expands consecutive association segments, inserting the
intermediate entity resolved from each association's target
(resolveAssociationDestination). Safe by construction: only runs of slash-joined
qualified names anchored at an association from the datasource entity are touched,
and an entity is inserted only between two segments that both resolve as
associations — so the already-correct full form, single-hop constraints, and
attribute paths are returned verbatim. Verified against the reporter's Travel
schema: the two-hop Timeline datasource resolves, mx check 0 errors.

Known related (separate): attribute-over-association shorthand
([Assoc/Attribute = x], needs [Assoc/Entity/Attribute = x]) is not yet expanded.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…erColor)

A TimeSeries/LineChart with a default 'line' series tripped CE0463: the series'
markerColor textTemplate was serialized as an empty Forms$ClientTemplate, but
Studio Pro stores it as null when the property is hidden. chartSeriesTextTemplateVisible
honored only the dataSet (static/dynamic) gate and missed the item-level editorConfig
gates — markerColor is hidden unless lineStyle == 'lineWithMarkers' (default 'line'),
and fillColor unless enableFillArea is truthy (default true).

Add chartSeriesTextTemplateHiddenByItemConfig, mirroring the widget's
hideNestedPropertiesIn rules, so a hidden series textTemplate serializes as null
rather than an empty ClientTemplate. Verified: default TimeSeries line -> 0 errors,
lineStyle 'lineWithMarkers' keeps markerColor visible, full chart example (all
types) 0 errors.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…time JSON.parse)

A ColumnChart with a static series passed mx check but failed to render with a
client-side JSON.parse('Unexpected end of JSON input'). The object-list-item
builder emitted an unset String property as a single space " " instead of "".
The chart client feeds customSeriesOptions / customLayout / customConfigurations
to JSON.parse behind an empty-guard (value !== "" ? value : "{}"); a lone
space passes that guard, so the client runs JSON.parse(" ") and throws. mx check
doesn't execute the client, so it stayed green. A Pie (widget-level datasource,
no series object-list) was unaffected — the top-level String path already emitted
"".

Leave an unset String empty, matching Studio Pro and the top-level path, so the
client's empty-guard turns it into "{}". Verified: series customSeriesOptions is
now "" (was " "), zero space-valued primitives; mx check 0 errors and no
CE0463 regression across charts / DataGrid2 / Gallery.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…er's children

ALTER PAGE could only INSERT BEFORE/AFTER a sibling widget, so there was no way to
fill an EMPTY container or add a widget to a container/dataview without an existing
sibling to anchor to. Add:

  alter page Mod.Page { insert into containerName { <widgets> } }

which appends the widgets as the last children of the named container. Full-stack:
grammar (INSERT INTO), visitor (Position "INTO"), executor (children take the
target's own entity context, e.g. a dataview's entity), and both mutators
(pagemutator for MPR files, MCP for live Studio Pro). An empty container omits its
Widgets list, so it is created with the Mendix widget-list marker and written back
into the parent (the bson.D grows). Simple containers are supported (DivContainer,
Container, DataView, GroupBox, ScrollContainerRegion, Section); LayoutGrid and
TabContainer have no single child list and give a clear error pointing to
INSERT BEFORE/AFTER inside the target column/tab.

Verified on 11.12.1: insert into an empty container, append to a non-empty one, and
insert a data-bound widget into a dataview — mx check 0 errors. Unit test for the
mutator INTO path + error case; doctype example; skill / quick-reference / syntax
help updated.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…iation

The `test-integration` suite (TestMxCheck_DoctypeScripts) started failing once
the multi-version pluggable-widget reconciliation landed. Two showcase scripts
regressed — both because reconciliation stopped masking genuine widget
incompleteness, not because of a defect in the generated BSON:

32-pluggable-widget-object-lists-v010.mdl (modelsdk): the OL09 HeatMap only set
its SCALECOLOR entries and never bound a data series, so mx check reported
CE0642 "Property 'Series'/'Value attribute' is required". Reconciling the
HeatMap definition to the installed .mpk correctly marks those required (the old
embedded template understated it). Complete the example with the widget-level
DataSource / HorizontalAxisAttribute / VerticalAxisAttribute / ValueAttribute
binding, mirroring the passing HeatMap in 34-chart-widget-examples.mdl — the
object-list showcase now demonstrates a complete, deployable heat map.

17-custom-widget-examples.mdl (both engines): the IMAGE showcases author
bare/default static-image-mode Image widgets to demonstrate the IMAGE keyword's
basic/dimensions/onclick syntax. MDL exposes no property to bind a static image
resource (only imageUrl mode), so a default Image is legitimately
"No image selected." — exactly what a freshly-dropped Image shows in Studio Pro.
It previously passed only because a stale Atlas_Core.Content.Mendix template
default masked it; that default caused CE0463 and was removed in the Image
CE0463 fix. Whitelist the message for this script via scriptKnownCEErrors
(now documented to also accept a message substring where an error carries no CE
code), matching the existing syntax-showcase-limitation pattern.

Verified on Mendix 11.12.1: all three previously-failing subtests pass; mendixlabs#32
retains only the globally-tolerated Maps CE0463.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
govulncheck (the vuln-scan step in Build, Test & Lint) flags GO-2026-5970,
"Infinite loop on invalid input" in golang.org/x/text, reachable via
catalog.Catalog.Query → sql.Rows.Columns → norm.Form and
mpr.OpenWithOptions → sql.Open → norm.Form. The advisory is fixed in
golang.org/x/text v0.39.0; bump the (indirect) requirement to it. go mod tidy
also nudges the transitive golang.org/x/sync v0.20.0 → v0.21.0.

Build is clean. This gate lives in the same CI job as the doctype integration
tests, so it only surfaced once those passed; the fix greens the job and, once
merged, main.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
@ako
ako merged commit 4af2fea into mendixlabs:main Jul 22, 2026
4 checks passed
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