Scope: mapping
Executive Summary
Investigate whether Microsmith should adopt Mappie as the standard compile-time mapping approach for clearly structural Kotlin model projection, and if the evaluation is favorable, implement a narrowly scoped pilot plus repository guidance. The outcome of this issue must be explicit: either adopt Mappie with documented boundaries, validation, and at least one representative implementation slice, or reject adoption with written rationale and keep manual mapping as the repository standard.
Problem Statement
Microsmith already contains a growing number of explicit model-to-model transformations across the dsl -> resolve -> artifact -> compile -> gen pipeline. Some of those transformations encode real semantic lowering and should remain handwritten, but others are closer to structural projection and increasingly look like repetitive mapping code. That creates two pressures:
- repository maintainability and consistency can degrade if each module reinvents ad hoc mapping style
- the repository is also a reference implementation for future plugin authors, so its approach to mapping should be intentional rather than accidental
At the same time, adopting a mapping library indiscriminately would be a mistake. Much of Microsmith's pipeline is not bean-copying; it is semantic normalization, invariant enforcement, artifact shaping, and output-contract definition. A mapper should not obscure those responsibilities or collapse meaningful pipeline boundaries into annotation-driven magic.
This issue exists to evaluate that tradeoff rigorously rather than drifting into either extreme.
Objectives
- Evaluate whether Mappie improves consistency, readability, and maintainability for purely structural Kotlin model projection in Microsmith.
- Define explicit repository rules for where a mapping library is appropriate and where handwritten transformations must remain the standard.
- Validate the operational fit of Mappie with the current build, IDE, CI, testing, and contributor workflow.
- If the evaluation is positive, implement one or more representative pilot migrations in clearly structural mapping seams.
- Document the final decision and the expected contributor/plugin-author guidance.
Non-Objectives
- Blanket-replacing all existing transformations that happen to move data from one type to another.
- Hiding resolver logic, artifact assembly, validation, normalization, or compile-stage lowering behind mapping annotations.
- Introducing runtime reflection-based mapping.
- Re-architecting the pipeline away from
dsl -> resolve -> artifact -> compile -> gen.
- Forcing plugin authors to depend on Mappie unless the repository explicitly decides that the benefits justify that standard.
- Committing to Mappie before the repository has evaluated versioning, maintenance, generated-code transparency, and Kotlin-tooling compatibility.
Grounding In Current Code
Microsmith already has build and module characteristics that make this decision non-trivial:
gradle/libs.versions.toml pins Kotlin to 2.2.21.
settings.gradle declares org.jetbrains.kotlin.kapt version 2.2.21.
build.gradle applies org.jetbrains.kotlin.kapt across the build, but the repository does not currently use KSP.
- The repository contains many explicit transformation seams in contributor/compiler/renderer-adjacent modules, including representative examples such as:
modules/artifact-schemas-protobuf-rpc
modules/artifact-schemas-protobuf
modules/artifact-services-dotnet-packages
modules/compile-services-dotnet
modules/compile-services-dotnet-packages
modules/runtime-scripting
- Recent refactoring work has reinforced that generated-file ownership should flow through finalized artifact models rather than raw authoring state, which raises the bar for introducing any abstraction that could blur semantic stage boundaries.
Relevant Mappie constraints from official documentation that must be evaluated in-repo:
Functional Requirements
- Produce a written evaluation of Mappie against the repository's actual mapping patterns rather than generic mapper-library arguments.
- Classify current transformation seams into at least the following categories:
- structural projection that may be a valid mapper candidate
- semantic lowering that must remain handwritten
- mixed transformations that should remain handwritten unless further decomposition makes the structural part explicit
- Identify a small set of representative candidate mappings in the current codebase and explain why each candidate is or is not appropriate for Mappie.
- Evaluate the developer ergonomics of Mappie in this repository, including:
- declaration style in idiomatic Kotlin
- generated-code transparency during review and debugging
- IDE usability and error quality
- testability and regression coverage implications
- Gradle integration and CI behavior
- Evaluate build-tooling compatibility, including interaction with current
kapt usage and Kotlin version management.
- If adoption is justified, define a narrow repository contract for Mappie usage, including:
- which stages or module types may use it
- which categories of transformations must remain handwritten
- how mapper definitions should be organized and named
- what testing is required around mapped outputs
- If adoption is justified, implement at least one representative pilot in a clearly structural projection seam.
- If adoption is rejected, capture the decision and rationale explicitly so the repository does not revisit the same debate without new evidence.
Validation Requirements
- Validate that the chosen pilot mapping(s), if any, preserve existing behavior exactly.
- Validate that generated outputs remain deterministic and review-friendly.
- Validate that build execution, IDE sync, and CI remain healthy after introducing any Mappie plugin/dependency changes.
- Validate that compilation and test execution remain stable on the repository's current Kotlin version.
- Validate that mapper usage rules do not leak into semantic pipeline stages that should remain explicit.
- Validate that contributor guidance is specific enough that future plugin developers can distinguish structural projection from semantic lowering.
Non-Functional Requirements
- Any adopted mapping approach must preserve clear pipeline semantics and separation of concerns.
- The result must improve maintainability and consistency rather than merely reducing line count.
- The repository standard must remain easy for contributors and plugin authors to understand without architecture theatre.
- Any generated mapping approach must remain deterministic, reviewable, and debuggable.
- The build/tooling cost of adoption must be justified by a real quality gain.
Security Considerations
- Adding a compiler plugin changes the build toolchain and therefore must be treated as a supply-chain and maintenance decision, not just a syntax preference.
- Diagnostics, reporting, or generated artifacts must not expose unrelated environment or filesystem state.
- The repository must not adopt a mapper approach that obscures validation or safety-critical decisions inside implicit code generation.
Operational Readiness
- Contributor guidance must explain when to use Mappie and when not to use it.
- If adopted, module templates/examples and relevant docs should reflect the new standard.
- CI and local validation steps must cover any new plugin integration.
- The repository should remain easy to build and reason about for external contributors who have not used Mappie before.
Backward Compatibility And Migration
- Existing handwritten mappings should not be migrated wholesale.
- Any migration plan must be incremental and limited to seams that are demonstrably structural.
- Adoption, if approved, should be additive and should not force architectural churn across unrelated modules.
- If Mappie is rejected, the repository should document manual mapping as the standard and avoid partial one-off adoption.
Risks And Mitigations
- A mapper can hide semantic lowering behind declarative syntax: mitigate by defining hard boundaries and keeping semantic stages handwritten.
- Mappie is tightly coupled to Kotlin compiler versions: mitigate by explicitly evaluating upgrade cost and documenting version-management expectations before adoption.
- Generated code can reduce review clarity: mitigate by evaluating Mappie's reporting/debugging facilities and requiring pilot reviewability before wider use.
- Teams may over-apply the library once it exists: mitigate by documenting where mapper usage is prohibited, not only where it is allowed.
- The repository may become a poor example for plugin authors if the rule is vague: mitigate by documenting concrete examples of allowed and disallowed usage.
- The build may become more fragile: mitigate by validating IDE sync, CI, and full local builds as part of the investigation.
Acceptance Criteria
- The repository contains a written, evidence-based decision on whether Mappie should be adopted.
- The decision explicitly distinguishes structural projection from semantic lowering and explains the boundary in Microsmith terms.
- Representative current mapping seams have been reviewed and classified.
- Build/tooling compatibility has been evaluated against the repository's current Kotlin and Gradle setup.
- If Mappie is adopted:
- the repository defines explicit usage rules
- at least one representative structural mapping seam has been migrated successfully
- tests/regressions confirm no behavioral change
- contributor/plugin-author guidance is updated
- If Mappie is rejected:
- the repository records the rationale clearly
- the manual-mapping standard is documented clearly enough to avoid future ambiguity
- The issue closes with a concrete repository standard, not an open-ended discussion.
Test Strategy
- Review representative mapping-heavy modules and select pilot candidates with low semantic ambiguity.
- Add or update unit tests around any pilot migration so mapped outputs and normalization behavior remain unchanged.
- Run targeted module validation for any migrated seam.
- Run full repository validation if build-tooling changes are introduced.
- Verify CI and IDE/build integration expectations after any compiler-plugin setup changes.
- Verify docs/examples against the chosen repository standard.
Definition Of Done
- Microsmith has an explicit, documented repository standard for structural model mapping, backed by a real evaluation of Mappie against current code and either a validated pilot adoption or a clear rejection with rationale.
Scope: mapping
Executive Summary
Investigate whether Microsmith should adopt Mappie as the standard compile-time mapping approach for clearly structural Kotlin model projection, and if the evaluation is favorable, implement a narrowly scoped pilot plus repository guidance. The outcome of this issue must be explicit: either adopt Mappie with documented boundaries, validation, and at least one representative implementation slice, or reject adoption with written rationale and keep manual mapping as the repository standard.
Problem Statement
Microsmith already contains a growing number of explicit model-to-model transformations across the
dsl -> resolve -> artifact -> compile -> genpipeline. Some of those transformations encode real semantic lowering and should remain handwritten, but others are closer to structural projection and increasingly look like repetitive mapping code. That creates two pressures:At the same time, adopting a mapping library indiscriminately would be a mistake. Much of Microsmith's pipeline is not bean-copying; it is semantic normalization, invariant enforcement, artifact shaping, and output-contract definition. A mapper should not obscure those responsibilities or collapse meaningful pipeline boundaries into annotation-driven magic.
This issue exists to evaluate that tradeoff rigorously rather than drifting into either extreme.
Objectives
Non-Objectives
dsl -> resolve -> artifact -> compile -> gen.Grounding In Current Code
Microsmith already has build and module characteristics that make this decision non-trivial:
gradle/libs.versions.tomlpins Kotlin to2.2.21.settings.gradledeclaresorg.jetbrains.kotlin.kaptversion2.2.21.build.gradleappliesorg.jetbrains.kotlin.kaptacross the build, but the repository does not currently use KSP.modules/artifact-schemas-protobuf-rpcmodules/artifact-schemas-protobufmodules/artifact-services-dotnet-packagesmodules/compile-services-dotnetmodules/compile-services-dotnet-packagesmodules/runtime-scriptingRelevant Mappie constraints from official documentation that must be evaluated in-repo:
Functional Requirements
kaptusage and Kotlin version management.Validation Requirements
Non-Functional Requirements
Security Considerations
Operational Readiness
Backward Compatibility And Migration
Risks And Mitigations
Acceptance Criteria
Test Strategy
Definition Of Done