From be66e187cf623b2a148c78bf7b47576d3090c13b Mon Sep 17 00:00:00 2001 From: r Date: Fri, 25 Sep 2026 15:03:24 +0000 Subject: [PATCH] learn(bug-logs, skills): module-rename field report, M1-M17, re-checked on v0.24.0 A colleague's naming-conventions change on mxcli v0.23.0 / Mendix 11.12.4 reported mxcli defects. This commit de-duplicates them against the ledger and re-checks each on v0.24.0 where a probe was cheap, using a scratch copy of a small PoC model. - 7 new BUG-DRAFT entries. Verified on v0.24.0: rename-module XPath, rename-page renames the folder (root cause: first Name match, no $Type check), case-only folder twin, check --references with an in-script rename, diff-local missing untracked units, diff-local UUID module. Check half only: DG2 association path bindings. - Addenda: BUG-62 (no rename snippet), BUG-63 (microflow_type case, SQL vs Starlark entity types, activity_count scope; title widened), BUG-102 (legacy grid XPath has no offline route). - One note for the feature asks: lint conventions, rules dir, catalog gaps, MPR006 claim. - Four upstream drafts, NOT YET FILED. - STOP row 26 in learned-mdl-preflight.md. - Lint vocabulary note with a before/after in lint-that-actually-runs.md. Claude-Session: https://claude.ai/code/session_01VJgWP5vEoAsNsJYqCDMGNw Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 3 + bug-logs/mxcli-bugs.md | 200 +++++++++++++++++- .../dg2-association-path-bindings.md | 41 ++++ .../diff-local-misses-new-units.md | 47 ++++ .../rename-module-leaves-xpath.md | 61 ++++++ .../rename-page-renames-folder.md | 55 +++++ skills/learned-mdl-preflight.md | 1 + skills/lint-that-actually-runs.md | 24 +++ 8 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 bug-logs/pending-github-issues/dg2-association-path-bindings.md create mode 100644 bug-logs/pending-github-issues/diff-local-misses-new-units.md create mode 100644 bug-logs/pending-github-issues/rename-module-leaves-xpath.md create mode 100644 bug-logs/pending-github-issues/rename-page-renames-folder.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 30ebae98..4b927c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ three commits past it), and a bug report can name a release instead of a sha nob Sections dated before 2026-09-19 predate the cycle and stay as they are. ## Unreleased +- learn(bug-logs): **7 new drafts, 3 addenda and one feature-ask note from a module-rename field run, each re-checked on v0.24.0 where a probe was cheap.** New: `rename module` leaves XPath naming the old module; `rename page` renames a same-named folder instead (reproduced; root cause is a name match with no type check); a case-only `move` leaves an empty folder twin; a quoted DataGrid 2 association path passes `check` and fails CE1613; `check --references` ignores an in-script `rename module`; `diff-local` misses new (untracked) units; and `diff-local` prints a UUID for the module. Addenda: BUG-62 (no `rename snippet`), BUG-63 (`microflow_type` case, SQL-vs-Starlark entity types, `activity_count` scope; title widened), BUG-102 (legacy grid XPath has no offline route). Paste-ready upstream drafts for four, not filed. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4) +- learn(skills/learned-mdl-preflight.md): **STOP row 26: DataGrid 2 column and `sort by` paths over an association.** Write the column path unquoted, and do not sort over an association on ≤ v0.24.0. Both wrong forms pass `check --references` and fail CE1613 at build. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4) +- learn(skills/lint-that-actually-runs.md): **three more lint vocabulary facts, verified on v0.24.0, with a before/after rule.** `microflow_type` is `MICROFLOW`/`NANOFLOW`/`RULE`, and `microflows()` yields all three. SQL `PERSISTENT` is Starlark `Persistent`. `activity_count` counts top-level objects (splits, loops, annotations), not actions, and `activities_for()` does not see loop bodies. — field report from a colleague's naming-conventions project (mxcli v0.23.0, Mendix 11.12.4) - learn(skills/learned-file-upload-widget.md): **a file upload mxcli can author, with proof that it uploads.** The Mendix File Uploader 2.5.0 bound to a `System.FileDocument` specialisation: the MDL shape (entities, grants, create/delete microflows, advanced formats), which upload widgets mxcli cannot author (classic FileManager, PDS uploader), the two traps with workarounds (a simple-mode `allowedfileformat` passes exec and fails `mx check` with CE0463; an uploader DESCRIBE will not re-exec, `exposes 2 datasources`), and the six-step upload instrument. Field run on stock v0.24.0: the section-4 MDL taken verbatim from the skill gave `mx check` 0 errors, 2/2 files stored, 2/2 downloads sha256-equal, `.csv` rejected with 0 rows; both traps reproduce unchanged on v0.24.0 — a Mendix app-rebuild project - new(skills/mendix-best-practices-index.md): **one row per Mendix best-practice area: the Mendix docs page, the bundled `assess-quality` section, the toolkit skill that applies it before the write, and the `mxcli lint` rule that catches it after exec.** An index, not a copy — the practice text stays on the Mendix pages (17 URLs verified HTTP 200 on 2026-09-25) and in the mxcli-bundled skill; Mendix's own Best Practice Recommender rules (MXP001–016) anchor the performance rows, and four rows say out loud that no lint rule exists and the preflight checklist is the only check. Routed `all` agents, stages 3/5/6, group reference — Maurits Visser - learn(skills/microflow-preflight.md, agents/mdl-agent.md): **a microflow now gets a tier before any MDL — Simple, Guided or Split-first — and Split-first means a posted split plan (thin orchestrator + one `SUB_` per responsibility, with signatures) that the user confirms first.** Prompted by a colleague's session refusing a long microflow as "too difficult" while the same task went through on a stronger model: the piece was too big, not the task. mdl-agent gains two rules — never hand back "too difficult", hand back the split plan; escalate one failing `SUB_` by name after one retry, never the whole script. Also records the mxcli team's answer on positioning: a standalone `mxcli layout` command — which on v0.24.0 and upstream main (2026-09-25) arranges domain models only (`--dry-run` on a scratch copy of a PoC model: 10 entity moves, no microflow), so the no-`@position` rule and the if-branch workaround stand until a microflow mode ships; noted in the bug ledger and `learned-microflow-patterns.md` — Maurits Visser diff --git a/bug-logs/mxcli-bugs.md b/bug-logs/mxcli-bugs.md index 7962dde1..49110ea8 100644 --- a/bug-logs/mxcli-bugs.md +++ b/bug-logs/mxcli-bugs.md @@ -1984,6 +1984,13 @@ restore, rather than as a soft warning. ## BUG-62: `ALTER PAGE ... SET Snippet = ... ON ` passes `--references` but fails at exec time — `SNIPPETCALL` widgets need `REPLACE` with an explicit `Params` map, not `SET` +> **Also seen on v0.23.0 (2026-09-25), in a colleague's naming-conventions change on an existing Mendix 11.12.4 app. It widens this entry from "retarget a snippet call" to "rename a snippet":** +> - **There is no `rename snippet`.** v0.24.0 verified: `mxcli rename --help` lists entity, microflow, nanoflow, page, enumeration, association, constant and module. The only route is copy, repoint the callers, then drop, and that route loses content. +> - `describe` leaves out `Params:` on a **nested** `SNIPPETCALL` whose mapping goes to a same-named variable, so the copy loses the mapping. This is the "DESCRIBE never renders `Params:`" lesson below, now seen losing data. +> - A bare `ContentParams` path in the new snippet passed `check` but failed mxbuild when the snippet has 2+ entity parameters. It built only after being wrapped in a `DATAVIEW`, which is a structural change. +> - `SET Snippet = …` is still unsupported (this entry's title). `REPLACE` worked on 10 of 11 callers. On one, `describe` showed the new target, but mxbuild still saw the old snippet after the drop (5 of 5 tries). +> - Impact in the field: all 3 planned snippet renames were dropped. v0.24.0: the missing verb is verified; the three content-loss items were **not probed**. Upstream: no `rename snippet` on `main` (2026-09-24). + > ### ⚠️ PARTIALLY FIXED in mxcli v0.18.0 — retested 2026-08-20 > > Retested on v0.18.0, Mendix 11.12.0, graded with Studio Pro 11.12.0's `mx`, A/B'd against v0.17.0. @@ -2083,7 +2090,13 @@ remediation — `PLM.PLM_GraphAgentChat`'s `snippetCall1` re-target. --- -## BUG-63: `write-lint-rules.md` documents API values that do not exist — every `action_type` example is wrong, and `source_type` case is wrong — so rules written from the guide silently match nothing +## BUG-63: `write-lint-rules.md` documents API values that do not exist — every `action_type` example is wrong, and `source_type` case is wrong — so rules written from the guide silently match nothing (widened 2026-09-25: also `microflow_type` case, SQL-vs-Starlark entity-type spelling, and what `activity_count` counts) + +> **Also seen on v0.23.0 (2026-09-25), in a colleague's naming-conventions change: two more wrong values, and one count that means something else. v0.24.0 verified 2026-09-25 with a probe rule on a scratch copy of a small PoC model:** +> - **`microflow_type` is UPPERCASE.** Starlark returned `MICROFLOW` (the probe tallied `{"MICROFLOW": 51}`). The bundled `write-lint-rules/SKILL.md` still documents `"microflow"`/`"nanoflow"` in v0.24.0 and on `main`. 59db6e7b0 (2026-09-18, Refs #1027) left that row alone. +> - **`microflows()` also yields rules and nanoflows** (`RULE`, `NANOFLOW`), but only in non-platform modules. The v0.24.0 `mdl/linter/context.go` says so ("yields all three flow flavours"), and the field saw rules on v0.23.0. The probe model's 18 rules all sit in marketplace modules, which the linter skips, so the probe could not show one. +> - **SQL and Starlark disagree on entity type.** `CATALOG.ENTITIES` returns `PERSISTENT`/`NON_PERSISTENT`/`VIEW`, while Starlark `entity_type` returns `Persistent`/`NonPersistent`/`View`. A rule prototyped in SQL and then ported goes blind. The field's two handbook rules found 0 of 16 and 0 of 28 real hits this way. +> - **`activity_count` counts top-level flow objects, not actions.** On a probe microflow with an annotation, retrieve, if, loop{change}, commit and log, it returned `activity_count=6`: annotation, retrieve, split, loop, commit and log. It excludes start, end and merge, and it does **not** count the action inside the loop. `activities_for()` returns the same top-level objects: `StartEvent, ActionActivity:RetrieveAction, Annotation, ExclusiveSplit, ExclusiveMerge, LoopedActivity, ActionActivity:CommitObjectsAction, ActionActivity:LogMessageAction, EndEvent`. So the field workaround, counting `ActionActivity`, gives 3 of the 4 real actions. The docs say "Number of activities", and CONV009 over-reports (field: 16 counted, 11 actions). The toolkit note, with a before/after, is in `skills/lint-that-actually-runs.md` §1. Upstream: 5fb124129 / 84449c76c (2026-09-22, ARCH002/ARCH003 entity_type) are unreleased; no fix was found for the `microflow_type` doc row or for `activity_count`. > **CONFIRMED STILL OPEN on v0.21.0 — verified 2026-09-14 by inspection plus a live catalog query: the shipped `write-lint-rules/SKILL.md` still lists the same fictional `action_type` examples (line 318) and lowercase `source_type` (line 364); `SELECT DISTINCT SourceType FROM CATALOG.REFS` on a live scaffolded app returns the real, uppercase values.** See [mxlabs-v0.21.0-retest-2026-09-14.md](mxlabs-v0.21.0-retest-2026-09-14.md). @@ -3487,6 +3500,8 @@ judgment call. ## BUG-102: `ALTER PAGE … SET DataSource = … ON widget` silently no-ops on a native DataGrid — reports success, passes the mxbuild gate, XPath never changes +> **Also seen on v0.23.0 (2026-09-25), in a colleague's naming-conventions change: the neighbouring form fails loudly instead of silently.** On a **legacy** `Forms$DataGrid`, `ALTER PAGE … SET XPathConstraint = … ON ` is rejected, and `mxcli bson dump` is read-only, so a stale grid XPath (left behind by a module rename, see `BUG-DRAFT-rename-module-leaves-xpath`) has no offline route. The only routes are `--mcp` against a running Studio Pro, or editing by hand. Field workaround: replace the legacy grid with a Data Grid 2. v0.24.0: **not probed** (the probe copy cannot author a data grid, `unsupported widget type: datagrid`). + > **NOT RETESTED this round (v0.21.0, 2026-09-14) — the current `mxcli syntax page.alter` reference documents only `SET DataSource = $Param` (a variable form); no `DATABASE FROM … WHERE […] SORT BY …` form appears in the syntax reference at all, and DATAGRID now routes through the unified DataGrid2 engine (same v0.21.0 changelog note flagged on BUG-93/BUG-16). Unclear whether the original repro shape is still constructible without deeper investigation than this round had time for.** See [mxlabs-v0.21.0-retest-2026-09-14.md](mxlabs-v0.21.0-retest-2026-09-14.md). **Severity:** High — silent success, stale runtime behavior, surfaces only by testing the running app @@ -5758,3 +5773,186 @@ correct script that trips MPR008 through this defect looks identical to a real o gate-agent's "do not accept the rise with `--update-baseline`" rule needs this entry to tell the two apart: an MPR008 whose two elements are a merge and the activity after a loop in an `if` branch is this bug, and the fix is the workaround above, not a baseline bump. + +## BUG-DRAFT-rename-module-leaves-xpath: `rename module` reports its references updated but leaves every XPath constraint naming the old module — mxbuild CE1613 (2026-09-25) + +> **NOT YET FILED** — paste-ready draft in `bug-logs/pending-github-issues/rename-module-leaves-xpath.md`. + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** 2026-09-25 on a scratch copy of a small PoC model (Mendix 11.12.1). `mxcli rename -p app.mpr module RenA RenB` printed `Renamed module: RenA → RenB` / `Updated 6 reference(s) in 4 document(s)`; `describe microflow RenB.SUB_Find` then still showed `where RenA.Item/Name = 'x';` and `RenB.SUB_Assoc` still showed `where RenA.Item_Owner/RenA.Owner/Label = 'x';`; `grep -rl 'RenA' mprcontents/` listed the 2 units that still name it. Upstream: no fix found on `main` (2026-09-24). The XPath rewrite that does exist there (35efa0207, #910, unreleased) covers **attribute** rename only. + +**Discovered:** 2026-09-22..24, a naming-conventions change on an existing Mendix 11.12.4 app (MPR v2), reported from the field. +**mxcli version:** v0.23.0 (field), v0.24.0 (retest). **Severity:** High. The command says it worked, and the damage shows only at build. + +**Repro:** +``` +-- ModuleA has entity Item and a microflow that retrieves with XPath +retrieve $Items from ModuleA.Item where ModuleA.Item_Owner/ModuleA.Owner/Label = 'x'; +``` +``` +mxcli rename -p app.mpr module ModuleA ModuleB +mxcli -p app.mpr -c "describe microflow ModuleB.SUB_Find" +mx check app.mpr +``` + +**Expected:** every qualified name that starts with `ModuleA.` follows the rename, including those +inside retrieve XPath, widget datasource XPath and expression strings. + +**Actual:** the unit and structural references are renamed, and the success line counts them. Text +that holds a qualified name is not rewritten: retrieve XPath, a legacy data grid's XPath, and +expressions. In the field this gave "407 references updated" and then 34 CE1613 from 10 microflows +plus one grid XPath, all still naming the old module. + +**Impact:** a module rename is not safe offline. The reference count reads like proof that it is. + +**Workaround:** after the rename, `describe` each affected microflow, correct the module name, and +re-create it. Diff each regenerated microflow against a pre-rename export before you exec it, +because DESCRIBE output of non-nesting decision branches can drop merges on re-exec (upstream #923). +Find the affected units with `grep -rl 'ModuleA\.' mprcontents/` on the renamed copy (MPR v2). On v0.24.0, +`SEARCH 'ModuleA.'` returned "No matches found." for the stale XPath. Run `mx check` after the rename; the success line does not replace it. + +## BUG-DRAFT-rename-page-renames-folder: `rename page` renames a same-named folder instead of the page, and reports success (2026-09-25) + +> **NOT YET FILED** — paste-ready draft in `bug-logs/pending-github-issues/rename-page-renames-folder.md`. + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** 2026-09-25 on a scratch copy of a small PoC model, but only when the folder unit is older than the page. Three shapes did **not** reproduce: page at the module root with folder `Pages/Dup`, page in `Pages` beside `Pages/Dup`, and page name equal to the module name. In each, the folder was created by a `move` *after* the page. The shape that reproduces: `move page RenA.Other to folder 'Pages/Same'` first, then `create page RenA.Same`, then `mxcli rename -p app.mpr page RenA.Same Same_Overview`. That printed `Renamed page: RenA.Same → RenA.Same_Overview`. `show pages in RenA` then listed `RenA.Same` unchanged and `RenA.Other` in folder `Pages/Same_Overview`. `git status` showed one changed unit, whose `$Type` is `Projects$Folder`. **Root cause (v0.24.0 source):** `RenameDocumentByName` in `mdl/backend/modelsdk/infrastructure_write.go` walks every unit in the module's container set and rewrites the first one whose top-level `Name` equals the old name. It never checks `$Type`, and folders are units, so unit order decides the outcome. Upstream: the same code is on `main` (2026-09-24); no fix found. + +**Discovered:** 2026-09-22..24, same field report as above. +**mxcli version:** v0.23.0 (field), v0.24.0 (retest). **Severity:** High. The wrong object changes silently. + +**Repro:** see the status line. In the field the shape was page `ModuleA.PageX` alongside a folder +`Pages/PageX` in the same module. + +**Expected:** the page is renamed. A folder never matches a `rename page`. + +**Actual:** the folder is renamed. The page keeps its name, but callers are rewritten to the new +page name (3 in the field), so mxbuild reports CE1613 "page … no longer exists" on each caller. + +**Impact:** silent wrong change. The success line and the caller count look right. + +**Workaround:** after every `rename page`, read the model back (`show pages in ModuleA`). If a +folder of the same name exists, move its documents to a temporary folder, drop the folder, rename +the page, then move the documents back. + +## BUG-DRAFT-move-case-only-folder-twin: a case-only folder change by `move` leaves the old-case folder behind (2026-09-25) + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** (the twin) 2026-09-25 on a scratch copy of a small PoC model. First `move page RenA.Item_Overview to folder 'Pages/AbcArea'`, then `... to folder 'Pages/ABCArea'`. The page ends in `Pages/ABCArea`, and two `Projects$Folder` units remain, `AbcArea` (empty) and `ABCArea`. In this flat shape `drop folder 'Pages/AbcArea' in RenA` removed the empty twin (`Dropped folder: 'Pages/AbcArea' in RenA`). The field saw `DROP FOLDER` refuse, because it resolved to the new-case twin that holds documents. That was on nested paths (`Logic/SubfolderAbc/...`), which were **not probed**. Upstream: no fix found. + +**Discovered:** 2026-09-22..24, same field report. **mxcli version:** v0.23.0, v0.24.0. **Severity:** Medium. + +**Expected:** a move whose target differs only in case either renames the folder in place or +reuses it. No empty twin is left. + +**Actual:** a second folder is created, and the old-case folder remains empty. In the field there +were 6 nested twins, and `DROP FOLDER` could not remove them. + +**Workaround:** none offline in the field. Studio Pro can delete the empty folders. On v0.24.0, +try `drop folder '' in ModuleA` and confirm with `show pages`/`git status` that it +removed the *empty* twin. + +## BUG-DRAFT-dg2-association-path-bindings: a Data Grid 2 column or `sort by` over an association passes `check` in forms that build to CE1613 — quoting the path stores one attribute named `Assoc/Attr` (2026-09-25) + +> **NOT YET FILED** — paste-ready draft in `bug-logs/pending-github-issues/dg2-association-path-bindings.md`. + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: `check` half verified, build half not probed** 2026-09-25. A page with `datagrid dg1 (DataSource: database "RenA"."Item" sort by "Item_Owner/Label" asc)` and columns `(Attribute: "Item_Owner/Label")` and `(Attribute: Item_Owner/Label)` passed `mxcli check --references` (`Check passed!`). The quoted and unquoted sort forms both passed. The MDL-WIDGET16 info line derived the column names as `colQ → "Item_Owner/Label", colU → Item_Owner/Label`, so the quotes survive into the stored name. Exec and mxbuild were not run: the probe copy has no Data Grid 2 widget definition (`unsupported widget type: datagrid`). Upstream: fe5a7408e (2026-09-21, "let a sort column name the association it navigates", unreleased; see also closed #1152) addresses the **sort** half on `main`. No fix was found for the quoted **column** path; closed #830 covered unquoted association columns. + +**Family:** BUG-29 (quoted paths in nav expressions → CE0117), BUG-75 (quoted path as a call +argument → CE0117), BUG-41 (DG2 text-filter attributes). The toolkit had logged this binding only +as a row in `skills/learned-detection-gaps.md` (root cause there: `resolveAssociationAttributePath` +does not strip quotes before splitting on `/`). This entry is the ledger home for it. + +**Discovered:** 2026-09-22..24, same field report. **mxcli version:** v0.23.0, v0.24.0. **Severity:** Medium. The check is green and the build shows CE1613. + +**Repro:** +``` +column colX (Attribute: "Assoc_A_B/Name", Caption: 'B') -- quoted: CE1613 at build +column colY (Attribute: Assoc_A_B/Name, Caption: 'B') -- unquoted: builds +datagrid dg (DataSource: database ModuleA.EntityA sort by Assoc_A_B/Name asc) { ... } -- CE1613 +``` + +**Expected:** a quoted identifier that contains `/` is either split into a path or rejected by +`check`. A `sort by` over an association is either authored as a path or rejected by `check`. + +**Actual (field, v0.23.0):** +- Quoted column path: stored as **one attribute whose name contains a slash**, which gives CE1613. +- Unquoted `sort by Assoc/Attr`: written as a plain attribute of the grid's entity, which gives CE1613. +- The full `Module.Assoc/Module.Entity/Attr` sort form does not parse. Quoted, it parses and then gives CE1613 too. + +**Impact:** projects that follow the generated `CLAUDE.md` advice to "always quote identifiers" +hit this on every association column. The quote-everything convention has to break here. + +**Workaround:** write association paths unquoted in `Attribute:`. On ≤ v0.24.0 do not author +`sort by` over an association: sort by a local attribute, or use a microflow datasource that +sorts. See the STOP row in `skills/learned-mdl-preflight.md`. + +## BUG-DRAFT-check-references-ignores-in-script-rename: `check --references` resolves against the model before the script, so names after an in-script `rename module` fail (2026-09-25) + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** 2026-09-25 on a scratch copy of a small PoC model. The script `rename module RenA to RenB;` followed by `create persistent entity "RenB"."Extra" (...)` and a microflow retrieving `"RenB"."Item"` gave `✓ Syntax OK (3 statements)` and then `statement 2: module not found: RenB` / `statement 3: module not found: RenB` / `✗ 2 reference error(s) found`. The "(References to objects created within the script are skipped)" rule does not extend to renames. Upstream: no fix found. #955 (in-script creation order) is related but closed. + +**Discovered:** 2026-09-22..24, same field report. **mxcli version:** v0.23.0, v0.24.0. **Severity:** Medium. + +**Expected:** the reference checker applies `rename` statements to its view of the model as it +walks the script, the same way it already skips objects the script creates. + +**Actual:** every `ModuleB.*` reference after the rename line is an error (11 in the field). + +**Impact:** a rename script cannot pass the toolkit's pre-exec check. The only routes are a +guardrail override or checking against a pre-renamed copy. + +**Workaround:** run the rename as its own step (`mxcli rename … module`, then `mx check`). Then +check the follow-up script against the renamed model. If one script is unavoidable, run +`check --references` against a scratch copy that has already been renamed. + +## BUG-DRAFT-diff-local-misses-new-units: `diff-local` does not report new (untracked) documents (2026-09-25) + +> **NOT YET FILED** — paste-ready draft in `bug-logs/pending-github-issues/diff-local-misses-new-units.md`. + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** 2026-09-25 on a scratch copy of a small PoC model under git. On a clean checkout, creating a module, an entity, a microflow and a page left 6 untracked `mprcontents/…` directories, and `mxcli diff-local -p app.mpr` printed `No local changes found in mxunit files.` A second exec, adding an entity and a microflow to an existing module, gave `Summary: 0 new, 1 modified, 0 deleted`: the new microflow was missing. **Root cause (v0.24.0 source):** `mdl/executor/cmd_diff_local.go` builds its list from `git diff --name-status -- `, which never lists untracked files. `git add -N ` makes the new unit appear (`1 new`), but it then renders as `create or modify microflow .SUB_New ()` with an **empty module qualifier**, a second defect in the same path. Upstream: 0dce31214 (2026-09-10, unreleased) fixes other diff-local defects on `main` but not this one. Closed #1038 and #424 are different diff-local bugs. + +**Discovered:** 2026-09-22..24, same field report. **mxcli version:** v0.23.0, v0.24.0. **Severity:** High for any change check built on it. + +**Expected:** new documents are listed as `new` and rendered with their module. + +**Actual:** new documents are missing. The summary counts only modified and deleted units. + +**Impact:** a naming or convention check driven by `diff-local` skips exactly the documents most +likely to break the convention: the new ones. + +**Workaround:** build the change list from git yourself. Take +`git diff --name-only -- mprcontents/` plus `git ls-files --others --exclude-standard mprcontents/`, +then resolve unit ids to documents through `CATALOG.OBJECTS` (or `describe`). + +## BUG-DRAFT-diff-local-module-uuid: `diff-local` renders domain-model changes with the unit UUID where the module name belongs (2026-09-25) + +> **Status:** reported on v0.23.0 by a colleague; **v0.24.0: verified** 2026-09-25 on a scratch copy of a small PoC model. After adding an entity, `diff-local` printed `--- DomainModel. (current)` and `+create persistent entity .Thing (`. The DomainModel unit carries no `Name`, and `cmd_diff_local.go` falls back to the unit id instead of resolving the containing module. **Slowness on older commit ranges** (field: `--ref ~1..` produced nothing in 120 s, while a 14-document range took ~5 s) was **not probed**. Upstream: no fix found. + +**Discovered:** 2026-09-22..24, same field report. **mxcli version:** v0.23.0, v0.24.0. **Severity:** Low. + +**Expected:** `create persistent entity ModuleA.Thing (`: the module name, as valid MDL. + +**Actual:** the unit UUID stands in for the module. The line is neither readable nor valid MDL. + +**Workaround:** map the unit to its module through the `.mpr` `Unit` table or `CATALOG.OBJECTS` +(unit ids are stored in .NET byte order in the `.mpr`). Keep `--ref` ranges narrow. + +## Feature asks from the field, v0.23.0 (2026-09-25) + +Not defects. These are four asks from the same naming-conventions field report (mxcli v0.23.0, +Mendix 11.12.4), recorded so they are not re-discovered. Each carries its v0.24.0 state. None is +filed upstream. + +- **Bundled lint rules hard-code one convention set.** CONV005 requires `SNIPPET_`, CONV009/QUAL004 + suggest `SUB_`/`SCH_`, and CONV003 has a fixed page-suffix list. A team whose handbook forbids + those prefixes gets permanent noise. Ask: make the prefix/suffix lists `options` in + `lint-config.yaml`, like CONV018's `max_root_documents`. Field workaround: own rules, with the + built-ins left out of the gate. v0.24.0: not probed. +- **Rules load only from `.claude/lint-rules/`.** v0.24.0: verified. `mxcli lint --help` has no + `--rules-dir` and there is no config key. Projects that gitignore `.claude/` cannot track their + rules where they are loaded. Field workaround: a tracked copy plus a symlink. +- **Facts missing from the catalog.** Annotation text: v0.24.0 verified. In `CATALOG.ACTIVITIES` + and `activities_for()`, an `Annotation` row's caption is the generic `Activity`, not its text. + Widget heading level (`RenderMode: H1`) was not probed. Both are reachable only by parsing + DESCRIBE, so "one H1 per page" and "annotations are dated" cannot be lint rules. +- **MPR006 says an empty container "will crash at runtime".** Unverified in the field (34 hits), + and not probed here. The toolkit repeats the claim without evidence in + `skills/learned-workflow-patterns.md` (the MPR006 row and the page-patterns note). Treat it as + unconfirmed until someone runs an empty container. Ask upstream what the crash is. diff --git a/bug-logs/pending-github-issues/dg2-association-path-bindings.md b/bug-logs/pending-github-issues/dg2-association-path-bindings.md new file mode 100644 index 00000000..b0ca1ba8 --- /dev/null +++ b/bug-logs/pending-github-issues/dg2-association-path-bindings.md @@ -0,0 +1,41 @@ +**Repo:** `mendixlabs/mxcli` +**Source:** `bug-logs/mxcli-bugs.md`, `## BUG-DRAFT-dg2-association-path-bindings` — found 2026-09-25 (field report on v0.23.0; `check` half re-verified on v0.24.0) +**Status:** NOT YET FILED +**Suggested labels:** bug, pages, datagrid, check +**Duplicate check:** searched 2026-09-25 (`datagrid column quoted association path CE1613`, `sort by association attribute datagrid`). Related, closed: #830 (unquoted association column), #1152 (sort over association round-trip); fe5a7408e (unreleased) lets a sort column name its association. No issue found for the **quoted** column path. Before filing, check whether fe5a7408e also covers the DataGrid 2 `sort by` form; if so, file the column half only. + +--- + +**Title:** DataGrid 2: a quoted association path in a column `Attribute:` is stored as one attribute named `Assoc/Attr`; `check` passes, the build fails with CE1613 + +**Body:** + +## Summary + +`Attribute: "Assoc_A_B/Name"` (quoted) on a DataGrid 2 column is stored as a single attribute whose name contains a slash. The unquoted form is stored as a path. `check --references` passes both, and the quoted one fails at build with CE1613. The generated project `CLAUDE.md` tells agents to "always quote identifiers … always safe", so agents that follow it hit this on every association column. The same applies to `sort by Assoc/Attr` on the grid's database source: it passes `check` and is written as a plain attribute of the grid entity (CE1613). + +**Version:** field run on mxcli v0.23.0 / Mendix 11.12.4 (build results); `check` behaviour re-verified on v0.24.0. + +## Repro + +``` +create page ModuleA.EntityA_Grid (Title: 'Grid', Layout: Atlas_Core.Atlas_Default) { + datagrid dg1 (DataSource: database ModuleA.EntityA sort by "Assoc_A_B/Name" asc) { + column colQ (Attribute: "Assoc_A_B/Name", Caption: 'Quoted') + column colU (Attribute: Assoc_A_B/Name, Caption: 'Unquoted') + } +}; +``` + +## Measured + +- v0.24.0 `check --references`: `Check passed!`, with an MDL-WIDGET16 info line deriving the column names as `colQ → "Assoc_A_B/Name", colU → Assoc_A_B/Name`. The quotes survive into the stored name. +- v0.23.0 build (field): the quoted column gives CE1613, and the unquoted column builds. `sort by Assoc/Attr`, unquoted or quoted, gives CE1613. The fully qualified `Module.Assoc/Module.Entity/Attr` sort form does not parse. + +## Expected + +A quoted identifier that contains `/` is either split into a path or rejected by `check`. A sort over an association is either authored as a path or rejected by `check`. + +## Workaround + +Write association paths unquoted. Sort by a local attribute, or use a microflow datasource. diff --git a/bug-logs/pending-github-issues/diff-local-misses-new-units.md b/bug-logs/pending-github-issues/diff-local-misses-new-units.md new file mode 100644 index 00000000..a25d6b2c --- /dev/null +++ b/bug-logs/pending-github-issues/diff-local-misses-new-units.md @@ -0,0 +1,47 @@ +**Repo:** `mendixlabs/mxcli` +**Source:** `bug-logs/mxcli-bugs.md`, `## BUG-DRAFT-diff-local-misses-new-units` — found 2026-09-25 (field report on v0.23.0, reproduced on v0.24.0) +**Status:** NOT YET FILED +**Suggested labels:** bug, diff-local +**Duplicate check:** searched 2026-09-25 (`diff-local does not show new untracked units`). No match. #1038 and #424 are different diff-local bugs; 0dce31214 (unreleased) fixes other diff-local defects but not this one. Consider filing the domain-model UUID rendering (`BUG-DRAFT-diff-local-module-uuid`) as a second issue or a comment here. + +--- + +**Title:** `diff-local` does not report new documents: untracked `mprcontents` units are invisible + +**Body:** + +## Summary + +On an MPR v2 project under git, a document created since the ref is a new, **untracked** `mprcontents/**.mxunit` file. `diff-local` builds its change list from `git diff --name-status -- ` (`mdl/executor/cmd_diff_local.go`), which never lists untracked files, so new microflows, pages and entities are missing from the output and the summary. + +**Version:** mxcli v0.24.0 (also v0.23.0), Mendix 11.12.1, MPR v2. + +## Repro + +In a clean git checkout of an MPR v2 app: + +``` +create microflow ModuleA.SUB_New () begin log info node 'P' 'x'; end; +/ +create persistent entity ModuleA.Thing (Code: String(20)); +``` + +``` +mxcli exec repro.mdl -p App.mpr +git status --short # new mprcontents/... directories are untracked +mxcli diff-local -p App.mpr +``` + +## Measured (v0.24.0) + +- Only new units (new module + entity + microflow + page): `No local changes found in mxunit files.` +- New entity in an existing module + new microflow: `Summary: 0 new, 1 modified, 0 deleted`. The domain model is listed; the microflow is not. +- After `git add -N `: `1 new`, but the new microflow renders as `create or modify microflow .SUB_New ()`, with an empty module qualifier. + +## Expected + +New units are listed as `new`, rendered with their module, and counted in the summary. + +## Workaround + +Build the list from `git diff --name-only -- mprcontents/` plus `git ls-files --others --exclude-standard mprcontents/` and resolve unit ids yourself. diff --git a/bug-logs/pending-github-issues/rename-module-leaves-xpath.md b/bug-logs/pending-github-issues/rename-module-leaves-xpath.md new file mode 100644 index 00000000..f1da9876 --- /dev/null +++ b/bug-logs/pending-github-issues/rename-module-leaves-xpath.md @@ -0,0 +1,61 @@ +**Repo:** `mendixlabs/mxcli` +**Source:** `bug-logs/mxcli-bugs.md`, `## BUG-DRAFT-rename-module-leaves-xpath` — found 2026-09-25 (field report on v0.23.0, retested on v0.24.0) +**Status:** NOT YET FILED +**Suggested labels:** bug, rename, xpath +**Duplicate check:** searched 2026-09-25 (`rename module does not rewrite XPath constraints`). No match. Related but different: #910 / 35efa0207 (XPath rewrite on **attribute** rename, unreleased), #1049 (dangling XPath member passes `check --references`), #473 and #426 (rename module implementation). + +--- + +**Title:** `rename module` reports its references updated but leaves XPath constraints naming the old module (CE1613 at build) + +**Body:** + +## Summary + +`mxcli rename module A B` rewrites the structural references and reports a count, but a qualified name inside a retrieve's XPath constraint still names the old module. In a field run on a larger app this gave "407 references updated" and then 34 CE1613 from 10 microflows plus one legacy data grid's XPath. + +**Version:** mxcli v0.24.0 (also v0.23.0), Mendix 11.12.1 / 11.12.4, MPR v2. + +## Repro + +``` +create persistent entity RenA.Owner (Label: String(50)); +create association RenA.Item_Owner from RenA.Item to RenA.Owner; +create microflow RenA.SUB_Assoc () +returns Boolean as $Ok +begin + declare $Ok Boolean = false; + retrieve $Items from RenA.Item + where RenA.Item_Owner/RenA.Owner/Label = 'x'; + if $Items != empty then + set $Ok = true; + end if; + return $Ok; +end; +/ +``` + +``` +mxcli exec repro.mdl -p App.mpr +mxcli rename -p App.mpr module RenA RenB +mxcli -p App.mpr -c "describe microflow RenB.SUB_Assoc" +``` + +## Measured (v0.24.0) + +``` +Renamed module: RenA → RenB +Updated 6 reference(s) in 4 document(s) +... + where RenA.Item_Owner/RenA.Owner/Label = 'x'; +``` + +A simpler `where RenA.Item/Name = 'x'` in another microflow is left unchanged as well. `SEARCH 'RenA.'` returns "No matches found.", so the stale names cannot be found in-tool either. `grep -rl RenA mprcontents/` finds the units. + +## Expected + +Every module-qualified name in XPath constraints (retrieves, widget datasources, access rules) and in expressions follows the rename, as #910 now does for attribute renames. + +## Workaround + +Describe each affected microflow, correct the module name by hand, and re-create it, then run `mx check`. diff --git a/bug-logs/pending-github-issues/rename-page-renames-folder.md b/bug-logs/pending-github-issues/rename-page-renames-folder.md new file mode 100644 index 00000000..d19be2ce --- /dev/null +++ b/bug-logs/pending-github-issues/rename-page-renames-folder.md @@ -0,0 +1,55 @@ +**Repo:** `mendixlabs/mxcli` +**Source:** `bug-logs/mxcli-bugs.md`, `## BUG-DRAFT-rename-page-renames-folder` — found 2026-09-25 (field report on v0.23.0, reproduced on v0.24.0) +**Status:** NOT YET FILED +**Suggested labels:** bug, rename +**Duplicate check:** searched 2026-09-25 (`rename page renames folder with the same name`). No match (#426, #154 are unrelated). + +--- + +**Title:** `rename page` renames a folder with the same name instead of the page, and reports success + +**Body:** + +## Summary + +`RenameDocumentByName` (`mdl/backend/modelsdk/infrastructure_write.go`) walks every unit in the module's container set and rewrites the first unit whose top-level `Name` equals the old name. It never checks `$Type`. Folders are units too, so when a folder with the page's name comes first in unit order, the folder is renamed, the command prints "Renamed page", and callers are repointed to a page name that does not exist (CE1613 at build). + +**Version:** mxcli v0.24.0 (also v0.23.0), Mendix 11.12.1, MPR v2. Same code on `main` as of 2026-09-24. + +## Repro + +The folder must be older than the page: + +``` +create page RenA.Other (Title: 'Other', Layout: Atlas_Core.Atlas_Default) { + container c1 { dynamictext t1 (Content: 'y') } +}; +move page RenA.Other to folder 'Pages/Same'; +create page RenA.Same (Title: 'Same', Layout: Atlas_Core.Atlas_Default) { + container c1 { dynamictext t1 (Content: 'x') } +}; +``` + +``` +mxcli exec repro.mdl -p App.mpr +mxcli rename -p App.mpr page RenA.Same Same_Overview +mxcli -p App.mpr -c "show pages in RenA" +``` + +## Measured (v0.24.0) + +``` +Renamed page: RenA.Same → RenA.Same_Overview +| RenA.Other | RenA | Other | false | Pages/Same_Overview | ... +| RenA.Same | RenA | Same | false | | ... +``` + +`git status` shows one changed unit, and its `$Type` is `Projects$Folder`. If the folder is created *after* the page, the page is renamed correctly, which is why this looks intermittent. + +## Expected + +`rename page` only matches `Forms$Page` units (and the other `rename ` variants only their own type). + +## Workaround + +Move the folder's documents out, drop the folder, rename the page, move them back. Always read the model back after a rename. diff --git a/skills/learned-mdl-preflight.md b/skills/learned-mdl-preflight.md index bd6c33b1..6e0a3eac 100644 --- a/skills/learned-mdl-preflight.md +++ b/skills/learned-mdl-preflight.md @@ -67,6 +67,7 @@ Once you've picked a mode per operation, run the STOP table below against every | 23 | Name any document or entity that **might already exist** — `create or modify` on an entity, or any `create or replace` on a page, layout or microflow | **STOP → run `mxcli diff -p .mpr