Skip to content

Sync: describe round trip, read-only docker check, tooling version guard, check/lint vs mxbuild - #1279

Merged
ako merged 29 commits into
mendixlabs:mainfrom
ako:main
Oct 3, 2026
Merged

ako merged 29 commits into
mendixlabs:mainfrom
ako:main

Conversation

@ako

@ako ako commented Oct 3, 2026

Copy link
Copy Markdown
Collaborator

Syncs ako#955–ako#959 (fast-forward; mendixlabs main has nothing ako lacks). Fixes from the JTSBootLogboek assessment, a production app on Mendix 11.13.

Describe round trip (ako#959)

  • delete close page kept "close page" on describe but lost it on write: exec stored ClosePage=false.
  • return [%CurrentUser%]; is no longer described as $[%CurrentUser%], and return if … then … else … no longer as return $if ….
  • Navigation-list items describe with the current action syntax. Unnamed items, as Studio Pro stores them, are accepted and written the same way.

docker check is read-only; catalog cache race (ako#956)

  • docker check runs update-widgets and mx check on a temporary copy. Before, an MPRv1 .mpr was rewritten permanently, and theme-cache/ and deployment/sass/ were written on both formats. Measured: every file's hash and mtime is unchanged on v1 and v2, and a planted error is still reported.
  • The catalog cache is written to a temp file and renamed into place. 16 parallel lint runs went from 7 errors to 0.

Tooling newer than the binary (ako#955)

  • init and every sync stamp .ai-context/mxcli-tooling.json. A command run with -p warns once when the binary is older.
  • The bootstrap script won't link an older mxcli from PATH, and it downloads to a temp file and renames it.
  • A lint rule that needs a newer mxcli is an info line. report leaves every rule failure out of the score and lists them in "Rules That Could Not Run".
  • init --sync-skills (alias --sync) also refreshes the bundled lint rules and the marked mxcli section of CLAUDE.md/AGENTS.md.
  • init and new create mdlsource/.

check/lint vs mxbuild (ako#957, ako#958)

  • Void-action calls: output names on void Java/JavaScript action calls no longer count as variables (mxbuild accepts duplicates). Real duplicates in nanoflow branches and error handlers are now reported (CE0111).
  • Parameter names: unknown parameter names on java/js/microflow/nanoflow calls are reported (CE1613).
  • Page false positives: MDL-BUTTON01 no longer fires for a grid inside a data container. MPR012 and MDL-WIDGET40 no longer fire on native pages; catalog layouts.Platform is new, schema 18.
  • MPR002 no longer reports return-only flows.
  • CONV006 reports once per entity.
  • report --modules scores the selected modules

ako and others added 29 commits October 3, 2026 14:39
…race (#951)

SaveToFile now writes to a temp file in the cache's directory (VACUUM INTO,
manual-copy fallback into the same temp file) and renames it over the cache.
buildCatalog and refresh catalog communities no longer remove the cache first.
Opening a cache at the current schema version no longer writes to it: a write
on a file renamed underneath an open connection fails with
SQLITE_READONLY_DBMOVED. File-backed connections get a busy_timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A Starlark rule reading a struct field this mxcli does not expose is now
reported at info level as "rule <ID> needs a newer mxcli (<detail>)"; other
rule failures stay errors. Every rule failure is marked RuleFailure, kept out
of BuildReport's score, summary and categories, and listed in its own
"Rules That Could Not Run" section (ruleFailures in JSON). A configured rule
severity no longer applies to the rule's own failure, and a rule file failing
to load on an undefined name hints at a newer mxcli.

Part of #952.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sync rules and CLAUDE.md (#952)

- init and every sync write .ai-context/mxcli-tooling.json; any -p command
  warns once on stderr when the binary is provably older (releases by number,
  nightlies by tag date, mixed by build date, dev builds never).
- init --sync-skills (alias --sync) refuses from an older binary instead of
  downgrading, and now also refreshes the bundled lint rules (by file name;
  user rules untouched) and the CLAUDE.md/AGENTS.md section between new
  mxcli:begin/end markers, keeping project notes outside them.
- The bootstrap script compares the PATH binary and ./mxcli with the stamp
  before using them, downloads MXCLI_TAG instead of linking an older binary,
  and downloads through a temp file so a symlinked ./mxcli is never written
  through. Binaries <= v0.24.0 cannot read the stamp; the script is their guard.
- init and new create mdlsource/ with a README.

Closes #952.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docker check ran mx update-widgets on the user's project with only the MPRv2
storage snapshotted, so an MPRv1 .mpr was rewritten permanently, and mx check
itself rewrote theme-cache/ and created deployment/sass/ on both formats, with
or without --no-update-widgets. Both mx steps now run on a temporary copy
(build output, caches and VCS folders skipped), mx output is rewritten to the
project's own paths, and the output says that widgets were normalised on a
copy and what that hides (#568, #646). docker build keeps its snapshot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto itself (#951)

Check copies the project's directory, so a missing .mpr (or a path in /tmp)
would copy an unrelated directory: fail early instead, and give the existing
fake-mx tests a project file of their own. With TMPDIR inside the project the
walk met its own copy and recursed until the path was too long; skip it.
Trim the custom-widgets skill back under the 700-line limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A control-bar button of a data grid nested inside a data view or list
view passing $currentObject was refused as CE1571, but there the
control bar's $currentObject is the enclosing object and mxbuild 11.13
builds it clean. The walk now carries whether an ancestor data container
supplies an object context; the grid's own data source still never
scopes its control bar, so a top-level grid is still reported.

Part of #953 (item 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CE0582 is the React client's error. Measured on mxbuild 11.13.0: a
staticimage and a classic dropdown on a NativePhone_Default page build
clean, the same widgets on an Atlas_Default page are CE0582. A textbox
on an enumeration is CE2421 on both, so MDL-WIDGET39 is unchanged.

Nothing recorded a layout's platform: ListLayouts left Layout.Native
false for every layout, and LayoutType cannot tell the platforms apart.
- backend: Native is the content wrapper's type (NativeLayoutContent)
- catalog: layouts.Platform ("Web" / "Native"), schema 18
- linter: NativePages() joins pages.LayoutRef to layouts without the
  Marketplace filter (the native layouts live in Atlas_Core); MPR012
  skips those pages; Starlark layout.platform
- check: MDL-WIDGET40 skips a page whose layout resolves as native

Part of #953 (item 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A microflow or nanoflow whose only content is `return <expr>;` computes
its value in the end event, which ActivityCount does not count. A
non-Void return type is the witness that the end event returns a value,
so those flows are no longer reported.

Part of #953 (item 4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One finding per entity x role x CREATE/DELETE (111 on a mid-sized app)
becomes one per entity, listing the de-duplicated roles per right. The
test runs both the .claude and the embedded copy of the rule.

Part of #953 (item 5).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`lint` had -m, `report` only --exclude. `report --modules A,B` applies
the same LintContext module filter and scores only the findings located
in a selected module, so project-wide findings do not weigh on a module
score. The selection is printed in markdown, HTML and JSON output.

Part of #953 (item 6).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The visitor set ActionV3.ClosePage for `delete close page` but the page
builder's delete case did not copy it, so a describe -> exec round trip
stored ClosePage=false: the button stopped closing its page, with check,
exec and mx check clean. Audited the other page-action cases: save and
cancel already copy it; no other visitor flag is dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The return formatter prefixed $ to any stored return value without one
of + ' " ( ), so [%CurrentUser%] became $[%CurrentUser%] and
`if ... then ... else ...` became `$if ...`, neither of which parses.
Restore the sigil only for the shape a legacy writer stripped it from:
a bare name with an optional attribute path. The other $-adding sites
in describe prefix variable-name fields, not expressions.

Strikes two TestApp WorkflowCommons microflows from the allowlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Item actions were printed by a private copy of the page-action renderer
in the legacy `show_page 'M.P'` form, which does not parse; they now
use the shared client-action renderer, as buttons do, for every action
kind. With that fixed, exec refused the description because Studio Pro
leaves items unnamed, and the writer then wrote Name "" and no
visibility slot where Studio Pro stores no Name key and a null
ConditionalVisibilitySettings. An unnamed item is now accepted, described
as `item (...)` and written as Studio Pro writes it (mx check 11.14.0:
0 errors). Strikes TestApp's Rules.Entity_Menu from the allowlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
describe -> check -> exec -> describe on PedApp for a delete-close-page
button (stored ClosePage compared, plain delete as control), a flow
returning [%CurrentUser%], and a navigation list with an unnamed item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…MDL063 covers nanoflows

Two calls to a void action carrying the same output name (Studio Pro names a
JavaScript action's after the action, $RefreshEntity) are accepted by mxbuild
11.13.0, but check reported MDL063 (microflows) or 'already declared in this
scope' (nanoflows), and describe called the model invalid. Measured: a void
call's output name is inert - a later declare of the name builds clean, a use
is CE0109. The return type is resolved from the script or, with -p, the
project; an unresolvable action still counts.

describe keeps printing the stored `$X =`: Studio Pro stores the name with
UseReturnVariable=true, and the bare form would write an empty name.

MDL063 now runs for nanoflows too (flow-wide, as measured in mxbuild): a
duplicate output across if/else branches passed check and was CE0111. The
check-time body validator no longer reports duplicate names for flows - it
scoped them per branch and counted void calls; rules keep it.

Part of #953 (item 1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… errors

check --references accepted a Java action argument naming no parameter
(CE1613 in mxbuild) whenever the script also had a semantic error: the
reference tier was skipped, and a flow's body errors were returned instead of
its reference errors. Both are now reported. call microflow / call nanoflow
arguments are checked against the callee's parameters too (CE1613, measured
on 11.13.0), and an action or flow known to take no parameters reports any
named argument.

Part of #953 (item 7).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to c23-957

# Conflicts:
#	CHANGELOG.md
#	mdl/linter/report.go
A rule that could not run has no module; ScopeToModules dropped it, so a
--modules report hid the failure that #952 lists separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix: docker check never modifies the project; atomic catalog cache save (#951)
Tooling version guard: stamp, warn, keep rule failures out of the score, sync rules and CLAUDE.md (#952)
fix(check): void action calls declare no variable; unknown call parameters not hidden (#953 items 1, 7)
fix(lint/check): #953 items 2-6 — BUTTON01 nested grids, native pages, return-only flows, CONV006 grouping, report --modules
Describe round trip: delete close page, $[%…%] returns, navigation-list items (#950)
@ako
ako merged commit 7d04602 into mendixlabs:main Oct 3, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant