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")) -> It has one single path address.city

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.

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)

No Serialization

DynamicMigration is Pure ADT and can be inspected structurally, but it cannot be fully serialize/deserialize it due to existential types in SchemaExpr. SchemaExpr[DynamicValue, ?], not sure how to deal with this.

Claim

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

Contributors

AJ

Ajay RV

@Nanashi-lab

100%

Sponsors

ZI

ZIO

@ZIO

$4,000