Skip to content

fix(canvas): mf-canvas-facts.py reads a note line's sides by the model's Mendix version - #595

Closed
saingge wants to merge 1 commit into
MendixMau:masterfrom
saingge:fix/canvas-facts-note-numbering
Closed

saingge wants to merge 1 commit into
MendixMau:masterfrom
saingge:fix/canvas-facts-note-numbering

Conversation

@saingge

@saingge saingge commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Branch fix/canvas-facts-note-numbering, one commit (67d4875) on origin/master 95e1b30. Lane 3 (direct). It stands alone: nothing is stacked on it.

What changed and why

A note line (Microflows$AnnotationFlow) stores two integers: OriginConnectionIndex, the note's side, and DestinationConnectionIndex, the object's side. Every object but a note numbers its sides top 0, right 1, bottom 2, left 3. A note numbers its own sides differently by Mendix version:

top right bottom left
Note on Mendix 10 0 3 1 2
Note on Mendix 11 0 1 2 3

mf-canvas-facts.py has only the Mendix 10 table. On a Mendix 11 model it reads nearly every hand-drawn note line as leaving a side that faces away, and prints a false NOTE-SIDE fact (it also bends the line it checks for LINE, so those facts are false too).

The script now reads _ProductVersion from the .mpr's _MetaData table. Major version 11 or higher uses the activity numbering; 10 uses the old table. If the version cannot be read (no table, no row, no number) it counts as Mendix 11, the newer numbering and the one current mxcli writes. The first output line says which numbering was used, for example # note sides: Mendix 11 numbering (model version 11.15.0), so a reader can check it. Nothing else in the output changes.

Why the version and not the data: a note line's pair does not say which numbering it is in. (2, 0) is "out of the note's left" on Mendix 10 and "out of the note's bottom" on Mendix 11.

Impact

Row Answer
Process none. An instrument that prints facts; no gate reads it.
Dependencies project-bin/mf-canvas-facts.py and its fixture only. The version is read through Model._db() from mxpatch.py. A script that loads mf-canvas-facts.py as a module and reads NOTE_SIDES before main() runs now gets the Mendix 11 table; note_numbering(model) returns the right one for a model. Draft changes that edit tests/wave2/test-mf-canvas-facts.sh or CHANGELOG.md will need a rebase, nothing more.
Context cost none: no routed or always-loaded file touched. render-routing.sh --check: "Baseline: 65444 words (budget 80000)", the same as on origin/master.
Behaviour n/a: script only.
Runtime one extra SELECT on the .mpr per run.

Field evidence

One app's 305 hand-drawn note lines, matched across its 10.24 and 11.15 versions by ID. The upgrade changed the note's side on every line: top 0 stayed 0, bottom 1 became 2, left 2 became 3, right 3 became 1. It left the object's side unchanged. By geometry, on 10.24 an object below its note is stored (1, 0); on 11.15 the same lines are (2, 0).

mf-canvas-facts.py --all over both versions of the app (measured 2026-10-29): origin/master reads the 11.15 version with a NOTE-SIDE fact on most of those lines and about twice the LINE facts of the 10.24 version. With this change both versions give identical facts of every kind.

mxcli agrees for Mendix 11: v0.28.0 documents a note's sides as numbered like an activity's (sdk/microflows/microflows.go:418-420) and picks them by geometry (mendixlabs/mxcli#1620). From a read of the source, not a run, it has no check of the project's version on that path (mdl/backend/modelsdk/microflow_write.go:497-504), so on a Mendix 10 project the numbering it writes is the Mendix 11 one, and this script then reports such a line by the Mendix 10 table.

Not checked: how Studio Pro 10 or 11 draws a line whose pair is in the other numbering (read from the stored data only, not from a Studio Pro screenshot).

Checklist

  • No client data anywhere in the diff (LEAKGUARD_ALLOW_NO_DENYLIST=1 LEAKGUARD_BASE=origin/master bin/check-no-client-data.sh: clean; the fixture is the existing synthetic golden model).
  • Size: 2 counted files, 103 lines changed (the script 35 added, 11 removed; the fixture 54 added, 3 removed), excluding CHANGELOG. Within the cap.
  • Test tier: T1 (the fixture) and T2 (the field run above).
  • Golden input: the existing captured v0.27.0 model. It carries 11.14.0 in its dump; model() now stamps 10.24.18.103793 over it, because its golden facts are a Mendix 10 reading.
  • Both platforms: macOS only. Stdlib Python; check-portability.sh clean; not run under Git Bash.
  • CHANGELOG.md line under ## Unreleased, credited.
  • [n/a] New skill. [n/a] Bug entries.

Verification

Run on this branch (67d4875), macOS arm64, 2026-10-29, MXTK_NO_GUIDE=1.

bash tests/wave2/test-mf-canvas-facts.sh project-bin/mf-canvas-facts.py -> PASS=22 FAIL=0

New section V (8 checks): the first line names the numbering for a 10.24 and an 11.15 stamp; mxcli's (2, 0) note above its activity is NOTE-SIDE on 10 and not on 11; for each of the four origin sides, the golden model on 10 and the same model on 11 with the side renumbered as the upgrade does give the same NOTE-SIDE result (1, 0, 1, 1: only a note's bottom faces an activity below it); a model with no _MetaData table counts as Mendix 11, says so, and exits 0.

  • Control: the same fixture with origin/master's mf-canvas-facts.py -> PASS=16 FAIL=6: the numbering line (twice), the (2, 0) case, origin sides 1 and 3, and the unreadable-version case fail. Origin sides 0 and 2 pass on master by coincidence: top is 0 in both tables, and the renumbered left (3) is still a side facing away.
  • CI floor: bin/check-scripts.sh 125/125 shell and 25/25 Node parse; bash tests/wave2/test-manifest-clean-checkout.sh 1 passed; bin/check-pr-discipline.sh origin/master clean; bin/render-routing.sh --check in sync, baseline 65444; bin/mdl-rules.sh --check in sync; bin/check-portability.sh clean; bin/check-no-private-citations.sh clean; bin/check-no-client-data.sh clean; bash tests/run-tests.sh passed=33 failed=0; test-verify-module-446.sh (stubs this script) 15/15.
  • bash tests/wave2/run-all.sh: not run (about 180 fixtures). Only the fixtures that name this script were run.

…l's Mendix version

A note numbers its sides top 0, bottom 1, left 2, right 3 on Mendix 10, but like every other
object (top 0, right 1, bottom 2, left 3) on Mendix 11. The script knew only the Mendix 10 table,
so on a Mendix 11 model it read nearly every hand-drawn note line as leaving a side that faces
away and printed a false NOTE-SIDE fact.

It now reads _ProductVersion from the .mpr's _MetaData table: major 11 or higher uses the activity
numbering; a version that cannot be read counts as Mendix 11. The first output line says which
numbering was used. Fixture section V: the golden model stamped 10.x, and a Mendix 11 copy with
the note sides renumbered as the upgrade does, give the same NOTE-SIDE result for each of the
four sides.
@MendixMau

Copy link
Copy Markdown
Owner

Triage (outside PR, code not run): FIX track. Verdict: MERGE-AFTER-FIX. The only fix needed is a rebase: CHANGELOG.md conflicts with master 60e369b.

  • Injection / malicious code: none found. Every added line read. No hidden or bidi characters and no network calls. The script only adds a read-only SELECT _ProductVersion FROM _MetaData through the existing mxpatch.Model._db() (project-bin/mxpatch.py:301).
  • Value: real for every Mendix 11 project. With only the Mendix 10 side table, notes on an 11.x model produce false NOTE-SIDE and LINE facts. Reading the version is the only reliable signal, because a stored side pair is ambiguous across versions, as the PR body explains.
  • Regression risk: low.
    • The output gains a first line, # note sides: …. The only consumer is verify-module.sh rung 1c (project-bin/verify-module.sh:582). It logs the output as INFO and parses no lines, so no verdict or exit code changes.
    • If the version can't be read, the script assumes Mendix 11. A Mendix 10 model with an unreadable _MetaData would then be read with the wrong table. That case is unlikely, and the first output line states which numbering was used.
  • Repo rules:
    • Field-proof is cited: 305 lines from one app, matched across 10.24 and 11.15, give identical facts after the fix.
    • Section V fails 6 checks on master's script.
    • The golden input is the existing captured model, with the version stamp made explicit.
    • The CHANGELOG line is credited and baseline words are unchanged.
    • The script is stdlib Python. Git Bash was not run.
  • Note: this still needs the independent merge review per CLAUDE.md.

Generated by Claude Code

MendixMau added a commit that referenced this pull request Nov 1, 2026
…l's Mendix version (#605, port of #595)

A note numbers its connection sides one way on Mendix 10 and like every
other object on Mendix 11. The tool now reads _MetaData._ProductVersion
and states the numbering it used on its first output line. An
unreadable version counts as Mendix 11. Ported from #595 by saingge.

Review: MERGE — fixture section V fails 6/6 on master's script and passes on the PR's; the Mendix 11 numbering matches mxcli v0.29.0 microflows.go:418-420; the one consumer only logs the output

Co-authored-by: saingge <262679532+saingge@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LeNWZV2sVH62vkgfYh5u5
@MendixMau

Copy link
Copy Markdown
Owner

Thank you @saingge — this landed as #605 (already merged), with you kept as commit author. Closing in favour of that port.


Generated by Claude Code

@MendixMau MendixMau closed this Nov 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.

2 participants