+{"area": "mdl/executor", "date": "2026-10-25", "symptom": "`create or modify microflow` (mdl 1) and `alter microflow` refused any change of a loop body's shape — an activity inserted, dropped or moved inside `loop … end loop` — with 'the Loop at (x, y) changes inside its body; the splice does not edit inside a loop', and named `alter … replace loop`, which re-minted every element ID in the loop", "cause": "A loop body's nodes are drawn in the loop box's coordinates, so the splice had no layout for them: graph.node() refused every body node and only an in-place one-for-one replace (#1106) was allowed; the diff paired a loop only when its body had the same shape (editableLoopBody)", "file": "mdl/backend/mfmutator/splice.go (spliceOnFlow/makeRoom scoped to a loop, appendInLoop, prependInLoop, dropInLoop, replaceInLoop, fitLoopTo, growLoop, ReplaceLoopBody); mdl/executor/cmd_flow_modify.go (inLoopBody, bodyGap, bodyRefusal); mdl/executor/cmd_alter_flow.go (inLoopRefusal, inBodyTarget, notPlainFragment); mdl/executor/flow_splice_loop_body.go (replaceBody)", "fix": "Shift/room/pin are scoped to a collection (the top level or one loop's body); an edited body is fitted back into its box, which grows on its far side along the line the loop sits on (from the side its incoming flow enters) with what is past it moving along, and symmetrically across it so the flows in and out stay level, recursing into an enclosing loop. The diff runs inLoopBody as an LCS over the body, plain activities only; a decision/loop/return/break/continue/raise/handler is refused naming the new `alter … replace body of <loop>`, which keeps the loop's $ID, position, iterator and list and rebuilds only its contents (the loop restated with its stored header is built, and its body taken)", "insight": "Three facts settled the design and are cheap to re-measure: body flows live in the unit's top-level Flows list, not the loop; an empty loop body passes mx check (0 errors on 11.13), so dropping a body's only activity needs no refusal — but mxcli stores an empty body without its Objects key, so a writer into it must add the list (marker 3); and `create` itself draws a tall nested loop over the parameter row, so a room check that counts parameters refuses layouts the builder makes. A body restated from describe states every @position, so body positions have to be pinned (PinInLoop) like top-level ones or the second run of a spliced script reads its own shifted nodes as 'moved'", "refs": ["ako/mxcli#1693", "ako/mxcli#1399", "mendixlabs/mxcli#1517", "ako/mxcli#1106", "mendixlabs/mxcli#1598"], "test": "TestSpliceLoopBody1693_* , TestAlterReplaceBody1693 (mdl/executor/flow_splice_loop_body_1693_pedapp_test.go); TestSpliceLoop_* (mdl/backend/mfmutator/splice_loop_test.go)"}
0 commit comments