Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0dce312
fix(diff-local): implement the engine methods diff-local needs, and r…
ako Sep 10, 2026
1616cd5
fix(check): report a widget action's missing arguments (CE1571)
claude Sep 10, 2026
46e66ac
docs(syntax): teach the action argument list, and name the control ba…
claude Sep 10, 2026
be0303f
docs(soap): name the real reference, and what legacy gets wrong
claude Sep 10, 2026
d183e77
fix(soap): write names Mendix can resolve, not ids and guesses
claude Sep 10, 2026
a29e040
fix(soap): type the result from the receive mapping, not as Void
claude Sep 10, 2026
3ce3bdf
docs(soap): the parity test's note listed divergences since fixed
claude Sep 11, 2026
1daafa8
fix(marketplace): reconcile a transplanted module's access rules (CE0…
ako Sep 11, 2026
0d73eed
Merge remote-tracking branch 'origin/main' into claude/mendix-default…
claude Sep 11, 2026
1014f6f
fix(workflow): refuse an ALTER insert aimed at the wrong activity kind
claude Sep 11, 2026
bfb30c7
fix(soap): DESCRIBE prints the stored names; drop five dead resolvers
claude Sep 11, 2026
9e0cd46
docs(soap): propose syntax for the request body — arguments and send …
claude Sep 11, 2026
d14e973
Merge pull request #439 from ako/claude/mendix-default-styling-1fgvpm
ako Sep 11, 2026
f66b6a4
Merge branch 'mendixlabs:main' into main
ako Sep 11, 2026
6ad7ace
Merge pull request #440 from ako/claude/mxcli-unit-test-perf-n7ggx8
ako Sep 11, 2026
392cacd
Merge remote-tracking branch 'origin/main' into claude/mxcli-findings…
claude Sep 11, 2026
18dce5e
Merge remote-tracking branch 'origin/main' into claude/gallant-curie-…
claude Sep 11, 2026
642e7be
Merge pull request #442 from ako/fix/1085-marketplace-security-reconcile
ako Sep 11, 2026
6296dc4
Merge pull request #441 from ako/claude/mxcli-findings-nnl181
ako Sep 11, 2026
c5ec0d5
Merge origin/main into claude/gallant-curie-4vivo0
claude Sep 11, 2026
1294fe4
Merge pull request #443 from ako/claude/gallant-curie-4vivo0
ako Sep 11, 2026
331000e
fix(run): start --watch on a Mendix 11.14 app — the second copy of th…
ako Sep 10, 2026
23d16f4
fix(run): the 11.14 rebuild failure is mxbuild's, and not about the b…
ako Sep 10, 2026
5f9efe5
docs(run): the 11.14 config restore is a near-miss, not a workaround
ako Sep 10, 2026
388a490
Merge pull request #444 from ako/fix/mendix-1114-watch
ako Sep 11, 2026
f346134
fix(check): reject an unqualified association in an XPath constraint
ako Sep 11, 2026
a8a87a8
fix(demo): let take.js record the mobile pass its own skill mandates
ako Sep 11, 2026
f5ac008
fix(bootstrap,theme): four defects from ako/ChipCoV1's FINDINGS.md
ako Sep 11, 2026
cd3cddb
fix(brain): resolve a module-role anchor, and refuse a module one on …
ako Sep 11, 2026
9035657
Merge pull request #445 from ako/fix/chipco-findings
ako Sep 11, 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
7 changes: 7 additions & 0 deletions .claude/skills/fix-issue/findings/cmd-mxcli.jsonl

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions .claude/skills/fix-issue/findings/mdl-backend.jsonl
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,5 @@
{"area": "mdl/backend", "date": "2026-09-08", "symptom": "`alter page P { set PageSize = 10 on <datagrid2> }` errors `pluggable property \"PageSize\" not found` on a grid that `create page \u2026 (PageSize: 20)` had just written and the app really pages at. `mxcli check --references` passes the script, so it fails only at exec, after earlier statements have landed; DESCRIBE PAGE prints the same capitalised `PageSize:`, so describe \u2192 edit \u2192 exec produced a script mxcli refused to run", "cause": "A pluggable property key is lowerCamel in the widget template (`pageSize`). CREATE resolves the author's spelling case-INsensitively (widget engine `lookupProperty`, and `WidgetV3.GetStringProp` before it); ALTER went through `setPluggableWidgetPropertyMut`, which compared the template key byte-for-byte, so only the exact `pageSize` worked. Direct sequel to Findings #1 (2026-07-27), which fixed the same class for FIRST-CLASS props and deliberately left the pluggable fallback case-sensitive with the comment 'template keys must match the template exactly'", "file": "`mdl/backend/pagemutator/mutator.go` (`setPluggableWidgetPropertyMut`)", "insight": "`strings.EqualFold` against the widget's own PropertyTypes. **The disproven belief is the reusable part**: keys are STORED case-sensitively, which is not a reason to MATCH them that way \u2014 the resolver searches one object type's PropertyTypes, and across every shipped template and definition that scope holds no two keys differing only in case (96 scopes, 1208 keys, 0 collisions). Measure the ambiguity before assuming it; here there was none, and the assumption cost a whole verb. **Cheapest localiser**: run the failing statement with the template's own casing \u2014 `set pageSize` succeeded where `set PageSize` failed, in ONE measurement, on the same widget in the same project. Both engines share `pagemutator`, so an engine split says nothing here (verified: modelsdk and legacy both fixed by the one change). Tests `TestSetPluggableProperty_MatchesTemplateKeyRegardlessOfCase` (+ typo-still-errors control, + `TestPluggablePropertyKeysAreUniqueIgnoringCase` pinning the no-collision argument); repro `mdl-examples/bug-tests/alter-page-pluggable-property-casing.mdl`; verified 0 errors on `mx check` 11.13.0. Two reporter claims did NOT hold: `describe page` DOES emit PageSize, but only when it differs from the widget default 20 (deliberate, so describe round-trips) \u2014 at the default it is omitted, which reads as 'describe cannot show it'. Still open and separate: `check --references` does not resolve pluggable property names at all, so a genuine typo (`PagSize`) still checks clean and fails at exec", "refs": ["mendixlabs/mxcli#1069"]}
{"area": "mdl/backend", "date": "2026-09-09", "symptom": "A control that should have proven a guard was load-bearing PASSED with the guard removed — the test could not distinguish a correct writer from one that reset the property on every write", "cause": "The fixture stored `false` for a boolean property, and false is also the zero value. A writer that ignored the spec entirely wrote false; the correct writer preserved false. Identical output, so the assertion held either way", "file": "`mdl/backend/modelsdk/navigation_throw_sync_test.go`", "insight": "For a BOOLEAN property, a preservation test must exercise BOTH stored values — the non-zero one is the only case that can fail. This is the second time in one feature: CompatibilityMode needed a synthetic `true` because all seven reference configs carry false. The generalisation: when every real document agrees on a value, the fixture drawn from real documents cannot test preservation, and a synthetic counter-case is not optional. The tell is a control that fails to fail — if stubbing the guard leaves the suite green, the test is measuring nothing, and that is worse than no test because it reads as coverage", "refs": ["ako/mxcli#413", "ThrowPartialSyncError"]}
{"area": "mdl/backend", "date": "2026-09-09", "symptom": "`call web service` (legacy SOAP) on the DEFAULT engine: `mxcli exec 06b-soap-examples.mdl` reported success on all three microflows and `mx check` (11.13.0) then failed the project with `[CE0008] \"No action defined.\" at Action activity 'Activity'` plus two `[CE0109] \"Undefined variable 'Root'.\"`. Only reachable by rerunning with MXCLI_ENGINE=legacy, which is why legacy was still the documented fallback", "cause": "The codec engine READ the action (`actionFromGen` \u2192 `*microflows.WebServiceCallAction`, with a raw fallback) but `microflowActionToGen` had no case for it, so it hit `default: return nil` and the enclosing ActionActivity serialized with no action at all. The #850 shape: a missing WRITE case is not an unsupported feature, it is a silent drop that exec reports as success. The CE0109s are knock-on \u2014 the dropped action never bound $Root", "file": "`mdl/backend/modelsdk/microflow_webservice_write.go` (new), `microflow_write.go` (switch case)", "insight": "**Mirror the legacy serializer, and prove it by diffing the two engines' documents \u2014 do not re-derive the shape from the metamodel.** There is no Studio Pro-authored SOAP document in this repo, so legacy's output is the only reference that exists and is also what users' projects already contain. Method: exec the same script on each engine, `mxcli bson dump` both, normalise the random $IDs, diff. Three discrepancies fell out that no amount of reading would have shown, all in how the codec emits NULLS and MARKERS: (1) a Part property with no child encodes to nil and the encoder then SKIPS the key (`if val != nil`), so an unset part is an ABSENT key, never a null one \u2014 carry the null as a primitive `bson.Null{}` value instead, which marshals in place; (2) `codec.TypeDefaults.NullFields` does emit the key but APPENDS it after every property, so it cannot reproduce alphabetical key order; (3) both NullFields and list markers are registered per `$Type` and several types are SHARED between writers \u2014 `Microflows$HttpConfiguration` needs HttpHeaderEntries marker 3 for SOAP and 2 for REST, and legacy writes CustomLocationTemplate as null for SOAP but omits it for REST, so a global registration would have silently changed the REST path. Write those explicitly per call site. (The package already carries one such collision: `Microflows$HttpHeaderEntry` is registered 2 in microflow_write.go and 3 in odata_write.go, decided by file order.) Verified: the two engines' CallWebServiceAction documents are now identical key-for-key and value-for-value; `mx check` goes 3 structural errors \u2192 0, leaving only the script's 4 deliberate CE1613 dangling refs, which is exactly legacy's output. Revert control: removing the switch case fails all six unit tests with the CE0008 message. The doctype engineScriptSkip for modelsdk/06b was removed and the script now runs on BOTH engines", "refs": []}
{"area": "mdl-backend", "date": "2026-09-10", "symptom": "`mxcli diff-local` on an MPR v2 project fails with `Error: mprcontents directory not found` while mprcontents/ exists and is populated; `MXCLI_ENGINE=legacy` works", "cause": "The modelsdk engine (the default) never overrode `Backend.ContentsDir()`, so it fell through to the generated `unimplemented` stub and returned \"\". diff-local reads \"\" as 'not a v2 project'.", "file": "mdl/backend/modelsdk/backend.go", "insight": "gen_unimplemented.go's promise that an unoverridden method 'fails loudly rather than silently dropping data' is CONDITIONAL on the method having an error to fail through: the generated body is `errUnimplemented` only when a result is `error`, a panic when there are no results at all, and a silent `var r0 T; return r0` otherwise. ContentsDir is in the third bucket and its zero value is a MEANINGFUL in-band answer (\"\" == MPR v1), so the missing implementation was indistinguishable from a v1 project rather than looking like a bug. The detectable signature was the contradiction between two questions the same command asks: Version() (implemented) says 2, ContentsDir() says v1. Guard added in mdl/backend/modelsdk/unimplemented_silent_test.go \u2014 reflect over FullBackend for error-less methods, go/parser the package for methods actually declared on *Backend, since reflection cannot tell a promoted method from an override (Go synthesises a wrapper named (*Backend).X for both). It immediately found a second one, InvalidateCache (a latent panic, no caller today).", "refs": ["mendixlabs/mxcli#1080"]}
{"area": "mdl/backend", "date": "2026-09-10", "symptom": "SOAP `call web service` writes a document mxbuild accepts and Studio Pro would not have written. A SEND MAPPING is silently DROPPED by both engines \u2014 `send mapping Mod.Export` parses, `mxcli check` passes, `exec` reports success, and nothing in the stored action references the mapping. Operation ARGUMENTS are dropped the same way", "cause": "sdk/mpr.serializeWebServiceCallAction was written without a Studio Pro reference and hardcodes five things it cannot know, and the codec engine's new writer reproduced it deliberately for parity. Measured against three Studio Pro-authored calls in ako/TestApp (Mendix 11.14.0, Clients.GetOrders / GetCustomerOrders / SaveOrder): ServiceName is the WSDL SERVICE name (\"OrdersWS\") not the local part of the imported service's qualified name (\"OrderSoapClient\"); ImportMappingCall.ContentType is \"Xml\" for a SOAP import mapping, not \"Json\"; Range.SingleObject follows cardinality (false for a list) rather than being always true; VariableType is the real result type (DataTypes$ObjectType with an Entity, DataTypes$BooleanType) rather than always DataTypes$VoidType; and a send mapping is Microflows$MappingRequestHandling {ContentType, MappingId, MappingVariableName}. Arguments live in RequestBodyHandling.ParameterMappings as Microflows$WebServiceOperationSimpleParameterMapping entries keyed by an escaped ParameterPath (\"http%3A//www.example.com/:GetOrder|OrderId\")", "file": "`sdk/mpr/writer_microflow_actions.go` (serializeWebServiceCallAction), `mdl/backend/modelsdk/microflow_webservice_write.go`", "insight": "**A guessed type name in a comment becomes a permanent refusal.** Legacy refused send mappings citing `Mendix$AdvancedRequestHandling`, said it 'requires a Studio Pro-generated example to determine the correct type storage name', and that refusal then shipped for as long as nobody went looking. The real type is `Microflows$MappingRequestHandling` \u2014 which THIS CODEBASE ALREADY WRITES for REST result/request handling \u2014 and the guessed name occurs in none of the three reference documents. The lesson is not about SOAP: when a writer refuses because a storage name is unknown, check whether a sibling feature already writes it before treating the refusal as a standing constraint. **Second, and the reason this was found at all: 'no reference exists' is a claim about where you looked.** The parity work asserted that no Studio Pro-authored SOAP document existed to pin against and used that to justify mirroring legacy; one existed in a separate repo the whole time (ako/TestApp, which carries both a consumed client and a published service). Byte-parity with what ships is a legitimate goal for a change scoped to stopping a silent drop \u2014 it is NOT evidence the shape is right, and conflating the two is how six defects got a passing test. Where a reference project exists, name it in the code so the next reader does not repeat the search", "refs": []}
Loading
Loading