Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
306764b
fix: a change next to a find/filter `where` with a bare member is ref…
ako Oct 25, 2026
957fe86
fix: drop entity leaves the association member in the other entity's …
ako Oct 25, 2026
36fe5a9
fix: multi-line @expect silently truncated to its first line (ako/mxc…
ako Oct 25, 2026
ef3b0ea
fix: page check gave its verdict before the data source rendered (ako…
ako Oct 25, 2026
dccdfe6
fix: STRING_AGG in a view entity is refused as not aggregated (ako/mx…
ako Oct 25, 2026
7f10d0b
docs(skills): fence the multi-line @expect fragment as text
ako Oct 25, 2026
f200828
fix: splice refuses a moved producer and a variable an earlier alter …
ako Oct 25, 2026
1b343fa
fix: moving an OWNER Both association's TO end leaves stale member ac…
ako Oct 25, 2026
ab0b5e0
fix: create java action stores a bare enumeration type as an entity (…
ako Oct 25, 2026
7a6d5c3
fix: create java action writes a StringTemplate parameter as a String
ako Oct 25, 2026
b57af11
fix: call java action writes a text-template or document parameter as…
ako Oct 25, 2026
5ab2d3d
fix: create javascript action accepts a StringTemplate type (MDL-JSA01)
ako Oct 25, 2026
a919a99
fix: create java action writes an unreturnable type as Boolean (MDL-J…
ako Oct 25, 2026
61f257a
Merge pull request #1687 from ako/fix/1514-test-runner-false-greens
ako Oct 25, 2026
e3c4b2c
Merge pull request #1688 from ako/fix/1650-view-entity-string-agg
ako Oct 25, 2026
302f7b3
Merge pull request #1689 from ako/fix/1449-drop-entity-association-ac…
ako Oct 25, 2026
c7de926
Merge pull request #1691 from ako/fix/1557-microflow-splice-refusals
ako Oct 25, 2026
a2ff0e7
Merge pull request #1692 from ako/fix/1451-java-action-call-parameters
ako Oct 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"cmd/mxcli","date":"2026-10-25","symptom":"`mxcli test`: an @expect written over two lines (` * @expect $r = 'a;b'` then ` * and length($r) = 3`) kept only its first line with no message; --list, check and the run all asserted `$r = 'a;b'`, so with `and` the test passed on less than it said and with `or` it failed although the whole assertion held. Only a first line that did not parse on its own was reported, as a confusing \"expected a value at column 16\". Separately, `check -p` on a lone test file reported \"microflow not found\" for a target a setup script creates, with no sign that the script-set form (`check setup.mdl x.test.mdl -p`) resolves it","cause":"parseAnnotations read the doc comment one line at a time and expectPattern/verifyPattern captured the rest of the tag's own line; a following ` * …` line carries no tag, so it matched nothing and fell through every branch. The patterns also required text on the tag line (`\\s+(.+)`), so a bare `@expect` with the expression below it was dropped whole","file":"cmd/mxcli/testrunner/parser.go (parseAnnotations, openAssertion, continuationHint), cmd/mxcli/cmd_check.go (testFileMissingTargetHint, check --help)","fix":"@expect and @verify open an annotation whose text runs, as a javadoc block tag's does, to the next `@tag` line or the end of the comment; the joined text (single spaces) is what ParseExpect/ParseVerify compile. Text after the tag that is not part of the expression therefore makes the assertion an ERROR whose message says it spans N lines and that a description goes before the first tag. @test/@setup/@cleanup/@throws stay one line, so prose under a test's name is still description. check prints a hint naming the script-set form under a test file's \"not found\" reference errors, and check/test --help say a test file can be one of the set","insight":"The same silent-absence shape as the original @expect fix (#46), one level up: that fix made a line the parser could not compile an error, but a line the parser never LOOKED at was still dropped. `--list` printing the truncated text back is what made it look wired. Javadoc's rule (a block tag's text continues to the next tag) is the fail-closed choice; stopping at a blank line was considered and rejected because it re-opens the silent drop for an expression with a blank line in it, at the cost of turning prose written after the tags (seen once, in upgrade_source_test's fixture) into an ERROR with a message naming the fix. Runtime A/B on 11.13.0 (`mxcli test --local --db-type hsqldb`): baseline PASSED `$r = 'a;b'` + `and length($r) = 4` and FAILED the true `or` assertion with \"expected $r = 'zzz', actual: a;b\"; fixed inverts both. The paren-on-line-1 fixture is what makes `make check-mdl` fail if the continuation is lost again. Sibling not fixed: an untagged line after @throws is still ignored, so `@throws` + a message on the next line becomes \"any exception\"","test":"cmd/mxcli/testrunner/parser_multiline_annotation_test.go (8 tests; fail on revert with Raw = \"$r = 'zzz'\" etc.), cmd/mxcli/check_test_file_setup_hint_test.go TestCheck_TestFileMissingTargetPointsAtTheScriptSet (with the set-form and no-hint controls); mdl-examples/bug-tests/test-runner-1514-*.mdl","refs":["ako/mxcli#1514","mendixlabs/mxcli#1604"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"cmd/mxcli","date":"2026-10-25","symptom":"`mxcli run --local --page-check` and `mxcli playwright check` reported a page whose list view had not yet received its data as `text=37` with no `rows=` field, and the check exited 0 (\"OK 4 page(s)\"); the same URL checked again later read `rows=2 text=49`. A data source slower than ~1s, or than the 4s cap, was never waited for and nothing flagged the verdict as incomplete","cause":"pageProbeJS settled a page when its body text held still for three 250ms polls with no `.mx-progress/.mx-underlay-loading/[aria-busy]` element, capped at 4s, and broke out of the cap silently. Measured on 11.13.0: while a list view's microflow data source runs, `.mx-listview` sits EMPTY with no progress element, no aria-busy and no `.mx-listview-empty` placeholder, and the text holds still for the whole 2s/8s — the only sign is the open POST /xas/ runtimeOperation. Data grid 2 does render `widget-datagrid-spinner` with aria-busy=true, which is why grids were measured correctly and list views were not","file":"cmd/mxcli/docker/pagecheck.go (pageProbeJS settle loop, PageSignals.Unsettled/PendingRequests/WaitedMs/DataWidgets, formatPageVerdict, DefaultPageWaitMs), cmd/mxcli/docker/pagecheck_assert.go (EvaluatePage), cmd/mxcli/docker/runlocal.go (reportPageChecks), cmd/mxcli/cmd_playwright.go (--wait default + help)","fix":"the probe tracks same-origin requests (request/requestfinished/requestfailed, redirects collapsed) and counts a page settled only when none has been open for 500ms AND the text is unchanged AND nothing is busy; a page not settled by the cap is reported `STILL LOADING` with a `WAIT` line naming the open requests, and EvaluatePage fails it. The cap is now 15s (a cap, not a sleep: a fast page is still measured in ~1s). A page with a list view/data grid/gallery always prints `rows=`, rows=0 included","insight":"Decide what 'rendered' means by sampling the DOM and the network every 50ms during a deliberately slow data source (a Java action calling Thread.sleep behind a microflow data source), not by reasoning about Mendix: the list view gives NO DOM signal at all, so no selector-based wait could have been right, and the grid's spinner made the bug look intermittent. Also from the timeline: on a fast page the data request starts ~3ms AFTER `.mx-page` mounts, so 'no request open' must hold for a window (500ms), not an instant. Repro of the reported shape: the ledger's cold-boot first check is the same thing with the JIT as the slow part. A fake page in an httptest server reproduces it in a unit test; its /xas/ handler must read the request body before blocking, or r.Context() never sees the browser hang up and srv.Close() waits out the full simulated delay. Sibling not fixed: `run --local --screenshot` (screenshot.go) still shoots after a fixed 4s wait, so a PNG can show the same empty list","test":"cmd/mxcli/docker/pagecheck_settle_test.go: TestProbeWaitsForTheDataSourceToRender / TestProbeReportsAPageThatOutlastsTheWait drive the real probe against a fake page (skip without Node/Playwright; run with NODE_PATH set) and fail with the old probe JS (rows = 0, want 2; not reported as still loading); verdict/EvaluatePage tests fail with the Go side reverted. Runtime A/B on 11.13.0 (mdl-examples/bug-tests/pagecheck-845-slow-datasource.mdl): baseline `run --page-check` slow2/slow8 `text=37` no rows, `playwright check` OK exit 0; fixed rows=2 on all, and `--wait 3s` on the 8s page gives STILL LOADING, exit 1","refs":["ako/mxcli#845","ako/mxcli#714"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-25", "symptom": "(1) `alter microflow` with `insert after $X begin declare $Late Integer = 0; end;` and then `replace loop … with begin loop … set $Late = $Late + 1; … end;` passed check with a 'not predicted' note and failed at exec: 'the fragment has errors: variable 'Late' is not declared'. (2) A producer moved upstream — `create or modify` restating `$Code = call …` above the declare it followed, or the same as an alter insert+drop in either order — was refused 'the fragment declares $Code, which the microflow already has' (and, once past that, '$Code is still used by: log …; return $Code')", "cause": "Two variable verdicts of an alter block (and of the patch create or modify splices with, which is one) were still taken against the flow as stored: the fragment builder was seeded only with the stored flow's variables (storedVariables + the full build's entity types), so a later fragment could read but not `set` or member-access what an earlier operation declares; and checkFragmentScope refused a fragment declaring any variable a stored activity declares, at the moment it ran, before a later operation dropped that activity — while checkOutputUnused counted readers the inserted producer now feeds", "file": "mdl/executor/cmd_alter_flow.go (applyTo, fragmentBuilder, buildFragmentVars, noteFragment, checkOutputUnused, checkDeclaredUnclashed); mdl/executor/validate_flow_verdicts.go (alterFlowViolations)", "fix": "Each applied fragment's declared variables (with the types its builder resolved) seed later fragments' builders, in check's pre-build as in exec; the clash with a stored producer is judged once every operation is applied and skips one the block takes away (or whose loop it replaces); a stored or fragment reader of a removed output is no 'user' when another operation's fragment declares the variable upstream of it (declaredOnPath)", "insight": "2f42df658 moved checkOutputUnused to the end of the block but left its two siblings per-operation; any check that answers 'does this variable exist' has to be judged against the flow the block writes, or create or modify's own diff (which turns a reorder into insert+drop) trips it. A useful corollary: a create-or-modify body that builds declares each variable once, so a 'declares $X, which the microflow already has' refusal from the splice is always false — the 1361 test pinned one as expected and now asserts the splice. Known order rule kept: a declaration by a LATER operation is not known to an earlier fragment (check reports it unpredicted, exec refuses it)", "refs": ["ako/mxcli#1399", "mendixlabs/mxcli#1517", "mendixlabs/mxcli#1361"], "test": "TestAlterMicroflow_FragmentBuiltWithAnEarlierOperationsDeclaration, TestCreateOrModify_ProducerMovedEarlierKeepsItsReaders, TestAlterMicroflow_ProducerMovedEarlier (mdl/executor/cmd_alter_flow_block_vars_1399_pedapp_test.go); TestCheckFlowVerdicts_Issue1361_VariableClash"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-25", "symptom": "ako/mxcli#819 (follow-ups of #802), measured on a blank 11.13.0 app with security on. (1) `create or modify association Crm.Lead_Order from Crm.Lead to Hr.Employee owner both` — moving a cross-module OWNER Both association's TO end from Shop.Order — printed \"Modified association\" and mx check reported CE0066 \"Entity access is out of date\" at the domain models of both Shop (old TO) and Hr (new TO); moving it to another entity of the same module, or only changing the owner through create or modify, left CE0066 at the TO module. `update security` repaired Hr but not Shop. (2) `create association … from <non-persistent> to <persistent> owner both` passed check and exec and failed CE0001 \"An association between a persistable entity and a non-persistable entity must start in the non-persistable entity and have owner 'Default'.\"; so did a persistent FROM end under owner Default, and `alter association … set owner both`. (3) GRANT naming the TO-side member of a cross-module OWNER Both association (`read (Number, Lead_Order)`) already worked on main — fixed by 74bc820b7, verified 0 errors.", "cause": "(1) The cross-module OR MODIFY branch of execCreateAssociation overwrote ChildRef and owner and reconciled nothing itself; the end-of-program reconcile covered only the declaring module. And ReconcileMemberAccesses kept the old TO entity's entry even when its module was reconciled: a reference to another module's association was preserved on faith (the #758 rule for associations inherited across modules), and this one still exists, just not as a member. (2) No check or exec guard modelled CE0001.", "file": "mdl/executor/cmd_associations.go (OR MODIFY cross branch reconciles declaring, old TO and new TO modules via reconcileModulesAccess; refusals on create and alter set owner both); mdl/executor/validate_association_persistence.go (associationPersistenceViolation, projectEntityPersistence, storedAssociationEnds, ValidateAssociationPersistence — wired into ValidateProgram); mdl/backend/modelsdk/domainmodel_security_write.go (staleForeignRef: an existing foreign association on an entity whose generalization chain never leaves its module is stale unless collected as an incoming OWNER Both)", "insight": "The issue named one half of each defect. The move left a stale entry on the OLD TO module and a missing one on the NEW TO module — read the old ChildRef before overwriting it — and the CE0001 rule is two-sided: mxbuild's message (and a 4-cell measurement: NP->P default ok, NP->P both, P->NP default, P->NP both all CE0001) says FROM must be the non-persistable end AND owner Default, so refusing only `owner both` would have left the persistent-FROM case writing a broken model. Measure the whole matrix before scoping a refusal to the reported cell. For the reconcile, 'cannot be checked' was only true when the entity inherits from another module: with a module-local generalization chain the full member set is known (own + incoming OWNER Both), so anything else foreign is stale; the cross-module-inheritance control stays green. Persistability for the refusal comes from the backend (specializations resolved from their root, mendixlabs/mxcli#1600) in exec and from the script's own declarations first in check, through one predicate. A single bug-test script under-reports the move on the old binary: grants track Hr, so the end-of-program reconcile repairs the new TO module and only the old one shows.", "refs": ["ako/mxcli#819", "ako/mxcli#802", "ako/mxcli#1449"], "ce": ["CE0066", "CE0001"], "rules": ["MDL-ASSOC01"], "test": "mdl/executor/association_persistence_819_test.go (TestAssociationPersistenceViolation_MatchesMxbuild, TestValidateProgram_RefusesOwnerBothAcrossPersistenceFromTheScript, TestExecAssociation_RefusesOwnerBothAcrossPersistence, TestValidateAssociationPersistence_ResolvesTheProject, TestCreateOrModifyAssociation_MovingTheToEndReconcilesBothToModules); mdl/backend/modelsdk/reconcile_foreign_stale_assoc_test.go (TestReconcile_DropsAForeignAssociationWhoseToEndMoved, control TestReconcile_KeepsAForeignAssociationInheritedAcrossModules); mdl-examples/bug-tests/access-819-association-owner-both-member.mdl"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-25", "symptom": "`call java action BusinessEvents.PublishBusinessEvent_V2(Subject = 'Order shipped', BusinessEvent = $Event)` and `call java action AgentEditorCommons.Agent_CallDocument_WithoutHistory(Agent = 'M.MyAgent', …)` pass `check --references` and exec; mx check reports CE0115 \"The arguments that are passed to Java action '…' do not match the expected parameters and need to be refreshed\" at each call. `describe java action` showed the agent parameter as `Agent: String not null`; `describe microflow` printed a template value as its text only", "cause": "addCallJavaActionAction (mdl/executor/cmd_microflows_builder_calls.go) gave only entity-type and Microflow parameters their own value; a text-template parameter (CodeActions$StringTemplateParameterType) and a custom-document parameter (CodeActions$CustomBlobDocumentParameterType) fell to the default Microflows$BasicCodeActionParameterValue with the argument's source text. The document parameter TYPE also read back as a String (codeActionParamTypeFromGen had no case for it), and MDL had no way to write a template's {n} arguments at all", "file": "`mdl/executor/java_action_call_values.go` (javaActionTemplateValue, templateArgumentType + flowExprTypes, javaActionDocumentValue, javaActionCallValueErrors, MDL-JA02), called from `addCallJavaActionAction` and `validate.go` (validateFlowBodyReferences); `mdl/backend/modelsdk/microflow_write.go` / `microflow_read_actions.go` (PrimitiveTypedTemplateArgument, CustomBlobDocumentCodeActionParameterValue), `java_read.go` / `java_write.go` (CustomBlobDocumentType), `cmd_microflows_format_action.go` (describeTypedTemplate); grammar `callArgument … templateParams?` + visitor; tests `mdl/executor/cmd_microflows_builder_java_template_1451_test.go`, `mdl/backend/modelsdk/java_action_call_values_1451_test.go`, `mdl/visitor/visitor_java_action_template_1451_test.go`; fixtures `mdl-examples/bug-tests/java-action-1451-template-parameter.mdl`, `java-action-1451-expression-with-params.fail.mdl`", "insight": "**No Studio Pro reference exists here** (searched every .mpr/.mxunit/.mpk on the machine: 0 StringTemplateParameterValue, 0 CustomBlobDocumentParameterType outside module definitions; the Studio Pro MCP tunnel was down), so the shapes come from generated/metamodel and were *measured* against mxbuild 11.13 by hand-patching the unit (a throwaway Go probe over the v1 Unit table). What the probes settled, none of it guessable: a TypedTemplate argument is Microflows$PrimitiveTypedTemplateArgument{Expression, Type}; **Type is checked against the expression** (CE0117 for String-typed Integer, Integer-typed String, and for any Type on an enumeration expression — an enum is not one of the five); an absent Type reads as String; {1} with no argument is CE0720; Long attributes take Integer; `[%CurrentDateTime%]` takes DateTime — and exprcheck's inferKind calls every token a String, so use its argKind (now InferArgumentKind), which the built-in-function check already special-cased. The runtime hands Type to Java (ITemplateParameter.getParameterType), so the type is semantics, not decoration. For the document value mxbuild reports a wrong-type document as CE0115 and a missing one as CE1613 — check --references resolves agent-editor documents for that reason. The REST-body rule (#1444) carries over: a non-literal is '{1}' with the expression; but **describe must print `$X`, not `'{1}' with ({1} = $X)`**, because the declared-match pass (flow_declared_match) cannot know which CallArgument is a template, so only the short form re-execs as 'Unchanged' — except when the one argument is itself a string literal, which would read back as the text. A pre-fix build is no control for a script-created action: `create java action … StringTemplate(Text)` wrote a String parameter (separate fix), so the control is fixed-build action + pre-fix microflow (CE0115 x2), and the BusinessEvents module (CE0115 per call -> 0 errors)", "refs": ["ako/mxcli#1451", "mendixlabs/mxcli#1554", "ako/mxcli#1444", "mendixlabs/mxcli#1210"], "ce": ["CE0115", "CE0117", "CE0720", "CE1613"], "rules": ["MDL-JA02"], "test": "TestCallJavaAction_TemplateParameterWithArguments, TestCallJavaAction_TemplateParameterPlainString, TestCallJavaAction_TemplateParameterExpression, TestCallJavaAction_DocumentParameter, TestCallJavaAction_TemplateAndDocumentRefusals, TestCallJavaAction_TemplateAndDocumentDescribeRoundTrip, TestValidate_JavaActionTemplateAndDocumentArguments, TestJavaActionCallToGen_TemplateAndDocumentValues, TestJavaActionCallFromGen_TemplateAndDocumentValuesRoundTrip, TestJavaActionParamType_CustomBlobDocumentRoundTrips, TestCallJavaActionTemplateArgument, TestTemplateArgumentRefusedOutsideCallJavaAction"}
Loading
Loading