Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7887cb9
fix: use building block action override rebinds a pluggable button (c…
MeisamMahdian Nov 11, 2026
72036f2
fix: `check script.mdl` in a project directory checks references alth…
claude Nov 11, 2026
d888346
fix: domain model SVG draws associations from their stored anchors
claude Nov 11, 2026
3745b3a
fix: a REPL session never sees another process's write to the project…
claude Nov 11, 2026
5e9c54c
fix: auto-layout puts merges inside the activity before them and rejo…
claude Nov 11, 2026
6c2419a
fix: layout flows no longer leaves merges overlapping their neighbour…
claude Nov 11, 2026
736f248
fix: check reports a false CE0495 for a building block placed with `a…
claude Nov 11, 2026
8f49319
fix: `use building block … as <prefix>` leaves intra-block references…
claude Nov 11, 2026
7bad955
fix: `use building block … (action: …)` reports "no button to rebind"…
claude Nov 11, 2026
ae5f9cc
Merge remote-tracking branch 'origin/main' into claude/check-mxbuild-…
claude Nov 12, 2026
939bf33
feat(cli): MXCLI_CPUPROFILE writes a CPU profile of a command
claude Nov 12, 2026
0ec9aad
Merge remote-tracking branch 'origin/main' into claude/trusting-wrigh…
claude Nov 12, 2026
325b860
feat(cli): catalog progress per table only on a terminal; -q on every…
ako Nov 12, 2026
0bf0c91
fix(describe): auto-detect module roles, user roles and navigation pr…
ako Nov 12, 2026
70d5e27
feat(catalog): workflow activities with their kind and slots for lint…
ako Nov 12, 2026
f1c4c58
perf(mprread): keep a unit's decoded form until its stored bytes chan…
claude Nov 12, 2026
99fcd72
Merge pull request #2154 from ako/claude/check-mxbuild-drift-issues-w…
ako Nov 12, 2026
c025927
perf(mpr): a write retires the one unit it rewrote from the content c…
claude Nov 12, 2026
cf6d914
Merge remote-tracking branch 'origin/main' into claude/trusting-wrigh…
claude Nov 12, 2026
d1a7dbe
fix(mpr): another process's write drops the cached unit bytes (#2160,…
claude Nov 12, 2026
74eac27
perf: a check lists the project once, and the decoder borrows cached …
claude Nov 12, 2026
f2b94df
docs(adr): ADR-0015, what mxcli keeps of a unit is keyed by the unit'…
claude Nov 12, 2026
c3aafd9
Merge pull request #2159 from ako/claude/trusting-wright-cqa3bb
ako Nov 12, 2026
afd0b8e
perf(mpr): a write updates the unit list in place; modules list from …
claude Nov 12, 2026
d1aa3f8
Merge remote-tracking branch 'origin/main' into feature/1262-describe…
ako Nov 12, 2026
a480e20
Merge branch 'main' into fix/1821-bb-action-override-pluggable-button
MeisamMahdian Nov 12, 2026
e2daf71
Merge pull request #2161 from ako/claude/trusting-wright-cqa3bb
ako Nov 12, 2026
411cd99
perf(executor): a run of entity and association statements writes eac…
claude Nov 12, 2026
55ed1b6
test(run): the lifecycle test wants build #2 as a reload on 11.14+ again
claude Nov 12, 2026
681cf30
findings: nightly 11.14+ lifecycle test pinned the serve restart #215…
claude Nov 12, 2026
b93a6ed
Merge pull request #2165 from ako/claude/trusting-wright-cqa3bb
ako Nov 12, 2026
2ed5572
Merge pull request #2170 from ako/claude/mxcli-nightly-build-failure-…
ako Nov 12, 2026
cd1acc9
Merge pull request #2162 from ako/feature/1860-catalog-quiet
ako Nov 12, 2026
2123fb5
Merge pull request #2164 from ako/feature/1295-workflow-activities
ako Nov 12, 2026
e456647
Merge remote-tracking branch 'origin/main' into feature/1262-describe…
ako Nov 12, 2026
718447f
Merge mendixlabs/mxcli#1822: use building block action override rebin…
claude Nov 12, 2026
81c1486
perf(executor): entity lookups read one module's domain model
claude Nov 12, 2026
46b0cdf
Merge pull request #2171 from ako/integrate/mendixlabs-1822
ako Nov 12, 2026
176d619
Merge pull request #2172 from ako/claude/trusting-wright-cqa3bb
ako Nov 12, 2026
304bf5f
perf(mpr): a judged run keeps the digest of the write it holds
claude Nov 12, 2026
219c904
Merge branch 'main' into feature/1262-describe-members
ako Nov 12, 2026
a810c82
Merge pull request #2163 from ako/feature/1262-describe-members
ako Nov 12, 2026
4d8f6ac
Merge main into claude/trusting-wright-cqa3bb
claude Nov 12, 2026
7072eaf
Merge pull request #2175 from ako/claude/trusting-wright-cqa3bb
ako Nov 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/commands/mendix/check-script.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Validate an MDL script before executing it.
## Commands

```bash
# Syntax check only (no project needed)
mxcli check script.mdl
# Syntax check only (--no-project: do not auto-detect an .mpr in this directory)
mxcli check script.mdl --no-project

# Syntax + reference validation (checks entities/modules exist)
mxcli check script.mdl -p app.mpr --references
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"cmd/mxcli","date":"2026-11-11","symptom":"`mxcli check --help` offered `# Check syntax only (no project needed) mxcli check script.mdl`, but run from a directory holding an .mpr it printed `Using project: ...\\project.mpr (auto-detected in the current directory; pass -p to use another)` and resolved references against it; there was no way to get the advertised syntax-only check there","cause":"`rootCmd.PersistentPreRun` auto-discovery sets `-p` before `check` runs, and `check` treats any project as an implicit `--references` (the fix for an unqualified `Check passed!`); the help example was only true outside a project directory","file":"`cmd/mxcli/main.go` (`PersistentPreRun`, `noProjectOptOut`/`skipsProjectDiscovery`), `cmd/mxcli/cmd_check.go` (help, `checkNoProjectConflicts`)","insight":"Two individually right decisions (auto-detect the sole .mpr, mendixlabs/mxcli#1444; a project implies reference checks) composed into a help example that is false exactly where users run it — a project directory, which is also where the generated CLAUDE.md template told agents `check script.mdl # Syntax only`. Changing the default would have silently weakened every `cd app && mxcli check` that relies on the auto-detected refs, so the fix is an opt-out (`--no-project`, honoured by PersistentPreRun for any command that registers it), a notice on the auto-detect line naming it, a refusal when combined with -p/--references/--post-migration, and help/docs whose syntax-only example carries the flag. Note `Flags().Set` by auto-detection marks `-p` Changed, so a conflict check on Changed only works because discovery is skipped first. Test runs real main() in a temp dir with a non-project Stray.mpr (opening it would error); control: discovery forced on under --no-project prints the reported `Using project:` line","refs":["ako/mxcli#2135","mendixlabs/mxcli#1817"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-11-12", "symptom": "`describe Administration.Administrator` (no type) answered \"no describable document named ... found in the project\" although `describe module role Administration.Administrator` describes it; the same for a user role (`describe Administrator`) and a navigation profile (`describe Responsive`).", "cause": "resolveDescribeType resolved through the catalog's objects view and, on a miss, a live scan of top-level units plus domain-model entities and associations. Module roles, user roles and navigation profiles are members of the module-security, project-security and navigation documents, so neither path ever saw them.", "file": "cmd/mxcli/cmd_describe.go (describableMembers, called from resolveViaReader)", "insight": "Resolve members in the live fallback, not the objects view: the catalog has no complete module-role table (role_mappings lists only roles a user role maps), so a view built on it would answer 'not found' for an unmapped role, which is worse than a miss that falls back. The help text had codified the gap as a rule ('forms that have no single qualified name (... navigation, module role)'), which is why it read as by design for months.", "issue": "ako/mxcli#1262"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"cmd/mxcli","date":"2026-11-12","symptom":"The nightly goes red on the Mendix 11.14.0, 11.15.0 and 11.16.0 legs, in `TestRunLifecycle_DetachStatusExecWaitStop`: `wait (Mendix 11.14+): build #2 applied without mxcli restarting mxbuild --serve; if this mxbuild builds incrementally again, drop the 11.14+ branch`, with the run log showing `build #2 applied via reload in 3.7-8.5s`. Every older leg, push CI and the unit tests are green","cause":"Not a product defect: the improvement the test was written to notice. ako/mxcli#2150 (9156cf465, client_source_keep.go) copies aside the client source a serve build deletes and puts it back before the next, so --watch builds incrementally on the versions that bundle the client themselves. The test's 11.14+ branch still required serveRecovery's serve restart in the run log. The lifecycle test needs a cached mxbuild and a runtime, so it runs only in the nightly, never in the PR that changed the behaviour — the same path as 2026-10-23-nightly-11-14-11-15-runlifecycle-wants-serve-rebuild-hint","file":"`cmd/mxcli/cmd_run_lifecycle_integration_test.go` (`wantBuild2`, step 4); the behaviour is `cmd/mxcli/docker/client_source_keep.go` and `serve_recovery.go`","insight":"The branch was built to fail when the restart stopped being needed, and it did, a day after the change, which is the cost of a behaviour pinned only in a nightly-only test: whoever changes client_source_keep.go, serve_recovery.go or the watch loop should run the lifecycle test on 11.14 and 11.15 before merging. Rather than drop the 11.14+ branch, the test now pins the new contract on every version: a page change applies via reload and the run log never says `restarting mxbuild --serve`, the phrase every fallback that replaces the serve process prints — so a keep that stops holding the source fails it instead of degrading to a 20 s cold build per change unnoticed. The boot-race step keeps claiming only that build #2 applies. Reproduce in about 2 minutes: `mxcli setup mxbuild --version 11.14.0`, JAVA_HOME at a JDK 25, `MXCLI_RUNLIFE_VERSION=11.14.0 go test -tags integration -run TestRunLifecycle_DetachStatusExecWaitStop ./cmd/mxcli/` (the old test via `go test -overlay`). Controls: the old test against main fails at line 159 with the nightly's message; the new test passes on 11.14.0 and 11.15.0; with newClientSourceKeep stubbed to nil it fails on 11.14.0 naming the restart, the log showing `applied via restart in 22.9s`","refs":["mendixlabs/mxcli nightly run 43191062324","ako/mxcli nightly run 43190452893","ako/mxcli#2150"],"test":"cmd/mxcli/cmd_run_lifecycle_integration_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-11", "symptom": "mendixlabs/mxcli#1821: `use building block PlatformDesignSystem.Button (action: call microflow M.Act) as b_` failed with 'action override supplied, but the block has no button to rebind', on every PlatformDesignSystem block (Marketplace 44.4.0, Mendix 11.12.6, mxcli v0.31.0).", "cause": "The action override's target predicate isButtonWidget matched only the built-in button types (actionbutton, linkbutton, button). The PDS blocks are built from the pluggable pdsbutton, so no widget matched, although the engine already writes a pluggable widget's on-click slot from the same Action property the override sets.", "file": "mdl/executor/cmd_pages_builder_v3.go (isPluggableButtonWidget, the ActionOverride branch of the building-block expansion)", "insight": "A pluggable widget is a button target when its definition names it a button AND maps a slot to OnClick. The click slot alone is not enough: a Gallery and a Data grid 2 take OnClick for a row click and a PDS Link for a link click, and on a PDS page header the first clickable widget is the 'Back to' link, not the primary button. With no project there is no registry, and only the built-in types match, as before.", "refs": ["mendixlabs/mxcli#1821"], "test": "mdl/executor/cmd_pages_builder_bb_rebind_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-11-11","symptom":"`use building block PlatformDesignSystem.Button (action: call microflow M.F) as b_` fails exec with `action override supplied, but the block has no button to rebind`; the block is one pluggable `pdsbutton pDSButton1`. Same for any block whose only clickable widget is pluggable (Atlas Card_WithImage's Image)","cause":"The ActionOverride target predicate isButtonWidget matched the core keywords actionbutton/linkbutton/button only; a pluggable widget's action lives in a definition-declared property","file":"`mdl/executor/cmd_pages_builder_v3.go` (`pluggableClickActionSlot`, the `ActionOverride` branch of `expandBuildingBlockRef`)","insight":"Ask the widget definition, not a name list: GenerateDefJSON gives every click action (onClick, onClickAction, onClickEvent) Source \"OnClick\" via actionSourceForKey, and the engine reads that Source from Properties[\"Action\"] — so the override's write is unchanged, only the predicate widens. \"Has an action property\" alone is too wide: the pluggable Gallery and Data Grid 2 have onClick (an item action) and combobox/slider have onChange, so require Source OnClick and no datasource mapping. Try core buttons over the whole block FIRST and fall back to pluggable ones, or Atlas Card_ActionWithImage (image, then button) would silently move its override onto the image. Mock trap: a propertyless pluggable widget describes as the LAST SEGMENT of its widget id (extractCustomWidgetType), so a test id ending `.Button` renders as the core `button` keyword — use the real-shaped `…PDSButton`. PlatformDesignSystem is not fetchable here (no marketplace PAT, not in the cached catalog); measured instead on 11.14.0 with Card_WithImage: before, the same refusal; after, the Image gets OnClick and mx check reports 0 errors. Tests `use_building_block_pluggable_action_2145_test.go`; control = pre-fix run, the two pluggable tests failed with the reported message","refs":["ako/mxcli#2145","mendixlabs/mxcli#1821"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-11-11","symptom":"`use building block Atlas_Web_Content.Master_Detail as md_` fails exec with `failed to build page: failed to build datasource: widget not found: gallery2` — the widgets became md_gallery2 / md_dataView7 but the data view's `selection gallery2` kept the old name; without a prefix the same block builds","cause":"prefixWidgetNames renamed WidgetV3.Name only. A block's widgets reference each other by name in property values, and those were never visited","file":"`mdl/executor/widget_prefix_rename.go` (`prefixWidgetNames`, `widgetRefRenamer`; shared by `expandBuildingBlockRef` and `expandFragmentRef`)","insight":"A rename is a rename of declarations AND references in one pass — the same rule as $ID renumbering. Widget names are referenced in two spellings: bare (selection Reference, association ContextVariable, `delete $w` SourceVariable, LinkVariable — listed by type because Reference means an entity or flow for other source types) and as a `$name` token in any text (flow args, `$dv.Attr` template params, visibility/editability expressions, where clauses). Rewrite the token form generically by reflecting over every property value rather than enumerating property keys, restricted to names DECLARED in the block so outside references survive. Rewrite copy-on-write: cloneWidget copies the property map, not the values, so mutating a *DataSourceV3 in place corrupts the fragment definition for its next `use`. Measured on 11.14.0: prefixed Master_Detail now gives exactly the mx check errors the unprefixed one does (CE0488/CE3637 from the unbound template gallery); with `(datasource: database from E)` those clear and only the template's unbound text boxes (CE7005) remain. Tests `use_building_block_prefix_refs_560_test.go`; control = pre-fix run, selection reference stayed `listView2`","refs":["ako/mxcli#560"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-11-11","symptom":"`mxcli describe --format svg domainmodel <Module>` draws every association centre to centre; the stored association anchors are ignored (tested with extreme anchor values), so the SVG cannot be used to verify \"corner to corner\" lines","cause":"renderDomainModelSVG computed both line ends from the box centres (edgePointFrom) and never read Association.ParentConnection/ChildConnection, although the backend had parsed them since #872","file":"`mdl/executor/cmd_domainmodel_svg.go` (`svgBox.anchorPoint`, `outward`, `selfLoop`, association loop in `renderDomainModelSVG`)","insight":"**The encoding was already measured — reuse it, do not re-derive it**: #872's two findings (search `anchor`) settled that ParentConnection (FROM) / ChildConnection (TO) are \"x;y\" integer PERCENTAGES of the entity box, 0..100, no -1/auto sentinel, and the loader does not range-check; a blank 11.14.0 app's raw unit still holds `0;54`/`100;54`. So the renderer's job is only `box.x + x/100*w`, applied to the box AS DRAWN (the SVG's widths are its own estimate, and after spread/clamp — a percentage survives that, a pixel offset would not). **nil is the only 'unset'**: every association mxcli writes stores 0;50/100;50, so after the fix almost every real diagram changes, and an mxcli-made FROM-left-of-TO pair now draws from FROM's left edge to TO's right edge, through both boxes — that is the stored data, not a bug in the renderer. **A self-association needs a route, not a line**: centre to centre it was a zero-length line; two anchors on one box joined straight cross the entity, so it walks an outset rectangle the shorter way. Out-of-range anchors are clamped onto the box — an unverified choice (no Studio Pro here), documented in the test. Test the endpoints numerically with a centre-line golden captured BEFORE the change as the unset-anchor control; the anchored cases fail on the old code with the exact reported symptom (every line (400,139)-(190,125) whatever the anchors). Tests `TestDomainModelSVG_AssociationUsesStoredAnchors`, `TestDomainModelSVG_UnsetAnchorsKeepCentreLine`, `TestDomainModelSVG_SelfAssociationUsesStoredAnchors`; example `mdl-examples/bug-tests/1841-domain-model-svg-stored-anchors.mdl`. ako/mxcli#1841, part 1 of upstream #1692","refs":["#1841","#1692","#872"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-11-11","symptom":"Auto-layout put objects on or behind their neighbours and `layout flows` called the flow already laid out (ako/mxcli#1773): an if/else followed by an activity inside a THEN branch put the enclosing merge inside that activity (5px reported; 20px when the decision opens the branch); a handler row ending in `join` reserved about twice its drawn width; a falling-through handler of two or more statements rejoined at a merge left of the row's last activity, so the edge ran backwards. mx check 0 errors in every case.","cause":"Four measurer/builder disagreements. measureIfStatement measured from the split's centre as if it were the left edge (45px short) and gapBetween compensated after the IF only; measureStatements started every run at the left edge although the builder centres a first split where an activity's centre would be (15px short); measureBranch added an end event after any terminal statement, a join and a both-return IF included; and the rejoin merge was placed midway between the activity and the next one by mergeOnEdge while the row ran on past it. An IF/ELSE without a merge (one branch returns, or tailWithoutMerge at a loop body's end) was measured with a merge too.","file":"mdl/executor/layout.go (measureRun, measureIf, gapBetween, lastStmtDrawsEndEvent), mdl/executor/layout_lanes.go (ifHasMerge, ifJoinsNothingAtTail, ifMainWidth, rejoinsPastRow, rejoinAfterRow), mdl/executor/cmd_microflows_builder_flows.go (finishCustomErrorHandler, addErrorHandlerRejoinFlowForState)","insight":"The cheapest exact oracle for a measurer is a loop: fitContainerSize sizes the box from what was BUILT, measureLoopStatement from what was MEASURED, so wrapping any run in `loop … end loop` and comparing the two widths catches every disagreement to the pixel, including over-measures that never overlap anything (the join case). It found two defects the issue did not name (the first-element offset, and a merge counted for merge-less IF/ELSEs). Distinguish the main-line cursor from the drawn extent: an IF without a merge resumes at a point that is not an edge of anything, and folding that point into the extent re-introduced an over-measure at a body's tail. A `merge` label statement advances only half a pitch, so gapBetween's 20px floor over-measured it; MDL refuses join/merge in loops (MDL-FLOW04), but the oracle still applies because a run is measured the same way wherever it is. Moves: 10 of 376 doctype-example flows (02c CX_SYNC_FactoryTelemetry 5465->4315 wide, CX_VAL_Factory, CX_VAL_EmailTemplate, CX_ACT_BatchProcessFactories, CX_ACT_HandleAuthCode; 02 M008_NestedIf, M093_GetCountryLabel; 07 M020, M050, M053) and 4 of 29 fixture flows; no golden test changed. Not this class: vertical measurement (a Bounds height is not symmetric about the line, so an if-without-else inside nested loops pokes out of the outer box, MPR011) and a multi-value CASE outcome's own merge drawn on its first activity (documented at firstCaseGroupShift).","refs":["ako/mxcli#1773","ako/mxcli#1768","ako/mxcli#684"],"test":"mdl/executor/layout_measurer_1773_test.go, mdl/executor/layout_handler_lane_1768_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-11-11","symptom":"`check --references` refuses a building block placed several times with `as <prefix>`: `duplicate widget name 'Atlas_Web_Content.Card' (used 4 times) — … (CE0495)`, while exec writes a_container2/b_container2… and mx check reports 0 errors; since a reference error blocks exec, the documented prefix form could not be run without --no-check","cause":"validatePageContextTree counted names on the PARSED tree, where `use building block X` / `use fragment X` is a sentinel WidgetV3 whose Name is the block's name. exec expands the sentinel first (expandFragments) and only then registers widget names","file":"`mdl/executor/validate_page_context.go` (`expandUseRefsForCheck`, used by `validatePageContextTree`)","insight":"A check that walks the parsed tree must walk the tree exec BUILDS: any pre-pass exec runs before naming (here sentinel expansion; ALTER PAGE's insert path already expanded before its duplicate check) has to run in check too. Do not just skip the sentinel — that loses the real collision: the same block twice with NO prefix makes exec refuse `duplicate widget name 'text22'`, and check now reports it by those expanded names. With no project (or a script-defined fragment) the reference contributes no names. Measured on 11.14.0: four prefixed Atlas Cards — check passes, exec writes, mx check 0 errors; two unprefixed — check reports container2/text22, exec refuses. Tests `validate_page_context_bb_559_test.go`; control = the pre-fix run, which failed all four with the reported message","refs":["ako/mxcli#559"],"ce":["CE0495"]}
Loading
Loading