OCSADV-200: calculate program diffs

This is the first in a series of PRs aimed at transforming the VCS sync/merge algorithm to work with program differences instead of entire programs.  In the initial PR, I'm focusing on just calculating "differences" given a reference to a local program and a remote version map.  The differences aren't yet used for anything but will be sent back and forth between peers during a program sync.

Please focus on the second commit (containing `DiffNode` and `ProgramDiff`) since the first just contains a lot of trivial changes to existing test cases.  I'm proposing a somewhat simplistic diff calculation that provides a list of node information for all nodes that differ (including all their ancestors up to the root).  This will likely result in including some nodes that ultimately are not needed.  Obtaining the absolute minimum would require a more complex calculation that takes into account remotely deleted nodes, principals and observation statuses.  The simplistic "diff" will nevertheless drastically reduce the amount of information passed for large programs. For example I estimate that less than 0.1% of the total program nodes in the "Andy" program with its ~1,300 observations would be passed when editing a single observation.