Repository navigation
Sync ako/mxcli: microflow splice refusals, legacy table cells, System.owner references, describe round trips, settings, marketplace - #1638
Merged
Conversation
…th change (mendixlabs#1610) Under mdl 1, create or modify with only an @caption added to or reworded on an existing if was refused with 'changes where its paths end or meet'. The caption is a property of the decision, like its condition: it is now set in place through SetCondition, and the decision keeps its $ID and both paths. Refs #1538, #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…ixlabs#1489) Under mdl 1, create or modify and alter both refused any change to an activity with an on-error handler, and each advised the other. The activity replaced by one handling errors the same way is now swapped in place, keeping the stored handler, its error flow and the merge it rejoins at; create or modify diffs the handler body like an if branch, and alter recognises a restated handler. Remaining refusals name drop-and-create, not the other mode. Refs #1345, #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…endixlabs#1517) An @annotation before a statement's @position is a free note, which is where describe prints one. Restating an activity's note in that order was refused with 'note "…" is not in the stored flow', which was false. The refusal now names the order, the activity the stored note is attached to, and the spelling that keeps it attached; the write-microflows skill states the rule. Refs #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…andler (mendixlabs#1517) The in-place replace of an activity with a custom error handler kept only the activity from the fragment, so a note added to it was silently not written, and a reworded note was refused. The activity's own notes now come with it, drawn relative to the stored position, and stored notes are replaced. Refs #1399, #1345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
`mxcli git note -p App.mpr --write | head -1` wrote no note and said nothing (mendixlabs#1490, #1346). annotateCommits printed each note before writing it, and a Go program writing to a stdout whose reader has gone is ended by SIGPIPE, so the first print to the closed pipe stopped the write for that commit and every later one. With --write, every note is now written before anything is printed; the report is held and flushed afterwards. A preview has no side effect and still streams. Writing each note just before its own print (the issue's first suggestion) is not enough: with two commits the second print still kills the process before the second write. The test covers two commits for that reason. Controls, TestGitNote_WriteSurvivesAClosedStdout (child runs the real main() with stdout a pipe whose read end is closed; the child ending on SIGPIPE is asserted in every arm): original order: HEAD~1 lost, HEAD lost write-then-print per commit: HEAD~1 written, HEAD lost this fix: both written Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TYmgi2rk8ZbVZ9uEGxR3Nq
…mendixlabs#1517) Under mdl 1, a note-only change before an if was refused as a change of where its paths end, and one before the final return as an annotation change. A decision and an end event are changed in place, never replaced, and the mutator had no way to attach a note to a node that stays. A new AddNotes op does, and the diff sets their notes in place like their condition or value. Refs #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…ailed
With an mx of the project's minor but another patch, `mx update-widgets`
refuses the project ("Project is in different Mendix version", exit
status 4) while `mx check` accepts it (mendixlabs#1629, ako/mxcli
#1561). docker check carried on, as it should, then closed with "Note:
widget definitions were normalised on a temporary copy" a few lines
after "Warning: update-widgets failed (continuing): exit status 4". The
note was keyed on update-widgets being requested, not on it succeeding.
It now keys on the outcome. After a failure it says the check ran
without normalisation, so a CE0463 may be one normalisation clears, and
how to get an mx of the project's exact version.
Measured on real Mendix 10.24.18 tooling (mx 10.24.18 against a v1
project relabelled 10.24.13): update-widgets exit 4, mx check 0 errors;
the same project unrelabelled exits 0 on both. Before the fix the
output contradicted itself; after it, the not-normalised note appears,
and a matched project still gets the normalised note.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYmgi2rk8ZbVZ9uEGxR3Nq
`mxcli docker --help` listed "Mendix 11.6.1 or later" as a requirement of the whole command group (mendixlabs#1629, #1561). The floor is docker build's: a Portable App Distribution needs 11.6.1, and Build refuses anything older; run and reload go through Build. docker check has no gate and works on Mendix 10 (measured on 10.24.18: "The app contains: 0 errors."). The group help now scopes the floor to build, run and reload. docker check --help says it has no floor, and that a failing update-widgets (exit status 4 on a version mismatch, which mx check tolerates) does not stop the check. TestDockerHelp_VersionFloorIsBuildsNotChecks pins it: any line of the group help naming 11.6.1 must name build. It failed on the old text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TYmgi2rk8ZbVZ9uEGxR3Nq
… is 21%, not 68% A fourth project, a complete chess-game build measured with diag session-report, is the largest session recorded and it corrects this document rather than confirming it. N x S now holds across three orders of magnitude: 59 calls x 108k = 6M against 6.2M measured, 523 x 435k = 228M against 228M, 1,771 x 372k = 659M against 653.5M. Nothing else here is as well established. The unwelcome part is what that does to the levers. Tool output is 21% of this build's bill against 35% in BENCH-001 run 3, and the remaining ~79% is the conversation itself. The costliest single result is the same shape the benchmark made item 3b out of — a bootstrap skill file read early and re-read ~260 times — and it is 1.69M of 653.5M, 0.26%, where the benchmark put the same shape at 5.3%. A 59-call run is not a scale model of a 1,771-call build: it over-weights every lever aimed at what a tool returns, because in a short session tool results are most of what there is. The subsection that drew the original conclusion now carries a banner saying to read it as benchmark-local, and BENCH-002 at 2x the surface does not fix this. What it promotes is item 3c, new: one session per phase, each resumed from brain brief / brain plan. Splitting N calls across k near-empty phases is N x S / 2k, a factor of k rather than a percentage; the chess session proposed this itself and sized it at ~30%, which is the k = 2 case. Its price is one re-orientation per boundary — so 3b, 4 and 4b are not competing with it, they are what sets its price, and they are recorded as mis-sized token levers that are better justified that way. Two items resized downward: retries are 4.5% here against 13.6% in run 3, and `check` is 9% of invocations, the fourth project in a row to put it nowhere near the ledger's 83%. One shipped lever shows as adopted: `run wait` is the second most frequent command at 95 calls, where the three earlier projects hand-rolled nohup/poll/pkill loops. The wall-time attribution and the licence-session-cap diagnosis for 150 app restarts are the other session's estimates, not reproduced here, and are recorded as a lead to verify rather than as findings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgcYSQrLLbUcnAMaCHpyqQ
…ctTypes MDL-SET01 tracked, statement by statement, which entity each object and list variable holds. The next rule needs the same answer for an XPath operand, so the walk moves into one type both can use instead of a second copy. Behaviour is unchanged; the SET01 tests pass as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XD4JpQem7z5pjk2WuYRqf
`set (Action: call microflow M.F) on card1` was refused for a container CREATE had just written with an action (#1503, mendixlabs#1592): widget "card1" (Forms$DivContainer) has no Action property — Action can only be set on a widget that performs an on-click action, such as a button or a clickable container The setter looked only for an `Action` key. The metamodel spells the click action per type: Action on the buttons and navigation list items, OnClickAction on Forms$DivContainer, ClickAction on Forms$ListView and both image viewers. SetWidgetAction now writes the key the stored widget holds (types.WidgetClickActionKeys, in priority order; no type declares two) and still refuses a widget with none. The refusal test's fixture was a container without an OnClickAction, a shape no stored model holds; it now uses a dynamic text. Control: the new test fails on main with the reported message. Fixed, on a blank 11.12.5 app the reporter's script applies, describe shows the new microflow, re-executing the describe output reports `Unchanged page`, and `docker check --no-update-widgets` reports 0 errors — for a container that had an action and for one that had none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PALuhnbBpSb16e2a9A44z9
…kActionKeys The catalog's primary-action reader kept its own copy of the three keys a widget stores its on-click action under; ALTER PAGE's setter now reads the same list from mdl/types, so the two cannot drift again (the setter had known only Action, #1503). The comment's 'layout grids' was wrong: no LayoutGrid type declares OnClickAction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PALuhnbBpSb16e2a9A44z9
The free-note ordering rule added in b9bedb2 took the skill body to 705 lines, which TestLargeSkillsWereSplit refuses. The notes section is condensed; the rules it states are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…ame flow (mendixlabs#1517) check -p (and exec's preflight) gave up on a statement about a flow an earlier statement had changed, reporting it 'not predicted', and exec could then refuse it after the earlier statements ran. The writer gains a simulated mode: unit updates are held in memory and read back, never flushed, and any other write is refused at guardWrite. check applies each change it predicts as spliced to the simulation, so the next statement on that flow is predicted against what exec would see. Refs #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…n reading of it The full `diag session-report` supersedes the partial one recorded earlier (1,784 calls and 655.7M against 1,771 and 653.5M; the shares are unchanged) and shows the whole costliest-results list rather than its first entry. That entry was a skill file, and the previous commit generalised from it the way BENCH-001 had. The list says otherwise. Orientation at build scale is the agent re-reading its own work. Own MDL source in small `sed` ranges is 28% of the ten costliest results and subagent artifacts 30%, against the skills' 22%; the lookup counts say the same at full scale, 559 file reads against 101 doc lookups, 154 of them repeats, and 984 of 1,653 Bash calls are neither mxcli nor git nor build. One 17-line range of a generated file was re-read by 504 later calls. That is a different problem from item 3b with a different fix — not going back at all — so item 3d is added for it. The cost is also a long tail, which inverts the method this document has used throughout: the top ten are 12.2M of 134.6M, 9% of the tool re-read, against 75% in BENCH-001 run 3. At build scale there is no whale to harpoon, so only the structural levers (fewer calls, and not carrying the conversation between phases) touch the bill. Delegation is priced for the first time: 10 subagent calls produced 3 of the 10 costliest results, 3.6M, because a subagent saves its own context and not the caller's unless the handback is small. Item 6 now carries that cost line. Two defects named by the retry list are added to item 4c: `check` rejecting the Live Sync "On tick" property on a widget mxcli itself writes, and `Failed to fetch` on the first assertion after `run restart` — the worst chain in the session at 5 retries, which says whatever `run restart` returns on is not readiness. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgcYSQrLLbUcnAMaCHpyqQ
`ALTER SETTINGS CONFIGURATION 'Default' ExtraJvmParameters = '…'` failed with "unknown configuration setting: ExtraJvmParameters", and CREATE CONFIGURATION with "unknown configuration property". The reader already read the field and the settings overlay already wrote it back; only the executor's key switches lacked the case, and DESCRIBE never printed it, so a described project replayed without it. Both statements now accept the key, and DESCRIBE emits it when set. Every supported Mendix version stores the property (no versionInfo entry in the Model SDK; a Studio Pro-authored 11.14 configuration carries it). Fixes mendixlabs#131 (#1225). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
The last row of the #1326 (mendixlabs#1453) repro still failed after the item address landed. CREATE accepts `group grp1 (…)` and drops the name — an Accordion group stores none — so the next statement is `insert into grp1 { … }`, and on a page that also holds a data grid the miss pointed at the grid: widget "grp1" not found. DataGrid2 columns are addressed by a derived name (the bound attribute, or the caption), not the name written in MDL — available columns: Name (run DESCRIBE PAGE to confirm) The miss now lists every item address on the page, spelled as typed, before the column hint: widget "grp1" not found. An object-list item (an Accordion group, a pop-up menu item) stores no name, so a name written on one in CREATE is not kept — address it on its widget: acc1 item@1 = acc1 item('One'). DataGrid2 columns are addressed by … Listed are the widgets `item` resolves (exactly one object list), not a list keyed `columns`, which the column hint covers by derived name. check -p and exec share the message. Control: the new test fails on main with the message above, for insert into, set and drop. Fixed, on a blank 11.12.5 app the reporter's page gives the new message at check and exec; the address it names applies and `docker check --no-update-widgets` reports 0 errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PALuhnbBpSb16e2a9A44z9
…item-address miss Two sentences in paragraphs that already held the class: a click action is spelled per type (a setter knowing one key refused every container while the catalog knew all three), and a miss's hint has to cover every unnamed kind on the page, not the first one fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PALuhnbBpSb16e2a9A44z9
Under mdl 1, any change to a free note (one attached to nothing) was refused as 'the free annotations change'. A new SetFreeNotes mutator op replaces the flow's free notes and leaves every other element as stored; create or modify applies it beside the moves and header and reports 'set: free notes'. Refs #1399. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…#1517 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…row, column)` A legacy table cell stores no name and sits at a grid position, so an alter target names it by that position, counted from 1 as describe will print it. alterTarget gains `identifierOrKeyword CELL LPAREN row COMMA column RPAREN`; CELL is a new keyword, listed among the words usable as identifiers, so a widget named `cell` still parses. The visitor carries the address as WidgetRef.Cell and spells it into Widget (`table1 cell(1,2)`), the way a navigation list item's address travels, so every operation receives it unchanged. A 0 row or column is refused. The one-number @n read now takes NUMBER_LITERAL(0) and skips cell addresses, whose two numbers are the position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
MDL-RETRIEVE02 rewrites `retrieve $u from $obj/System.owner` to `retrieve $u from System.User where [id = $obj/System.owner] first;`. That rewrite passed `check -p` and exec, then mx check failed with [CE0161] "Error(s) in XPath constraint." whenever $obj's entity does not store its owner (#1306, follow-up on mendixlabs#1358). Measured with mx check on 11.12.5: $var/System.owner and $var/System.changedBy are clean iff the root of the variable's generalization chain stores the member (own entity, FileDocument specialization, specialization of an owning root) and CE0161 otherwise (plain entity, its specialization, a create-bound variable). - validateRetrieveSystemMemberPaths types the variable (flowObjectTypes) and judges the root's flag, for microflows and nanoflows; it names the `alter entity <root> add attribute owner: AutoOwner` that fixes it. - scriptSystemMemberRoot judges an entity the same script declares from its declaration, and treats an altered one as unknown (the alter is how a user applies the fix). #641's [System.owner = ...] check now uses it, so it no longer skips the one-script shape. - MDL-RETRIEVE02's suggestion states the precondition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XD4JpQem7z5pjk2WuYRqf
`$S = create M.Entity (Name = 'x', System.owner = $User);` passed `check -p`, and exec refused it with "member "System.owner" on entity M.Entity is not a known association ... create the association first (`create or modify association System.owner from ... to ...`)" — advice no project can follow (mendixlabs#1612, #1540). The issue expected the member to be written. Measured with mx check on 11.12.5, a MemberChange with Association "System.owner" (or System.changedBy) is CE1050 "Unknown association 'System.owner'." for an entity storing its owner and one that does not, a FileDocument specialization, a specialization of an owning root, in a microflow and a nanoflow. There is nothing to write, so this is a refusal: - MDL-CHANGE01, project-free (plain check reports it) and exec-enforced, covering create, change and `set $o/System.owner`. - The flow builder refuses at the create/change call sites with the same message, for paths that skip the rule (--no-check, alter). - The suggestion is an association to System.User the project models, verified clean with mx check. Kept out of resolveMemberChange on purpose: list operations share it, and `find $l by System.owner = $u` builds clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XD4JpQem7z5pjk2WuYRqf
`create association ... to System.User` wrote the association and then exited 1: "failed to reconcile access rules of module System: load domain model 00000000-0000-0000-0000-000000000002: ... no such file or directory". reconcileModuleAccess already skips the virtual System module and has a unit test; the issue asked for an exec test. This runs the statement through exec on PedApp, with an access rule in the FROM module so the reconcile has work to do, for System.User and System.Language, and asserts check and exec agree and describe round-trips. Control: with the skip removed it fails with the reported "no such file or directory". On 11.12.5 the result is mx check clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XD4JpQem7z5pjk2WuYRqf
…wjn8 # Conflicts: # mdl/executor/cmd_flow_modify.go
…tion A legacy table cell stores no name, so an EMPTY one could not be reached at all; the widgets already inside cells became addressable by name in #1463 (#1326, mendixlabs#1453). Now: insert into table1 cell(1,2) { … } -- append to the cell replace table1 cell(1,1) with { … } -- swap its content drop table1 cell(1,2) -- empty it (the cell stays: the table's grid needs it) INSERT BEFORE/AFTER a cell is refused with the form that works. A position under a spanning cell names that cell, and a miss lists the table's cells. A cell is not a data container: widgets inserted into it bind in the context of the table's surroundings, as a navigation item sees its list's. The stored shape was taken from the modeler, not from gen: a table injected into a blank 11.13.0 app and run through `mx convert -p` (0 errors) came back as Forms$Table { Cells [2] of Forms$DbTableCell { TopRowIndex, LeftColumnIndex, Width, Height, IsHeader, Widgets [2] }, ColumnWidths [2], Rows [2], WidthUnit "Weight" }. gen's Forms$TableCell and Columns are not what Mendix 11 stores; the fixture is the converted shape. Control: the new tests fail before the change with `widget "table1 cell(1,2)" not found`; the data-context test fails without the table-cell mapping with an empty entity. On the converted table inside a data view, inserting an attribute-bound text box into the empty cell binds T.Item.Name, replace and drop act on their cells, and `docker check --no-update-widgets` reports 0 errors; main does not parse the address. The regenerated LSP completion list gains the CELL keyword. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
…root `marketplace update` (and `install`) left the package's own metadata — manifest.json, License.txt, the READMEOSS report, Mendix EULA.docx — in the app root as untracked files (mendixlabs#1487, #1344). InstallPackageFiles copied every archive entry but project.mpr and package.xml. It now installs what package.xml lists under <files>, which is what `mx module-import` installs: measured on 11.12.1 with ExternalDatabaseConnector 6.3.0 and BusinessEvents 3.12.1, mx wrote exactly the listed files and passed over a listed one the archive lacks. Entries left out are reported on one line. A package with no <files> list falls back to leaving out root-level entries only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDwYCiqWmrM3iXhnz2YeJT
MDL cannot create a legacy table, so describe prints it as one NOT re-executable line — which left the new `table1 cell(row, col)` address undiscoverable and hid which cell held which widget. The cells are now listed under that line, 1-based as ALTER PAGE takes them: -- Forms$Table (table1) -- NOT re-executable: … -- cell(1,1): tInCell -- cell(1,2): (empty) Control: without the output change the test misses all three cell lines. On the converted 11.13.0 table after replace/drop, describe prints cell(1,1): tRep and cell(1,2): (empty), matching the stored cells. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019httGxDh8UXt1Zoyh3Gh52
On Windows, `marketplace diff` and `update` failed building the reference project (mendixlabs#1486, #1343): Extracting module files into C:\Users\<user>\AppData\Local\Temp\mxdiff1185592798\target-ref The specified file name or path is too long, or a component of the specified path is too long. mx refuses to write any file whose path is 260 characters or longer, and it does so itself, so the limit holds on Linux too: measured with mx 11.12.1, 259 is written and 260 refused with the reported message. Bundled node_modules trees reach 181 characters (11.12.1 blank app) to about 202 (NanoflowCommons 7.x), and %TEMP%\mxdiff<digits>\target-ref left room for no user name at all. NewWorkDir builds references under the shortest root the user owns — %USERPROFILE%\.mxcli\t on Windows, /tmp on POSIX, or TMP/TMPDIR when shorter — with one-letter names beneath it. A drive-root folder is not a candidate: children of C:\ inherit Modify for every authenticated user. A remaining refusal names the directory, its length and the budget left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDwYCiqWmrM3iXhnz2YeJT
…ndings Re-synthesized from the 21 package-operation records in findings/cmd-mxcli/ (2026-07-31 to 2026-10-22), update.go, workdir.go, scratch.go and the marketplace guide. New beats: package.xml's <files> list is the payload contract; replacing a module is a delete that cascades into other modules' associations, and a transplant arrives unreconciled; order steps so a failure is not half an install; mx's 260-character path limit makes the scratch directory mxcli's choice. Drops the quoted finding count; covers: adds cmd/mxcli/marketplace. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDwYCiqWmrM3iXhnz2YeJT
The TestApp round-trip ratchet ("the allowlist may only shrink") failed
on this branch because 17 listed documents now round-trip:
- the 16 view-entity associations, whose describe printed a plain
`create or modify association` that exec refuses (CE6771); describe now
gives them no statement, the view's OQL column declares them;
- WorkflowCommons.ConflictedWorkflowDefinitionView, a Studio Pro-authored
view entity whose only loss was the stored OQL text that describe → exec
re-indented.
gofmt realigned the map once its longest keys were gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017jEcJZDio1jrTrWtVzagjY
…sing-issues-pve1cy Conflict in widgetNotFoundError: main added the legacy table-cell address check (#1621) where this branch added the object-list item hint. Both are kept, the cell check first, since it only fires for a cell(r, c) address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PALuhnbBpSb16e2a9A44z9
…ues-bkrdmk fix: System.owner / System.changedBy references that pass check and fail the build (CE0161, CE1050)
…ler_test TestSpliceRerun_FreeNoteLineEndings (integration, parity suite) used a reworded free note as its control for 'still refused'. Free notes now change in place (mendixlabs#1517), so the control asserts the reword is written while a line-ending-only difference still writes nothing. splice_handler_test.go was formatted with a Go 1.24 gofmt; reformatted with the 1.27.3 toolchain's, as CI's fmt-check runs it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F7x31pk37iZUX9desbsBdf
…sociations qualified `$m = find $l by System.owner = $User;` was refused at exec with advice to create a System association, though mxbuild builds it; describe printed a stored one as `by owner`, and an inherited System association over Administration.Account as `by User_Language`, which re-executed as the attribute Administration.Account.User_Language (CE1613) (#1629). Measured with mx check on 11.12.5: find/filter by System.owner or System.changedBy is clean when the generalization root stores the member (own entity, FileDocument specialization, specialization of an owning root), CE0091 "No member selected." when it does not, and System.Owner is CE1613. - resolveMemberChange resolves System.owner / System.changedBy to the System association and refuses another case with the CE1613 spelling. Create/change still refuse them first (MDL-CHANGE01, CE1050). - validateListOperationSystemMembers (reference tier: check -p and exec's pre-flight) refuses the CE0091 shape and names the alter. - extractFieldName keeps a System association qualified, and the member speller spells a find's member with the same function, so a declared find and the stored one's description compare alike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015XD4JpQem7z5pjk2WuYRqf
Resolves a CHANGELOG.md conflict at the head of Unreleased › Fixed: main added the System.owner / System.changedBy entries, this branch the two marketplace entries. All four kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDwYCiqWmrM3iXhnz2YeJT
…wjn8 # Conflicts: # CHANGELOG.md
…s-cxgna9 fix: alter settings sets ExtraJvmParameters and the Web UI client; check refuses unknown sections
…enTelemetry part `create configuration 'Staging'` on a Mendix 11.14 project was refused with "3 element id(s) are used more than once". A new configuration copies an existing one as its shape template, and from 11.12 a configuration Studio Pro has saved carries a nested OpenTelemetry part whose elements (the part and its Logs / Traces children) have $IDs of their own. The shallow copy kept them, and the duplicate-id guard refused the write. The template is now deep-copied with a fresh $ID for every nested storage object; the values are still inherited, and the sibling no longer shares sub-documents with the copy. A blank `mxcli new` 11.14 app stores OpenTelemetry = null and does not reproduce it; on testdata/testapp-views the fixed build creates the configuration and `mx check` reports the same errors as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
Studio Pro's Configuration ▸ Server ▸ Java heap ▸ Maximum size (in MB) sits beside Extra JVM parameters (mendixlabs#131). It was read and written back, but `alter settings configuration` and `create configuration` refused the key and DESCRIBE omitted it. Both statements now accept it (Integer, MDL-SET01 at check time), and DESCRIBE emits it when it is not 0 — the stored configuration has no Default/Custom flag, so 0 is Studio Pro's "Default". No version gate: the Model SDK has no versionInfo entry for maxJavaHeapSize. Measured on a blank 11.14.0 app: `mx check` reports 0 errors after setting it to 2048. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
A configuration's Extra JVM parameters — the proxy mendixlabs#131 was filed for — and its Java heap maximum are what Studio Pro passes to the runtime JVM. `mxcli run --local` and `test --local` started the JVM with a fixed argument list, so both were silently absent from every local run. The run now takes them from the same configuration it takes the constant values from (chooseConfiguration, extracted from resolveConstantOverrides, and carried on the same constantChain, so the project is read once): `-Xmx<n>m` for a non-zero MaxJavaHeapSize, then the parameters split like a shell would (a quoted run stays one argument), after mxcli's own -D flags and before -jar. It prints what it passes, without -D values, and refuses an unbalanced quote before booting. Verified on the process: booted a blank 11.14.0 app with heap 768 and `-Dmxcli.probe="from the configuration" -Dhttps.proxyPort=29758`; the runtime JVM's /proc/<pid>/cmdline held -Xmx768m, the probe as one argument and the port, all before -jar. The previous build's JVM held none of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
The LIST / DESCRIBE SETTINGS page documented `DESCRIBE SETTINGS [category]` with examples `DESCRIBE SETTINGS MODEL`, `… CONFIGURATION` and `… WORKFLOWS`; none of them parse. The forms that do are `DESCRIBE SETTINGS` and `DESCRIBE SETTINGS CONFIGURATION 'name'`. The section table now says what DESCRIBE emits for each section, in the order it emits it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014hU79xp8jYcDYXASt1GHHY
fix: describe round-trip gaps — view entity associations and XML-schema mappings
The guard that refuses rewriting a mapping sourced from an imported web service (#365) never fired on a Studio Pro mapping: gen read the source under its SDK name `ImportedWebService`, but Mendix stores it as `WsdlFile` (and an export mapping's header flag as `IsHeaderParameter`, not `IsHeader`). mxbuild's own metadata pairs each storage name with those SDK names; both pairs sat in keyaudit's known-wrong list. So describe → exec of a SOAP mapping rewrote it and dropped the binding (CE6896), and describe printed no SOURCE NOT REPRESENTABLE marker (#1631). - gen: storage-name overrides for both keys, in init and in the by-name lookup of InitFromRaw; struck from keyaudit. - roundtrip: the #365 refusal joins the harness's deliberate refusals (ADR-0012), and the three TestApp Clients.Soap* mappings, allowlisted as breaking GetPut since #743, are struck — they are now refused with nothing written. Control on those Studio Pro-authored mappings: with the gen fix reverted the harness reports "executing the describe output wrote 1 unit(s)"; with it, "refused, nothing written: … service OrdersWS, operation GetOrder". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jEcJZDio1jrTrWtVzagjY
A comment before a view entity query's first token or after its last was dropped: the stored query was the token span, and the lexer skips comments. Every describe → exec into another project lost it (#1632). The query now widens over comments between `as (` and the first token and between the last token and `)`; whitespace handling is unchanged. Measuring that on a real build showed the comment is only legal from Mendix 11.7.0. 10.24.25 and 11.6.6 report CE0174 for a comment anywhere in the query (UseOQLVersion2 on), while 11.7.0 and 11.13.0 report 0 errors. So a query that contains a comment is now refused by `check -p` and `exec` below 11.7 (MDL-VERSION01, oql_functions.comments). That also catches the comment between clauses mxcli always stored, which check passed and mxbuild then rejected. `--` inside a string is not a comment. Measured: on 10.24.25 the script is refused and nothing is written. On 11.7.0 all four comments are stored, describe → exec into a fresh project keeps 4 of 4 (pre-fix binary 0), mx check 0 errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jEcJZDio1jrTrWtVzagjY
fix: cli-contract-defects — git note loses notes to a closed stdout; docker check's help and output misstate what it does
…e1cy fix(alter page): set Action on a container; a miss names item addresses
fix: marketplace package metadata in the app root; 'path too long' under %TEMP% (mendixlabs#1487, #1486)
…references-issues-bkrdmk # Conflicts: # CHANGELOG.md
…wjn8 # Conflicts: # CHANGELOG.md
…s-cxgna9 fix: create configuration on 11.12+, run --local JVM options, MaxJavaHeapSize
fix: SOAP mapping source read under its storage key; view query comments kept and gated on 11.7
…ues-bkrdmk fix: find/filter by System.owner builds, and describe keeps System associations qualified
On 2026-10-22 a transient empty page cut the listing of existing mirrors short, and mirror.py re-created the 40 oldest upstream issues as new mirrors. When duplicates exist, it also tracked the newest mirror (the listing is newest first), so a closed duplicate shadowed the open original and upstream closures were applied to the wrong issue. - paged() asks again before treating an empty page after a full one as the end of the listing - with duplicates, track the open mirror, and the oldest of those - refuse to create mirrors (exit 1) when the listing is empty but the fork has mirrors, or more than 5 upstream issues older than the newest mirrored one are unmirrored; --allow-backfill overrides - test_mirror.py runs the scenarios against a fake API; the previous script fails the four that cover the incident Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTDRrgJhKKmSUnBFaDUw62
…wjn8 # Conflicts: # CHANGELOG.md
fix: microflow-splice refusals — error handlers, captions, notes, chained check (mendixlabs#1489, #1610, #1517)
Stop mirror.py from duplicating mirrors on a short listing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Syncs
ako/mxcli:maininto upstream: 50 commits from fork PRs ako#1617, ako#1619, ako#1621, ako#1623–ako#1628, ako#1630 and ako#1633–ako#1635, plus ako#1638 (fork tooling).Most of these work through the clusters on the fork's triage board, one commit per defect. Each has a test that fails with the reported symptom when its fix is reverted.
Fixes #131, #1486, #1487, #1489, #1490, #1549, #1610, #1623, #1627 and #1629. Addresses #610, #1358 and #1612. Refs #1453, #1517 and #1592.
Microflow splices (#1489, #1610, #1517)
Under
mdl 1,create or modify/alter microflowrefused several changes that touch only one node.mdl 1: an activity with a custom error handler cannot be changed in place —create or modifyandalterboth refuse, and each advises the other #1489). Before,create or modifyandalter … replaceeach refused the change and advised using the other.ifis set in place (MDL-V1-REBUILD refuses a create-or-modify that only adds an @caption to an existing If #1610). It used to be refused as "changes where its paths end or meet".AddNotesandSetFreeNotes.@annotationbefore@positionnow says it reads as a free note.check -ppredicts a flow statement after an earlier change to the same flow. It used to give up on statements that exec then refused.ALTER PAGE (#1453, #1592)
table1 cell(row, column). It can fill, replace and empty a cell, and describe lists a legacy table's cell addresses and contents.set (Action: …)writes a container's OnClickAction (alter page cannot change the on-click action of a container: set (Action: …) says "has no Action property", OnClick points back to Action #1592). It used to be refused as "has no Action property". A widget-name miss now names the object-list item addresses.SETkeeps the dynamicText template it hides or shows.set (ShowContentAs: attribute)on a dynamicText column left the template filled, which gave CE0463.System module references (#610, #1358, #1612)
[id = $obj/System.owner]is refused when the entity stores no owner. MDL-RETRIEVE02's own rewrite used to fail the build with CE0161.create/changeofSystem.owneris refused, with advice that applies.find/filterbySystem.ownerbuilds. Describe keeps System associations qualified, so a specialization ofSystem.Userno longer re-executesby User_Languageas an attribute.describe → exec round trips (#1623, #1627)
Modified import mappingand empty the root element and every XmlPath. Any other rewrite of such a mapping is refused, naming what it would delete.Settings and run --local (#131, #1549)
alter settings configurationacceptsExtraJvmParametersand setsMaxJavaHeapSize.run --localpasses the configuration's JVM options to the runtime.create configurationworks on 11.12+. It used to be refused for duplicate ids in the copied OpenTelemetry part, and now mints fresh ones.alter settings webuisetsOptimizedClient, and describe emits it.checkrefuses an unknownalter settingssection or key, as exec does.describe settingstakes no category, onlyCONFIGURATION 'name'.Marketplace (#1486, #1487)
marketplace install/updateno longer writes package metadata into the app root. It installs only the filespackage.xmllists. Before,License.txtandmanifest.jsonlanded in the project.marketplace diff/updateno longer fail with "path too long" under%TEMP%on Windows.CLI contract (#1490, #1629)
git note --writeno longer loses notes when the reader of stdout exits early. All notes are written before anything is printed.docker checkno longer says widgets were normalised afterupdate-widgetsfailed.docker buildonly, and check works on Mendix 10.docker checkneither downloads MxBuild nor uses Docker. Seven texts said otherwise, and the error a reader of the old docs hits now namesmxcli setup mxbuild.Docs and fork tooling
describe-round-trip-gaps,mutator-addressingandpackage-operations-damage.flowObjectTypes.types.WidgetClickActionKeys.