Repository navigation
Sync ako/mxcli: folded-decision inversion, external-action associations, marketplace update, module version/type, test-endpoint cleanup - #1739
Merged
Conversation
The hosted macOS queue is this workflow's one known runner flake: it sometimes cancels tunnel-seam-cross-platform (macos-latest) before it gets a runner, failing a PR that has nothing wrong with it. It is also the scarcest queue (5 concurrent on GitHub Free). On a PR, the Windows leg already executes the same !linux stub, so macOS added only a darwin compile. It now runs on pushes to main and on workflow_dispatch, and in a new nightly job (tunnel-seam-macos) that does not gate the release, so a darwin-only break is still caught within a day. The seam test body moves to scripts/test-tunnel-seam.sh so the two workflows cannot drift; its vacuous-run guard is unchanged (on Linux, where the !linux tests are excluded, it fails with "matched 0"). The steward skill's note on this job is updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82simPxcdrRu9PUSPcQ
…message clause (#1913) `validation feedback $E/Error message 'x'` -- what describe writes for an attribute named Error -- failed check with "missing MESSAGE": ERROR_MESSAGE is one compound lexer token, so the member name and the MESSAGE keyword after it were lexed as the `error message` clause (mendixlabs#1720). ERROR_MESSAGE now carries a left-edge predicate: it never matches right after a `/` or `.` member separator on the same line. A block comment's `*/` and a line comment ending in `.` or `/` are not separators, so the clause keeps lexing everywhere it did. gen-completions rebuilt the rule from its first line, which is now the predicate, and dropped ERROR MESSAGE from the LSP keywords; it strips a leading predicate first. Proven by stubbing the predicate to false (the reported error returns in the visitor and describe round-trip tests), by the newline-skipping draft failing the comment controls, and by checking all 1210 .mdl files in the repo with a control binary and the fixed one: identical results. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
) The left-edge predicate added for #1913 is evaluated by ANTLR at every token start, which disables the lexer's DFA cache: `check` over 300 example scripts went from 43 s to 91 s and the conformance and upgrade corpus tests hit the 30-minute timeout, while every unit test passed. On the right edge the predicate runs only once `error message` has matched (42 s vs 44 s, within noise). The character before the token is read from TokenStartCharIndex, since LA(j) for a negative j is relative to the current index. gen-completions strips the group's opening paren instead of a leading predicate, and the generated keyword list is unchanged. Re-proven on this version: stubbing the predicate brings back "missing MESSAGE", the newline-skipping variant fails the comment controls, and all 1210 .mdl files check identically to the control binary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
ci: run the macOS tunnel-seam leg on main and nightly, not on PRs
…24rqgv fix(grammar): a member named Error before `message` is not the error-message clause
On Windows `run stop` ends a detached run with `taskkill /F`, so the run's own teardown never ran and the project kept the MxTest module, its after-startup microflow, themesource/mxtest/ and javasource/mxtest/. The next build failed with CE1613 once the module was dropped (mendixlabs#1723). A crash, or the SIGKILL after stopGrace, skipped it on any platform. The run now writes a restore record before it installs anything: the original after-startup, whether MxTest pre-existed, and the project file with its document-tree digest. Remove deletes it after a clean removal. RestoreAbandonedEndpoint performs the same removal when the record's owner is gone; `run stop` calls it once the run's processes are gone, and a new --test-endpoint run calls it before capturing the project's state. TestRunStop_RestoresTestEndpointOfAKilledRun (integration, linux, mxbuild 11.12.6) SIGKILLs the detached run - what taskkill /F is - and runs `run stop`: before the fix the after-startup, MxTest and 14 files were left; after it the .mpr and every touched file are byte-identical to before the run. A binary with only the runStop call stubbed fails it again. The graceful SIGTERM stop is the control and leaves no record. The other half of #1917, page bundles 404 after `test --attach`, has a separate cause and is not addressed here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…e on rewrite (#1914) "Associations to include" on a call external action parameter had no field in the semantic model, the reader skipped it and the writer built each mapping from scratch, and MDL has no syntax for it. So a create or modify that restated the call wrote it with none, and the OData request silently left out the associated objects at runtime while check, lint and the build all passed. It is a tree, not a flag (measured on ako/TestApp, Studio Pro 11.16.0): a list of Microflows$IncludedAssociation per parameter mapping, an association ticked under another nested in it, marker 2 at both levels. The model now holds it, the reader reads it with its $IDs, the writer writes Studio Pro's shape, and a rewrite carries the stored tree onto the restated call, matched on service, action and parameter name, and only while the parameter binds the same entity. Two stored calls to one action with different trees are refused rather than guessed at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…ndex (#1917) The run stop note added for #1917 took the body to 701 lines (TestLargeSkillsWereSplit) and left the section index stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…pendency change (#1920) UpdateModuleSettings rebuilt the Projects$ModuleSettings unit from the nine keys mxcli models, and the write path filled the rest with defaults: a jar dependency change wiped PackageId (Studio Pro's Module ID) and a Marketplace module's Checksum, and switched detailed troubleshooting on. The write now starts from the stored unit and overwrites only the modelled keys, so what mxcli does not model — including keys Studio Pro adds later — keeps its stored value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…e type (#1921) Measured on Mendix 11.16: the module type is ExportLevel (Source = App, Protected = Add-on; ProtectedModuleType is AddOn on every module), the version is ModuleSettings.Version, and Location is Projects$ModuleImpl.FromAppStore. Proposes a property list on create module and alter module set, describe printing the non-default settings, and Location as a later key. Supersedes the read-only show-describe-module-settings.md, whose storage notes were wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…ssociations fix(microflows): keep a call external action's associations to include on rewrite (#1914)
fix(modules): keep the module ID and Marketplace checksum on a jar dependency change (#1920)
…1921) The General tab of Studio Pro's Module settings dialog, as a property list on create module and alter module set: create or modify module Inventory (Version: '2.3.1', ModuleType: addon); alter module Inventory set (Version: '2.4.0'); describe module prints the settings that differ from a new module's (App, 1.0.0) and the location as a comment; list modules gains Version and Type columns. The type is ExportLevel (Source = App, Protected = Add-on), measured on 11.16 — ProtectedModuleType is AddOn on every module. Version must be SemVer, the type app or addon (9.12+, gated); check and exec refuse the same statements, and restating the stored settings writes nothing. Writes go through UpdateModuleSettings, which since #1920 keeps the module ID and checksum. A second `create or modify module` in a script is no longer MDL-DUPDEF, since it now applies settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82ttaGzay5CwiC2V7cf
…rioritization-24rqgv # Conflicts: # CHANGELOG.md
…24rqgv fix(run): run stop removes a --test-endpoint the run could not
After a green `mxcli test --attach` against `run --local --test-endpoint`, the app answered 404 on dist/pages/*.js and every page showed the generic error dialog until it was restarted (mendixlabs#1723). The attach built through the dev loop's mxbuild --serve. Its builds are never that process's first, and on the prebuilt-client Mendix versions a later build replaces web/dist with a bundle that has no page modules (mendixlabs#1580). The dev loop's own reloads recover through serveRecovery by restarting their serve process; the attach called /build directly and got the defect without the recovery. docker.AttachedServe runs the attach's builds through the same serveRecovery, over a process whose Restart starts a private mxbuild --serve on a free port rather than touching the dev loop's, which keeps its own recovery for its next build. The attach stops the private one when it ends. TestTestAttach_KeepsTheHostingAppsPageBundles (integration, linux, mxbuild 11.12.6) GETs a page module the boot produced (200 before the attach): on main it answers 404 afterwards with 0 page modules left; with the fix, 200. A binary whose AttachedServe.Build bypasses only the recovery fails it again. Unit tests: the host's serve is never restarted, the private one takes the cleanup build and is stopped on Close, and a complete host build starts nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
feat(modules): describe and set a module's version and module type (#1921)
…24rqgv fix(test): --attach no longer leaves the hosting app's pages 404
…1934) Every `marketplace update` failed with "open package target.mpk: no such file or directory" after it had dropped the installed module and copied in units, leaving the project half-updated (mendixlabs#1732). The update spelled the package path out as work/target.mpk while referenceFor(…, "t") downloads to work/t.mpk. referenceFor now returns the path it downloaded to, and the update uses it, so the two cannot drift. And PerformUpdate opened the package only after the destructive steps. preflightUpdate now checks, before the first write, that the reference project opens and holds the module and that the package opens; a failure there is ErrUpdateNotStarted, reported as "nothing was changed" rather than "the project may be mid-update". TestPerformUpdate_RefusesBeforeDroppingWhenAnInputIsMissing hashes every file of a fixture project: on main a missing package or reference project changed it (the reported error, after the drop); with the preflight stubbed it fails again. The existing PerformUpdate/PerformInstall tests are the control with valid inputs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…24rqgv fix(marketplace): update no longer drops the module and then fails
…#1930) describe prints a decision whose true path goes straight to its merge, and whose false path holds the activities, folded: `if not(X) then <false path>`, with the paths swapped. Fed back through `create or modify` with only the condition changed, the in-place condition edit (#888) stored the printed `not(Y)` as the decision's expression while its flows stayed: the decision was inverted, and check, exec ("edited in place") and diff all looked clean (mendixlabs#1728). splitCondition now negates the stated condition back when describe prints the decision folded. decisionPrintedNegated decides that from the stored flows with describe's own merge computation, not from the text: describe also strips a stored not(Z) to Z. negateExpression, extracted from negateIfCondition, is its own inverse, so printed not(Y) stores Y and printed Z stores not(Z). TestCreateOrModify_FoldedDecisionKeepsItsMeaning runs the reporter's flow on a pedapp copy: describe, change only the attribute in the printed condition, exec under mdl 1. Both fold shapes kept the decision's $ID and store the un-negated expression; with the negation stubbed both fail with the inversion. A decision in a loop body is refused by the splice, not inverted (second test). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oK82qrr1WnXxq1eRn7qRJ
…24rqgv fix(microflows): a condition edit no longer inverts a folded decision
sergiusz-woznicki
pushed a commit
to sergiusz-woznicki/mxcli
that referenced
this pull request
Nov 5, 2026
fix: a constant in an XPath constraint — parse it, refuse it (CE0161), stop losing it (mendixlabs#1685)
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: 12 commits since #1722 — 5 upstream issues addressed, module settings in MDL, and a CI change for the macOS runner flake.Microflows: rewrites that silently changed behaviour
if not(X) then <false path>. Fed back throughcreate or modifywith only the condition changed, the in-place edit stored the printednot(Y)while the flows stayed, inverting the decision — and check, exec and diff all looked clean. The stated condition is now negated back when describe printed it folded, decided from the stored flows rather than the text. A decision in a loop body is refused, not inverted. Fixes create or modify microflow inverts a decision when only its condition changes: describe folds it to "if not(X)", the in-place edit stores not(X) literally #1728Microflows$IncludedAssociationper parameter mapping, nestable) had no field in the model, so restating the call wrote none and the OData request silently left out the associated objects at runtime. It is now read and written in Studio Pro's shape, and a rewrite carries the stored tree onto the restated call, matched on service, action and parameter name and only while the parameter binds the same entity. MDL syntax to set it is not added. Refs CALL EXTERNAL ACTION — no MDL syntax for IncludeAssociations flag #1721Grammar
Errorbeforemessage(validation feedback $E/Error message 'x', what describe writes) no longer lexes as theerror messageclause. The fix is a predicate on the compound token, placed on its right edge so the lexer's DFA cache stays on (a left-edge version doubledchecktime over 300 scripts). All 1210.mdlfiles in the repo check identically to a control binary. Fixes roundtrip for validation feedback on member named 'error' does not work as expected #1720Marketplace
marketplace updateno longer drops the module and then fails. It looked for the package attarget.mpkwhile the download wrotet.mpk, and opened it only after the destructive steps, leaving the project half-updated. The download path is now returned rather than re-spelled, and a preflight checks the reference project and the package before the first write; a failure there reports "nothing was changed". Fixes Unable to update marketplace module #1732Modules
UpdateModuleSettingsrebuilt the unit from the keys mxcli models, soPackageIdandChecksumwere wiped and detailed troubleshooting switched on. The write now starts from the stored unit and overwrites only the modelled keys.list modulesgains Version and Type columns. Measured on 11.16: the type isExportLevel(Source = App, Protected = Add-on). Version must be SemVer; the type is gated to 9.12+. Proposal included.run --local --test-endpoint / test --attach
run stopremoves a test endpoint the run could not. On Windowstaskkill /Fskipped the run's teardown, leaving MxTest, its after-startup microflow and its theme/java folders, and the next build failed with CE1613. The run now writes a restore record before installing anything, andrun stop(or the next--test-endpointrun) restores from it when the owner is gone.test --attachno longer leaves the hosting app's pages 404. The attach built through the dev loop'smxbuild --servewithout its recovery, and a later build there replacesweb/distwith a bundle that has no page modules. It now builds through the same recovery on a private serve process.Together these Fix #1723.
CI
The macOS tunnel-seam leg runs on pushes to main, on dispatch and nightly, no longer on PRs: the hosted macOS queue sometimes cancels it before it gets a runner, and on a PR the Windows leg already exercises the same
!linuxstub. The seam test moves toscripts/test-tunnel-seam.shso the two workflows can't drift