Repository navigation
Sync ako/mxcli: marketplace package and search --exclude-marketplace (#1383, #1493); MCP alter page in folders (#1593) - #1607
Merged
Merged
Conversation
…es (#1477) An audit of the app's own text reported a vendor module's text beside the project's. The flag drops hits whose module was downloaded from the Marketplace, a module's own documentation included. It is off by default and the SEARCH statement is unchanged. Which modules are Marketplace modules is read from the current snapshot only, so a module that was one in an older snapshot is not left out of every later search. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… a list The hand-written list of document types would drift as the objects view grows; "every element the catalog records" stays true. Suggested in review of #1478. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) Wraps `mx create-module-package` (-l by default, --all-libs to bundle every JAR), the reverse of `marketplace install --file`. Warns on stderr about other modules' resources/javasource/themesource files in the package, with the plain-dot --exclude that drops them. mx writes into the project (measured), so it runs on a temp copy. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… review follow-ups (#1383) ResolveMxForVersion prefers an mx on PATH and falls back to any cached one, so the package could silently be made by another Mendix version than its app. mxcli now reads the version of the mx it found (mx.deps.json beside it, else its version-named folder) and refuses a different major.minor.patch, or an mx whose version it cannot tell, naming both versions and the fix. --mxbuild-path is the override: a mismatch then only warns on stderr; a path that does not exist is an error rather than a quiet fall back to PATH. Also: mx's output on a successful export goes to stderr; the context reaches mx (exec.CommandContext); the printed --exclude is quoted for a POSIX shell; an output directory inside the project is not copied into the temporary copy; the unused inspectPackage is dropped. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ALTER PAGE over the MCP backend failed for every page inside a folder: failed to open page for mutation: module not found: <uuid> The uuid was the page's parent folder. resolvePageUnit passed page.ContainerID straight to GetModule, which only holds for a page at the module root. The backend already had the folder-aware answer, moduleNameForContainer; the page mutator now uses it, for saved pages and for pages created this session. The same direct lookup sat in UpdateConstant and UpdateWorkflow (CREATE OR MODIFY on a foldered constant or workflow failed the same way) and in forgetSessionConstant / forgetSessionEnum (DROP of a foldered document left it registered). Those now resolve through the same helper. Control: with the production change stashed, page_mutator_folder_test.go fails with "OpenPageForMutation: module not found: fPages" plus the three sibling failures; the module-root case passes either way. Fixes mendixlabs#1593 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZCjbSMETkeDrr8bHi6LCD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZCjbSMETkeDrr8bHi6LCD
…ions (mendixlabs#1498) Point 2 of the 2026-10-16 follow-up on #1498: `check -p --references` reports CE5400 for an `export level api` microflow exposing a Hidden entity of a Protected (add-on) module, but MDL had no way to make the entity Usable. `create persistent entity Shop.Order (...) export level api` failed with "extraneous input 'export' expecting the start of a statement" (reproduced on main), and attributes, associations and enumerations had no clause either. check also missed CE5400 for a Hidden enumeration. The microflow's `export level api|hidden` clause now goes on create entity / view entity / each attribute / create association / create enumeration, and `set export level` on alter entity / association / enumeration and modify attribute. An absent clause keeps the stored level. The converters write the semantic level (Hidden when unset), and the #801/#816 carries stand down for an authored one. Reads fill Attribute / Association / CrossModuleAssociation / Enumeration ExportLevel, describe prints `export level api` (Hidden omitted), and the clause is gated at 9.3.0 (DomainModels exportLevel and Projects Document.exportLevel, mendixmodelsdk 4.116.0). The Protected-module check takes a level stated anywhere in the script over the stored one, checks enumerations for CE5400, and its hints name the alter statement. The MCP backend refuses a level PED would drop. Measured on blank 11.14.0 apps with the module set to Protected: - API microflows exposing a Hidden entity and enumeration: CE5400 x2; after `alter ... set export level api`: 0 errors. - Another module changing a Hidden attribute and retrieving over a Hidden association: CE1406 x2; with `export level api` on both: 0. - The bug-test file: 0 errors; with its clauses stripped: CE1406 x4. - Ordinary module with API levels: 0 errors. - describe -> exec round-trips all four, `create or modify` without the clause keeps API, and the alter forms set Hidden back. Controls: with the backend changes reverted, the write tests store "Hidden" for an authored API (the reported symptom). With the validator and describe reverted, their tests fail. With the visitor's entity clause stubbed, the parse test reads nil. Not covered: check does not yet predict CE1406 for a Hidden attribute or association used from another module (it judges entity, microflow and page targets). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT
…lements by rule, not by a list Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
…her Mendix version, and review follow-ups (#1383) CHANGELOG.md conflict resolved by keeping both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
fix(mcp): resolve a foldered document's module through its folder chain
…e to see the list mendixlabs#1493 replaced the hand-kept list of document types in `search --help` with "every element the catalog records", which claims too much: role mappings, references and other catalog rows carry no documentation. It now reads "every element that has documentation" and names the commands that show the full list (the catalog tables with a Description or Documentation column). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
mendixlabs#1383 added the package section and moved the ones after it. Regenerated with scripts/skill-index.py (make build). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
Integrate wave 3 of the upstream PRs (mendixlabs/mxcli #1493 #1383), with review follow-ups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QiMsnXa9crge2qnSk9S7Zn
A `@curve` on a statement inside a `loop` or `while` body passed check and exec and was not stored; `describe` printed the body without it, while the same annotation after the loop was kept. The body is built by its own flowBuilder, which recorded the curve, and the loop hoisted that builder's flows to the parent without the curves that belong on them. applyFlowCurves runs once, on the builder that owns the flows, so the body's curves were never applied. The error-handler builder had the same merge (#991); it is now one helper, adoptCurves, which the loop, while and error-handler merges all call. Refs #1507 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjYj5GTj2in3ckFYaDBAuN
…ent entity A specialization stores no Persistable flag — its Generalization element has no such property; the flag lives on the root's NoGeneralization. entityFromGen defaulted it to true and never revisited it, so `describe entity` printed `persistent entity Probe.Child extends Probe.Base` for a child of a non-persistent Probe.Base, and the same wrong flag reached the bulk `where non-persistent` filter, the catalog, the diagrams and the microflow builder. The System module's HttpRequest/HttpResponse/SoapFault read persistent for the same reason. The domain-model reads (ListDomainModels, GetDomainModel, GetDomainModelByID) now resolve each specialization's flag by walking its generalization chain across every stored module and the virtual System module. entityUnchanged takes the statement's value for a specialization, since the resolved flag is not stored on the element and comparing it with the raw default would rebuild every such entity on each domain-model write. Fixes #1510 (mendixlabs#1600). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KjZvGAo8FZaqUbDAd2SdsH
…#1597) `@annotation('Why this commit is here.')` in an `alter microflow … insert` fragment passed check and exec ("Altered microflow") and no note was written; the same line in `create or modify microflow` is refused as MDL079. The annotation rules — MDL059, MDL060, MDL079, MDL092 — ran over create bodies only. A fragment is built by the same flowBuilder, which drops an annotation the visitor could not read, so all four reached the builder unchecked in an alter. check now runs them over every insert and replace fragment, and execAlterFlow refuses the exec-enforced subset as create does, for `-c` and the REPL, which skip the check preflight. Refs #1507 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjYj5GTj2in3ckFYaDBAuN
A quoted attribute segment in DynamicClasses, DynamicCellClass or a pluggable widget's Expression-typed property was stored with its quotes, $currentObject/"Code", while ContentParams and Visible stored $currentObject/Code. check passed; mxbuild reported CE0117 at the widget. Every widget slot that stores expression text now strips identifier quotes, as the microflow expression slots do. The mdl 0 read-back check compares against the stripped text, so the quoted-expression rewrite is still offered. Fixes #1489 (mendixlabs#1584). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEg7VrNNsoTxh9QXviwYgU
retrieve $Notes from M.Note where [IsOpen = true() and Count > 0]; was stored as [IsOpen = true() and Count > 0]. The visitor kept the source; the shared XPath formatter sent every constraint with a line break through the #979 canonical layout, which renders a short one flat. A constraint that already holds a line break is now the author's layout and is stored as written (operator case still folded). A flat constraint is laid out as before. Describe prints a stored constraint on one line only when its layout is the one the writer derives; an authored layout is printed as stored, for retrieves and access rules alike, so describe -> exec stores it again. Fixes #1440 (mendixlabs#1542). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEg7VrNNsoTxh9QXviwYgU
…lkTypedFlow) checkFlowMembers carried the only walk that types a flow's variables for the --references checks (parameters, create, database and association retrieves, loop iterators, nested blocks and error handlers). The Protected-module member check needs the same typing, and a second copy would drift on which statements type a variable (the duplicate-resolver-drift class), so it becomes walkTypedFlow with a visit callback. visit runs before a statement's own output is typed, which is the order the old inline checks relied on. No behaviour change: the member-reference tests pass unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT
…dule (CE1406, mendixlabs#1498) `check -p --references` passed a flow in an ordinary module that used a Hidden attribute or association of a Usable entity in a Protected (add-on) module. mxbuild refuses it: "… is not allowed to use attribute 'AddOn.Request.Payload' because app modules cannot reference hidden elements in add-on modules" (CE1406). checkFlowMembers resolves the members a flow uses, over walkTypedFlow: - change / create members (attributes, through generalizations, and associations) - association retrieves - XPath steps of a database retrieve - `$v/…` expression paths in return, declare, set, decision, while, log, call arguments and member values It reports CE1406 when the member's module is Protected, the flow's is not, and the member is Hidden. The level is the one the script states, else the stored one, else Hidden for a member the script creates. The hint is the alter statement that makes the member Usable, with the stored type restated. A use it cannot resolve is silent. Measured on 11.14.0, one microflow per shape: all nine shapes are CE1406 while the member is Hidden. The Usable controls, use inside the add-on, and the whole script in an ordinary module give 0 errors. check now reports the same nine (4 attribute, 5 association) and nothing for the controls. After the two hinted alters, check passes and mxbuild reports 0 errors. The new bug-test: 0/0 as written; with its clauses removed, 8 CE1406 from check and from mxbuild. Control: with checkFlowMembers stubbed, all 14 refusal cases of TestValidateProtectedModuleRefs fail with no error reported, the reported symptom. Not covered: page widgets binding a Hidden member. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT
return $Parent/Mod.Child_Parent; passed check --references and was CE0117 at the end event; loop $c in $Parent/Mod.Child_Parent was written with no list (CE0099), because the visitor read only a bare variable and dropped the path the grammar accepts. MDL049 now covers the return value of a microflow or nanoflow, with its existing exemptions (the target-entity step builds clean, measured), and MDL094 refuses a loop over any path. The loop path is kept in the AST instead of being dropped, and MDL094 is exec-enforced since the builder has nowhere to store it. Fixes #1231 (mendixlabs#199). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEg7VrNNsoTxh9QXviwYgU
…ssing name, describe the qualified one A Custom chart's `eventDataAttribute: EventData` inside a data view over a page parameter whose entity has no EventData passed check and exec and only mx check reported CE1613. misboundAttributeError refused a bare name only when another entity in scope had it; a name no entity has is now refused too, by check and exec alike. Bound to another entity (MyFirstModule.ChartContext.EventData), the property was stored qualified but described bare, so re-running the description rebound it to the data view's entity. The generic pluggable describer now keeps the qualified name for an unlinked attribute of another entity, and a data view over a page or snippet parameter puts the parameter's stored entity in scope rather than its name. Mirror of mendixlabs#1591 (#1502). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SiV1dB1yMWeXnjFhWFDSvg
…ociation (mendixlabs#1599) DESCRIBE PAGE printed a gallery whose "Database" source runs over an association as `$currentObject/Assoc` with no `sort by` and no `where`, and `create page` refused the faithful `database from $currentObject/Assoc/Entity` form for anything but a list view. Studio Pro stores that source as a CustomWidgets$CustomWidgetXPathSource with an IndirectEntityRef, its XPath and sort bar beside it. The reader treated it as an association source (the #941 reading), which drops both and replays as a Forms$AssociationSource — a different retrieve. - Reader: a pluggable XPath source with complete hops reads through parseEntityPathSource, as the list view source already does; a hop without a stored destination keeps the association reading. - Writer: on 10+ buildPluggableDataSourceV3 builds the form and customWidgetDataSourceToGen stores the hops as an IndirectEntityRef with the start parameter in SourceVariable (9.x keeps the #1399 database source). Widgets with their own builder still refuse it in buildDataSourceV3. Measured on 11.12.1: the reporter's shape authored in MDL, mx check 0 errors, describe -> exec "Unchanged page"; with the association byte-patched to a nonexistent name mx check reports CE1613 at Gallery 'g1'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hjeuk6NPBWq3QTxCKxsARF
…by key (mendixlabs#1586) DESCRIBE PAGE omitted expression-typed (and other) settings of the widgets with a dedicated describe reader: a combo box's customEditability / customEditabilityExpression / ariaRequired, a text or number filter's defaultValue expression and delay. Exec wrote them; describe -> edit -> exec reset them. The report's own case, a generic pluggable widget's top-level expression with a false MDL-WIDGET06 warning, reproduces only on the binary before mendixlabs#1578 and is already fixed on main. - The combo box and the four data grid filters now run the by-key reader (mendixlabs#1573) beside their keyword reader, skipping the keys it already prints. - Values are compared with what exec writes for an absent key (the embedded template), not the schema DefaultValue: the combo box template stores readOnlyStyle `bordered` against a default of `text`, so Studio Pro's combo boxes (Administration.Account_Edit) lost `text` on an edit-replay. - A combo box's database/static-mode settings, a mode DESCRIBE does not spell, are named in a NOT re-executable note instead of printed. - `check` without -p tops the hand-crafted definitions up from the embedded template, so describe output passes it as it does with -p. Corpus diff against a baseline build over the Blank 11.12.1 app: only the intended lines change, every description replays "Unchanged", mx check 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hjeuk6NPBWq3QTxCKxsARF
…bs#1520) The snippet half of the report: a data view sourced from a snippet parameter described without its DataSource. Already fixed by the snippet-parameter slot read (#721 L3); retested on 11.12.1, describe prints `DataSource: $View` and replays "Unchanged snippet". The page half was fixed by #1416. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hjeuk6NPBWq3QTxCKxsARF
…ame (mendixlabs#1588) `create java action` had no way to set a parameter's description or the return value's name. `describe` printed both as `--` comments (`Input: String not null -- The text to convert.`, `-- return NAME: 'UpperText'`), which read like syntax: written in a script they passed check and exec and were dropped, leaving the description empty and the return name `ReturnValueName`. Both now use the spelling the language already has for the same thing elsewhere: - a `/** … */` doc comment before a parameter is its description, as on an entity attribute; - `returns T as $Name` names the return value, as on a microflow. Java and JavaScript actions share these grammar rules, so both visitors read them through one helper and both describers print them through one emitter; describe output now re-executes as "Unchanged". On `create or modify` an omitted description or name still keeps what is stored. A multi-line description, of which the `--` form printed only the first line, now round-trips whole; one holding `*/`, which a doc comment cannot carry, is still shown as a comment so the output parses. Refs #1496 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HjYj5GTj2in3ckFYaDBAuN
Ported from #1527 so this PR's build-and-test can go green: govulncheck fails on crypto/x509@go1.27.2 (GO-2026-6809, fixed in 1.27.3), reached through internal/marketplace/client.go. main is red on the same check. Identical change; it no-ops once #1527 lands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hjeuk6NPBWq3QTxCKxsARF
govulncheck now fails build-and-test on Go standard-library advisory GO-2026-6809: "Distrust compromised intermediate certificates in crypto/x509", found in crypto/x509@go1.27.2 and fixed in go1.27.3. The reachable trace is marketplace.Client.Download -> io.Copy -> x509.Certificate.Verify. main pins go1.27.2, so every PR is red on it (first seen on #1519). Toolchain go1.27.3 in go.mod and in the workflows' setup-go. The go directive stays 1.26.0. The devcontainer needs no change: it sets GOTOOLCHAIN=auto, so go.mod's toolchain line decides. govulncheck with go1.27.2: "affected by 1 vulnerability" (GO-2026-6809). With go1.27.3: "affected by 0 vulnerabilities". make build, make test and make lint pass on go1.27.3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HxAn3VqxUnZ7ZGUnzAYpbT (cherry picked from commit a3b33a8)
… brackets A Studio Pro constraint can end in a line break (WorkflowCommons' WorkflowUserTaskView rule). Described as stored, it failed IsBracketedXPath and fell back to the deprecated quoted form, which broke TestStringLiteralsRoundTripUnderMdl1 on TestApp. Whitespace outside the brackets is now trimmed, as flattening always did. WorkflowCommons.WorkflowAttachment and WorkflowComment stay on the TestApp allowlist: their stored constraints end in a line break too, and since a rule is keyed by role plus constraint text (#936), the trimmed spelling adds a rule beside the stored one, as the flattened one did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEg7VrNNsoTxh9QXviwYgU
Ported from #1527: govulncheck fails every build on the crypto/x509 vulnerability fixed in go1.27.3, on main as on this branch. No-ops once #1527 is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PEg7VrNNsoTxh9QXviwYgU
fix(deps): keep the klauspost/compress floor across go mod tidy
fix: silent-property-drop cluster — loop @Curve, alter annotations, Java action descriptions
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
fix(executor): check a flow's use of Hidden members of a Protected module (CE1406, mendixlabs#1498)
Brings in #1527 (Go 1.27.3), which makes this branch's cherry-picked copy of the same bump a no-op, and resolves the CHANGELOG conflict: main moved the Unreleased "Fixed" entries into a second block, so the resolution is main's side plus this branch's one new entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KjZvGAo8FZaqUbDAd2SdsH
fix: describe round-trip gaps on pages (gallery sort over association, by-key combo box / filter settings)
…ig.yaml (mendixlabs#1509) QUAL004 (orphaned elements) hard-coded its entry-point prefixes and CUSTOM002 (microflow prefix convention) its valid prefixes, and `mxcli init` rewrites the shipped rule files, so a project with its own naming convention could not keep an edit: the reporting project got 84 QUAL004 and 121 CUSTOM002 findings for TEST_/GET_/PRS_ microflows. Both rules now read an option - rules.QUAL004.options.entry_point_prefixes and rules.CUSTOM002.options.valid_prefixes - as a YAML list or comma-separated text. A configured list replaces the built-in one; unset, the built-in list applies as before. Underneath, goValueToStarlark converted scalars only, so any YAML list or map under a rule's options reached the rule as None, indistinguishable from "unset". Lists and string-keyed maps now convert recursively. A new get_list_option(key, default) builtin reads a list of strings in either spelling. An option value a rule cannot use is recorded and reported after the run as a warning naming rules.<ID>.options.<key> (RuleFailure, so it stays out of the score) while the rule runs on its default. QUAL004 still counts only callers in the model; a microflow called only from tests/*.test.mdl is reported, and its prefix belongs in the option (maintainer decision). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
fix: binding-context cluster — pluggable attribute scope, control-bar SHOW PAGE selection
fix: check-references cluster — move/rename targets, page XPath script members, ALTER PAGE column targets
… properties (mendixlabs#1511) A snippet call renders no element of its own: the snippet's widgets are inlined into the parent, so the Class, Style, DynamicClasses and design properties stored on a Forms$SnippetCallWidget never reach the DOM. check, exec and mx check were all clean, so the setting was silently useless. Measured on Mendix 11.15.0 (run --local + playwright check): a snippetcall with Class 'probe-x', Style 'border: 3px solid red', DynamicClasses 'probe-dyn' and 'Align self' / 'Hide on' produced no element carrying any of them (the snippet's container was a direct child of the enclosing container), while a container on the same page with the same four settings carried every one. - MDL-WIDGET48 (check, warning): in the widget-tree walk for CREATE PAGE / SNIPPET and ALTER PAGE INSERT / REPLACE; and in the reference pass for `alter page ... { set (Class|Style|DynamicClasses|<design prop>) on sc }` and `alter styling ... widget sc set ...`, where the stored widget's $Type comes from the page mutator. Clearing a value stays silent. - MPR013 (lint, correctness/warning): catalog Class/Style/DynamicClasses, plus design properties read from the stored document. - Docs: lint rule table, create-page skill + widget reference, docs-site widget types, `syntax snippet` help. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
`create workflow … call workflow M.Child … boundary event interrupting timer …`
failed to parse ("mismatched input 'boundary' expecting ';'"), although the
reader, writer, describer, ALTER mutator and MCP backend all handle
Workflows$CallWorkflowActivity.boundaryEvents (10.14+, the same floor as every
other owner). DESCRIBE printed the clause for such an activity, so its output
did not re-parse.
workflowCallWorkflowStmt now takes call microflow's exact boundary-event clause
(no new tokens), the visitor fills a new BoundaryEvents field on
WorkflowCallWorkflowNode, and buildCallWorkflowActivity writes them through
buildBoundaryEvents.
The AST walkers each switched on the boundary-event owners themselves and none
knew call workflow, so WF07/08/09/10/15/18/19, the rewrite guard's count and the
11.11 notification gate would have skipped the new bodies. A single helper,
workflowActivityBoundaryEvents, now lists the owners; the two walkers that label
by owner (WF15, WF19) gained the case. On the stored side, ALTER's end-ancestry
walk lost the non-interrupting context under a call workflow and MDL-WF05 did
not see jump targets inside its boundary body; both gained the case.
Measured: interrupting and non-interrupting timer boundary events on call
workflow, mx check 0 errors on 11.6.6 and 11.15.0; describe -> exec "already in
sync" on both. A notification boundary event on call workflow is 0 errors on
11.15.0 and refused by the existing 11.11 gate on 11.6.6.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…d on (mendixlabs#1518) An object created with commit = No exists only in memory. If the microflow never commits it, returns it or hands it to anything that could, it is discarded when the microflow ends - and check, mx check and the build are all silent. In the field an after-startup seed microflow logged "Seeded 20" and the table had 0 rows. CONV020 (warning, category quality) walks each microflow's stored object graph via FullMicroflow, like CONV011. It reports a CreateObjectAction with an explicit Commit = No whose entity the catalog lists as persistent, when nothing else in the flow uses the output variable except to read a member ($o/Attr) or change it without commit. Every other mention counts as passing the object on: the walker scans every string of every object in the flow (loops and error-handler paths included) by reflection, so a field holding the variable name (commit, delete, rollback, page passed object, workflow context, export mapping source, ...) or a bare $o in any expression (return value, call arguments, list change, association value) keeps the rule quiet, including action types the rule does not know. It is flow-insensitive on purpose: a commit on one branch only is an accepted false negative. Nanoflows, rules, non-persistent entities, an unstored commit value and System/Marketplace modules are out of scope. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
… transformers (mendixlabs#1510) lint QUAL002 asks for documentation on import and export mappings, published REST services and data transformers, and MDL could not write it: the four create statements had no Documentation field, so the `/** ... */` doc comment above them was dropped with MDL089 and the findings were permanent. Two more defects kept them that way: - every create or modify wrote an empty Documentation over the stored text (the executors never set it; the data transformer writer wrote a literal ""), so describe -> exec of a Studio Pro-documented mapping or transformer deleted its documentation; - the catalog wrote "" for published_rest_services.Documentation, so QUAL002 reported every published REST service, documented or not. The doc comment is now each statement's documentation, as on a JSON structure: the visitor reads it with its presence bit, the executors set it and carry the stored text when no comment is written (#1018), the modelsdk backend reads and writes the top-level `Documentation` key for published REST services and data transformers (verified against modelsdk/gen and against Mendix's own reader with `mx dump-mpr` on 11.6.6 and 11.15), describe prints it back, and the catalog stores it. PublicDocumentation (the OpenAPI text) keeps being carried as stored. Java action parameter descriptions were already writable (mendixlabs#1588); the bug-test script covers them alongside. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
… create (mendixlabs#1510) A doc comment above a create that stores no documentation was warned with "Move the doc comment directly above `create json structure ...`, after the `create or modify published rest service ...`" -- moving text written for one element onto a different one. The next-statement suggestion is right when a drop, grant, revoke, set or alter stands between a comment and its create (#877), but a create is itself the element the comment describes. For a create, MDL089 now says MDL cannot store documentation for that element and suggests a `--` comment; the move suggestion stays for the other statements. The check-syntax skill says the same (and no longer lists `create module`, which stores documentation since #1314). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
fix: describe prints persistent for a specialization of a non-persistent entity
…-events feat(workflow): boundary events on call workflow (mendixlabs#1532)
…e-warning feat(check,lint): warn when a snippet call carries Class/Style/design properties (mendixlabs#1511)
…ver-persisted feat(lint): CONV020 — object created in a microflow and never committed, returned or passed on (mendixlabs#1518)
Resolve the CHANGELOG conflict with #1532 (CONV020) by keeping both "Added" entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…ings-rest-javaparams fix(mdl): document import/export mappings, published REST services and data transformers (mendixlabs#1510)
…ixes feat(lint): configurable QUAL004 entry-point and CUSTOM002 prefixes (mendixlabs#1509)
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: 8 commits from fork PRs ako#1501 and ako#1517.Integrated contributor PRs (ako#1517)
Both features are approved. The contributor's commits (@stagknee) are kept unchanged, so GitHub should mark the PRs as merged when this lands.
mxcli search --exclude-marketplaceleaves out hits in Marketplace modules. It is off by default (#1477). The MDLSEARCHstatement is unchanged.mxcli marketplace package <Module>exports a module as a.mpkthroughmx create-module-package(#1382)What #1383 adds over calling
mxdirectly:mxon a temporary copy, so the project isn't changed.mxwritestheme-cache/,deployment/sass/and the module'sthemesource/into whatever project it's given.mxof a different Mendix version than the project's.--mxbuild-pathoverrides this, with a warning.resources/,javasource/orthemesource/files that belong to other modules, and prints the--excludepattern that drops them.<Module>.mpkinto place in one step, mapsmxexit codes to readable messages, and has--jsonoutput.Follow-ups on top:
search --helpnow says "every element that has documentation", not "every element the catalog records". It also names the commands that show the full list.MCP backend: documents in folders (#1593, ako#1501)
alter pageover the MCP backend now works for a page inside a folder. It used to fail withmodule not found: <uuid>, because it looked up the page's container, which is the folder, as a module.create or modifyof a constant in a foldercreate or modifyof a workflow in a folderdocs-wiki/bug-patterns/duplicate-resolver-drift.md.Validation
go buildandgo vet(Linux and Windows) are clean.