Skip to content

Delete sdk/mpr — the legacy engine is gone - #1114

Merged
ako merged 2 commits into
mendixlabs:mainfrom
ako:claude/upstream-legacy-removal
Sep 16, 2026
Merged

ako merged 2 commits into
mendixlabs:mainfrom
ako:claude/upstream-legacy-removal

Conversation

@ako

@ako ako commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Deletes sdk/mpr. 163 files, 41,674 lines. This is the last step of
docs/plans/2026-09-14-retire-legacy-engine.md, whose porting slices are already
upstream — this branch is those two commits and nothing else, on top of current
main.

Why it can land on its own

The importer count was taken from 27 to 0 by the slices already merged here. On
this base the only remaining mention of the package is the guard test that held
the count at zero, and the six importers of the sdk/mpr/version subpackage.
Both are handled in the first commit.

Zero importers was not the same as safe to rm -rf

Two live dependencies survived the count reaching zero, and neither is visible
to a check written against the parent package's import path
:

dependency why an importer census misses it
sdk/mpr/version — 6 importers, two of them shipping code (docker/build.go, patch.go) a subpackage is a different import path
sdk/mpr/testdata/v1-project — read by docker/update_widgets_test.go an os.DirFS string, not an import at all

Before deleting a package, search for three things: its own import path, its
subpackages' paths, and its directory as a literal string (testdata,
go:embed, scripts). The last two are invisible to any importer census.

The six went to mdl/types, not to modelsdk/mpr/version, which looks like
the natural home and is the wrong one:

// sdk/mpr/version — an ALIAS, so types.ProjectVersion is the same type
type ProjectVersion = types.ProjectVersion

// modelsdk/mpr/version — a DUPLICATE STRUCT, which would be a different type
type ProjectVersion struct { ... }

Reading the declaration rather than the name is what distinguishes them. The v1
fixture moved to modelsdk/mpr/testdata/.

Everything was repointed and proven green with the package still present,
then deleted as a separate step — which is what separates "the repoint was wrong"
from "the deletion was wrong".

Two measurements worth keeping

  • The shipped binary is identical in size before and after, so the linker had
    already dropped the package: this removes source weight, not runtime
    behaviour. docker check and check --post-migration are byte-identical to
    the pre-deletion binary.
  • sdk/widgets fell to zero importers as a side effect but is deliberately
    kept
    modelsdk/widgets/dirty_template_test.go reads
    sdk/widgets/templates/mendix-11.6 by path. The same path-not-import trap,
    caught by grepping the directory name. Worth its own look; not this PR's call.

The import guard is removed

The guard test that held the count at zero is deleted with the package: an import
of something that does not exist is a compile error, which is strictly
stronger than a test asserting the same thing.

The second commit: CLAUDE.md routing

Deleting the package left the always-in-context file pointing at files that are
gone — the architecture tree described the deleted engine and omitted modelsdk
entirely, the BSON storage-name procedure sent you to
sdk/mpr/parser_microflow.go, and the test-first checklist sent a parser test to
sdk/mpr/. Eight sites updated; every path the file now names was checked to
exist. Two checklist rules that were about the dead package are restated as
rules about the engine that does exist.

Docs under docs/ are deliberately untouched: they describe what the code used
to do, and ADRs are immutable by convention.

Verification

Run on this branch, on top of current upstream main:

gate result
make build pass
go test ./... pass
cherry-pick onto this base clean, no conflicts

And on the fork before merge: make vet (incl. -tags integration),
the full repo-wide make test-integration (exit 0, no failures), make check-mdl
(560), make check-findings (1,091 records)

163 files, 41,674 lines. This finishes
docs/plans/2026-09-14-retire-legacy-engine.md.

Zero importers was not the same as safe to rm -rf. Two live dependencies
survived, and neither is visible to a check written against the parent package's
import path. sdk/mpr/version had six importers, two of them shipping code
(cmd/mxcli/docker/build.go and patch.go) — a subpackage is a different import
path. And cmd/mxcli/docker/update_widgets_test.go read
sdk/mpr/testdata/v1-project by filesystem path, an os.DirFS string rather than
an import.

So: before deleting a package, search for three things — its own import path,
its subpackages' paths, and its directory as a literal string (testdata,
go:embed, scripts). The last two are invisible to any importer census.

The six importers went to mdl/types, not to modelsdk/mpr/version.
sdk/mpr/version.ProjectVersion is `type ProjectVersion = types.ProjectVersion`,
an alias, so types.ProjectVersion is the same type — while modelsdk/mpr/version
declares a duplicate struct that would have been a different one. Read the
declaration, not the name. The v1 fixture moved to modelsdk/mpr/testdata/.
Everything was repointed and proven green with the package still present, which
separates "the repoint was wrong" from "the deletion was wrong".

Two measurements worth keeping. The shipped binary is identical in size before
and after, so the linker had already dropped the package: this removes source
weight, not runtime behaviour. And sdk/widgets fell to zero importers as a side
effect but is deliberately kept — modelsdk/widgets/dirty_template_test.go reads
sdk/widgets/templates/mendix-11.6 by path. Same trap, caught by grepping the
directory name rather than the import.

The import guard added in the previous slice is removed: with the package gone,
an import is a compile error, strictly stronger than a test asserting it.

Gates: build, vet (incl. -tags integration), go test ./..., check-mdl (560),
check-findings, and the full repo-wide integration suite: exit 0, no failures.
docker check and check --post-migration are byte-identical to the pre-deletion
binary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hifgRSawfaRWXS44YKtSJ
Deleting sdk/mpr left the always-in-context routing document pointing at files
that are gone. CLAUDE.md is where a session looks first, so a dead path there
does not just go stale — it sends the next reader somewhere that cannot be
opened, and every one of these was a routing instruction rather than prose.

Eight sites. The architecture tree listed sdk/mpr's reader/writer/parser/utils
and no modelsdk at all, which had it describing the deleted engine as the format
layer and omitting the real one. The BSON storage-name procedure said to verify
against sdk/mpr/parser_microflow.go; that now points at modelsdk/codec and
modelsdk/gen. The write-choke-point list named both engines' files — there is one
engine, so the list is now one entry and says so. The test-first checklist sent a
parser test to sdk/mpr/ and a backend mutation test to mdl/backend/mpr/, neither
of which exists. Useful Files offered sdk/mpr/parser.go and writer_widgets.go.

Two checklist items were rules about a package that no longer exists, so they are
restated as rules about the engine that does: "no sdk/mpr write imports in the
executor" becomes "no engine internals in the executor" (modelsdk/mpr,
modelsdk/codec, modelsdk/gen), with the note that a missing backend method gets
implemented rather than bypassed — which is what the last five slices kept
running into. The shared-types rule described sdk/mpr re-exporting aliases; it
now states the rule directly and cites modelsdk/mpr/version.ProjectVersion as the
cautionary case, since that one duplicates types.ProjectVersion instead of
aliasing it and the two print under the same name.

Every path the file now names was checked to exist.

Docs under docs/ are deliberately untouched: they describe what the code used to
do, and ADRs are immutable by convention.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018hifgRSawfaRWXS44YKtSJ
@github-actions

Copy link
Copy Markdown

AI Code Review

Critical Issues

  • None found

Moderate Issues

  • None found

Minor Issues

  • None found

What Looks Good

  • The PR correctly deletes the entire sdk/mpr legacy engine package as the final step in retiring it, following the verified porting slices already merged.
  • All necessary dependency updates were handled: sdk/mpr/version aliases moved to mdl/types, test fixtures relocated to modelsdk/mpr/testdata/, and literal string references (like in docker/update_widgets_test.go) were addressed.
  • The import guard test was removed with the package, turning a test assertion into a compile-time safety.
  • CLAUDE.md was thoroughly updated to remove references to the deleted package and correct the architecture tree/checklist.
  • Verification shows zero runtime impact (binary size identical) and all tests pass (make build, go test ./..., make test-integration, etc.).
  • The two commits are appropriately scoped: first handles code/repointing, second updates documentation.
  • No MDL syntax or features were modified, so related checklist sections are not applicable.
  • The PR adheres to the project's deletion protocol by verifying three things before removal: import paths, subpackage paths, and literal string directory references.

Recommendation
Approve the PR. The deletion is safe, complete, and well-verified. No changes are needed.


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

@ako
ako merged commit f761410 into mendixlabs:main Sep 16, 2026
4 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