Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
51ca51c
ci: run the macOS tunnel-seam leg on main and nightly, not on PRs
claude Nov 3, 2026
53a4796
fix(grammar): a member named Error before `message` is not the error-…
claude Nov 3, 2026
4482397
perf(grammar): move the ERROR_MESSAGE predicate to the right edge (#1…
claude Nov 3, 2026
056c58e
Merge pull request #1916 from ako/feature/macos-main-nightly-only
ako Nov 3, 2026
2de8a1e
Merge pull request #1919 from ako/claude/issue-triage-prioritization-…
ako Nov 3, 2026
f663e32
fix(run): run stop removes a --test-endpoint the run could not (#1917)
claude Nov 3, 2026
57ba383
fix(microflows): keep a call external action's associations to includ…
ako Nov 3, 2026
0f53383
docs(run-local): keep the skill under its 700-line cap, refresh its i…
claude Nov 3, 2026
0308a03
fix(modules): keep the module ID and Marketplace checksum on a jar de…
ako Nov 3, 2026
86d6136
docs(proposals): module settings — describe and set version and modul…
ako Nov 3, 2026
78b5325
Merge branch 'main' into fix/1914-external-action-included-associations
ako Nov 3, 2026
8ab1340
Merge pull request #1922 from ako/fix/1914-external-action-included-a…
ako Nov 3, 2026
aaa09f8
Merge branch 'main' into fix/1920-module-settings-carry
ako Nov 3, 2026
4475045
Merge pull request #1923 from ako/fix/1920-module-settings-carry
ako Nov 3, 2026
5dae9a0
feat(modules): describe and set a module's version and module type (#…
ako Nov 3, 2026
616b892
Merge remote-tracking branch 'origin/main' into claude/issue-triage-p…
claude Nov 3, 2026
05acd9d
Merge remote-tracking branch 'origin/main' into feature/1921-module-s…
ako Nov 3, 2026
b375522
Merge pull request #1924 from ako/claude/issue-triage-prioritization-…
ako Nov 3, 2026
d3acaf0
fix(test): --attach no longer leaves the hosting app's pages 404 (#1917)
claude Nov 3, 2026
d59c664
Merge pull request #1925 from ako/feature/1921-module-settings
ako Nov 3, 2026
d8d1d1c
Merge pull request #1926 from ako/claude/issue-triage-prioritization-…
ako Nov 3, 2026
57568d8
fix(marketplace): update no longer drops the module and then fails (#…
claude Nov 3, 2026
81ab5b9
Merge pull request #1936 from ako/claude/issue-triage-prioritization-…
ako Nov 3, 2026
d40d34f
fix(microflows): a condition edit no longer inverts a folded decision…
claude Nov 3, 2026
00d89c0
Merge pull request #1937 from ako/claude/issue-triage-prioritization-…
ako Nov 3, 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-11-03", "symptom": "ako/mxcli#1934 (mendixlabs/mxcli#1732): `marketplace update 170 --to 11.5.1 --force` (Community Commons) failed with \"install the new version's bundled files: open package target.mpk: … no such file or directory\" after it had already dropped the installed module and copied units: the project was left half-updated (245 files deleted in mprcontents/) and had to be restored from git.", "cause": "Two defects. The caller derived the package path itself as work/target.mpk, while referenceFor(…, \"t\") downloads to work/t.mpk — so every update looked for a file that never existed. And PerformUpdate read the package only after `drop module`, TransplantModule, identity and grant restore, so the missing input surfaced after the destructive steps.", "file": "cmd/mxcli/cmd_marketplace_diff.go (referenceFor returns the package path it downloaded to), cmd/mxcli/cmd_marketplace_update.go (uses it; no 'mid-update' warning when nothing was written), cmd/mxcli/marketplace/update.go (preflightUpdate before the drop: reference project opens and holds the module, package opens; ErrUpdateNotStarted)", "insight": "A destructive multi-step operation must read every input it will need before the first write — the order, not just the input, was the bug: with the path fixed, a corrupt download or a reference without the module would still have stranded the project. And a path two functions agree on by convention ('the slot letter plus .mpk') belongs to one of them: returning it from referenceFor makes the mismatch impossible rather than corrected. The test hashes every file of a fixture project before and after PerformUpdate with a missing package / reference project; on main both cases changed the project (the reported 'open package' error after the drop), with the preflight stubbed they fail again. The full command needs the marketplace (a PAT) and mx, so it was not driven end to end here.", "refs": ["ako/mxcli#1934", "mendixlabs/mxcli#1732", "ako/mxcli#641"], "test": "cmd/mxcli/marketplace/update_preflight_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-11-03", "symptom": "ako/mxcli#1917 (mendixlabs/mxcli#1723): after `run --local --test-endpoint --detach` and `run stop` on Windows the project kept module MxTest, AfterStartupMicroflow 'MxTest.RegisterEndpoint', themesource/mxtest/ and javasource/mxtest/ — git status dirty, and once MxTest was dropped the next build failed CE1613 on the after-startup. Reported success throughout.", "cause": "The endpoint is removed only by HostedEndpoint.Remove inside the dev-loop process (a defer and the os.Exit path). On Windows terminateProcess is `taskkill /T /F` — the code comment even said the teardown does not run — so a detached run never got to Remove; on any platform a SIGKILL after stopGrace or a crash skipped it too. Nothing outside the process knew what to undo.", "file": "cmd/mxcli/testrunner/host_restore.go (restore record + RestoreAbandonedEndpoint), cmd/mxcli/testrunner/host.go (record written before install, removed by Remove, stale one cleaned before a new install), cmd/mxcli/cmd_run_lifecycle.go (runStop restores after the process is gone)", "insight": "Teardown that lives in a process's exit path needs a durable record the moment it has something to undo, because a stop the process cannot see (taskkill /F, SIGKILL, crash) is a normal stop on one platform. The record carries the pre-install .mpr bytes and tree digest so the cross-process restore is as byte-exact as the in-process one, and it is gated on the owner PID being dead so a live run's endpoint is never pulled. The Windows bug reproduces on Linux by SIGKILL-ing the detached run before `run stop` — that is what taskkill /F is — so the integration test runs where mxbuild does; the graceful SIGTERM stop is the control (it already restored). Revert proof: a binary with only the runStop call stubbed fails the killed-run phase with the reported leftovers; beware a stub that does not compile (unused import) — the test then fails in 9 s for the wrong reason. The second half of the issue (dist/pages 404 after `test --attach`) is a separate cause: runAttached's applyModelChange calls serve.Build directly, bypassing the bundler/serve-recovery path the run's own reload uses; reproduced on Linux 11.12.6.", "refs": ["ako/mxcli#1917", "mendixlabs/mxcli#1723", "mendixlabs/mxcli#1645"], "test": "cmd/mxcli/cmd_run_test_endpoint_integration_test.go (integration && linux, mxbuild 11.12.6); cmd/mxcli/testrunner/host_restore_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-11-03", "symptom": "ako/mxcli#1917 (mendixlabs/mxcli#1723): after a green `mxcli test --attach` against `run --local --test-endpoint`, the hosting app answered 404 on dist/pages/<Module>.<Page>.js and every page showed the generic error dialog until the app was restarted. Reproduced on Linux with Mendix 11.12.6 (reported on Windows): dist/pages held 0 page modules after the attach.", "cause": "runAttached's applyModelChange built with a bare ServeServer pointed at the dev loop's serve port. Every attach build is a later build in that mxbuild --serve process, and on the prebuilt-client versions a later build replaces web/dist with a monolithic bundle without pages (mendixlabs/mxcli#1580). The dev loop's own reloads go through serveRecovery, which restarts the serve process on that outcome; the attach bypassed it, and could not reuse it as is, because the serve process belongs to the other mxcli.", "file": "cmd/mxcli/docker/serve_attached.go (AttachedServe: serveRecovery over a borrowedServe whose Restart starts a private mxbuild --serve on a free port instead of touching the host's; Close stops only that), cmd/mxcli/testrunner/runner_attach.go (builds through it, closes it when the attach ends)", "insight": "A recovery that lives in one process's loop does not travel with the API it drives: the attach called the same /build endpoint and inherited the defect but not the fix. Reuse the recovery and swap only its Restart for one this process owns — the host's serve is left in its stale state, which its own serveRecovery already handles on its next build. The cleanup build lands on the private serve as a later build too, so it restarts that one: two cold builds per attach, the price #1580 already set (correct beats fast). Integration test drives the reporter's sequence with a real 11.12.6 runtime and GETs a page module the boot produced (control: 200 before the attach); a binary whose AttachedServe.Build bypasses only the recovery fails it with 0 page modules left. A lingering java process after the run is mxbuild's Gradle daemon, not a leaked serve.", "refs": ["ako/mxcli#1917", "mendixlabs/mxcli#1723", "mendixlabs/mxcli#1580"], "test": "cmd/mxcli/cmd_test_attach_bundle_integration_test.go (integration && linux, mxbuild 11.12.6); cmd/mxcli/docker/serve_attached_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-11-03", "refs": ["ako/mxcli#1920"], "ce": [], "symptom": "`alter module … add | set | drop jar dependency` reports success and mx check stays clean, but the module's Projects$ModuleSettings loses PackageId (Studio Pro's Module ID) and, on a Marketplace module, its Checksum, and EnableDetailedTroubleshooting flips from false to true.", "file": "mdl/backend/modelsdk/module_settings_write.go (UpdateModuleSettings, moduleSettingsContents); test module_settings_carry_test.go with fixture testdata/TestApp.WorkflowCommons.ModuleSettings.11_16.bson", "cause": "UpdateModuleSettings marshalled a fresh bson.M of the nine keys types.ModuleSettings models; the six it does not (PackageId, Checksum, ConvertedChecksum, OriginalPackageId, ModuleDependencies, EnableDetailedTroubleshooting) were absent, and canon.CompletePropertySets put the names back with metamodel defaults rather than the stored values. The default enableDetailedTroubleshooting is true, which is why a false came back true.", "insight": "**A completed property set looks like a carry and is not one.** The rewritten unit had every key Studio Pro writes, so a key-presence check passed; only comparing VALUES against the stored unit showed the loss, and only on a module whose values differ from the defaults — an app module made by mxcli or Studio Pro holds defaults everywhere but PackageId, so the reproduction has to be a Marketplace module (WorkflowCommons in ako/TestApp: a Checksum, a PackageId and troubleshooting off). The fix starts the document from the stored keys and overwrites only the modelled ones, rather than adding six more fields to the rebuild, so the next key Studio Pro adds is carried too. One writer only (cmd_modules.go is its sole caller); CreateModule still writes a new module without a PackageId, unmeasured against Studio Pro. Control: the extracted function ignoring the stored bytes fails the fixture test on Checksum, PackageId, EnableDetailedTroubleshooting, ConvertedChecksum and OriginalPackageId; end to end on a TestApp copy the jar statement now changes only JarDependencies and mx check (11.16.0 Beta) reports 0 errors."}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-03", "refs": ["ako/mxcli#1914", "mendixlabs/mxcli#1721"], "ce": [], "symptom": "A `call external action` whose object parameter has \"Associations to include\" ticked in Studio Pro loses them on every `create or modify microflow` that restates the call: the OData request then carries only the object's own attributes and silently drops the associated objects at runtime. DESCRIBE shows nothing, and check, lint and docker check all pass.", "file": "mdl/executor/external_action_carry.go (carryIncludedAssociations, wired in cmd_microflows_build.go); mdl/backend/modelsdk/microflow_read_actions.go (includedAssociationsFromGen); mdl/backend/modelsdk/microflow_external_action_write.go (includedAssociationsToGen, marker-2 lists); sdk/microflows ExternalActionParameterMapping.IncludedAssociations", "cause": "The semantic model had no field for Microflows$ExternalActionParameterMapping.IncludedAssociations, the reader did not read it, callExternalActionToGen built each mapping from scratch, and the rebuild had no MDL to take it from. Same class as rewrite-drops-unauthored-state.", "insight": "**The report called it a boolean flag; it is a tree.** The Studio Pro reference (ako/TestApp Odata.IncludeAssociationsMF, 11.16.0 Beta) stores a list of Microflows$IncludedAssociation {Association, IncludedAssociations, IsParent} per parameter mapping, an association ticked under another nested in its IncludedAssociations; marker 2 at both levels; IsParent true where the object on that side is the association's FROM (ParentPointer) entity. The control microflow (_Off, nothing ticked) differs only in that list, so one property is the whole test. Building the reference took two contracts: Studio Pro refuses a ComplexType action parameter (R017 \"One of the parameters is not supported\"), so the reporter's DTOs are entity types without an entity set. **Matching stored to rebuilt calls cannot use position**: a flow's stored object order is Studio Pro's, not the statement's. The carry keys on service.action and parameter name; when two stored calls to one action hold different trees it refuses, and a shared tree carried twice gets fresh $IDs on the second copy. A tree is not carried onto a parameter whose resolved entity changed. **Under `mdl 1;` the rewrite usually does not reach the rebuild at all**: create or modify splices into the stored flow by re-parsing DESCRIBE's output, and for this reference that output is `additional = )` (Studio Pro 11.16 stored an unfilled nullable argument as \"\", which DESCRIBE prints bare), so every mdl-1 rewrite of the microflow is refused before anything is lost; the carry covers headerless scripts and the rebuild fallback. ALTER passes the untouched call through as stored bytes and was never affected. **mx check could not be the end-to-end check**: Studio Pro 11.16.0 Beta's mx crashes (NullReferenceException in DocumentCheck) on the untouched TestApp too. Controls: disabling the carry call fails TestCreateOrModify_CarriesIncludedAssociations; disabling the writer's list fails TestCallExternalAction_IncludedAssociationsRoundTrip on the On fixture while the Off fixture passes. **Left out on purpose**: AdditionalAttributes (no reference holds one), the action-level IncludedAssociations (empty in both references), and the empty marker lists Studio Pro writes on every mapping (version-gated: 10.11+ / 11.5+, unwritten since #1073)."}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-03", "symptom": "ako/mxcli#1930 (mendixlabs/mxcli#1728): a validation decision (`if trim($X/Code) != '' then else set $Valid = false; end if;`) is described folded, `if not(trim($X/Code) != '') then set $Valid = false; end if;`. Feeding that description back through `create or modify microflow` with only the condition text changed stored `not(trim($X/Reference) != '')` as the decision's expression while its true/false flows stayed: the decision was inverted, and check --references, exec (\"spliced: 1 edited in place\") and diff all looked harmless.", "cause": "describe's empty-then swap (true path straight to the merge, false path with content) prints negateIfCondition(expr) and swaps the paths, but the splice's in-place condition edit (patchDiff.conditionEdit → splitCondition → SetCondition, ako/mxcli#888) stored the script's condition text as it was. The flows are untouched by a condition edit, so the printed negation went into the model un-negated.", "file": "mdl/executor/cmd_alter_flow.go (splitCondition negates when decisionPrintedNegated), mdl/executor/cmd_microflows_show_helpers.go (negateExpression extracted from negateIfCondition; decisionPrintedNegated recomputes describe's fold from the stored flows with findSplitMergePoints + findBranchFlows)", "insight": "A describer that rewrites what it prints (here: negate and swap for readability) creates an obligation on every path that reads its output back: the inverse transform. Decide the fold from the stored flows with describe's own merge computation, never from the text — describe also strips a stored not(Z) to Z, so 'the printed condition starts with not(' detects neither case reliably. negateExpression is its own inverse, which is what makes the round trip exact: printed not(Y) stores Y, printed Z stores not(Z). Test: create the reporter's flow on a pedapp copy, describe, change only the attribute in the printed condition, exec under mdl 1; assert the decision kept its $ID and stores the un-negated expression, for both fold shapes; with the negation stubbed both fail with the inversion. A decision in a loop body is not edited at all (the splice refuses), pinned by a second test.", "refs": ["ako/mxcli#1930", "mendixlabs/mxcli#1728", "ako/mxcli#888", "ako/mxcli#1761"], "test": "mdl/executor/flow_splice_negated_condition_pedapp_test.go"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/grammar", "date": "2026-11-03", "symptom": "ako/mxcli#1913 (mendixlabs/mxcli#1720): `validation feedback $Entity2/Error message 'not good';` failed check with \"missing MESSAGE at ''not good''\" for an attribute named Error (any case) — exactly what describe writes for such an attribute, so describe output for the microflow did not re-parse; quoting it (`$Entity2/\"Error\"`) worked.", "cause": "ERROR_MESSAGE is one compound lexer token (`E R R O R WS+ M E S S A G E`, for the `error message` clause). The lexer has no context, so the member name and the MESSAGE keyword after it were swallowed into it and the path ended at `$Entity2/`.", "file": "mdl/grammar/MDLLexer.g4 (right-edge predicate {!p.followsMemberSeparator()}? on the grouped ERROR_MESSAGE alternatives, helper in @lexer::members reading TokenStartCharIndex); cmd/gen-completions/main.go (firstAlternative strips the group's opening paren, else ERROR MESSAGE dropped out of lsp_completions_gen.go)", "insight": "A multi-word lexer token is a keyword collision that no keyword list shows: `Error` and `message` are each fine as names, only the pair collides, so lexesAsBareIdentifier/mdlIdent cannot see it and quoting in describe would not have helped an unquoted script. Fixing it in the lexer, not the one parser rule, covers every position an attribute path can take. Two traps in the predicate: skipping line breaks backwards lets a line comment ending in '.' or '/' (`-- see the docs.`) read as a separator and break the clause on the next line, and a block comment's closing `*/` ends in a slash — both are controls in the test, and the newline-skipping draft failed them. `$` inside an @lexer::members comment is an ANTLR attribute reference (error 128), and gen-completions reconstructs a multi-line rule from its first line, so a grouped `( E R R O R …` must have its paren stripped there. **A lexer predicate goes on the right edge**: the first version put it on the left edge, which ANTLR evaluates at every token start, disabling the lexer DFA cache — `check` over 300 example scripts went from 43 s to 91 s and the conformance and upgrade corpus tests hit the 30-minute timeout, while every unit test passed. On the right edge it runs only after `error message` matched (42 s vs 44 s, noise); the token start then comes from TokenStartCharIndex, since LA(j<0) is relative to the current index. Time a lexer change against a control binary, not just its tests. Proven by stubbing the predicate to false (the reported 'missing MESSAGE' returns in the visitor and describe round-trip tests) and by a control-binary sweep of all 1210 .mdl files in the repo: identical results.", "refs": ["ako/mxcli#1913", "mendixlabs/mxcli#1720", "docs-wiki/bug-patterns/keyword-collisions.md"], "test": "mdl/visitor/error_member_name_test.go; mdl/executor/cmd_microflows_format_action_test.go (TestFormatAction_ValidationFeedback_MemberNamedErrorReparses); cmd/gen-completions/predicate_test.go"}
Loading
Loading