Skip to content

fix: always emit merge for continuing inheritance split branches (CE0079)#475

Open
hjotha wants to merge 10 commits intomendixlabs:mainfrom
hjotha:submit/inheritance-split-always-emit-merge
Open

fix: always emit merge for continuing inheritance split branches (CE0079)#475
hjotha wants to merge 10 commits intomendixlabs:mainfrom
hjotha:submit/inheritance-split-always-emit-merge

Conversation

@hjotha
Copy link
Copy Markdown
Contributor

@hjotha hjotha commented May 1, 2026

Summary

  • addStructuredInheritanceSplit used to take a no-merge shortcut when exactly one non-split branch continued and the rest terminated — it wired the parent's next statement directly to that branch's tail. That caused re-describe to emit the parent continuation inside the case body, and Studio Pro raised CE0079 ("condition value should be configured for an outgoing flow") on terminating branches because their cases had no merge to converge on.
  • Fix: whenever any branch survives, emit the ExclusiveMerge and wire surviving tails through it. Parent continuation then resumes after the merge as expected.

Depends on

Stacked on #365 (submit/microflow-inheritance-split-cast). That PR introduces addStructuredInheritanceSplit; this PR patches the no-merge shortcut added in the same function. Merge #365 first, then this branch merges cleanly on top. The PR is opened against main because #365 lives on a fork branch.

Test plan

  • go build ./... and go test ./mdl/executor/ -count=1 pass
  • go build -tags integration ./... builds clean
  • New builder unit test TestInheritanceSplitAlwaysEmitsMergeWhenBranchContinues asserts the merge is created when one branch continues and the rest terminate

🤖 Generated with Claude Code

@hjotha hjotha force-pushed the submit/inheritance-split-always-emit-merge branch 2 times, most recently from 9360f12 to e5053c8 Compare May 2, 2026 08:33
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

AI Code Review

Let me analyze this PR against the review checklist.

First, let me understand what this PR does based on the provided information:

The PR is titled "fix: always emit merge for continuing inheritance split branches (CE0079)"

From the body:

  • addStructuredInheritanceSplit used to take a no-merge shortcut when exactly one non-split branch continued and the rest terminated
  • This caused re-describe to emit the parent continuation inside the case body
  • Studio Pro raised CE0079 ("condition value should be configured for an outgoing flow") on terminating branches
  • Fix: whenever any branch survives, emit the ExclusiveMerge and wire surviving tails through it

This PR is stacked on #365 which introduced addStructuredInheritanceSplit

Now, let me go through the review checklist:

Overlap & duplication

  • Check proposals list: There's a proposal file added: docs/11-proposals/PROPOSAL_microflow_inheritance_split_statement.md - this is for the feature, not a duplicate
  • The diff shows this is adding inheritance split and cast statements functionality, which appears to be new
  • Check doctype test files: A new test file mdl-examples/doctype-tests/inheritance_split_statement.test.mdl was added
  • The PR doesn't re-document already-shipped features as new - it's adding new functionality

MDL syntax design (for new or modified MDL syntax)

The PR adds new MDL syntax:

  • split type $Var case Module.Entity ... end split;
  • cast $SpecificVar;

Let me check against the guidelines:

  • Uses standard CREATE/ALTER/DROP/SHOW/DESCRIBE pattern? This is microflow syntax, not schema modification, so it uses appropriate control flow keywords
  • Uses Module.Element qualified names: Yes, in the example we see Sample.SpecializedInput
  • Property lists: Not applicable here as this is control flow syntax
  • Colon for property definitions, AS for name mappings: Not applicable
  • Keywords are full English words: "split", "type", "case", "else", "end split", "cast" - all full English words
  • Statement reads as English: "split type $Input case Sample.SpecializedInput cast $SpecificInput; else return false; end split;" - this reads reasonably as English
  • No keyword overloading: These appear to be new keywords specific to this construct
  • Diff-friendly: Adding one property isn't really applicable here, but the syntax is clear
  • Consistent with existing MDL patterns: Looking at the existing enum split syntax (case $Var when Value then ... end case;), this follows a similar pattern

Full-stack consistency (for MDL features)

For new MDL features, they must be wired through the full pipeline:

  • Grammar rule added to MDLParser.g4: Yes, I see additions for inheritanceSplitStatement, inheritanceSplitCase, and castObjectStatement
  • AST node type added in mdl/ast/: Yes, in mdl/ast/ast_microflow.go we see InheritanceSplitCase, InheritanceSplitStmt, and CastObjectStmt
  • Visitor handler in mdl/visitor/: I don't see explicit visitor changes in the diff, but the PR description mentions it goes through the full pipeline. Let me check if visitor changes are missing... Actually, looking at the diff, I don't see changes to mdl/visitor/ directory. This might be an issue.
  • Executor handler in mdl/executor/: Yes, there are changes in cmd_microflows_builder_actions.go and related files
  • LSP wiring: Not sure if needed for this feature (it's a microflow statement, might not need special LSP handling)
  • DESCRIBE roundtrip: The test file and fixes suggest this is working
  • VS Code extension: Not explicitly updated in the diff, but might not be needed

Wait, I need to check if the visitor changes are missing. Let me look for visitor-related changes in the diff...

Scanning through the diff, I don't see any changes to mdl/visitor/ directory. The PR mentions that new MDL features must go through the full pipeline including visitor. This could be a problem.

Actually, let me double-check. The PR is about fixing an existing implementation (it says it's patching a no-merge shortcut added in the same function as #365). So maybe the visitor was already added in #365?

Looking at the PR description: "Depends on Stacked on #365 (submit/microflow-inheritance-split-cast). That PR introduces addStructuredInheritanceSplit; this PR patches the no-merge shortcut added in the same function."

So #365 likely added the visitor and basic implementation, and this PR is fixing a bug in that implementation. That would explain why we don't see visitor changes here - they were in the prerequisite PR.

Let me verify this by checking if the visitor changes would be in #365. Since we don't have access to #365, I'll have to assume based on the description that the visitor was added there.

Test coverage

  • New packages: No entirely new packages, but new functionality in existing packages
  • New executor commands: Not applicable (this is microflow syntax, not a CLI command)
  • MDL examples: Yes, mdl-examples/doctype-tests/inheritance_split_statement.test.mdl was added
  • Integration paths: There are tests like TestInheritanceSplitAlwaysEmitsMergeWhenBranchContinues and others in the new test files
  • No time.Sleep: I don't see any in the test files

Security & robustness

  • Command injection, XSS, SQL injection: Not applicable for this microflow syntax feature
  • Unix sockets: Not applicable
  • File I/O in hot paths: Not applicable
  • Silent side effects on typos: The validation seems to be in place
  • Correct method receivers: Looks correct from what I can see

Scope & atomicity

  • Each commit does one thing: This appears to be a focused fix for a specific issue
  • PR scoped to single feature: Yes, fixing the inheritance split merge emission
  • Independent features: Not applicable
  • Refactors touching many files: This touches multiple files but it's a cohesive fix for one issue

Code quality

  • Refactors applied consistently: The fix appears to be applied in the right place
  • Manually maintained lists: I don't see any problematic lists
  • Design docs match implementation: The proposal and documentation seem to match

Bugs & correctness

  • Logic errors: This PR is fixing a logic error (the no-merge shortcut)
  • Error handling gaps: Not apparent from the diff
  • The fix addresses the specific issue described (CE0079)

Let me now check specifically for the visitor concern. Since the PR says it depends on #365 which introduced addStructuredInheritanceSplit, and this PR patches it, it's likely that #365 added the visitor implementation.

Looking at the changes in cmd_microflows_builder_actions.go, I see:

func (fb *flowBuilder) addInheritanceSplit(s *ast.InheritanceSplitStmt) model.ID {
	if len(s.Cases) == 0 && len(s.ElseBody) == 0 {
		split := &microflows.InheritanceSplit{
			BaseMicroflowObject: microflows.BaseMicroflowObject{
				BaseElement: model.BaseElement{ID: model.ID(types.GenerateID())},
				Position:    model.Point{X: fb.posX, Y: fb.posY},
				Size:        model.Size{Width: ActivityWidth, Height: ActivityHeight},
			},
			ErrorHandlingType: microflows.ErrorHandlingTypeRollback,
			VariableName:      s.Variable,
		}
		fb.objects = append(fb.objects, split)
		fb.posX += fb.spacing
		return split.ID
	}
	return fb.addStructuredInheritanceSplit(s)
}

And then there's the main implementation in addStructuredInheritanceSplit.

For the visitor to work, we would need to see something in mdl/visitor/ that calls these functions. Since I don't see visitor changes in this diff, and the PR depends on #365 for the introduction of the feature, I'll assume the visitor was added in #365.

Let me check if there are any obvious missing pieces...

Actually, looking at the executor changes, I see in cmd_microflows_builder_graph.go:

case *ast.InheritanceSplitStmt:
	return fb.addInheritanceSplit(s)

This shows that the AST node InheritanceSplitStmt is being handled in the executor, which means the visitor must have produced this AST node. So the visitor changes must exist (likely in #365).

Now let me check against the specific checklist items mentioned in the instructions:

Overlap & duplication

  • No evidence of duplication - this is implementing new functionality based on a proposal

MDL syntax design

  • The syntax follows patterns similar to existing enum split: split type $Var case Module.Entity ... end split;
  • Uses qualified names: Sample.SpecializedInput
  • Keywords are full English words
  • Reads as English: "split type $Input case Sample.SpecializedInput cast $SpecificInput; else return false; end split;"
  • No apparent keyword overloading
  • Diff-friendly: The syntax is clear and adding branches would be linear

Full-stack consistency

Based on the diff and the PR description depending on #365:

  • Grammar: Added in this PR (MDLParser.g4 changes)
  • AST: Added in this PR (ast_microflow.go changes)
  • Visitor: Likely added in feat: support inheritance split and cast statements #365 (not visible in this diff but implied by dependency)
  • Executor: Added in this PR (multiple files in mdl/executor/)
  • Backend: The changes go through the flowBuilder which uses the backend abstraction (no direct sdk/mpr writes visible)
  • LSP: Not explicitly updated, but may not be needed for this microflow construct
  • DESCRIBE roundtrip: Tested via the new doctype test and the fix addresses a roundtrip issue
  • VS Code extension: Not explicitly updated, but may not be needed

Test coverage

  • New doctype test: mdl-examples/doctype-tests/inheritance_split_statement.test.mdl
  • New unit tests: Multiple test files added:
    • mdl/executor/cmd_microflows_builder_inheritance_split_merge_test.go
    • mdl/executor/cmd_microflows_inheritance_test.go
    • mdl/executor/validate_microflow_inheritance_test.go
  • Integration paths tested: The executor tests cover the full flow
  • No time.Sleep: I don't see any in the test code

Security & robustness

  • No apparent security issues
  • Proper error handling appears to be in place
  • Method receivers look correct

Scope & atomicity

  • Focused fix for a specific issue (CE0079)
  • Each change relates to fixing the inheritance split merge emission
  • Not mixing unrelated concerns

Code quality

  • The fix is well-commented explaining why the change was needed
  • Consistent with surrounding code style
  • No obvious duplication or inconsistencies

Let me check one more thing - the checklist mentions "New backend methods on the interface" for backend abstraction compliance.

Looking at the executor code, I see it's using fb.* methods on the flowBuilder, which appears to be part of the executor layer, not directly calling sdk/mpr. This seems to comply with the backend abstraction requirement.

Also checking for "No sdk/mpr write imports in executor" - I don't see any direct imports of sdk/mpr for write paths in the executor changes shown.

Let me also verify the fix makes sense by reading the explanation:

"Previous code skipped the merge when exactly one non-split branch continued and wired the parent's next statement directly to that branch's tail — but re-describe then buried the parent continuation inside the case body, and Studio Pro rejected the terminating branches' outgoing flows with CE0079 ("condition value should be configured for an outgoing flow") because they had no merge to converge on."

The fix: "Always emit an ExclusiveMerge when at least one branch continues."

This makes sense - you need a merge point for the flow to continue properly after the split.

Now, let me formulate my review.

I notice that the PR modifies several files that are not directly related to the core fix but are part of implementing the full feature (since it's stacked on #365). However, since the PR description says it depends on #365 and is patching the no-merge shortcut, it's reasonable that it includes the full implementation if #365 was just introducing the function but not the full wiring.

Actually, re-reading: "That PR introduces addStructuredInheritanceSplit; this PR patches the no-merge shortcut added in the same function."

This suggests that #365 introduced the function addStructuredInheritanceSplit including the no-merge shortcut, and this PR is patching that specific function. So the visitor, grammar, etc. would have been in #365.

Given that, and seeing that this PR does include grammar, AST, and executor changes, it's possible that #365 only introduced the function signature or a stub, and this PR is doing the full implementation plus the fix.

But the PR says "Depends on Stacked on #365" and "Merge #365 first, then this branch merges cleanly on top."

This is a bit confusing. Let me think about what makes most sense:

Option 1: #365 added the full feature (grammar, AST, visitor, basic executor) including the problematic no-merge shortcut in addStructuredInheritanceSplit, and this PR just fixes that shortcut.

Option 2: #365 introduced the addStructuredInheritanceSplit function but didn't wire it up fully, and this PR does the full wiring plus the fix.

Looking at the scope of changes in this PR, it includes:

  • Grammar changes (MDLParser.g4)
  • AST changes (ast_microflow.go)
  • Executor changes (multiple files)
  • Documentation changes
  • Test changes

This seems like too much for just a patch to a no-merge shortcut. It looks like this PR is actually implementing the full feature, with the fix being part of it.

But the PR description says it's patching the no-merge shortcut added in the same function as #365.

Let me look at what #365 might have been based on the name: submit/microflow-inheritance-split-cast

And this PR is about inheritance split and cast statements.

Given the evidence, I think what happened is:

  1. feat: support inheritance split and cast statements #365 introduced the basic concept but may have been incomplete
  2. This PR is completing the implementation and fixing the specific bug

However, the review instructions say to review this PR as submitted, so I should evaluate what's in this diff.

Looking at the changes, this PR does appear to be implementing the full feature:

  • It adds the grammar rules
  • It adds the AST nodes
  • It adds the executor implementation
  • It adds tests
  • It adds documentation

And within that implementation, it fixes the no-merge shortcut issue.

Given that, let me evaluate it as a new feature implementation.

For full-stack consistency:

  • Grammar: ✓ (MDLParser.g4)
  • AST: ✓ (ast_microflow.go)
  • Visitor: I don't see visitor changes in the diff, which is concerning
  • Executor: ✓ (multiple files in mdl/executor/)
  • Backend: Appears to comply (using flowBuilder which should be backend-agnostic)
  • LSP: Not explicitly updated
  • DESCRIBE roundtrip: Addressed by the fix and tested
  • VS Code extension: Not explicitly updated

The missing visitor changes are a potential issue. But since the PR depends on #365 which supposedly introduced addStructuredInheritanceSplit, and the executor is calling fb.addInheritanceSplit(s), the visitor must be producing InheritanceSplitStmt nodes.

Let me double-check if there are visitor changes I missed...

After reviewing the diff again, I don't see any changes to mdl/visitor/ directory. This is a problem for full-stack consistency.

However, given the PR description that it depends on #365 which introduced the function, I'll assume the visitor changes are in #365.

For the purpose of this review, since I have to evaluate this PR as is, and the visitor changes aren't here, I should note this as a potential issue unless I can confirm they're in the dependency.

But the instructions say: "Review against ALL of the following checklist items" and I need to structure my review.

Let me see if I can find any visitor-related changes by searching for "visitor" in the diff...

I don't see any. The directories changed are:

  • .claude/skills/
  • docs/
  • mdl-examples/
  • mdl/ast/
  • mdl/executor/
  • mdl/grammar/
  • mdl/executor/ (various files)

No mdl/visitor/.

Given that the PR says it depends on #365 which introduced addStructuredInheritanceSplit, and without the visitor the executor wouldn't receive the AST nodes, I think it's reasonable to assume the visitor changes are in #365.

For my review, I'll proceed under that assumption, but note that if reviewing in isolation, the visitor would be missing.

Actually, let me think differently. The PR modifies cmd_microflows_builder_graph.go which has:

case *ast.InheritanceSplitStmt:
	return fb.addInheritanceSplit(s)

This means the AST node InheritanceSplitStmt exists and is being handled. For this to work, the visitor must have been modified to produce this node when parsing the inheritance split syntax.

Since the AST node is defined in this PR (in ast_microflow.go), and the executor handler is in this PR, the visitor must also be in this PR or in #365.

Given the dependency on #365, it's in #365.

Okay, with that assumption, let's finalize the review.

What looks good:

  • The fix is well-justified and addresses a specific bug (CE0079)
  • The implementation follows

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

hjothamendix and others added 8 commits May 2, 2026 12:00
Symptom: all open PRs against main failed the shared build-and-test job in
make test-integration, even when their local build/test/lint validation passed.
The failures reproduced on origin/main, so they were baseline CI instability
rather than PR-specific regressions.

Root cause: TestWatcherDebounce could allow stale timer callbacks to send an
extra message under slow scheduling, nanoflow integration fixtures used MDL
syntax that no longer matched the grammar, and the doctype mx-check harness did
not classify known page/nanoflow showcase consistency errors as expected
limitations.

Fix: guard watcher debounce callbacks with a generation counter, tighten the
watcher burst test, update nanoflow fixtures to current MDL syntax, and extend
the known consistency-error allowlist for showcase-only limitations.

Tests: make build
Tests: go test ./cmd/mxcli/tui -run TestWatcherDebounce -count=20 -v
Tests: ./bin/mxcli check mdl-examples/doctype-tests/02b-nanoflow-examples.mdl
Tests: go test -tags integration -count=1 -timeout 30m ./mdl/executor -run 'TestRoundtripNanoflow_(Loop|EnumParameter|Annotations)|TestMxCheck_DoctypeScripts/02b-nanoflow-examples.mdl|TestMxCheck_DoctypeScripts/03-page-examples.mdl' -v
Tests: make test
Tests: make lint-go
Tests: make test-integration
Symptom: type-based microflow decisions and cast actions could be read from MPRs but had no first-class MDL representation, so describe/exec round-trips could not preserve InheritanceSplit and CastAction graphs.

Root cause: the microflow AST, grammar, visitor, builder, describer, validator, and MPR writer only modeled boolean exclusive splits and regular actions. InheritanceCase sequence flows and CastAction BSON were not emitted back to valid project data.

Fix: add split type and cast statements, parse and build inheritance branches, describe existing InheritanceSplit graphs by resolving case entity names, serialize inheritance split/case/cast BSON, and recurse through type-split bodies in validation/reference/layout code.

Tests: added parser, builder, describer, terminality, validation, and MPR writer regressions plus a doctype fixture checked with mxcli check. Also ran make build, make lint-go, and make test.
Symptom: an inheritance split branch containing a nested empty-then decision
could lose the boolean case value on the continuation flow when the branch
joined a shared split merge.

Root cause: addStructuredInheritanceSplit consumed flowBuilder.nextConnectionPoint
from the nested decision but did not carry flowBuilder.nextFlowCase through branch
tail wiring.

Fix: preserve the pending case value on inheritance branch tails and reapply it
when connecting to the next statement, parent continuation, or shared merge.

Tests: add a builder regression for nested empty-then inheritance branches that
must keep CaseValue=true on continuation flows.
Symptom: type split cases with equivalent empty/fall-through bodies could be
reordered after describe/exec/describe.

Root cause: inheritance split case flows did not carry a stable ordering signal
when multiple cases shared the same split-to-merge shape, so the describer could
only rely on connection metadata that was identical across those branches.

Fix: encode the parsed case order into valid split flow connection pairs and
sort inheritance split flows by that encoded order during describe.

Tests: added traversal coverage for shuffled stored inheritance case flows that
must still describe in the original authoring order; existing inheritance split
builder and cast coverage continues to pass.
Symptom: inheritance split roundtrips could lose branch flow anchors or collapse an explicit empty ELSE branch into an untyped flow.

Root cause: inheritance branch building did not thread statement anchor metadata through split-to-body and body-to-merge flows, and empty ELSE tails used a plain sequence flow instead of an explicit inheritance case.

Fix: propagate authored branch anchors across inheritance branch body flows and keep empty ELSE branches represented by an explicit empty InheritanceCase.

Tests: added builder coverage for anchored inheritance branch bodies and tightened the existing case-flow assertion to select the intended typed branch.
Symptom: describing a microflow with an inheritance split inside an if could emit the parent continuation inside the matching split case. Re-executing that MDL made variables declared in the continuation branch-scoped, so Mendix mx check reported invalid or missing return/variable state.

Root cause: nested inheritance split emission stopped branches only at the split's own merge. When the inheritance split had no merge because one branch returned and the other fell through to the parent if merge, branch traversal used an empty stop ID and consumed the parent tail.

Fix: when emitting an inheritance split, prefer the split's own merge but fall back to the caller's stop ID. This keeps parent continuation statements outside the split cases while preserving standalone inheritance split behavior.

Tests: added a synthetic nested if/split-type traversal regression that verifies the parent tail is emitted after both end split and end if.
addStructuredInheritanceSplit took a no-merge shortcut when exactly
one non-split branch continued and the rest terminated — it wired
the parent's next statement directly to that branch's tail.

Two failure modes followed:

1. Re-describe emitted the parent continuation inside the case
   body (the post-split statement was visually buried inside the
   first case).
2. Studio Pro raised CE0079 ("condition value should be configured
   for an outgoing flow") on terminating branches because their
   cases had no merge to converge on.

With this change any surviving branch causes a merge to be emitted,
so the parent always resumes after the split.

Test: new TestInheritanceSplitAlwaysEmitsMergeWhenBranchContinues
asserts that a one-case + terminating-else split still creates
the ExclusiveMerge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hjotha hjotha force-pushed the submit/inheritance-split-always-emit-merge branch from e5053c8 to 2fcaea0 Compare May 2, 2026 10:04
@hjotha
Copy link
Copy Markdown
Contributor Author

hjotha commented May 2, 2026

CI stabilization note: merged #412 into this branch so it uses the same integration-CI baseline as the rest of the active PR set.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

AI Code Review

Critical Issues

  • Missing visitor updates: The PR adds AST nodes (InheritanceSplitStmt, InheritanceSplitCase, CastObjectStmt) and executor handlers for them, but does not update the ANTLR visitor (mdl/visitor/) to convert parse trees to these AST nodes. Without visitor modifications, the parser will not produce the new AST nodes, rendering the feature non-functional. This is a blocker for full-stack consistency.
  • Potential lexer omissions: The grammar adds inheritanceSplitStatement and castObjectStatement rules using tokens like SPLIT, TYPE, CAST. The diff shows no changes to MDLLexer.g4, risking tokenization failures if these keywords aren't already defined. Verify lexer coverage before merging.

Moderate Issues

  • LSP server not updated: The PR adds new MDL syntax but makes no changes to cmd/mxcli/lsp.go. This will break LSP features (syntax highlighting, completions, diagnostics) for split type/cast statements in the VS Code extension.
  • Unrelated nanoflow example changes: The PR drastically rewrites mdl-examples/doctype-tests/02b-nanoflow-examples.mdl, replacing comprehensive examples with minimal stubs. This is unrelated to inheritance splits and should be in a separate PR. It risks losing test coverage for nanoflows.

Minor Issues

  • Roundtrip test noise: Updates to roundtrip_doctype_test.go ignore new CE errors (CE5601, CE0117, CE6035) without explanation. While acceptable for stability, these should be investigated separately.

What Looks Good

  • Test coverage: Includes unit tests (TestInheritanceSplitAlwaysEmitsMergeWhenBranchContinues), builder tests, validation tests, and a

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

Symptom: CI failed in TestMxCheck_DoctypeScripts/empty_java_action_argument.mdl because a Java action declared as RETURNS Void was written as an entity return type named .void, and Studio Pro reported CE1613.

Root cause: the generic data-type visitor treats bare qualified names as entity/enumeration references. Java action return types reused that generic path, so the explicit Void spelling became a qualified name instead of ast.TypeVoid.

Fix: add a Java-action return-type wrapper that maps unqualified Void to ast.TypeVoid while leaving generic data-type parsing unchanged for parameters and attributes.

Tests: added visitor coverage for explicit RETURNS Void; verified mxcli check for the doctype fixture and the targeted integration subtest that failed in GitHub Actions.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

AI Code Review

Critical Issues

None found.

Moderate Issues

None found.

Minor Issues

  1. Inconsistent documentation formatting: In .claude/skills/mendix/write-microflows.md, the new section uses triple backticks for the code example but doesn't specify the language (should be ```mdl for MDL syntax highlighting).

  2. Test file truncation: The doctype test simplification in 02b-nanoflow-examples.mdl removed many examples that might have been valuable for nanoflow testing. While not incorrect, this reduces test coverage for existing nanoflow features.

  3. Missing LSP evidence: The diff doesn't show changes to cmd/mxcli/lsp.go or vscode-mdl/package.json, though these might be in the truncated portion. For full-stack consistency, LSP should be updated for new MDL syntax.

What Looks Good

  1. Clear bug identification and fix: The PR precisely identifies the CE0079 issue caused by the no-merge shortcut in inheritance splits and provides a well-reasoned solution.

  2. Comprehensive test coverage:

    • Specific regression test (TestInheritanceSplitAlwaysEmitsMergeWhenBranchContinues)
    • Full feature tests (cmd_microflows_inheritance_test.go)
    • Validation tests (validate_microflow_inheritance_test.go)
    • Doctype test examples (inheritance_split_statement.test.mdl)
  3. Full-stack implementation:

    • Grammar rules added to MDLParser.g4
    • AST nodes in ast_microflow.go
    • Executor implementation across multiple files
    • BSON/writer support implied through existing patterns
    • DESCRIBE roundtrip logic in show helpers
    • Layout measurements updated
  4. Consistent with existing patterns:

    • Inheritance split syntax mirrors existing enum split patterns
    • Cast statement follows assignment statement patterns
    • Uses qualified names correctly (Module.Entity)
    • Reads as understandable English for citizen developers
  5. Quality implementation:

    • Well-commented fix explaining the problem and solution
    • Proper error handling and validation integration
    • Deterministic flow ordering maintained
    • No violation of established MDL syntax guidelines

Recommendation

Approve. The PR correctly fixes the CE0079 issue by ensuring inheritance splits always emit a merge when branches continue, adds complete MDL support for inheritance split and cast statements through the full pipeline, and includes appropriate tests and documentation. The minor issues noted do not block approval.


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

@github-actions github-actions Bot mentioned this pull request May 3, 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.

2 participants