Migration And Anti-Patterns
Most Morph mistakes look convenient in the short term.
They become expensive when the framework grows.
Common Anti-Patterns
These are the patterns to watch for:
- feature behavior implemented directly in core as a shortcut
- package runtime code moved into generic runtime folders
- package command behavior wired directly into core CLI
- provider assumptions left undeclared
- build or execution behavior hidden in manual wiring
- domain knowledge (tokens, type names, syntax forms) hardcoded anywhere in
src/\u2014 the most dangerous leak
The Core Leak Anti-Pattern
A Core leak is any case where src/ files contain knowledge that belongs exclusively to packages.
Examples of leaks:
// LEAK \u2014 src/parser/ParseDeclarations.cpp
if (token == "is") { /* ... */ } // Token knowledge in Core
// LEAK \u2014 src/sema/ExpressionAnalyzer.cpp
if (typeName == "Int") { /* ... */ } // Type knowledge in Core
// LEAK \u2014 src/codegen/LLVMCodeGen.cpp
if (node->kind == NodeKind::Tensor) { } // Domain concept in Core
The correct form: Core receives opaque plugin-dispatched facts. It never inspects token surfaces, type names, or construct identities by name.
// CORRECT \u2014 Core dispatches to the plugin that owns the semantic family
morphSemaRuntime.dispatch(surfaceView, context); // Core knows nothing about what this does
If you find a match on a keyword string, a type name, or a construct-specific enum value inside src/ while implementing a feature: stop. Move that knowledge to the package that owns the concept. If no hook exists yet to support the move, widen the framework \u2014 but never leave domain knowledge in Core as a shortcut.
The "Just This Once" Trap
The most dangerous Morph mistake is:
"We will hardcode this one in core for now."
That usually turns into permanent ownership drift.
If a package cannot express the feature, fix the framework surface immediately instead of creating a temporary core shortcut.
Migration Rule
When moving an existing behavior into Morph:
- identify the true package owner
- move declarations into manifests
- move implementation into package folders
- widen framework APIs only where the package genuinely needs it
- add boundary tests so ownership does not regress
Smells That Mean You Need A New Package
You probably need a new package when:
- an existing package boundary becomes unclear
- a feature needs unrelated runtime and tooling semantics
- the package's README would need a long apology section to justify the addition
Distinct ownership deserves a distinct package.
Smells That Mean You Need Framework Work
You probably need framework or SDK widening when:
- the manifest cannot declare the needed relationship
- the public SDK cannot describe the needed callback or descriptor
- generated glue cannot wire the package behavior cleanly
That is the correct time to change the framework.
Next Steps
- Tooling, Build, and Execution - package-owned orchestration surfaces
- Ternary Condition Case Study - final concrete ownership example