Repository navigation
Sync ako/mxcli: Business Events channel identity, describe/write round-trip fixes, more check coverage - #1564
Merged
Merged
Conversation
…e XPath (mendixlabs#1466) After MDL055 refused two hops, two one-hop comparands still passed check and failed mxbuild with CE0161: a hop landing on an entity unrelated to the left side's (MDL-XPATH02, also association vs attribute) and an unqualified comparand association (MDL-XPATH01, page arm). Runs in the no-project tier from the script's declarations, the project filling in the rest; silent where an entity or generalization chain cannot be established. Stubbing it fails 9 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VKmbj53BC2vuUWYmgWgfQ5
…ption (mendixlabs#1466) The issue's own script omitted CaptionAttribute on both combo boxes; check and exec passed and mxbuild reported CE0642 "Property 'Caption' is required." per combo box. MDL-WIDGET16 returned clean once a data source was present. It now requires the caption the caption type selects (attribute, or type expression + expression), measured on fresh 11.13.0/11.14.0 projects; enumeration mode is not judged. Test table mirrors the measurement; stubbing the check fails 8 cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VKmbj53BC2vuUWYmgWgfQ5
The skill grew with the comparand note; make check-skill-index refuses stale ranges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VKmbj53BC2vuUWYmgWgfQ5
…ox-caption fix(executor): refuse the remaining #1466 shapes — XPath comparand type and combo box caption (mendixlabs#1466)
…ify (mendixlabs#1525) createBusinessEventService called generateChannelName() for every message on every build, including CREATE OR MODIFY of an existing service. Three runs of an unchanged script gave three different ChannelNames, each reported "Modified". The ChannelName is the Kafka topic a deployed app publishes on, so every re-run moved every topic and disconnected subscribers in other apps, with a clean mx check; and the rewrite could never be elided (ADR-0008). On a rewrite, carry the stored definition $ID and, per declared message matched by message name, the stored channel's $ID and ChannelName, the message $ID, attribute $IDs (by attribute name) and the operation $ID. A new message gets a fresh channel name. A stored channel holding several messages is handed to the first one only, so no two channels share a topic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…ping (mendixlabs#1531) The gen->sdk workflow reader converted a CallWorkflowActivity's Workflow, ParameterExpression and boundary events but never its ParameterMappings, so describe printed `call workflow M.WF_Child;` for a call stored with `(WorkflowContext = $WorkflowContext/M.Parent_Current/M.Item)`. Re-executing that output let autoBindCallWorkflow write the default `$WorkflowContext`, silently passing the parent's context object instead (CE0117 on 11.15.0). Add workflowParamMappingsFromGen, the call-workflow twin of microflowParamMappingsFromGen, and wire it into the CallWorkflowActivity case. A writer->gen->reader unit test covers the reader layer the describe tests skip, and an integration test proves describe -> exec reports "Unchanged workflow" with the mapping intact. Measured on 11.15.0: the pre-fix round trip goes 0 -> 1 error (CE0117); the fixed one stays at 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…ted members (mendixlabs#1525) A message attribute named like a member the event entity inherits from BusinessEvents.PublishedBusinessEvent (the reporter's EventId) passed check and exec; mxbuild then reported "The Business Events attribute 'EventId' is not present on the entity." (measured on 11.6.6 and 11.15.0 with a stub base entity; the control without the attribute is clean of it). An inherited attribute does not count and cannot be redeclared, so such a message can never be satisfied. The --references pass now walks the message entity's generalization chain, script-declared entities first and then the project, and reports a message attribute an ancestor declares. The inherited members are read from the model, not a list in mxcli; where the chain cannot be read (no BusinessEvents module) nothing is reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…endixlabs#1520) DESCRIBE PAGE left out a Data grid 2 column with no attribute and an empty header (the usual actions column, ShowContentAs: customContent) together with every widget inside it. Re-executing the unchanged output was a no-op ("Unchanged page"), but the first real edit replaced the page and deleted the column and its buttons from the model, with mx check clean. Cause: extractDataGrid2Columns took the first property holding Objects and kept a column only when it had an attribute or a caption. Fix: find the `columns` property by its resolved key and treat every object in it as a column; the old heuristic remains only for an unresolved key, widened to columns with content or a content mode. A column with neither attribute nor caption is printed with `Caption: ''`, which the writer stores as the empty header template. Measured on 11.6.6 and 11.15.0: describe -> edit -> exec keeps the column and button, mx check 0 errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…xt (mendixlabs#1530) A workflow has exactly one parameter and mxcli always stores it as WorkflowContext; the name in a `parameter $Task: M.Item` header is only an alias. buildCallWorkflowActivity wrote the mapping key as <called workflow>.<key> verbatim, so `call workflow M.WF_Child(Task = $WorkflowContext)` passed check and exec and failed the build with CE1613 "The selected parameter 'M.WF_Child.Task' no longer exists" (measured on 11.6.6 and 11.15.0). The syntax help taught that form. New rule MDL-WF18 refuses any other key at check time (create and the activities an alter inserts) and at exec, naming WorkflowContext; a casing variant is accepted and written in the stored spelling. The syntax-help example, the quick reference and the write-workflows skill now show `(WorkflowContext = ...)`. Measured: the corrected form is 0 errors on both versions; the repro is refused by check and by exec --no-check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…#1522) `create or modify navigation Responsive { menu item ... }` cleared the profile's home page, role-based home pages, login page and not-found page, so the next build failed with CE0527 "Select a default home page for this profile". navPatchWebProfile wrote those four fields unconditionally from the spec, while the menu, sync block, ON SYNC ERROR and PROGRESSIVE WEB APP were already left alone when omitted. navPatchNativeProfile rebuilt RoleBasedNativeHomePages the same way. An omitted clause now keeps the stored value for every field. `home ... for <role>` replaces that role's home page only; a role the statement does not mention keeps its own (navMergeRoleHomes). MDL has no clause that clears a home, login or not-found page, so such a page can no longer be removed by leaving it out. describe -> exec is unaffected, since describe states every clause. Both patchers now work on a copy of the stored profile, because navSetField writes in place. The docs said both "fully replaces" and "omitting the block leaves it alone"; syntax help, skills and docs-site now describe the one rule. Measured with mx check after a menu-only statement on a profile with a home page: 11.15.0 and 11.6.6 both CE0527 (1 error) before, 0 errors after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…-column fix(executor): describe keeps an untitled Data grid 2 actions column (mendixlabs#1520)
`dropdownfilter f (attributes: [Status])` stored attrChoice "auto" with an empty `attr`. check, exec and mx check stayed clean, describe printed a bare `dropdownfilter`, and in a gallery's filter bar (no column to inherit an attribute from) the filter failed at runtime with "Unable to get filter store". Cause: dropdownfilter.def.json mapped `Attributes:` onto `attributes` and `defaultFilter`, the text filter's keys. The DataWidgets 3.x drop-down filter (3.4.0 in 11.15; same keys in the 11.6 template) has one attribute slot, `attr`, which its editorConfig shows only under attrChoice "linked". Every builder Set* operation skips a key the template does not declare, so the value was dropped without a word. Fix: - def: a new `attribute` mode (condition `hasAttributes`) writes attrChoice=linked and the attribute on `attr`; a bare filter keeps "auto". `Attributes:` feeding the single-attribute op resolves one attribute and refuses a list of more (exec, and MDL-WIDGET47 at check). - engine: an AUTHORED value mapped to a key the loaded template does not declare now fails the statement (optional backend.WidgetPropertyDeclarer, implemented by widgetobj.Builder; the MCP builder cannot answer and is unchanged). Mapping constants are exempt. - check: widgetValueMap read the constants of every mode, last one winning, so the new `attr` was reported hidden under the default mode's "auto" and the association mode's baseType "ref". Inactive modes' constants are now ignored. - describe: reads `attr` back as `Attributes: [A]` under attrChoice linked. Measured (fixture copies, create + mx check): 11.6.6 and 11.15.0 both store attrChoice=linked, attr=Tmp.Item.Status for the column and the gallery filter, 0 errors, describe prints `(Attributes: [Status])`. Before: auto, empty attr, 0 errors, bare describe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…xlabs#1529) `call microflow M.ACT_Bind(Workflow = $Workflow, Item = $WorkflowContext)` in a workflow passed `check --references` and `exec`, then the build failed CE0117 "Error(s) in expression.". No workflow rule looked at the variables an expression names, and the code asserted the context was the only one in scope; `$WorkflowInstance` (System.Workflow) was nowhere in mxcli. The same root cause behind mendixlabs#1523: the unmapped-parameter error suggested the deprecated `with (Workflow = ...)` and never what value to pass, and with no argument list auto-bind mapped every parameter, a System.Workflow one included, to $WorkflowContext. Scope measured with mx check on 11.6.6 and 11.15.0 (identical verdicts): $WorkflowContext and $WorkflowInstance build in call microflow arguments, decisions, wait-for-timer, user task due dates, boundary timers and event sub-process timers; the workflow's own header due date sees only the context. $Workflow, $currentUser, $currentSession and $WorkflowUserTask are CE0117 everywhere, and so is a lower-case $workflowInstance as stored. - MDL-WF19 (validate_workflow_scope.go): every $name outside a string literal in a workflow expression must be WorkflowContext (any case), the header's declared name, or WorkflowInstance (not in the header due date). Applied by check to CREATE and ALTER, and refused by exec too, since exec is reachable without check. The message names $WorkflowInstance for $Workflow. - Auto-bind maps a System.Workflow parameter to $WorkflowInstance. - The unmapped-parameter error names the current `call microflow M(P = v)` form, with $WorkflowInstance / $WorkflowContext by parameter type. - The writer rewrites the declared context name and casing (and now $WorkflowInstance casing) at every expression site; boundary timers, event sub-process timer starts, call-workflow arguments and the header due date used to be written verbatim, which the rule's allow-list would otherwise have hidden. mx check on a fixture copy: the probe set went from 10 x CE0117 to 0 errors on both versions once the out-of-scope names were refused and auto-bind fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…pping fix(workflows): call workflow parameter mapping — describe keeps it, check refuses a non-WorkflowContext key (mendixlabs#1531, mendixlabs#1530)
…s#1522) MDL078 reported a glyph code the Mendix glyph font does not define as a warning, so exec wrote it, mx check passed it at 0 errors, and `mxbuild --target=deploy` crashed: exit 1, InvalidOperationException "Sequence contains no matching element" at GlyphFont.GetClass, a layout named instead of the icon, and no --write-errors file for a build gate to read. A real model error in the same build exits 3 and writes the file. The warning hedged against the font table being a snapshot that Mendix might extend. That was measurable: mxbuild bundles its own modeler/glyphicons-halflings-regular.ttf, byte-identical in 9.24, 10.12, 11.6.6 and 11.15.0, and its cmap's private-use range is exactly the 247 codes in glyphIcons. MDL078 is now an error, so check fails and exec refuses before writing. Every carrier (navigation menu items, menu documents, page/snippet/layout widgets) goes through the same validator. A glyph has no name, so the suggestion names the defined glyphs either side of the bad code (57388 -> 57385 play-circle, 57392 repeat). navigation-glyph-code.mdl becomes a .fail.mdl, since check now rejects it. Measured with the reported code 57388: before, exec applied it, mx check 0 errors, mxbuild deploy exit 1 with no error file (11.15.0 and 11.6.6). After, check reports MDL078 as an error and exec prints "Refusing to execute ... Nothing was written". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…labs#1519) `set (ColumnWidth: manual, Size: 220) on dg column(Name)` followed by `set (ColumnWidth: autoFill) …` stored width=autoFill with size=220, and mx check reported CE0463 on the Data grid 2. Cause: setColumnPropertyMut writes exactly the property named. Data grid 2 hides `size` unless width is "manual" (and `minWidth` unless width is "autoFit", `minWidthLimit` unless minWidth is "manual"), and a hidden property holding anything but its default is CE0463. The create path writes hidden properties at their default; ALTER never re-evaluated them. Fix: after a column SET the executor hands the column's visibility rules — lifted from the installed Data grid 2 package's editorConfig, not a list in mxcli — to the mutator (optional backend.ColumnHiddenPropertyResetter). pagemutator resets every primitive column property a rule now hides to the default the stored Type declares, repeating until nothing changes, so a reset that hides a further property resets that one too. A hidden property the same statement names with a non-default value is refused instead of silently overwritten (`ColumnWidth: autoFill, Size: 220`); its default (`Size: 1`) is accepted. check judges a column SET as a whole as well as per property, applying the same follow-up. Measured (fixture copies, create → manual/220 → autoFill, then mx check): 11.6.6 and 11.15.0 both 1 CE0463 before, 0 after; size stored 1 after the switch and still 220 under manual. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
Resolve conflicts with #1418 (MDL-WF18): keep both the WF18 call-workflow key check and the WF19 expression-scope check in execCreateWorkflow and the ValidateWorkflow rule list; regenerate the write-workflows skill index. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…rites (mendixlabs#1517) An alter block's operations are aimed at the flow as stored, but the block writes one flow. Three scope verdicts were taken per operation, or from text that hides part of the fragment: - checkOutputUnused ran per operation, in order, against the stored candidates, so a consistent rename (producer, reader, return in one block) was refused "$Code is still used by: log ...; return $Code" by readers that later operations replace. The checks now run once every operation is applied; a return value or condition set in place marks its node rewritten, so its stored reads retire and its new ones count. - checkFragmentScope ignored what earlier operations of the block declare (unscopedRefs honoured it, but without position), so a fragment reading a variable an earlier insert declares upstream of it was refused MDL090. Each declaration now records the operation and stored target that put it in, and declaredOnPath credits it only where that site is upstream of the later operation's position; both checks use it. - the scope check read a fragment's variables from formatActivity, which renders a loop as its header only, so a replaced loop's body was never checked: a body reading an undefined variable was "Altered" and mx check gave CE0109 (11.6.6 and 11.15.0). fragmentReads now walks loop bodies, with the iterator and the body's own declarations local to it. The output check is shared with `create or modify`'s splice, so moving a retrieve and its only reader into a sub-flow is now spliced instead of refused "$Reporter is still used by" (the issue's repro A). Two tests used that false refusal as their vehicle for check/preflight prediction of a call to a flow the script creates; they now use a loop-body change, which is still refused. One commit: the A2 repro also needs the B2 fix (the replaced reader reads the $Code2 the first operation declares), and the three share the test harness. Each has its own revert control. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…al (mendixlabs#1517) The MDL-V1-REBUILD refusal of a `create or modify` that changes a loop body named only the replace-loop alter, while every other splice refusal also names the deliberate rebuild: drop the flow and create it in the same script. Both now share that advice (deliberateRebuildAdvice), so check, which quotes exec's refusal, says it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…endixlabs#1515) `formatDecimal($d, 2)` passes a number where the String pattern goes. mxbuild refuses it with CE0117 on 11.6.6 and 11.15.0, but `mxcli check` printed "Check passed!" with and without -p. Cause: checkCallExpr compared argument counts only, although its comment and the E005 func-arg-type registry entry promised kinds; and it ran only in the catalog tier (TypeCheckProgram, `check -p --references`), so a plain check missed even a wrong count such as `formatDecimal($d, '#', 'en', 4)`. Fix: - checkCallExpr now reports E005 when an argument's inferred kind cannot stand in the parameter: Boolean / String / number / DateTime are separate families; Integer and Long are interchangeable and widen to Decimal; Decimal into an Integer/Long parameter is refused. Unknown, empty, enumeration, object and Any are always tolerated, date tokens are typed DateTime, and rows marked unverified are skipped. - BuiltinCallHints runs E005/E006 in the no-project validator (checkExprFunctions, microflows and nanoflows) with the kinds of literals, parameters and declares. The catalog tier only runs on a script this tier passed, so the two never report the same call. Not exec-enforced: --no-check still writes. - Every mismatch class and the signature rows below were measured with mx check on 11.6.6 and 11.15.0 (they agreed on all ~130 probes) and pinned in builtin_arg_types_test.go. Turning the check on surfaced arity rows that were already false E006s on the -p tier: find/findLast take a start index, max/min are variadic and accept DateTimes, dateTime/dateTimeUTC take 1-6 parts, formatDateTime(UTC)'s format is optional. formatDecimal's format is required (min 2, was 1). parseDecimal's second argument may be a Decimal default. - The one new diagnostic over mdl-examples was a true positive: use-cases/02-agentic-search.mdl passed the quoted string '[%CurrentDateTime%]' to addDays (CE0117); unquoted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…labs#1528) run --local never set ScheduledEventExecution in the boot update_configuration payload, so the runtime's own default NONE applied: an app's scheduled events silently never fired, the only trace being a "Synchronizing scheduled events: None" runtime log line. RunLocal now defaults ScheduledEventExecution=ALL after building the runtime settings, unless the user passed --runtime-setting ScheduledEventExecution=..., which still wins. It prints one line at boot naming the effective value, the number of scheduled events in the model, and how to override it. The shared runtimeConfigParams payload is unchanged, so the test runner (StartLocalApp) keeps NONE and test runs stay deterministic; a test pins that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
fix(executor): an undefined glyph code is an error, MDL078 (mendixlabs#1522)
…of install (mendixlabs#1527) A headless module or widget install leaves CE0463 (stored widget instances older than the installed packages) and, for a module, CE6087 (renamed design properties) for Mendix's own tools to fix. install only printed 'mxcli fix widgets' / 'mxcli fix design-properties' as a Next step, so the field run was left with 41 units of CE0463. install now runs them itself through docker.RunToolPreservingFormat, the same call 'mxcli fix' makes, which keeps MPR v2: both repairs after a transplant module install, the widget resync after a widget install (online and --file). When the project's Mendix version cannot be read or mx cannot be resolved, it prints a warning and the manual commands instead of failing; a failing repair names its own command and the next one still runs. The mx resolution and tool runner are package-level seams so the tests need no mx and no marketplace network. Not changed: marketplace update (still prints the steps), the --allow-format-change module-import path, and dependency resolution. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…n clauses (mendixlabs#1533) Two bare parse errors in workflow MDL: 1. `call microflow M.ACT_Close as close` gave "mismatched input 'close' expecting {IDENTIFIER, QUOTED_IDENTIFIER}" with no hint: the keyword hint only matched the fixed 41-word hintedKeywordSet. Now any identifier-shaped offending token whose raw expecting set contains QUOTED_IDENTIFIER (read before simplifyExpecting truncates it) gets reservedKeywordHint — such a token can only be a lexer keyword, and a quoted name is exactly what that slot accepts. QUOTED_IDENTIFIER, not IDENTIFIER, because the statement-start set also lists IDENTIFIER. The branch returns before the fixed-list loop, so no word is hinted twice. 2. `returns` after `exposed as workflow action …` (or folder / url / …) gave "mismatched input 'returns' expecting BEGIN", read as "an exposed microflow cannot return a value". The grammar fixes the return type before the option clauses; the error now says so. It fires only when the parser context is a create microflow / nanoflow / rule header — not inside the body, and not past it — so a stray `returns` in a body is not mis-hinted. No grammar change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…eses (mendixlabs#1514) `create microflow M.F returns Boolean as $b` gave "missing '(' at 'returns'" and "missing ':' at 'Boolean'"; with a bare `$l: List of …` parameter "missing '(' at '$l'" and "missing ')' at 'returns'". ANTLR's recovery inserts the missing `(` and parses `returns Boolean` as a parameter, so every message points past the real mistake. The hint is keyed off the source line: `create [or modify] microflow|nanoflow|rule <name>` followed by returns / `$` / as / begin instead of `(`. A header with parentheses cannot match. deduplicateHint already keeps the cascade on that line to one explanation. The follow-on error on the body line is left alone. No grammar change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
The #732 hint fired on any parse error on a line containing `\'` and always said "Under mdl 1 a backslash is an ordinary character, so `\'` ends the string literal". In a headerless (mdl 0) script the backslash escapes the apostrophe and the literal does not end there, so the advice pointed the wrong way. build() now reads the escape rule the script was lexed with (parser.HasStrictEscapes on the char stream from newScriptStream) and hands it to the error listener; under mdl 0 the hint explains that `\'` does not end the literal, that a trailing backslash must be doubled, and that a doubled apostrophe means the same under every version. The mdl 1 text is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
fix(workflows): check the variables a workflow expression names; $WorkflowInstance (mendixlabs#1529, mendixlabs#1523)
…-width fix(pages): drop-down filter keeps its attribute; ALTER column SET resets hidden properties (mendixlabs#1519)
…alized (mendixlabs#1521) create or modify entity and alter entity ... modify attribute keep a stored DateTime LocalizeDate when the statement does not state localized / not localized (#743, #1373). That rule stays, but it was invisible: a script that meant Studio Pro's default left a not localized DateTime in UTC with no output saying so. carryStoredLocalizeDate now reports whether it kept a stored false. The create-or-modify path derives the kept attributes from the written result (an unstated DateTime written not localized can only be the carry), and both paths print one Note line per attribute naming it and the `DateTime localized` spelling that changes it. Nothing is printed when the clause is stated or the stored value is localized. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
fix(exprcheck): check built-in argument kinds, without a project too (mendixlabs#1515)
…ject (mendixlabs#1516) `retrieve $L from $h/M.Line_Header` from the TO entity of a Reference (the "one" side) binds a LIST. Using it as an object -- `$L/Qty`, `change $L`, passing it to an object parameter -- passed check --references and exec, then mx check failed with CE0117 / CE7247 (measured identically on 11.6.6 and 11.15.0; the bare list retrieve, count and loop build clean on both). MDL-RETRIEVE03 only seeded database retrieves: list-vs-object over an association needs the association's type, owner and which end the start variable is. The decision now lives in associationRetrieveYieldsList, used by the flow builder and by a new --references pass that tracks each object variable's entity, resolves the start end (script + project associations, generalization chain) and reports member-path, change and object-parameter use of the list under MDL-RETRIEVE03, through the walk the no-project rule now shares. Owner Both (one-to-one) and the FROM side stay objects. MDL043: with a project or a script that creates it, a bare declare type that is an enumeration is not an object declare -- exec writes it as the enumeration variable and it builds (11.15.0). It now warns with describe's `enum` spelling instead of refusing it with the object wording. Docs: microflow.variables documents the conditional-create idiom (one create with conditional values, or a sub-microflow returning per branch; the same name created in both branches is CE0111 on 11.15.0) and the enum declare; microflow.retrieve and the error reference describe association list results; MDL063's suggestion names the idiom for a create. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…istency fix(executor): judge an alter block's scope against the flow it writes (mendixlabs#1517)
…of each kind (mendixlabs#1513) scanWidgetOwnRefs collected every Microflow/Nanoflow/Entity/Form value in a widget's own BSON but returned only the lexicographically smallest of each, and the refs table is projected from that single widgets_data column. A Data grid 2 (or gallery, list view) with `datasource: microflow Tmp.Rows` and `onClick: call microflow Tmp.Open(…)` therefore recorded only Tmp.Open: Tmp.Rows had no inbound reference, `show callers` found none, and QUAL004 said "not called from anywhere. Remove if unused" about a live datasource. The comment claiming page-level dedup made the choice immaterial was wrong. scanWidgetAllRefs now returns every name (sorted, deduped); rawWidgetInfo.AllRefs carries them, buildPages/buildSnippets collect the names beyond the single column onto the Builder, and buildReferences inserts them after the widget projections with WHERE NOT EXISTS so a page still gets one edge per target. The single columns keep their choice (the smallest) for `show widgets` and Starlark's microflow_ref; the lint-rules skill now says the column is one name and to ask refs_to() instead. Datasource microflows keep RefKind `action`: `datasource` is not in show callers' callerRefKinds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…abs#1526) The project id — the $ID of the Projects$Project root unit every module points to, which Business Events uses as the app id — was shown by no command, so two apps made from one copied model could only be found to share it by grepping mprcontents. The model-engine backend's GetProjectRootID was still the generated "unimplemented" stub; only CreateModule reached the reader's method directly. Backend.GetProjectRootID now delegates to the reader (struck off the unreachable-unimplemented allowlist). describe settings prints it as a `-- Project ID: …` comment, so the output still executes, and show settings (table and JSON) adds a Project row. Read-only: no re-ID command. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…tion fix(check): refuse a list retrieved over an association used as an object (mendixlabs#1516)
fix(run): run --local runs scheduled events by default and says so (mendixlabs#1528)
…nd-returns-order fix(visitor): parse hints for a keyword used as a name, misplaced returns, and a header without parentheses (mendixlabs#1533, mendixlabs#1514)
feat(settings): show the project id, read-only (mendixlabs#1526)
…otice fix(executor): say when an unstated DateTime keeps its stored `not localized` (mendixlabs#1521)
…widgets fix(marketplace): install runs the widget and design-property repairs itself (mendixlabs#1527)
fix(catalog): a widget that names two microflows keeps both references (mendixlabs#1513)
Resolve the manage-navigation skill index conflict with #1421 by regenerating the skill index. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
…keeps-stored fix(navigation): an omitted clause keeps the stored value (mendixlabs#1522)
AI Code ReviewCritical IssuesNone found. Moderate IssuesNone found. Minor IssuesNone found. What Looks GoodThe PR successfully syncs fixes from the ako/mxcli fork, addressing multiple important issues:
The changes follow established patterns:
The PR demonstrates good understanding of the system architecture, particularly around:
RecommendationApprove the PR. The changes represent important bug fixes and validation improvements that enhance the correctness and reliability of mxcli. The sync from the fork brings in well-tested solutions to real user issues, and the accompanying test coverage provides confidence in the fixes. No violations of the review checklist were identified. Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
This was referenced Oct 17, 2026
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: 24 commits from fork PRs ako#1390, ako#1416–ako#1419 and ako#1421–ako#1431.Writes that changed or lost what was stored
create or modify(create business event service cannot express unlimited attributes, collides with the CloudEvent id attribute, leaves V2 subject and channel name unmanaged #1525). Every run of an unchanged script used to mint a new ChannelName, which is the Kafka topic the deployed app publishes on. So every re-run moved every topic.manualtoautoFillleftsizestored, which gave CE0463.localizedkeeps a storednot localizedDateTime (An existing DateTime attribute cannot be switched to localized by create or modify entity or alter entity #1521).check catches more of what mxbuild refuses
-p(check passes expressions the build rejects or that misbehave at runtime (function arguments, Decimal toString, raw backslash literals) #1515). For example,formatDecimal($d, 2)is CE0117.$WorkflowInstance(check passes an out-of-scope variable in a workflow call microflow argument (build: CE0117) #1529).WorkflowContextis refused (check passes a called workflow whose parameter is not $WorkflowContext (build: CE1613); syntax help shows that form #1530). It used to give CE1613.mxbuild --target=deploythen crashed.$currentObject/<association>passes check, then mxbuild CE0161 #1466):Parse-error hints
returnsafter option clauses (Two unhelpful parse messages in workflow MDL (reserved activity name close, exposed before returns) #1533).mdl 0.Commands
marketplace installruns the widget and design-property repairs (marketplace install does not install module dependencies and leaves CE0463 widget definitions #1527). It no longer leaves CE0463 / CE6087 behind with only a "Next step" message.run --localboots with scheduled events running (run --local boots with scheduled events disabled and prints nothing at start #1528). Before, scheduled events silently never fired. Startup now says so.describe settings/show settingsshow the project id (Business Events AppId is the project unit id: copied with the model and shown by no command #1526). Business Events uses it as the app id.Docs