anchor.diff:  
     String _sanitize(String message) {
       message = message.split('\n').first;
  -    final periodNumberIndex = message.lastIndexOf('. (#');
  -    if (periodNumberIndex == -1) return message;
  -    return message.replaceFirst('. (#', ' (#', periodNumberIndex);
  +    message = message.substring(0, 1).toUpperCase() +
  +        message.substring(1, message.length);
  +    const prPrefix = ' (#';
  +    final periodNumberIndex = message.lastIndexOf('.$prPrefix');
  +    if (periodNumberIndex != -1) {
  +      message = message.replaceFirst('.$prPrefix', prPrefix, periodNumberIndex);
  +    }
  +    final prIndex = message.indexOf(prPrefix);
  +    final endPrIndexExclusive = message.lastIndexOf(')');
  +    final pr = message.substring(
  +      prIndex + prPrefix.length,
  +      endPrIndexExclusive,
  +    );
  +    return message.substring(0, prIndex) +
  +        ' [#$pr](https://github.com/flutter/devtools/pull/$pr)';
     }
   
     bool _shouldSkip(String message) {
       message = message.split('\n').first;
       message = message.replaceAll(RegExp('\\(#\\d*\\)'), '').trim();
  -    return ignoredCommitNames.contains(message);
  +    for (final ignore in lowercaseIgnoredCommitNames) {
  +      if (message.toLowerCase().contains(ignore)) {
  +        return true;
  +      }
  +    }
  +    return false;
     }
   }
  -
  -/// Converts versions into a monotonically-increasing integer.
  -///
  -/// This is used to determine which version is the most recently-pushed
  -/// tagged commit. After finding this version, we take all commits pushed
  -/// after the tagged commit to release.
  -int getVersion(String versionNumber) {
  -  final nums = versionNumber.replaceFirst('v', '').split('.');
  -  return int.parse(nums[0]) * 1000000 +
  -      int.parse(nums[1]) * 1000 +
  -      int.parse(nums[2]);
  -}
  
positive.code:   ///
    /// We will only check for exact matches on this, after trimming out the
    /// trailing commit number.
    static const ignoredCommitNames = [
      'update goldens',
      'Update Goldens',
      'Update goldens'
    ];
  
    @override
  
negative.code:   @override
    Future run() async {
      final repo = DevToolsRepo.getInstance()!;
      String? nextVersion = argResults?[versionArg];
      final sinceTag = argResults?[sinceArg];
  
      final List<Map<String, dynamic>> tags = (jsonDecode((await http.get(
                  Uri.https(
                      '${auth}api.github.com', '/repos/flutter/devtools/tags')))
              .body) as List)
          .cast<Map<String, dynamic>>();
  
      bool isDevBuild(String tagName) => tagName.contains('dev');
      bool isCherryPickRelease(String tagName) => tagName.contains('+');
      String nameOf(tag) => tag['name'];
  
      Map<String, dynamic>? closestTag;
      if (sinceTag != null) {
        print('Attempting to find tag with name $sinceTag, '
            'as specified by --$sinceArg...');
        closestTag = tags.firstWhere((tag) => nameOf(tag) == sinceTag);
      } else {
        print('Retrieving the most recent tag...');
        closestTag = tags.skipWhile((tag) {
          final skip =
              isDevBuild(nameOf(tag)) || isCherryPickRelease(nameOf(tag));
          return skip;
        }).first;
      }
  
      final commitInfo = closestTag['commit'] as Map<String, dynamic>;
      print('Getting the date of the tagged commit for ${closestTag['name']}...');
      final taggedCommit = jsonDecode((await http.get(Uri.https(
        '${auth}api.github.com',
        '/repos/flutter/devtools/commits/${commitInfo['sha']}',
      )))
          .body);
  
      final commitDate = taggedCommit['commit']['author']['date'];
      print(
          'Adding entries to the changelog for all commits since $commitDate...');
  
      // TODO(kenz): handle cases where there are more than 100 commits.
      final uri = Uri.https(
        '${auth}api.github.com',
        '/repos/flutter/devtools/commits',
        {
          'since': commitDate,
          'per_page': '100',
        },
      );
      final commits = jsonDecode((await http.get(uri)).body);
      final changes = <String>[];
      for (var commit in commits) {
        if (commit['sha'] == taggedCommit['sha']) {
          print(
              'Skipping commit ${commit['sha']} because this is the commit of the previous tag');
          continue;
        }
        final message = commit['commit']['message'];
        if (_shouldSkip(commit['commit']['message'])) {
          print('Skipping commit marked to be ignored: $message');
          continue;
        }
        final entry = '* ' + _sanitize(commit['commit']['message']);
        changes.add(entry);
      }
  
      if (nextVersion != null) {
        print('Using specified version $nextVersion...');
      } else {
        print('Incrementing version number...');
        final currentVersion = nameOf(closestTag).replaceFirst('v', '');
        // Increment the minor version by 1 and reset the patch version to 0
        // (e.g. 2.4.2 => 2.5.0)
        final List<String> parts = currentVersion.split('.');
        parts[1] = '${int.parse(parts[1]) + 1}';
        parts[2] = '0';
        nextVersion = parts.join('.');
        print('Incremented version number for the changelog from '
            '$currentVersion to $nextVersion. Note that this is not '
            'inserted to any files other than changelog.');
      }
  
      final changelogFile =
          File('${repo.repoPath}/packages/devtools/CHANGELOG.md');
      final output = '## $nextVersion\n' + changes.join('\n') + '\n\n';
      await changelogFile.writeAsString(
        output + changelogFile.readAsStringSync(),
      );
  