Repository navigation
Sync ako/mxcli: references to missing members, reserved and inherited names, constants in XPath, workflow notes - #1661
Merged
Merged
Conversation
…s it on re-render (#1685) `retrieve $Items from Shop.Item where [Total > @Shop.C_Limit];` failed with "mismatched input 'Shop' expecting ']'", which reads as a gap in MDL. Three silent losses sat behind it: a data source written `where Total > @Shop.C_Limit` stored `[Total > ]`; describe of a stored constraint holding a constant, on an entity with an enumeration attribute, printed `where Total > @;`; and a long one written in the quoted form was laid out and stored as `[Total > @]`. Cause: the XPath grammar had no constant. `@` was admitted by the negated xpathWord set as a one-word name, so the strict parse failed at the module name, and ParseXPathConstraint (error listeners off) recovered past it and returned ok with an attribute called "@" — every re-render of that parse (enum enrichment, FormatXPathConstraint, check's member walk) dropped the constant. The page-side xpathExprToString had no ConstantRefExpr case and rendered "" for the expression-grammar form. The issue expected the constant to be stored and built. Measured, mxbuild rejects it: on 11.13.0, each case alone in a fresh app, CE0161 "Error(s) in XPath constraint." for an Integer, String and Boolean constant in a retrieve, in a list view's database source, in an access rule (production security — with security off mx check validates no access rule, a garbage `[Total >]` passes) and in a user task's targeting; an unknown constant is the same CE0161, not CE1613. The retrieve is CE0161 on 11.15.0 too. The control, `declare $Limit Integer = @Shop.C_Limit;` then `[Total > $Limit]`, is clean. Fix: `@Module.Name` is an xpathValueExpr (xpathConstantRef — a value, not a path step) and AT is out of xpathWord; the visitor builds ast.ConstantRefExpr and the page renderer prints it, so every slot stores the constraint as written and describe prints it back. `mxcli check` (ValidateProgram, so exec too; no project needed) refuses a constant in any XPath slot as MDL-XPATH03 with the variable workaround; an excluded flow warns. walkXPathConstraints gains a sibling that names the slot. Verification: visitor, check and executor tests; the PedApp test writes the constraint into a retrieve, a list view and an access rule, describes all three back, re-executes the descriptions with no file changed, and renames the constant through them ("Updated 3 reference(s)"). Reverting the grammar fails every test with the reported parse error and `[Total > @]`; reverting only the renderer case gives `[Total > ]`; stubbing the check fails the refusal tests. Real 11.13.0 app: baseline describe printed `where Total > @;` for both retrieves, fixed describe prints the constraints and describe -> exec reports 5 documents in sync; `rename constant` updated 5 references in 4 documents, and mx check is the same five CE0161 before and after the rename with the variable control clean. TestMxCheck_DoctypeScripts passes for the microflow, nanoflow, page, security, xpath, workflow and offline-sync scripts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1690) `retrieve $C from $O/Ord_Cust;` - an association path written with the association's short name - passed `check -p --references` and exec and was stored as the association ".Ord_Cust": mx check CE1613 "The selected association '.Ord_Cust' no longer exists.", and describe printed `$O/.Ord_Cust`, which does not parse. Cause: addRetrieveAction joined the AST's empty Module to the name, and nothing on the check side looked at a bare retrieve association. MDL-RETRIEVE03's qualifyAssoc guessed the start entity's module - a second answer to the same question. Fix: one resolver, resolveBareAssociation (bare_association.go), a function of plain data - the name, the start entity's generalization chain, and an association catalog with both ends of every association. A bare name resolves when exactly one association of that name has an end on the chain (either end; a specialization inherits) and is stored qualified; none or several is refused, with the qualified spelling to write. The builder feeds it the project as the earlier statements left it, check --references the project plus the associations declared before the flow (validate_flow_member_refs.go), so the two agree; exec also refuses a bare name it cannot resolve rather than writing ".Name". The describe speller and MDL-RETRIEVE03 ask the same resolver, so a re-run of the script reports "Unchanged microflow". Verification: retrieve_bare_association_1690_test.go (PedApp, check and exec agree; stored unit bytes; describe; re-run unchanged; refusals; speller). Reverting the fix fails every case with ".Ord_Cust" stored and check/exec accepting. Real 11.13.0 app: the reported repro went from CE1613 to 0 errors with "Shop.Ord_Cust" stored and described; owner side, TO side, specialization, cross-module inherited and Account/UserRoles -> System.UserRoles all resolve and build at 0 errors; a missing and an ambiguous name are refused by check, exec and exec --no-check. No doctype or bug-test script changes verdict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…heck and exec (#1646) `find $l by Numbr = '42'`, and filter / sort / sum by a member the list's entity does not have, passed `check -p` and exec; mx check then reported CE1613 "The selected attribute 'Shop.Order.Numbr' no longer exists." once per activity. An aggregate by an INHERITED attribute was broken the same way: `sum $sl by Total` was written as "Shop.SubOrd.Total" (CE1613). Cause: the builder's member resolution (resolveMemberChange via resolveListOperationMember, the sort branch, the aggregate) fell back to writing `<entity>.<name>` when the name resolved to nothing, and the aggregate never walked the generalization chain. check --references judged CREATE/CHANGE members and retrieve constraints, but no list operation member. Fix: one chain walk, memberVerdictOver (member_verdict.go), over a per-link interface - read from the backend by the builder, from the script over the backend by check - so the script overlay changes how a link is read, never the rule. The builder refuses a member established as missing with listMemberRefusal, the message check reports, so exec without the preflight says what check says; resolveMemberOnEntity now delegates to the same walk. The aggregate qualifies an attribute with the entity that declares it. A sort may read createdDate/changedDate where the root stores them; an aggregate may not (CE0226, measured). Verification: list_member_refs_1646_test.go (PedApp, check and exec agree): the four reported shapes plus maximum, bare `owner` and an aggregate over createdDate are refused; own/inherited attributes, bare and inherited cross-module associations, System.owner, sorts on a stored system date, an untyped list and a member the script adds first stay accepted; the inherited aggregate stores the declaring entity. Reverting the fix fails the refusal tests with check and exec accepting and the aggregate storing B1646.SubOrd.Total. Real 11.13.0 app: the repro went from 4 x CE1613 to refused by check and exec; the controls build at 0 errors. No doctype or bug-test script changes verdict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…id (#1697) `toString($User/id)`, `$A/id = $B/id` and `$User/Bogus` passed `check -p --references` - the type pass said "Expression types OK" - and exec wrote them; mx check reported CE0117 "Error(s) in expression." (mirror of mendixlabs#1650). Cause: nothing resolved the member steps of an expression's `$Var/...` path against the variable's entity. The type pass infers an unknown attribute as KindUnknown and stays silent, and it is not part of exec's preflight anyway. Fix: the reference pass - which check --references and exec's preflight both run - follows every `$Var/...` path in a flow statement's expressions through the same member verdict as #1646, across association hops: an attribute the entity (or anything it extends) does not have, a bare association, an association that does not exist or does not start at the entity are reported, and `id` gets the compare-the-objects / CommunityCommons.getGUID hint. The hop's target entity may follow the association qualified or bare (the builder qualifies a bare one, #829). Paths are collected by reflecting over each statement's fields, so a statement kind added later is covered; nested bodies are left to the typed walk. Verification: expression_member_refs_1697_test.go (PedApp): the twelve shapes measured as CE0117 on 11.13.0 are reported, the ten measured clean are not (plus the bare target entity step), the System.User repro and a loop/IF body. Reverting the fix fails every report case. Real 11.13.0 app: the repro went from 2 x CE0117 to refused by check and exec; the controls build at 0 errors. Every CE0117 shape was measured in an app with no other error - a CE1613 elsewhere suppresses them all. No doctype or bug-test script changes verdict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and exec (#1645) A specialization's attribute or association named like a member it inherits, a generalization gaining a member a specialization already has, a rename into such a name, and an entity's own attribute and association of one name all passed `check -p` and exec; mxbuild rejected the model with CE0069 "Duplicate member name". Cause: nothing decided "this entity already has a member of that name" along the chain. The only CE0069 guard was dropInheritedTargets inside bulk ALTER ENTITIES, which looks only within the target set; the single statements checked the entity's own attributes or the module's association names. Fix: one verdict, memberNameClash, over a member world (each entity's generalization and attributes, each association's ends): - exec calls it against the project before writing, in create entity, alter entity add/rename attribute, create association, alter association set owner both and rename association; bulk ALTER ENTITIES judges every target before its first write; - check -p replays the script over the project's members in statement order (so a drop-then-re-add passes and a one-script parent/child pair is caught), judging each statement with the same verdict; - `check` without a project runs the same replay over the System module from modelsdk/meta (MDL-MEMBER01), so the issue's scripts fail even there. The message names the member already holding the name, its declaring entity, and the CE0069 it prevents. Measured on mx 11.13.0 (17 shapes in one app, then 4 more): CE0069 for attribute/attribute, association/association, both mixed directions, two levels up, System.User.Name, System.UserRoles, System.FileDocument.Size, the downward direction, attribute and association renames, and an entity's own attribute vs association; an association is a member of its TO entity only under owner Both. Clean: names differing only in case, siblings, an unrelated entity, an owner-Default TO-side attribute. Verification: PedApp check/exec agreement tests for every shape plus controls, and a project-free test; reverting the wiring fails all nine (controls still pass), reverting only the check pass fails check's half. Real 11.13 app: baseline wrote 16 CE0069 models; fixed, check and exec refuse those 16, the 5 clean shapes are written, mx check 0 errors. Doctype sweep (81 scripts, check with and without -p) and 238 domain-model bug-test/skill scripts: identical to main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mirror of mendixlabs#1642. A page parameter named `Context` passed check and exec, and mx check reported CE7247 "The name 'Context' is a reserved word." — after the page and its callers had been written. Cause: the platform reserved-word list (types.PlatformReservedWords) was applied to attribute names (MDL021) and enumeration values (MDL010) only; nothing looked at parameter names. The list also lacked `object`. Fix: MDL-PARAM01 checks the parameters of create page / create snippet / alter page|snippet add parameters / create java action / create javascript action against that same list (case-insensitive, quotes stripped), in ValidateProgram (check, exec's pre-flight) and in the five exec handlers, so --no-check cannot write it either. The message names the CE7247 and suggests the parameter's entity as a name ($Sale). `object` is added to the shared list, so MDL021/MDL010 cover it too. Measured on mx 11.13.0, ~120 names over six contexts: pages, snippets, Java and JavaScript actions take exactly the attribute list — every listed name tried is CE7247 in any case and quoted, every unlisted one clean (incl. currentObject, latestError, String, System, User, List, record) — except `Object`, CE7247 there and on an attribute, an enumeration value and an entity. Microflow and nanoflow parameters and page variables do not use this list ($Context, $Type, $Class build clean); flows refuse the system-variable names instead (CE0110/CE0039), which this does not cover. Verification: unit tests per context plus controls (another name, a system-variable name, microflow/nanoflow parameters), a PedApp check/exec agreement test; reverting the wiring fails all of them, reverting only the page handler fails exec's half. Real 11.13 app: the 61 probe scripts baseline mx check reported CE7247 for (62 parameters) and the reporter's page are refused by check and exec, the other 109 are written, mx check 0 errors. Doctype sweep (81 scripts, check with and without -p) and 412 related bug-test scripts: identical to main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reserved-names note grew CLAUDE.md past the budget TestRepoClaudeMDStaysWithinItsContextBudget enforces (28224 bytes). Keep the facts it carries — Object is reserved, the list binds page/snippet/Java/ JavaScript action parameters (MDL-PARAM01), and where the list lives — in fewer words; the microflow-parameter nuance is in the skills and the finding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ences # Conflicts: # mdl/executor/validate_member_refs.go
fix: a constant in an XPath constraint — parse it, refuse it (CE0161), stop losing it (#1685)
The header's `annotation '…'` is the note on the workflow's start. Since #707 mxcli wrote it to the workflow's own Annotation, and describe read only that. Studio Pro shows the start's note from the start activity: mxbuild 11.15.0's workflow editor (ide-client/workflow-editor) draws note badges in four views, ActivityView, BoundaryEventView, EventSubProcessView and StartActivityView. Each draws its own element's annotation, and the Workflow view draws none. So a note mxcli wrote showed nowhere in Studio Pro, and a Studio Pro author's note on the start was dropped by describe → replay. Both slots are in the metamodel from 9.15.0, which is why the metamodel could not settle it. CREATE now writes the header clause to the start activity. The reader reads the start activity's note. describe prints StartNote(): the start activity's note, else the workflow's own for workflows written before this change. Measured on 11.15.0: - CREATE stores the note on the start activity and null on the workflow. - A workflow written by the previous build describes the same; its replay moves the note to the start once ("Modified", then "Unchanged"). - mx check is clean. Refs #1717 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019xfGeNtrQ5BJrH2Ew64rt5
`alter workflow M.W { set (Annotation: '…'); }` was refused with "a
workflow has no property Annotation", and so was `set (Annotation: '…')
on X`. CREATE writes both notes, but the refusal never named its
spellings, so an eval agent concluded that workflow notes were
unsupported.
`Annotation` is now a workflow key and an activity key:
- The workflow key sets the start activity's note, which is the header's
`annotation '…'`. It also clears the workflow's own Annotation, so
describe does not find a stale note there.
- `on X` sets the `@annotation '…'` before activity X. `on Start` is the
workflow key.
- `''` stores null and removes the note.
- An end is refused: Studio Pro's editor draws no note on an end.
The note is written as Studio Pro's exact set {$ID, $Type:
Workflows$Annotation, Description}. An edited note keeps its $ID. A
document stored without the Annotation slot is refused rather than given
one. MCP refuses the key, as it refuses every unsupported property.
Measured on 11.15.0: after the ALTER the project checks clean, describe
prints the notes in CREATE's spellings, and replaying describe reports
"Unchanged workflow".
Refs #1717
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019xfGeNtrQ5BJrH2Ew64rt5
`alter workflow M.W set (Annotation: '…');` ended its errors with "`set (annotation` is a session command". The old per-action form takes `set display '…'` without braces, so the parser tried that form, failed at the parenthesis and recovered into the session command `set <name> = <value>`. Its refusal read as the diagnosis, and no error mentioned the braces. A line of that shape now gets a hint that shows the braced statement. The session-command refusal stands down on a line the parser already reported, because the syntax error is the one to act on. A session command on a line of its own is still refused. Fixes #1717 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019xfGeNtrQ5BJrH2Ew64rt5
feat(workflows): set workflow and activity notes in ALTER; the start's note is the start activity's
engalar
pushed a commit
to engalar/mxcli
that referenced
this pull request
Oct 27, 2026
…l7uoj fix: misleading diagnostics — MDL031 on CASE columns, and a parenless routine header
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: 10 commits from fork PRs ako#1738, ako#1739, ako#1740 and ako#1742.Fixes #1642 and #1650.
References to members that don't exist (#1650)
These all passed
check -pand exec, then failed mx check:$Var/<member>for a member the entity lacks, including the systemid(check passes$Var/<member>for a member the entity does not have, incl. the systemid(mx check CE0117; check/exec pass) #1650).toString($User/id),$A/id = $B/idand$User/Boguspassed the type pass, then gave CE0117.find $l by Numbr = '42'gave CE1613 once per activity. A retrieve constraint was already checked for this, and list operations now are too. An aggregate by an inherited attribute was mishandled as well.retrieve $C from $O/Ord_Cust;was stored as.Ord_Cust, with an empty module, and gave CE1613.Names Mendix rejects (#1642)
Contextis refused (A page parameter namedContextpasses check and exec; mx check then reports CE7247 "The name 'Context' is a reserved word" #1642). It gave CE7247 "reserved word", after the page and its callers had been written. The platform reserved-word list now binds page, snippet, Java action and JavaScript action parameters (MDL-PARAM01).A constant in an XPath constraint
where [Total > @Shop.C_Limit]parses. It used to be a parse error.where Total > @Shop.C_Limitstored[Total > ].Workflows
alter workflowsets a workflow's or an activity's note.set (Annotation: '…')andset (Annotation: '…') on Xused to be refused.setinalter workflownames the braces it needs.Docs