Skip to content

Sync: stub-then-real flows keep the real flow (error-handler returns splice, MDL-STUB01) - #1258

Merged
ako merged 8 commits into
mendixlabs:mainfrom
ako:main
Oct 1, 2026
Merged

ako merged 8 commits into
mendixlabs:mainfrom
ako:main

Conversation

@ako

@ako ako commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Fast-forward sync of ako/mxcli main (016f784 → 2b73b82, 8 commits). This fixes the last beta blocker found by acceptance rehearsal 3 (ako#905): on a real project, an upgraded stub-then-real script set kept the placeholder flow on every run, while mx check reported 0 errors.

Splicing (ako#909)

  • Under mdl 1, create or modify can splice in a new activity whose custom error handler ends in its own return. The handler's return becomes a new end event, placed in free room; a case with genuinely no room is refused and nothing is written. Before, the error-handler builder never passed its returns to the main flow, so the splice refused them as unsupported.
  • A log, show-message or validation-feedback message written as an expression ('x ' + $y) now matches its stored '{1}' template, so an identical second run is Unchanged rather than refused.

Stub-then-real detection (ako#908)

  • mxcli check accepts several files and reads them as one script set. A flow declared twice in the set gets an MDL-STUB01 warning naming both statements, with the advice to drop the stub: a recursive flow is created in one statement.
  • fmt --upgrade over several files decides the mdl 1; header for both files of such a pair together, so a mixed pair can no longer rebuild the real flow from its stub on every run. A pinned mdl 0; stub holds its partner back.
  • Single-file behaviour is unchanged.

Verified on a CapTrack copy: after fmt --upgrade -p and two runs, ACT_Export_Excel is the real export flow, the second run writes nothing, and mx check matches the baseline.

ako and others added 8 commits October 1, 2026 17:25
…exiting

The check command's body becomes runCheckFile, which returns the exit code
where it called os.Exit. Behaviour is unchanged for the one file check takes;
it lets a caller check several files and combine their codes (#905).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r stub-then-real flows (#905)

check and fmt --upgrade take several files, run in the order given. A flow
two create-or-modify statements of the set declare - a stub, then the real
flow - is reported as MDL-STUB01 (a warning) naming both statements, and
fmt --upgrade decides the language header for the files sharing such a
flow together: all take it or none does. Decided file by file, the stub's
file was declined the header while the real flow's file took it, and run in
order the mdl 0 stub rebuilt the real flow every run while the mdl 1 real
statement was refused, with mx check clean. One file alone is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…an already-headed file is reported, not declined (#905)

canTakeHeader read any written header as 'already under it', so a stub
pinned `mdl 0;` let its real file take `mdl 1;` and the pair split again.
A file already carrying the header cannot be declined it (fmt never removes
one); fmt now says the pair stays split instead of 'no language header added'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed '{1}' template (#905)

A log, show message or validation feedback whose message is an expression
(`'failed for ' + $User/Name`) is stored as the template '{1}' with the
expression as its parameter, and describe prints that form. declaredMatches
compared the two spellings as different statements, so wherever the built
comparison does not decide (a spliced or Studio Pro-drawn flow) the
statement diff replaced the activity on every run: absorbed by the write
elision on the main path, refused under mdl 1 when the message sits in a
stored activity's error handler ("cannot replace … it has an error
handler"). That was the second run of CapTrack's ACT_Export_Excel once the
splice could grow it.

matchValue normalises the three statements to the builder's stored form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eturn when spliced (#905)

Under mdl 1, `create or modify` refused to grow a stored flow by an activity
whose custom error handler ends in `return` ("an error handler in the
fragment ends at an end event of its own … a return inside an error handler
is not spliced yet"), as an insert or a replace, on every run; mdl 0 rebuilt
the flow. On CapTrack this left a stub-then-real pair with the placeholder
stored.

The handler is built by a child flowBuilder whose returnEndIDs never reached
the parent, so cutFragment took the handler's return end event for one the
builder added. addErrorHandlerFlow now carries them up: the return is a new
end event of the flow, placed where the builder drew it relative to the
fragment, like a guard clause's (#888), and checkRoom/checkBranches refuse
where it would be drawn over or across stored content.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(flow-modify): splice a new activity whose error handler ends in its own return (#905 part 1, G2)
check/fmt: read several files as one script set; report and pair stub-then-real flows (#905 part 2)
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

AI Code Review

Critical Issues

None found.

Moderate Issues

None found.

Minor Issues

  • In mdl/executor/flow_declared_match.go, the messageAsTemplate function modifies the AST node directly (setting Template and Message fields). While this appears safe due to the use of storedFlowDataType creating a copy, it would be clearer to document that this mutation is intentional and confined to the matching scope. However, given the existing test coverage and the localized use, this is low risk.
  • The script_set.go file contains a comment "// Beta blocker: a stub-then-real script set silently replaces the real flow with its placeholder after fmt --upgrade ako/mxcli#905: check over a script set warns when two of its create or modify statements declare one flow — a stub-then-real pair — naming both and saying to drop the stub." This duplicates information already in the PR description and CHANGELOG. While not harmful, it could be simplified to avoid maintenance overhead.

What Looks Good

  • The PR successfully addresses the beta blocker (Beta blocker: a stub-then-real script set silently replaces the real flow with its placeholder after fmt --upgrade ako/mxcli#905) by:
    • Enabling splicing of error handlers that end in return (fixing the core issue where handler returns were refused)
    • Implementing message expression templating so identical expressions match stored {1} templates
    • Adding script set awareness to check and fmt --upgrade with MDL-STUB01 warning for stub-then-real flows
    • Making fmt --upgrade decide language headers for stub-then-real pairs collectively
  • Test coverage is excellent:
    • New unit tests for message templating (flow_message_respelling_test.go)
    • New unit tests for error handler splicing (cmd_alter_flow_handler_return_test.go)
    • New integration test for splicing roundtrip (flow_splice_handler_return_test.go)
    • Comprehensive script set tests (script_set_test.go)
  • Changes follow the project's architectural patterns:
    • Modifications are localized to the affected areas (executor, CLI commands)
    • No violation of the full-stack consistency requirement (no new MDL syntax added)
    • Test-first approach evident with tests added alongside implementation
    • Documentation updated in skills and error messages to reflect new behavior
  • The solution is principled:
    • Uses existing warning framework (MDL-STUB01) rather than inventing new mechanisms
    • Respects the idempotence principle (second run writes nothing when unchanged)
    • Provides clear actionable advice ("drop the stub") in warnings
    • Maintains single-file behavior unchanged as requested

Recommendation

Approve the PR. The changes are correct, well-tested, and fully address the described issue while maintaining backward compatibility and following project conventions. The minor issues noted do not block merging and can be addressed in follow-up work if desired.


Automated review via OpenRouter (Nemotron Super 120B) — workflow source

@ako
ako merged commit b7b1245 into mendixlabs:main Oct 1, 2026
15 checks passed
ako added a commit to ako/mxcli that referenced this pull request Oct 1, 2026
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