ZI

/claim #519 /closes #519

Compile Time Validation

Both Scala 2 and Scala 3 have compile time validation. They extract the ShapeTree of SchemaA and SchemaB, and do a Tree.diff which returns added and removed, of the form List[List[Segement]]

Segement

private[migration] object Segment {
case class Field(name: String) extends Segment
case class Case(name: String) extends Segment
case object Element extends Segment
case object Key extends Segment
case object Value extends Segment
case object Wrapped extends Segment
}

When .build is run, as we go through MigrationAction, each migration action collects Handled and Provided, which is also of the form List[List[Segement]] , which are then compared against added and removed. On success we compile.

Example of List[List[Segement]] : List((Field("address"), Field("city")), Field("age")) -> It has two path address.city and age.

Note - This is a different List of Lists, rather than encoding level and field. I though having a clear path to the field which was added or removed was a better decision.

Selector Syntax

Support for Selector Syntax for _.field, _.nested.field, _.case.when[Batman]. _.field.each. Also includes support for bare Literal SchemaExpr, so it is easier to write migration code.

Deviations

Joint and Split for nested fields.

_.address.street + _.address.city → _.address.fullAddress -> this is done

_.address.street + _.origin.country → _.address.fullAddress -> This gets complex since now we have to extract values from multiple nested source paths, combine to targeted nested path, remove the nested source fields, and rebuilt the whole structure immutability.

So if the parent is not the same, it gracefully errors out at both runtime (if .buildpartial was used) and during compile validation (if .build was used)

Serialization

Added Serialization - Using a new DynamicSchemaExpr a serializable version of SchemaExpr . Manually derived schema for all things which make up DynamicMigration

final case class SchemaExpr[A, B](
dynamic: DynamicSchemaExpr,
inputSchema: Schema[A],
outputSchema: Schema[B]
)

Structural Support

Added Structural tests, to showcase the structural can be migrated properly. Deviation is they are not supported via compile time validation. During .build they fall through and are parsed as a PrimitiveNode. All the tests currently used .buildPartial. Maybe fixable by adding a check to see if they are refinement type and exploring their structure at compile time in both 2 and 3.

Claim

Total prize pool $8,000
Total paid $0
Status Pending
Submitted February 02, 2026
Last updated February 02, 2026

Contributors

AJ

Ajay RV

@Nanashi-lab

100%

Sponsors

MA

marianaguzmanguerrero16-dev

@marianaguzmanguerrero16-dev

$4,000
ZI

ZIO

@ZIO

$4,000