anchor.diff:    @override
     Iterable<NullabilityNode> get guards => upstreamNodes.skip(1);
   
  -  @override
  -  bool get isHard => _kind != _NullabilityEdgeKind.soft;
  +  /// Indicates whether it's possible for migration to cope with this edge being
  +  /// unsatisfied by inserting a null check.  Graph propagation favors
  +  /// satisfying uncheckable edges over satisfying hard edges.
  +  bool get isCheckable =>
  +      _kind == _NullabilityEdgeKind.soft || _kind == _NullabilityEdgeKind.hard;
  +
  +  @override
  +  bool get isHard =>
  +      _kind == _NullabilityEdgeKind.hard || _kind == _NullabilityEdgeKind.union;
   
     @override
     bool get isSatisfied {
  
positive.code:     var edgeDecorations = <Object>[];
      switch (_kind) {
        case _NullabilityEdgeKind.soft:
          break;
        case _NullabilityEdgeKind.hard:
          edgeDecorations.add('hard');
  
negative.code:           suffix = ' [label="union"]';
          } else if (edge.isHard) {
            suffix = ' [label="hard"]';
          } else if (edge.isCheckable) {
            suffix = '';
          } else {
            suffix = ' [label="uncheckable"]';
          }
          var upstreamNodes = edge.upstreamNodes;
          if (upstreamNodes.length == 1) {
  