Skip to content

Sync ako/mxcli: configurable flow layout styles (layout-config.yaml), MPR012 follows the Web UI client - #1694

Merged
ako merged 24 commits into
mendixlabs:mainfrom
ako:main
Nov 1, 2026
Merged

ako merged 24 commits into
mendixlabs:mainfrom
ako:main

Conversation

@ako

@ako ako commented Oct 31, 2026

Copy link
Copy Markdown
Collaborator

Syncs ako/mxcli:main into upstream: 12 commits from fork PRs ako#1783, ako#1828, ako#1842 and ako#1846.

Fixes #1226.

Configurable microflow/nanoflow layout styles

The problem: teams disagree on how a microflow should look, and every mxcli layout flows run undid a team's hand-applied house style.

The fix: the flow layout is now a committed project setting. layout-config.yaml lives in .claude/ or next to the .mpr, and is looked up like lint-config.yaml:

flows:
  preset: true-right-false-down   # happy-line (default) | true-right-false-down
  if-else: true-right-else-column # lanes | true-right-else-column
  case-split: lanes               # lanes | first-right-rest-columns
  guard: return-below             # return-below | true-right
  wrap: rows                      # rows | off
  max-row-width: 2880             # px, 640..20000
Option Non-default value draws
if-else: true-right-else-column TRUE on the line, and ELSE as a column under the decision that rejoins the merge from below
case-split: first-right-rest-columns the first outcome on the line, and every other outcome as a column under the decision, side by side
guard: true-right a guard's early return stays on the line, and the happy path drops to a new line
wrap: off, max-row-width never wrap, or wrap at another width
  • Strict config: unknown keys or values are errors, not a silent fallback.
  • New commands: mxcli layout config shows the style in force, and mxcli layout flows --style <preset> tries one.
  • The style travels with the flow: a flow laid out in a non-default style records its options in one documentation line, @mxcli-layout: …, so describe and later layouts keep it.
  • No config means no change:
    • 137 created flows have identical positions, sizes, connection sides, curves and documentation before and after.
    • The same holds after layout flows on every module.
    • Describe of 163 flows, including Studio Pro-drawn Marketplace flows, is identical.
  • Fixes inside the new styles:
    • Nanoflow describe now passes the flow's documentation, so it can see the recorded style.
    • A TRUE-right guard in a branch no longer moves the final end event.
    • Column measurements no longer let an outer column land on a nested one.
  • Validated: mxbuild 11.6.6 mx check gives 0 errors on a microflow and a nanoflow using every new option at once. It hasn't been opened visually in Studio Pro yet.
  • Docs:
    • The proposal is PROPOSAL_configurable_flow_layout.
    • mxcli syntax microflow layout gains a Layout style section.
    • The docs-site and write-microflows skill point to it.
  • Not in this PR: wrap: snake, the spacing options and error-handler: row-end.

Lint

Dependencies

  • serialize-javascript goes from 7.1.0 to 7.1.4 in the vega-charts widget pack. This is a Dependabot dev-dependency bump

dependabot Bot and others added 24 commits October 29, 2026 17:21
Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) from 7.1.0 to 7.1.4.
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](yahoo/serialize-javascript@v7.1.0...v7.1.4)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-version: 7.1.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Presets and options for the flow layout engine, including TRUE-right /
ELSE-as-column for IF/ELSE and a separate guard option, read from a
committed layout-config.yaml so canonical DESCRIBE stays stable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
CE0582 is the React client's error, but MPR012 assumed the React client is
the only client on Mendix 11 and warned "mxbuild reports CE0582" on every
legacy image widget of an app still on the classic client, where they build
clean.

The rule now reads Web UI's UseOptimizedClient, as the executor's check for
the same CE0582 does: a warning under the React client ("Yes"), an info note
to convert before switching under "No" and "MigrationMode".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds case-split columns for enumeration/inheritance splits, the
empty-THEN rule, keeps error-handler row-end in scope, and records the
layout style per flow as an @mxcli-layout line in its documentation,
which DESCRIBE and exec use instead of the project file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…-right-else-column)

The builder and measurer carry a flowLayout whose zero value is the
layout mxcli always drew. Under IfElseColumn the TRUE body stays on the
centre line and the ELSE body is stacked top to bottom under the split,
each statement moved down to sit RowGap under the one before, rejoining
the merge from below. Loop bodies inherit the style.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…ut flows --style

The project's committed layout-config.yaml (.claude/ or next to the
.mpr) picks the style CREATE and 'mxcli layout flows' use: presets
happy-line and true-right-false-down, and the if-else option. Unknown
keys and values are errors.

A flow laid out in a non-default style records its options as an
'@mxcli-layout:' line in its documentation; CREATE OR MODIFY and
DESCRIBE's derived-layout check use it for that flow, so its
description stays free of @position when the project style changes.
'layout flows' re-styles in the project style (or --style) and updates
the line; 'mxcli layout config' shows the style in force.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…e budget

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…appy path below

A guard laid out TRUE-right keeps its branch on the centre line and
drops the happy path from the split's bottom onto a new line in the
split's column, RowGap under what the guard drew. The measurer knows,
so ELSE lanes and merges after such a body stay clear; baseY no longer
leaks out of an IF branch.

DESCRIBE reads that shape as a guard only in a flow recording
guard=true-right, so consecutive guards describe as guards rather than
an elsif chain; nanoflow descriptions now see the flow's documentation
for this. The overlap test helper no longer exempts a box inside
another unless the container is a loop.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…splits

The first outcome, as written, stays on the centre line; every other
outcome is a column under the split, side by side in case order, placed
by measured width so enclosing bodies agree with the measurer. Columns
leave the split's bottom and rejoin the merge from below; a multi-value
first outcome is moved clear of its own merge. Part of the
true-right-false-down preset.

DESCRIBE reads column order left to right in a flow recording this
style (columns share a side pair and a top edge). IF-column and the new
split report their height as if centred on the line, so an outer ELSE
column clears a nested one.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
fix(lint): MPR012 follows the app's Web UI client (#1287)
'wrap: off' keeps the main line on one row; 'max-row-width' (640..20000
px, default 2880) moves where a row wraps. Option values may now be
numbers; the default width is stored and recorded as the default, so
it never appears in a flow's @mxcli-layout line.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…skills/packs/mendix-vega-charts/widget/serialize-javascript-7.1.4

build(deps-dev): bump serialize-javascript from 7.1.0 to 7.1.4 in /.claude/skills/packs/mendix-vega-charts/widget
Configurable microflow/nanoflow layout styles (layout-config.yaml). Refs #1832.
'mxcli syntax microflow layout' (and a search for layout-config,
layout style, mxcli-layout, wrap) now explains layout-config.yaml and
the @mxcli-layout documentation line; the Microflow Structure page
links to choosing a style; CHANGELOG entry for #1832.

Refs #1832

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rvP7gba1U24g8Mq9s
…tes (#1640)

A Data grid 2 an older mxcli stored with SortBar.SortItems marker 3 kept it
through every `create or replace page`, including one that changed the page,
where Studio Pro and a page created from nothing store 2. A registered marker
reached only the lists the encoder builds; a rewrite passes much of a stored
document through as bytes (an unchanged pluggable widget's Type and Object,
an existing element's clean properties), and the stored list with it.

The marker tables move to canon, and every write (normalizeForStorage: insert,
update, transaction) runs canon.NormalizeListMarkers, which gives each list
with a registered owner/key marker that marker anywhere in the unit.
Unregistered lists and child-type registrations are left as stored: those are
the encoder's defaults for lists it builds, not measurements.

Applying a registration to stored bytes makes a wrong one rewrite Studio Pro's
documents, so a census now holds every owner/key registration against
ako/TestApp and PedApp and requires each fixture unit to be a fixed point.

Also registers the populated nanoflow parameter lists, which took the child
type's default 3: Forms$CallNanoflowClientAction.ParameterMappings (78 of 78
marker 2) and Forms$NanoflowSource.ParameterMappings (21 of 21).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUbjJ5DeS2vysn9hfKir4Y
docs(layout): make flow layout styles discoverable. Refs #1832.
…s firstOfType

main added a generic firstOfType in flowlayout_ifelse_column_test.go, so the
merged package did not compile (integration (executor) on #1847).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUbjJ5DeS2vysn9hfKir4Y
)

integration (roundtrip) on #1847 reports that these snippets no
longer break getput, and the allowlist may only shrink.

The populated nanoflow parameter lists this PR registers as marker 2 are what
broke them: on origin/main 0 of the 5 round-trip; on this branch 5 of 5; with
the two Forms$CallNanoflowClientAction / Forms$NanoflowSource registrations
removed, 0 of 5 again, each failing on Action/ParameterMappings[0] or
DataSource/ParameterMappings[0]: 2 -> 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUbjJ5DeS2vysn9hfKir4Y
fix(codec): every write gives a stored list the marker Studio Pro writes (#1640)
@ako
ako merged commit ddde38d into mendixlabs:main Nov 1, 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.

MPR012 warns on every legacy image widget in a classic-client app, which Mendix 11 builds without CE0582

2 participants