Skip to content

Fix the two urgent triage items: while-true join describe, in-place edit proxy reset - #2207

Merged
ako merged 2 commits into
mainfrom
claude/beautiful-thompson-96trn4
Nov 13, 2026
Merged

ako merged 2 commits into
mainfrom
claude/beautiful-thompson-96trn4

Conversation

@ako

@ako ako commented Nov 13, 2026

Copy link
Copy Markdown
Owner

Fixes the two class:urgent items on the triage board (#1357). There is one commit per issue, so the PR can be split if needed. The session could push to only one branch.

1. #2168: describe puts the step after an if/else join inside while true into the THEN branch

Upstream: mendixlabs#1829.

Reported symptom (reproduced verbatim on Mendix 11.14.0):

    if $i = 2 then
      set $created = $created + 1;
      set $i = $i + 1;          -- moved into the then branch
    else

If you rebuild from that text, the ELSE branch skips the increment and the loop never ends.

Cause. Inside while true, every node is on a cycle. Three reachability walks that pair a split with its join run past the split, round the loop, and into the split's own branches:

  • findMergeForSplit's bypass filter rejected the real join.
  • resolveNestedMergeID swapped the loop header in as the join.

Fix. All three walks for a split now stop at that split (collectReachableDistances, splitJoinCandidateDoesNotHaveDownstreamBypass, resolveNestedMergeID).

Evidence.

  • TestDescribeWhileTrue_StepAfterIfJoinStaysAfterEndIf failed with the reported text before the fix. It also checks the description rebuilds the stored graph (assertDescriptionRebuildsGraph).
  • Controls, each barrier removed on its own, each fail one test:
    • no distance barrier: ExitInElseStaysInElse fails
    • no bypass barrier: StepAfterIfJoin fails
    • no resolveNestedMergeID barrier: StepAfterIfJoin fails
  • I diffed every microflow and nanoflow description over TestApp (261) and PedApp (29), baseline binary against fixed. A first version that fixed only two of the walks changed WorkflowCommons.SUB_UserTaskView_Migrate: the loop exit came out of its ELSE arm. That is why the third barrier exists, and ExitInElseStaysInElse pins it. Final diff: 0 lines on both corpora.
  • Real project: describe → change the log text → drop + create → describe gives the same text. The before binary's rebuild, described by the fixed binary, shows the ELSE arm genuinely missing the increment.

2. #2169: an in-place edit resets a REST call's proxy (and the activity's documentation)

Upstream: mendixlabs#1830.

Reported symptom: after changing Timeout: 300 to 301, exec prints "spliced: 1 edited in place", and the dump changes RequestProxyType from Override to DefaultProxy and drops ProxyConfiguration.

Cause. swapKeeping carries the stored $IDs, but the content is serialized from the statement. MDL has no spelling for the proxy or for an activity's documentation, so the writer's defaults win.

Fix. mfmutator.unstated is a table, keyed by $Type, of properties MDL cannot state:

  • ActionActivity.Documentation
  • RestCallAction.RequestProxyType and ProxyConfiguration

These are copied from the stored element on an in-place edit. The carried sub-element's $IDs are taken off the removed set, so the integrity check accepts them.

Evidence.

  • The TestSplice_EditKeeps* tests (Override, NoProxy, documentation) failed with exactly the reported values before the fix.
  • Real run on Mendix 11.14.0: I created a REST call, patched its stored proxy to Override, and confirmed with mx check (0 errors) that the patched baseline is valid. Then I spliced a timeout-only edit with each binary:
    • before: ProxyConfiguration: null, RequestProxyType: "DefaultProxy"
    • after: proxy kept, timeout 301, mx check 0 errors
  • describe → exec afterwards reports Unchanged.

Out of scope: the reset that drop + create causes is #2178, filed separately.

Checks

  • make build && make test && make lint && make check-mdl pass locally.
  • Bug-test scripts: mdl-examples/bug-tests/2168-…, 2169-…
  • One finding file per fix; make check-findings passes.
  • Docs: alter-microflow.md and the write-microflows skill now say what an in-place edit keeps; the describe-round-trip-gaps pattern page is synced.

Generated by Claude Code

Inside a while-true loop every node is on a cycle, so the walks that pair a
split with its join reached the split's own branches round the loop. The
inner if was paired with the loop header, and the step after its join was
printed inside the THEN arm; rebuilt from that text, the ELSE arm skipped it
and a counter loop never ended (#2168, mendixlabs#1829).

All three walks for a split now stop at that split: the branch distances,
the join's downstream-bypass check and resolveNestedMergeID.

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

An activity edited in place kept its $IDs but took its content from the
statement, and MDL cannot spell a REST call's proxy or an activity's
documentation, so both came back at the writer's defaults: Override or
NoProxy became DefaultProxy, the proxy expressions were dropped, and the
documentation was cleared (#2169, mendixlabs#1830).

The edit now carries those stored values onto the replacement.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011oK82rmxc4mZcUDT8ePYWM
@ako
ako marked this pull request as ready for review November 13, 2026 07:23
@ako
ako merged commit 3967924 into main Nov 13, 2026
21 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.

2 participants