Revert "176989 unifiedCheckRunFlow flag removal" (#5145)

Reverts flutter/cocoon#5144
diff --git a/app_dart/config.yaml b/app_dart/config.yaml
index 58d3522..275a1ff 100644
--- a/app_dart/config.yaml
+++ b/app_dart/config.yaml
@@ -28,6 +28,20 @@
 # The Gemini model to use for log analysis.
 geminiModel: gemini-3-flash-preview
 
+# Whether to allow unified check run flow to specific users or to everyone.
+unifiedCheckRunFlow:
+  useForAll: true
+  useForUsers:
+    - ievdokdm
+    - eyebrowsoffire
+    - andywolff
+    - camsim99
+    - walley892
+    - loic-sharma
+    - vashworth
+    - mboetger
+    - justinmc
+
 # Whether to process LUCI notifications of builds progress ordered within check run.
 orderedPresubmit:
   useForAll: true
diff --git a/app_dart/lib/cocoon_service.dart b/app_dart/lib/cocoon_service.dart
index e54286c..2fd0263 100644
--- a/app_dart/lib/cocoon_service.dart
+++ b/app_dart/lib/cocoon_service.dart
@@ -60,6 +60,7 @@
 export 'src/service/firestore.dart';
 export 'src/service/flags/dynamic_config.dart';
 export 'src/service/flags/ordered_presubmit_flags.dart';
+export 'src/service/flags/unified_check_run_flow_flags.dart';
 export 'src/service/gerrit_service.dart';
 export 'src/service/github_checks_service.dart';
 export 'src/service/issue_service.dart';
diff --git a/app_dart/lib/src/generated_config.dart b/app_dart/lib/src/generated_config.dart
index 6b95616..8337901 100644
--- a/app_dart/lib/src/generated_config.dart
+++ b/app_dart/lib/src/generated_config.dart
@@ -32,6 +32,20 @@
 # The Gemini model to use for log analysis.
 geminiModel: gemini-3-flash-preview
 
+# Whether to allow unified check run flow to specific users or to everyone.
+unifiedCheckRunFlow:
+  useForAll: true
+  useForUsers:
+    - ievdokdm
+    - eyebrowsoffire
+    - andywolff
+    - camsim99
+    - walley892
+    - loic-sharma
+    - vashworth
+    - mboetger
+    - justinmc
+
 # Whether to process LUCI notifications of builds progress ordered within check run.
 orderedPresubmit:
   useForAll: true
diff --git a/app_dart/lib/src/model/common/presubmit_completed_check.dart b/app_dart/lib/src/model/common/presubmit_completed_check.dart
index 8bafb12..d7a3139 100644
--- a/app_dart/lib/src/model/common/presubmit_completed_check.dart
+++ b/app_dart/lib/src/model/common/presubmit_completed_check.dart
@@ -34,6 +34,7 @@
   final int checkRunId;
   final int? checkSuiteId;
   final String? headBranch;
+  final bool isUnifiedCheckRun;
   final CiStage? stage;
   final int? prNum;
   final int attempt;
@@ -52,6 +53,7 @@
     required this.checkRunId,
     required this.checkSuiteId,
     required this.headBranch,
+    required this.isUnifiedCheckRun,
     this.stage,
     this.prNum,
     this.attempt = 1,
@@ -78,6 +80,7 @@
       checkRunId: userData.guardCheckRunId ?? userData.checkRunId!,
       checkSuiteId: userData.checkSuiteId,
       headBranch: userData.commit.branch,
+      isUnifiedCheckRun: userData.guardCheckRunId != null,
       stage: userData.stage,
       prNum: userData.pullRequestNumber,
       attempt: _getAttempt(build),
@@ -100,7 +103,7 @@
   cocoon_checks.CheckRun get checkRun {
     return cocoon_checks.CheckRun(
       id: checkRunId,
-      name: Config.kDashboardCheckName,
+      name: isUnifiedCheckRun ? Config.kDashboardCheckName : name,
       headSha: sha,
       conclusion: status.toConclusion(),
       checkSuite: CheckSuite(
@@ -118,11 +121,7 @@
       slug: slug,
       prNum: prNum ?? 0,
       checkRunId: checkRunId,
-      stage:
-          stage ??
-          (slug == Config.flutterSlug
-              ? CiStage.fusionTests
-              : CiStage.genericTests),
+      stage: stage ?? CiStage.fusionTests,
     );
   }
 
diff --git a/app_dart/lib/src/request_handlers/presubmit_subscription.dart b/app_dart/lib/src/request_handlers/presubmit_subscription.dart
index ad4c1b0..be629c2 100644
--- a/app_dart/lib/src/request_handlers/presubmit_subscription.dart
+++ b/app_dart/lib/src/request_handlers/presubmit_subscription.dart
@@ -47,11 +47,13 @@
     required super.subscriptionName,
     super.authProvider,
   }) : _ciYamlFetcher = ciYamlFetcher,
+       _githubChecksService = githubChecksService,
        _luciBuildService = luciBuildService,
        _scheduler = scheduler,
        _firestore = firestore;
 
   final LuciBuildService _luciBuildService;
+  final GithubChecksService _githubChecksService;
   final CiYamlFetcher _ciYamlFetcher;
   final Scheduler _scheduler;
   final FirestoreService _firestore;
@@ -141,16 +143,20 @@
     tagSet ??= BuildTags.fromStringPairs(build.tags);
     final builderName = build.builder.builder;
     var rescheduled = false;
+    final isUnifiedCheckRun = userData.guardCheckRunId != null;
+    log.info('Unified Check Run ${isUnifiedCheckRun ? 'Enabled' : 'Disabled'}');
     if (build.status.isTaskFailed()) {
-      // If failed we need summaryMarkdown. For github check run flow this
-      // called in [GithubChecksService.updateCheckStatus(...)]
-      build = await _luciBuildService.getBuildById(
-        build.id,
-        buildMask: bbv2.BuildMask(
-          // Need to use allFields as there is a bug with fieldMask and summaryMarkdown.
-          allFields: true,
-        ),
-      );
+      if (isUnifiedCheckRun) {
+        // If failed we need summaryMarkdown. For github check run flow this
+        // called in [GithubChecksService.updateCheckStatus(...)]
+        build = await _luciBuildService.getBuildById(
+          build.id,
+          buildMask: bbv2.BuildMask(
+            // Need to use allFields as there is a bug with fieldMask and summaryMarkdown.
+            allFields: true,
+          ),
+        );
+      }
       final maxAttempt = await _getMaxAttempt(
         userData.commit,
         builderName,
@@ -159,14 +165,17 @@
       if (tagSet.currentAttempt < maxAttempt) {
         rescheduled = true;
         log.info('Rerunning failed task: $builderName');
-        await UnifiedCheckRun.reInitializeInProgressJob(
-          firestoreService: _firestore,
-          completedJob: PresubmitCompletedJob.fromBuild(
-            build,
-            userData,
-            summaryPrepend: '### ⚠️ Test failed but automatically rescheduled',
-          ),
-        );
+        if (isUnifiedCheckRun) {
+          await UnifiedCheckRun.reInitializeInProgressJob(
+            firestoreService: _firestore,
+            completedJob: PresubmitCompletedJob.fromBuild(
+              build,
+              userData,
+              summaryPrepend:
+                  '### ⚠️ Test failed but automatically rescheduled',
+            ),
+          );
+        }
         await _luciBuildService.reschedulePresubmitBuild(
           builderName: builderName,
           build: build,
@@ -190,6 +199,21 @@
             '### ⚠️ Test failed but marked as suppressed on dashboard';
       }
     }
+    if (!isUnifiedCheckRun) {
+      if (userData.checkRunId == null) {
+        log.error('checkRunId is null for non-unified check run');
+        return;
+      }
+      await _githubChecksService.updateCheckStatus(
+        checkRunId: userData.checkRunId!,
+        build: build,
+        luciBuildService: _luciBuildService,
+        slug: userData.commit.slug,
+        rescheduled: rescheduled,
+        conclusionOverride: override,
+        summaryPrepend: suppressedMessage,
+      );
+    }
     if (!rescheduled) {
       final check = PresubmitCompletedJob.fromBuild(
         build,
diff --git a/app_dart/lib/src/service/firestore/unified_check_run.dart b/app_dart/lib/src/service/firestore/unified_check_run.dart
index b9b272f..b763671 100644
--- a/app_dart/lib/src/service/firestore/unified_check_run.dart
+++ b/app_dart/lib/src/service/firestore/unified_check_run.dart
@@ -36,10 +36,14 @@
     CheckRun? mergeQueueGuard,
     @visibleForTesting DateTime Function() utcNow = DateTime.timestamp,
   }) async {
-    if (dashboardChecks != null && pullRequest != null) {
+    if (dashboardChecks != null &&
+        pullRequest != null &&
+        config.flags.isUnifiedCheckRunFlowEnabledForUser(
+          pullRequest.user!.login!,
+        )) {
       // Create the presubmit_guard and associated presubmit_job documents.
       log.info(
-        'Storing UnifiedCheckRun data for ${slug.fullName}#${pullRequest.number}.',
+        'Storing UnifiedCheckRun data for ${slug.fullName}#${pullRequest.number} as it enabled for user ${pullRequest.user!.login}.',
       );
       // We store the creation time of the guard since there might be several
       // guards for the same PR created and each new one created after previous
diff --git a/app_dart/lib/src/service/flags/dynamic_config.dart b/app_dart/lib/src/service/flags/dynamic_config.dart
index 2cf5f5d..0e73507 100644
--- a/app_dart/lib/src/service/flags/dynamic_config.dart
+++ b/app_dart/lib/src/service/flags/dynamic_config.dart
@@ -15,6 +15,7 @@
 import 'content_aware_hashing_flags.dart';
 import 'dynamic_config_updater.dart';
 import 'ordered_presubmit_flags.dart';
+import 'unified_check_run_flow_flags.dart';
 
 part 'dynamic_config.g.dart';
 
@@ -38,6 +39,7 @@
     contentAwareHashing: ContentAwareHashing.defaultInstance,
     closeMqGuardAfterPresubmit: false,
     enableGeminiLogAnalysis: false,
+    unifiedCheckRunFlow: UnifiedCheckRunFlow.defaultInstance,
     orderedPresubmit: OrderedPresubmit.defaultInstance,
     dynamicTestSuppression: false,
     geminiModel: 'gemini-3-flash-preview',
@@ -67,6 +69,10 @@
   @JsonKey()
   final bool enableGeminiLogAnalysis;
 
+  /// Flags related tp unified check-run flow configuration.
+  @JsonKey()
+  final UnifiedCheckRunFlow unifiedCheckRunFlow;
+
   /// Flags related to ordered presubmit configuration.
   @JsonKey()
   final OrderedPresubmit orderedPresubmit;
@@ -85,6 +91,7 @@
     required this.contentAwareHashing,
     required this.closeMqGuardAfterPresubmit,
     required this.enableGeminiLogAnalysis,
+    required this.unifiedCheckRunFlow,
     required this.orderedPresubmit,
     required this.dynamicTestSuppression,
     required this.geminiModel,
@@ -99,6 +106,7 @@
     ContentAwareHashing? contentAwareHashing,
     bool? closeMqGuardAfterPresubmit,
     bool? enableGeminiLogAnalysis,
+    UnifiedCheckRunFlow? unifiedCheckRunFlow,
     OrderedPresubmit? orderedPresubmit,
     bool? dynamicTestSuppression,
     String? geminiModel,
@@ -114,6 +122,8 @@
           defaultInstance.closeMqGuardAfterPresubmit,
       enableGeminiLogAnalysis:
           enableGeminiLogAnalysis ?? defaultInstance.enableGeminiLogAnalysis,
+      unifiedCheckRunFlow:
+          unifiedCheckRunFlow ?? defaultInstance.unifiedCheckRunFlow,
       orderedPresubmit: orderedPresubmit ?? defaultInstance.orderedPresubmit,
       dynamicTestSuppression:
           dynamicTestSuppression ?? defaultInstance.dynamicTestSuppression,
@@ -149,6 +159,13 @@
   /// The inverse operation of [DynamicConfig.fromJson].
   Map<String, Object?> toJson() => _$DynamicConfigToJson(this);
 
+  bool isUnifiedCheckRunFlowEnabledForUser(String githubUsername) {
+    if (unifiedCheckRunFlow.useForAll) {
+      return true;
+    }
+    return unifiedCheckRunFlow.useForUsers.contains(githubUsername);
+  }
+
   bool isOrderedPresubmitEnabledForUser(String githubUsername) {
     if (orderedPresubmit.useForAll) {
       return true;
diff --git a/app_dart/lib/src/service/flags/dynamic_config.g.dart b/app_dart/lib/src/service/flags/dynamic_config.g.dart
index a760949..d958c97 100644
--- a/app_dart/lib/src/service/flags/dynamic_config.g.dart
+++ b/app_dart/lib/src/service/flags/dynamic_config.g.dart
@@ -21,6 +21,11 @@
             ),
       closeMqGuardAfterPresubmit: json['closeMqGuardAfterPresubmit'] as bool?,
       enableGeminiLogAnalysis: json['enableGeminiLogAnalysis'] as bool?,
+      unifiedCheckRunFlow: json['unifiedCheckRunFlow'] == null
+          ? null
+          : UnifiedCheckRunFlow.fromJson(
+              json['unifiedCheckRunFlow'] as Map<String, dynamic>?,
+            ),
       orderedPresubmit: json['orderedPresubmit'] == null
           ? null
           : OrderedPresubmit.fromJson(
@@ -37,6 +42,7 @@
       'ciYaml': instance.ciYaml.toJson(),
       'closeMqGuardAfterPresubmit': instance.closeMqGuardAfterPresubmit,
       'enableGeminiLogAnalysis': instance.enableGeminiLogAnalysis,
+      'unifiedCheckRunFlow': instance.unifiedCheckRunFlow.toJson(),
       'orderedPresubmit': instance.orderedPresubmit.toJson(),
       'dynamicTestSuppression': instance.dynamicTestSuppression,
       'geminiModel': instance.geminiModel,
diff --git a/app_dart/lib/src/service/flags/unified_check_run_flow_flags.dart b/app_dart/lib/src/service/flags/unified_check_run_flow_flags.dart
new file mode 100644
index 0000000..85cfc47
--- /dev/null
+++ b/app_dart/lib/src/service/flags/unified_check_run_flow_flags.dart
@@ -0,0 +1,53 @@
+// Copyright 2025 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:json_annotation/json_annotation.dart';
+import 'package:meta/meta.dart';
+
+part 'unified_check_run_flow_flags.g.dart';
+
+/// Flags related to content-aware hashing.
+@JsonSerializable()
+@immutable
+final class UnifiedCheckRunFlow {
+  /// Default configuration for [UnifiedCheckRunFlow] flags.
+  static const defaultInstance = UnifiedCheckRunFlow._(
+    useForAll: false,
+    useForUsers: [],
+  );
+
+  /// Whether to use unified check-run flow with only one check-run created
+  /// for all LUCI tests or github check-run flow.
+  @JsonKey()
+  final bool useForAll;
+
+  /// List of users to use unified check-run flow.
+  @JsonKey()
+  final List<String> useForUsers;
+
+  const UnifiedCheckRunFlow._({
+    required this.useForAll, //
+    required this.useForUsers, //
+  });
+
+  /// Creates [UnifiedCheckRunFlow] flags from the provided fields.
+  ///
+  /// Any omitted fields default to the values in [defaultInstance].
+  factory UnifiedCheckRunFlow({bool? useForAll, List<String>? useForUsers}) {
+    return UnifiedCheckRunFlow._(
+      useForAll: useForAll ?? defaultInstance.useForAll,
+      useForUsers: useForUsers ?? defaultInstance.useForUsers,
+    );
+  }
+
+  /// Creates [UnifiedCheckRunFlow] flags from a [json] object.
+  ///
+  /// Any omitted fields default to the values in [defaultInstance].
+  factory UnifiedCheckRunFlow.fromJson(Map<String, Object?>? json) {
+    return _$UnifiedCheckRunFlowFromJson(json ?? {});
+  }
+
+  /// The inverse operation of [UnifiedCheckRunFlow.fromJson].
+  Map<String, Object?> toJson() => _$UnifiedCheckRunFlowToJson(this);
+}
diff --git a/app_dart/lib/src/service/flags/unified_check_run_flow_flags.g.dart b/app_dart/lib/src/service/flags/unified_check_run_flow_flags.g.dart
new file mode 100644
index 0000000..7c8879f
--- /dev/null
+++ b/app_dart/lib/src/service/flags/unified_check_run_flow_flags.g.dart
@@ -0,0 +1,24 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+// ignore_for_file: always_specify_types, implicit_dynamic_parameter
+
+part of 'unified_check_run_flow_flags.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+UnifiedCheckRunFlow _$UnifiedCheckRunFlowFromJson(Map<String, dynamic> json) =>
+    UnifiedCheckRunFlow(
+      useForAll: json['useForAll'] as bool?,
+      useForUsers: (json['useForUsers'] as List<dynamic>?)
+          ?.map((e) => e as String)
+          .toList(),
+    );
+
+Map<String, dynamic> _$UnifiedCheckRunFlowToJson(
+  UnifiedCheckRunFlow instance,
+) => <String, dynamic>{
+  'useForAll': instance.useForAll,
+  'useForUsers': instance.useForUsers,
+};
diff --git a/app_dart/lib/src/service/luci_build_service.dart b/app_dart/lib/src/service/luci_build_service.dart
index a26f080..01bc943 100644
--- a/app_dart/lib/src/service/luci_build_service.dart
+++ b/app_dart/lib/src/service/luci_build_service.dart
@@ -293,6 +293,8 @@
     final slug = pullRequest.base!.repo!.slug();
     final commitBranch = pullRequest.base!.ref!.replaceAll('refs/heads/', '');
     final isFusion = slug == Config.flutterSlug;
+    final isUnifiedCheckRunFlow = _config.flags
+        .isUnifiedCheckRunFlowEnabledForUser(pullRequest.user!.login!);
     final isOrderedPresubmit = _config.flags.isOrderedPresubmitEnabledForUser(
       pullRequest.user!.login!,
     );
@@ -305,7 +307,7 @@
     late PresubmitUserData userData;
     // If the unified check run flow is enabled, do not create individual
     // check runs for each target but use the guard check run instead.
-    if (dashboardChecks != null) {
+    if (isUnifiedCheckRunFlow && dashboardChecks != null) {
       userData = PresubmitUserData(
         commit: CommitRef(slug: slug, sha: commitSha, branch: commitBranch),
         guardCheckRunId: dashboardChecks.id!,
@@ -324,7 +326,7 @@
     for (final MapEntry(key: target, value: attemptNumber) in targets.entries) {
       // If the unified check run flow is disabled create individual check runs
       // for each target.
-      if (dashboardChecks == null) {
+      if (!isUnifiedCheckRunFlow || dashboardChecks == null) {
         final checkRun = await _githubChecksUtil.createCheckRun(
           _config,
           target.slug,
@@ -394,7 +396,7 @@
             userData: userData,
             properties: properties,
             // if unified check run flow is enabled, use guard check run othervise check run id.
-            tags: dashboardChecks != null
+            tags: isUnifiedCheckRunFlow && dashboardChecks != null
                 ? BuildTags([
                     GuardCheckRunIdBuildTag(
                       guardCheckRunId: dashboardChecks.id!,
@@ -447,7 +449,7 @@
     // initial run. For Re-run Failed Checks, if all failed jobs were reset, we
     // need to re-request the check run before updating it to in progress.
     final isRerun = targets.values.first > 1;
-    if (dashboardChecks != null) {
+    if (isUnifiedCheckRunFlow && dashboardChecks != null) {
       if (isRerun && stage != null) {
         try {
           final presubmitGuardDoc = await _firestore.getDocument(
diff --git a/app_dart/lib/src/service/scheduler.dart b/app_dart/lib/src/service/scheduler.dart
index d7550db..ab98409 100644
--- a/app_dart/lib/src/service/scheduler.dart
+++ b/app_dart/lib/src/service/scheduler.dart
@@ -19,10 +19,12 @@
 import '../model/ci_yaml/ci_yaml.dart';
 import '../model/ci_yaml/target.dart';
 import '../model/commit_ref.dart';
+import '../model/common/checks_extension.dart';
 import '../model/common/presubmit_completed_check.dart';
 import '../model/common/presubmit_guard_conclusion.dart';
 import '../model/common/presubmit_job_state.dart';
 import '../model/firestore/base.dart';
+import '../model/firestore/ci_staging.dart';
 import '../model/firestore/commit.dart' as fs;
 import '../model/firestore/pr_check_runs.dart';
 import '../model/firestore/presubmit_guard.dart';
@@ -347,6 +349,10 @@
       return;
     }
 
+    final isUnifiedCheckRun = _config.flags.isUnifiedCheckRunFlowEnabledForUser(
+      pullRequest.user!.login!,
+    );
+
     // Always cancel running builds so we don't ever schedule duplicates.
     log.info(
       'Attempting to cancel existing presubmit targets for ${pullRequest.number}',
@@ -361,9 +367,12 @@
     final lockResult = await lockMergeGroupChecks(
       slug,
       sha,
-      detailsUrl:
-          'https://flutter-dashboard.appspot.com/#/presubmit?repo=${slug.name}&sha=$sha',
-      isPresubmit: true,
+      // Override details url of merge queue guard check for users with unified
+      // check run flow enabled
+      detailsUrl: isUnifiedCheckRun
+          ? 'https://flutter-dashboard.appspot.com/#/presubmit?repo=${slug.name}&sha=$sha'
+          : null,
+      isUnifiedCheckRun: isUnifiedCheckRun,
     );
     final dashboardChecks = lockResult.dashboardChecks;
     final mergeQueueGuard = lockResult.mergeQueueGuard;
@@ -376,12 +385,11 @@
 
     log.info('Creating presubmit targets for ${pullRequest.number}');
     Object? exception;
-    final isFlutterRepo = slug == Config.flutterSlug;
-    final isPackagesRepo = slug == Config.packagesSlug;
+    final isFusion = slug == Config.flutterSlug;
+    final isPackages = slug == Config.packagesSlug;
     do {
       try {
-        // If it's not flutter or packages, unlock the merge group lock.
-        if (!isFlutterRepo && !isPackagesRepo) {
+        if (!isFusion && !(isPackages && isUnifiedCheckRun)) {
           unlockMergeGroup = true;
         }
 
@@ -425,7 +433,7 @@
           );
           break;
         }
-        final presubmitTargets = isFlutterRepo
+        final presubmitTargets = isFusion
             ? await _getTestsForStage(pullRequest, CiStage.fusionEngineBuild)
             : await getPresubmitTargets(pullRequest);
         final presubmitTriggerTargets = filterTargets(
@@ -433,45 +441,59 @@
           builderTriggerList,
         );
 
-        final stage = isFlutterRepo
-            ? CiStage.fusionEngineBuild
-            : CiStage.genericTests;
-
         // When running presubmits for a fusion PR; create a new staging document to track tasks needed
         // to complete before we can schedule more tests (i.e. build engine artifacts before testing against them).
-        await UnifiedCheckRun.initializeCiStagingDocument(
-          firestoreService: _firestore,
-          slug: slug,
-          sha: sha,
-          stage: stage,
-          tasks: [...presubmitTriggerTargets.map((t) => t.name)],
-          pullRequest: pullRequest,
-          config: _config,
-          dashboardChecks: dashboardChecks,
-          mergeQueueGuard: mergeQueueGuard,
-        );
-        // Even though this appears to be an engine build, it could be a
-        // release candidate build, where the engine artifacts are built
-        // via the dart-internal builder.
-        //
-        // In either case, providing FLUTTER_PREBUILT_ENGINE_VERSION has no
-        // consequences for engine builds, as it just won't be used (it is
-        // only understood by the Flutter CLI).
-        //
-        // See https://github.com/flutter/flutter/issues/165810.
-        final engineArtifacts = isFlutterRepo
-            ? EngineArtifacts.usingExistingEngine(commitSha: sha)
-            : const EngineArtifacts.noFrameworkTests(
-                reason: 'This is not the flutter/flutter repository',
-              );
+        final EngineArtifacts engineArtifacts;
+        if (isFusion) {
+          await UnifiedCheckRun.initializeCiStagingDocument(
+            firestoreService: _firestore,
+            slug: slug,
+            sha: sha,
+            stage: CiStage.fusionEngineBuild,
+            tasks: [...presubmitTriggerTargets.map((t) => t.name)],
+            pullRequest: pullRequest,
+            config: _config,
+            dashboardChecks: dashboardChecks,
+            mergeQueueGuard: mergeQueueGuard,
+          );
 
+          // Even though this appears to be an engine build, it could be a
+          // release candidate build, where the engine artifacts are built
+          // via the dart-internal builder.
+          //
+          // In either case, providing FLUTTER_PREBUILT_ENGINE_VERSION has no
+          // consequences for engine builds, as it just won't be used (it is
+          // only understood by the Flutter CLI).
+          //
+          // See https://github.com/flutter/flutter/issues/165810.
+          engineArtifacts = EngineArtifacts.usingExistingEngine(commitSha: sha);
+        } else {
+          // For non-flutter repos, if unified check run flow is enabled, create
+          // a presubmit_guard document to track presubmit tests.
+          if (isUnifiedCheckRun) {
+            await UnifiedCheckRun.initializeCiStagingDocument(
+              firestoreService: _firestore,
+              slug: slug,
+              sha: sha,
+              stage: CiStage.genericTests,
+              tasks: [...presubmitTriggerTargets.map((t) => t.name)],
+              pullRequest: pullRequest,
+              config: _config,
+              dashboardChecks: dashboardChecks,
+              mergeQueueGuard: mergeQueueGuard,
+            );
+          }
+          engineArtifacts = const EngineArtifacts.noFrameworkTests(
+            reason: 'This is not the flutter/flutter repository',
+          );
+        }
         await _luciBuildService.scheduleTryBuilds(
           targets: presubmitTriggerTargets,
           pullRequest: pullRequest,
           engineArtifacts: engineArtifacts,
           dashboardChecks: dashboardChecks,
           mergeQueueGuard: mergeQueueGuard,
-          stage: stage,
+          stage: isFusion ? CiStage.fusionEngineBuild : CiStage.genericTests,
         );
       } on FormatException catch (e, s) {
         log.warn(
@@ -507,9 +529,13 @@
     // there are situations (see code above) when it needs to be unlocked
     // immediately.
     if (unlockMergeGroup) {
-      await unlockCheckRun(slug, sha, dashboardChecks);
-      if (mergeQueueGuard != null) {
-        await unlockCheckRun(slug, sha, mergeQueueGuard);
+      if (isUnifiedCheckRun) {
+        await unlockMergeQueueGuard(slug, sha, dashboardChecks);
+        if (mergeQueueGuard != null) {
+          await unlockMergeQueueGuard(slug, sha, mergeQueueGuard);
+        }
+      } else if (mergeQueueGuard != null) {
+        await unlockMergeQueueGuard(slug, sha, mergeQueueGuard);
       }
     }
     log.info(
@@ -632,7 +658,7 @@
     final lockResult = await lockMergeGroupChecks(
       slug,
       headSha,
-      isPresubmit: false,
+      isUnifiedCheckRun: false,
     );
     final dashboardChecks = lockResult.dashboardChecks;
     final mergeQueueGuard = lockResult.mergeQueueGuard!;
@@ -640,7 +666,7 @@
     // If the repo is not fusion, it doesn't run anything in the MQ, so just
     // close the merge group guard.
     if (!isFusion) {
-      await unlockCheckRun(slug, headSha, mergeQueueGuard);
+      await unlockMergeQueueGuard(slug, headSha, mergeQueueGuard);
       return;
     }
 
@@ -845,7 +871,7 @@
     RepositorySlug slug,
     String headSha, {
     String? detailsUrl,
-    required bool isPresubmit,
+    required bool isUnifiedCheckRun,
   }) async {
     final mergeQueueGuard = await _githubChecksService.githubChecksUtil
         .createCheckRun(
@@ -857,7 +883,7 @@
             title: Config.kMergeQueueLockName,
             summary: kMergeQueueLockDescription,
           ),
-          detailsUrl: isPresubmit ? null : detailsUrl,
+          detailsUrl: isUnifiedCheckRun ? null : detailsUrl,
         );
 
     final dashboardChecks = await _githubChecksService.githubChecksUtil
@@ -870,10 +896,10 @@
             title: Config.kDashboardCheckName,
             summary: kDashboardChecksDescription,
           ),
-          detailsUrl: isPresubmit ? detailsUrl : null,
+          detailsUrl: isUnifiedCheckRun ? detailsUrl : null,
         );
 
-    if (!isPresubmit) {
+    if (!isUnifiedCheckRun) {
       // Skip Dashboard Checks
       await _githubChecksService.githubChecksUtil.updateCheckRun(
         _config,
@@ -948,7 +974,7 @@
   ///
   /// If the guard is guarding a pull request, this immediately makes the pull
   /// request eligible for enqueuing into the merge queue.
-  Future<void> unlockCheckRun(
+  Future<void> unlockMergeQueueGuard(
     RepositorySlug slug,
     String headSha,
     CheckRun lock,
@@ -1103,20 +1129,56 @@
     if (kCheckRunsToIgnore.contains(check.name)) {
       return true;
     }
+    final flow = check.isUnifiedCheckRun ? 'unified' : 'github';
     final requestor = check.isMergeGroup ? 'merge group' : 'pull request';
     final logCrumb =
-        'checkCompleted(${check.name}, $requestor, ${check.slug}, ${check.sha}, ${check.status})';
+        'checkCompleted(${check.name}, $flow, $requestor, ${check.slug}, ${check.sha}, ${check.status})';
 
-    final stage =
-        check.stage ??
-        (check.slug == Config.flutterSlug
-            ? CiStage.fusionTests
-            : CiStage.genericTests);
-    final stagingConclusion = await _markUnifiedCheckRunConclusion(
-      guardId: check.guardId,
-      state: check.state,
-    );
+    final isFusion = check.slug == Config.flutterSlug;
+    if (!isFusion && !check.isUnifiedCheckRun) {
+      return true;
+    }
 
+    late CiStage stage;
+    late PresubmitGuardConclusion stagingConclusion;
+
+    if (check.isUnifiedCheckRun) {
+      stage = check.stage!;
+      stagingConclusion = await _markUnifiedCheckRunConclusion(
+        guardId: check.guardId,
+        state: check.state,
+      );
+    } else {
+      // for github flow check runs are processed only if the build succeeded or
+      // some kind of failure occurred.
+      if (!check.status.isComplete) {
+        return true;
+      }
+      // Check runs are fired at every stage. However, at this point it is unknown
+      // if this check run belongs in the engine build stage or in the test stage.
+      // So first look for it in the engine stage, and if it's missing, look for
+      // it in the test stage.
+      stage = CiStage.fusionEngineBuild;
+      stagingConclusion = await _recordCurrentCiStage(
+        slug: check.slug,
+        sha: check.sha,
+        stage: stage,
+        name: check.name,
+        conclusion: check.status.toTaskConclusion(),
+      );
+
+      if (stagingConclusion.result == PresubmitGuardConclusionResult.missing) {
+        // Check run not found in the engine stage. Look for it in the test stage.
+        stage = CiStage.fusionTests;
+        stagingConclusion = await _recordCurrentCiStage(
+          slug: check.slug,
+          sha: check.sha,
+          stage: stage,
+          name: check.name,
+          conclusion: check.status.toTaskConclusion(),
+        );
+      }
+    }
     // First; check if we even recorded anything. This can occur if we've already passed the check_run and
     // have moved on to running more tests (which wouldn't be present in our document).
     if (!stagingConclusion.isOk) {
@@ -1172,7 +1234,7 @@
           summary: stagingConclusion.summary,
           details: stagingConclusion.details,
         );
-      } else {
+      } else if (check.isUnifiedCheckRun) {
         final guard = checkRunFromString(stagingConclusion.dashboardChecks!);
         final detailsUrl =
             'https://flutter-dashboard.appspot.com/#/presubmit?repo=${check.slug.name}&sha=${check.sha}';
@@ -1221,7 +1283,6 @@
             logCrumb: logCrumb,
           );
         }
-        break;
       case CiStage.fusionTests:
         await _closeSuccessfulTestStage(
           dashboardChecks: stagingConclusion.dashboardChecks,
@@ -1229,16 +1290,23 @@
           slug: check.slug,
           sha: check.sha,
           logCrumb: logCrumb,
+          isUnifiedCheckRun: check.isUnifiedCheckRun,
         );
-        break;
       case CiStage.genericTests:
-        await _closeSuccessfulTestStage(
-          dashboardChecks: stagingConclusion.dashboardChecks,
-          mergeQueueGuard: stagingConclusion.mergeQueueGuard,
-          slug: check.slug,
-          sha: check.sha,
-          logCrumb: logCrumb,
-        );
+        if (check.isUnifiedCheckRun) {
+          await _closeSuccessfulTestStage(
+            dashboardChecks: stagingConclusion.dashboardChecks,
+            mergeQueueGuard: stagingConclusion.mergeQueueGuard,
+            slug: check.slug,
+            sha: check.sha,
+            logCrumb: logCrumb,
+            isUnifiedCheckRun: check.isUnifiedCheckRun,
+          );
+        } else {
+          // generic tests do not have a staging document nor are associated
+          // with a merge group - they are only used to collect commit stats.
+          log.warn('$logCrumb: generic tests have no merge queue guard.');
+        }
         break;
     }
     return true;
@@ -1296,13 +1364,32 @@
     required RepositorySlug slug,
     required String sha,
     required String logCrumb,
+    required bool isUnifiedCheckRun,
   }) async {
     log.info('$logCrumb: Test stage completed');
-    if (dashboardChecks != null) {
-      await unlockCheckRun(slug, sha, checkRunFromString(dashboardChecks));
-    }
-    if (mergeQueueGuard != null) {
-      await unlockCheckRun(slug, sha, checkRunFromString(mergeQueueGuard));
+    if (isUnifiedCheckRun) {
+      if (dashboardChecks != null) {
+        await unlockMergeQueueGuard(
+          slug,
+          sha,
+          checkRunFromString(dashboardChecks),
+        );
+      }
+      if (mergeQueueGuard != null) {
+        await unlockMergeQueueGuard(
+          slug,
+          sha,
+          checkRunFromString(mergeQueueGuard),
+        );
+      }
+    } else {
+      if (mergeQueueGuard != null) {
+        await unlockMergeQueueGuard(
+          slug,
+          sha,
+          checkRunFromString(mergeQueueGuard),
+        );
+      }
     }
   }
 
@@ -1341,7 +1428,7 @@
 
     // Unlock the guarding check_run.
     final checkRunGuard = checkRunFromString(mergeQueueGuard);
-    await unlockCheckRun(slug, sha, checkRunGuard);
+    await unlockMergeQueueGuard(slug, sha, checkRunGuard);
   }
 
   /// Schedules post-engine build tests (i.e. engine tests, and framework tests).
@@ -1508,6 +1595,37 @@
     }
   }
 
+  Future<PresubmitGuardConclusion> _recordCurrentCiStage({
+    required RepositorySlug slug,
+    required String sha,
+    required CiStage stage,
+    required String name,
+    required TaskConclusion conclusion,
+  }) async {
+    final logCrumb = 'checkCompleted($name, $slug, $sha, $conclusion)';
+    final documentName = CiStaging.documentNameFor(
+      slug: slug,
+      sha: sha,
+      stage: stage,
+    );
+    log.info('$logCrumb: $documentName');
+
+    // We're doing a transactional update, which could fail if multiple tasks are running at the same time; so retry
+    // a sane amount of times before giving up.
+    const r = RetryOptions(maxAttempts: 3, delayFactor: Duration(seconds: 2));
+
+    return r.retry(() {
+      return CiStaging.markConclusion(
+        firestoreService: _firestore,
+        slug: slug,
+        sha: sha,
+        stage: stage,
+        checkRun: name,
+        conclusion: conclusion,
+      );
+    });
+  }
+
   Future<PresubmitGuardConclusion> _markUnifiedCheckRunConclusion({
     required PresubmitGuardId guardId,
     required PresubmitJobState state,
diff --git a/app_dart/test/model/common/presubmit_completed_check_test.dart b/app_dart/test/model/common/presubmit_completed_check_test.dart
index c89ba0b..a2b9de2 100644
--- a/app_dart/test/model/common/presubmit_completed_check_test.dart
+++ b/app_dart/test/model/common/presubmit_completed_check_test.dart
@@ -50,11 +50,48 @@
       expect(check.checkRunId, 123);
       expect(check.checkSuiteId, 456);
       expect(check.headBranch, 'gh-readonly-queue/master/pr-123-abc');
+      expect(check.isUnifiedCheckRun, true);
       expect(check.checkRun.name, Config.kDashboardCheckName);
       expect(check.buildNumber, 0);
       expect(check.buildId, Int64.MAX_VALUE);
     });
 
+    test('fromBuild creates correct legacy check', () {
+      final build = Build(
+        id: Int64.MAX_VALUE,
+        builder: BuilderID(builder: 'test_builder'),
+        status: Status.SUCCESS,
+        number: 1234,
+      );
+
+      final userData = PresubmitUserData(
+        commit: CommitRef(
+          slug: slug,
+          sha: sha,
+          branch: 'gh-readonly-queue/master/pr-123-abc',
+        ),
+        stage: CiStage.fusionEngineBuild,
+        pullRequestNumber: 1,
+        checkRunId: 123,
+        checkSuiteId: 456,
+      );
+
+      final check = PresubmitCompletedJob.fromBuild(build, userData);
+
+      expect(check.name, 'test_builder');
+      expect(check.sha, sha);
+      expect(check.slug, slug);
+      expect(check.status, TaskStatus.succeeded);
+      expect(check.isMergeGroup, true);
+      expect(check.checkRunId, 123);
+      expect(check.checkSuiteId, 456);
+      expect(check.headBranch, 'gh-readonly-queue/master/pr-123-abc');
+      expect(check.isUnifiedCheckRun, false);
+      expect(check.checkRun.name, 'test_builder');
+      expect(check.buildNumber, 1234);
+      expect(check.buildId, Int64.MAX_VALUE);
+    });
+
     test('fromBuild handles custom status and summaryPrepend', () {
       final build = Build(
         id: Int64.MAX_VALUE,
diff --git a/app_dart/test/request_handlers/github/webhook_subscription_test.dart b/app_dart/test/request_handlers/github/webhook_subscription_test.dart
index ef462c1..85f01d4 100644
--- a/app_dart/test/request_handlers/github/webhook_subscription_test.dart
+++ b/app_dart/test/request_handlers/github/webhook_subscription_test.dart
@@ -12,11 +12,11 @@
 import 'package:cocoon_server_test/mocks.dart';
 import 'package:cocoon_server_test/test_logging.dart';
 import 'package:cocoon_service/cocoon_service.dart';
+import 'package:cocoon_service/src/model/firestore/ci_staging.dart';
 import 'package:cocoon_service/src/model/firestore/commit.dart' as fs;
 import 'package:cocoon_service/src/model/github/checks.dart' hide CheckRun;
 import 'package:cocoon_service/src/request_handling/exceptions.dart';
 import 'package:cocoon_service/src/service/big_query.dart';
-import 'package:cocoon_service/src/service/firestore/unified_check_run.dart';
 import 'package:cocoon_service/src/service/github_service.dart';
 import 'package:fixnum/fixnum.dart';
 import 'package:github/github.dart' hide Branch;
@@ -96,7 +96,9 @@
       wrongBaseBranchPullRequestMessageValue:
           '{{target_branch}} -> {{default_branch}}',
     );
-    config.dynamicConfig = DynamicConfig();
+    config.dynamicConfig = DynamicConfig(
+      unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+    );
     issuesService = MockIssuesService();
     when(
       // ignore: discarded_futures
@@ -147,8 +149,6 @@
         any,
         any,
         output: anyNamed('output'),
-        conclusion: anyNamed('conclusion'),
-        detailsUrl: anyNamed('detailsUrl'),
       ),
     ).thenAnswer((_) async {
       return CheckRun.fromJson(const <String, dynamic>{
@@ -2792,23 +2792,13 @@
       });
 
       test('Tries to schedule tests for a duplicate SHA warns', () async {
-        final pr = generatePullRequest(
-          number: 1,
-          headSha: '66d6bd9a3f79a36fe4f5178ccefbc781488a596c',
-        );
-        final checkRunGuard = generateCheckRun(
-          1,
-          name: Config.kDashboardCheckName,
-        );
-        await UnifiedCheckRun.initializeCiStagingDocument(
+        await CiStaging.initializeDocument(
           firestoreService: firestore,
           slug: Config.flutterSlug,
           sha: '66d6bd9a3f79a36fe4f5178ccefbc781488a596c',
           stage: CiStage.fusionEngineBuild,
           tasks: [],
-          config: config,
-          pullRequest: pr,
-          dashboardChecks: checkRunGuard,
+          checkRunGuard: '',
         );
         config.maxFilesChangedForSkippingEnginePhaseValue = 1;
         await testActions(
diff --git a/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart b/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart
index 59a5e5c..058cc17 100644
--- a/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart
+++ b/app_dart/test/request_handlers/presubmit_luci_subscription_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:archive/archive.dart';
 import 'package:buildbucket/buildbucket_pb.dart' as bbv2;
 import 'package:cocoon_common/task_status.dart';
 import 'package:cocoon_integration_test/testing.dart';
@@ -80,6 +79,15 @@
 
   test('Requests with repo_owner and repo_name update checks', () async {
     when(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+      ),
+    ).thenAnswer((_) async => true);
+
+    when(
       mockGithubChecksService.conclusionForResult(any),
     ).thenAnswer((_) => github.CheckRunConclusion.empty);
     when(
@@ -102,19 +110,28 @@
     );
 
     await tester.post(handler);
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+      ),
+    ).called(1);
 
     verify(mockScheduler.processCheckRunCompleted(any)).called(1);
   });
 
   test('Requests when task failed but no need to reschedule', () async {
-    buildBucketClient.getBuildResponse = Future.value(
-      bbv2.Build(
-        id: Int64(1),
-        builder: bbv2.BuilderID(builder: 'Linux A'),
-        status: bbv2.Status.FAILURE,
-        summaryMarkdown: 'test summary',
+    when(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
       ),
-    );
+    ).thenAnswer((_) async => true);
+
     when(
       mockGithubChecksService.conclusionForResult(any),
     ).thenAnswer((_) => github.CheckRunConclusion.empty);
@@ -153,27 +170,27 @@
         userData: userData,
       ),
     );
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+      ),
+    ).called(1);
     verify(mockScheduler.processCheckRunCompleted(any)).called(1);
   });
 
   test('Requests when task failed but need to reschedule', () async {
-    buildBucketClient.getBuildResponse = Future.value(
-      bbv2.Build(
-        id: Int64(1),
-        builder: bbv2.BuilderID(builder: 'Linux presubmit_max_attempts=2'),
-        status: bbv2.Status.FAILURE,
-        summaryMarkdown: 'test summary',
+    when(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: true,
       ),
-    );
-    firestore.putDocument(
-      PresubmitJob.init(
-        slug: RepositorySlug('flutter', 'flutter'),
-        jobName: 'Linux presubmit_max_attempts=2',
-        checkRunId: 1,
-        creationTime: 12345,
-        attemptNumber: 1,
-      ),
-    );
+    ).thenAnswer((_) async => true);
 
     tester.message = createPushMessage(
       Int64(1),
@@ -191,19 +208,19 @@
     );
     await tester.post(handler);
 
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: true,
+      ),
+    ).called(1);
     verifyNever(mockScheduler.processCheckRunCompleted(any));
   });
 
   test('Build rescheduled when in merge queue', () async {
-    firestore.putDocument(
-      PresubmitJob.init(
-        slug: RepositorySlug('flutter', 'flutter'),
-        jobName: 'Linux A',
-        checkRunId: 1,
-        creationTime: 12345,
-        attemptNumber: 1,
-      ),
-    );
     when(
       mockGithubChecksService.updateCheckStatus(
         build: anyNamed('build'),
@@ -215,14 +232,7 @@
     ).thenAnswer((_) async => true);
     when(
       mockLuciBuildService.getBuildById(any, buildMask: anyNamed('buildMask')),
-    ).thenAnswer(
-      (_) async => bbv2.Build(
-        id: Int64(1),
-        builder: bbv2.BuilderID(builder: 'Linux A'),
-        status: bbv2.Status.INFRA_FAILURE,
-        summaryMarkdown: 'test summary',
-      ),
-    );
+    ).thenAnswer((_) async => bbv2.Build(summaryMarkdown: 'test summary'));
 
     tester.message = createPushMessage(
       Int64(1),
@@ -280,18 +290,19 @@
         userData: anyNamed('userData'),
       ),
     ).called(1);
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: true,
+      ),
+    ).called(1);
     verifyNever(mockScheduler.processCheckRunCompleted(any));
   });
 
   test('Build not rescheduled if not found in ciYaml list.', () async {
-    buildBucketClient.getBuildResponse = Future.value(
-      bbv2.Build(
-        id: Int64(1),
-        builder: bbv2.BuilderID(builder: 'Linux C'),
-        status: bbv2.Status.FAILURE,
-        summaryMarkdown: 'test summary',
-      ),
-    );
     when(
       mockGithubChecksService.updateCheckStatus(
         build: anyNamed('build'),
@@ -341,19 +352,20 @@
         nextAttempt: 1,
       ),
     );
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: false,
+      ),
+    ).called(1);
 
     verify(mockScheduler.processCheckRunCompleted(any)).called(1);
   });
 
   test('Build not rescheduled if ci.yaml fails validation.', () async {
-    buildBucketClient.getBuildResponse = Future.value(
-      bbv2.Build(
-        id: Int64(1),
-        builder: bbv2.BuilderID(builder: 'Linux C'),
-        status: bbv2.Status.FAILURE,
-        summaryMarkdown: 'test summary',
-      ),
-    );
     when(
       mockGithubChecksService.updateCheckStatus(
         build: anyNamed('build'),
@@ -402,6 +414,15 @@
         nextAttempt: 1,
       ),
     );
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: false,
+      ),
+    ).called(1);
     verify(mockScheduler.processCheckRunCompleted(any)).called(1);
   });
 
@@ -435,15 +456,6 @@
   });
 
   test('Build contains data from build_large_fields', () async {
-    firestore.putDocument(
-      PresubmitJob.init(
-        slug: RepositorySlug('flutter', 'flutter'),
-        jobName: 'Linux presubmit_max_attempts=2',
-        checkRunId: 1,
-        creationTime: 12345,
-        attemptNumber: 1,
-      ),
-    );
     when(
       mockGithubChecksService.updateCheckStatus(
         build: anyNamed('build'),
@@ -453,22 +465,9 @@
         rescheduled: anyNamed('rescheduled'),
       ),
     ).thenAnswer((_) async => true);
-    final fullBuild =
-        createBuild(
-            Int64(1),
-            status: bbv2.Status.FAILURE,
-            builder: 'Linux presubmit_max_attempts=2',
-          ).build
-          ..mergeFromBuffer(
-            const ZLibDecoder().decodeBytes(
-              createBuild(Int64(1)).buildLargeFields,
-            ),
-          )
-          ..summaryMarkdown = 'test summary';
-
     when(
       mockLuciBuildService.getBuildById(any, buildMask: anyNamed('buildMask')),
-    ).thenAnswer((_) async => fullBuild);
+    ).thenAnswer((_) async => bbv2.Build(summaryMarkdown: 'test summary'));
 
     tester.message = createPushMessage(
       Int64(1),
@@ -585,6 +584,91 @@
     );
   });
 
+  test('Requests when task failed and is suppressed', () async {
+    final userData = PresubmitUserData(
+      commit: CommitRef(
+        sha: 'abc',
+        branch: 'master',
+        slug: RepositorySlug('flutter', 'flutter'),
+      ),
+      checkRunId: 1,
+      checkSuiteId: 2,
+    );
+
+    // Setup Firestore
+    firestore.putDocument(
+      SuppressedTest(
+          name: 'Linux A',
+          repository: 'flutter/flutter',
+          issueLink: 'https://github.com/flutter/flutter/issues/123',
+          isSuppressed: true,
+          createTimestamp: DateTime.now(),
+        )
+        ..name = firestore.resolveDocumentName(
+          SuppressedTest.kCollectionId,
+          'suppressed_1',
+        ),
+    );
+
+    when(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        conclusionOverride: github.CheckRunConclusion.neutral,
+        summaryPrepend: argThat(
+          contains('marked as suppressed'),
+          named: 'summaryPrepend',
+        ),
+      ),
+    ).thenAnswer((_) async => true);
+
+    when(
+      mockScheduler.processCheckRunCompleted(any),
+    ).thenAnswer((_) async => true);
+
+    tester.message = createPushMessage(
+      Int64(1),
+      status: bbv2.Status.FAILURE,
+      builder: 'Linux A',
+      userData: userData,
+    );
+
+    await tester.post(handler);
+
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        conclusionOverride: github.CheckRunConclusion.neutral,
+        summaryPrepend: argThat(
+          contains('### ⚠️ Test failed but marked as suppressed on dashboard'),
+          named: 'summaryPrepend',
+        ),
+      ),
+    ).called(1);
+
+    final captured = verify(
+      mockScheduler.processCheckRunCompleted(captureAny),
+    ).captured;
+    expect(captured, hasLength(1));
+    expect(
+      captured[0],
+      isA<PresubmitCompletedJob>()
+          .having((e) => e.status, 'status', TaskStatus.neutral)
+          .having(
+            (e) => e.summary,
+            'summary',
+            contains(
+              '### ⚠️ Test failed but marked as suppressed on dashboard',
+            ),
+          ),
+    );
+  });
+
   test('Requests when unified check run failed and is suppressed', () async {
     final userData = PresubmitUserData(
       commit: CommitRef(
@@ -723,6 +807,49 @@
     },
   );
 
+  test('Suppression check skipped when rescheduled', () async {
+    tester.message = createPushMessage(
+      Int64(1),
+      status: bbv2.Status.FAILURE,
+      builder: 'Linux presubmit_max_attempts=2',
+      userData: PresubmitUserData(
+        commit: CommitRef(
+          sha: 'abc',
+          branch: 'master',
+          slug: RepositorySlug('flutter', 'flutter'),
+        ),
+        checkRunId: 1,
+        checkSuiteId: 2,
+      ),
+    );
+
+    when(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: true,
+        conclusionOverride: null,
+        summaryPrepend: null,
+      ),
+    ).thenAnswer((_) async => true);
+
+    await tester.post(handler);
+
+    verify(
+      mockGithubChecksService.updateCheckStatus(
+        build: anyNamed('build'),
+        checkRunId: anyNamed('checkRunId'),
+        luciBuildService: anyNamed('luciBuildService'),
+        slug: anyNamed('slug'),
+        rescheduled: true,
+        conclusionOverride: null,
+        summaryPrepend: null,
+      ),
+    ).called(1);
+  });
+
   test('Unified Suppression check skipped when rescheduled', () async {
     buildBucketClient.getBuildResponse = Future.value(
       bbv2.Build()
@@ -879,7 +1006,14 @@
 
       expect(response, Response.emptyOk);
       expect(pubSub.topics, isEmpty);
-      verify(mockScheduler.processCheckRunCompleted(any)).called(1);
+      verify(
+        mockGithubChecksService.updateCheckStatus(
+          build: anyNamed('build'),
+          checkRunId: anyNamed('checkRunId'),
+          luciBuildService: anyNamed('luciBuildService'),
+          slug: anyNamed('slug'),
+        ),
+      ).called(1);
     },
   );
 }
diff --git a/app_dart/test/request_handlers/presubmit_ordered_subscription_test.dart b/app_dart/test/request_handlers/presubmit_ordered_subscription_test.dart
index 13efb12..b0eee7f 100644
--- a/app_dart/test/request_handlers/presubmit_ordered_subscription_test.dart
+++ b/app_dart/test/request_handlers/presubmit_ordered_subscription_test.dart
@@ -105,6 +105,14 @@
       final response = await tester.post(handler);
 
       expect(response, Response.emptyOk);
+      verify(
+        mockGithubChecksService.updateCheckStatus(
+          build: anyNamed('build'),
+          checkRunId: anyNamed('checkRunId'),
+          luciBuildService: anyNamed('luciBuildService'),
+          slug: anyNamed('slug'),
+        ),
+      ).called(1);
       verify(mockScheduler.processCheckRunCompleted(any)).called(1);
     },
   );
diff --git a/app_dart/test/service/firestore/unified_check_run_test.dart b/app_dart/test/service/firestore/unified_check_run_test.dart
index 2a8ad46..f6b486a 100644
--- a/app_dart/test/service/firestore/unified_check_run_test.dart
+++ b/app_dart/test/service/firestore/unified_check_run_test.dart
@@ -48,7 +48,11 @@
 
     group('initializeCiStagingDocument', () {
       test('creates PresubmitGuard and Checks when enabled for user', () async {
-        config.dynamicConfig = DynamicConfig();
+        config.dynamicConfig = DynamicConfig.fromJson({
+          'unifiedCheckRunFlow': {
+            'useForUsers': ['dash'],
+          },
+        });
 
         await UnifiedCheckRun.initializeCiStagingDocument(
           firestoreService: firestoreService,
@@ -83,6 +87,37 @@
         );
         expect(checkDoc.name, endsWith(checkId.documentId));
       });
+
+      test('initializes CiStagingDocument when NOT enabled for user', () async {
+        config.dynamicConfig = DynamicConfig.fromJson({
+          'unifiedCheckRunFlow': {'useForUsers': <String>[]},
+        });
+
+        await UnifiedCheckRun.initializeCiStagingDocument(
+          firestoreService: firestoreService,
+          slug: slug,
+          sha: sha,
+          stage: CiStage.fusionEngineBuild,
+          tasks: ['linux', 'mac'],
+          config: config,
+          pullRequest: pullRequest,
+          mergeQueueGuard: checkRun,
+        );
+
+        // Verify PresubmitGuard is NOT created
+        final guardId = PresubmitGuard.documentIdFor(
+          slug: slug,
+          prNum: 1,
+          checkRunId: 123,
+          stage: CiStage.fusionEngineBuild,
+        );
+        expect(
+          () => firestoreService.getDocument(
+            'projects/flutter-dashboard/databases/cocoon/documents/presubmit_guards/${guardId.documentId}',
+          ),
+          throwsA(isA<Exception>()),
+        );
+      });
     });
 
     group('markConclusion', () {
@@ -689,6 +724,7 @@
           checkRunId: 123,
           checkSuiteId: 234,
           headBranch: 'master',
+          isUnifiedCheckRun: true,
           prNum: 567,
           attempt: 1,
           endTime: 2000,
diff --git a/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart b/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart
index 86692db..e8caad7 100644
--- a/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart
+++ b/app_dart/test/service/luci_build_service/schedule_try_builds_test.dart
@@ -16,6 +16,7 @@
 import 'package:cocoon_service/src/service/firestore.dart';
 import 'package:cocoon_service/src/service/flags/dynamic_config.dart';
 import 'package:cocoon_service/src/service/flags/ordered_presubmit_flags.dart';
+import 'package:cocoon_service/src/service/flags/unified_check_run_flow_flags.dart';
 import 'package:cocoon_service/src/service/luci_build_service.dart';
 import 'package:cocoon_service/src/service/luci_build_service/build_tags.dart';
 import 'package:cocoon_service/src/service/luci_build_service/engine_artifacts.dart';
@@ -419,7 +420,11 @@
 
         // Enable Unified Check Run Flow
         luci = LuciBuildService(
-          config: FakeConfig(dynamicConfig: DynamicConfig()),
+          config: FakeConfig(
+            dynamicConfig: DynamicConfig(
+              unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+            ),
+          ),
           cache: CacheService.inMemory(),
           buildBucketClient: mockBuildBucketClient,
           githubChecksUtil: mockGithubChecksUtil,
@@ -487,7 +492,11 @@
 
       // Enable Unified Check Run Flow but provide NO guard
       luci = LuciBuildService(
-        config: FakeConfig(dynamicConfig: DynamicConfig()),
+        config: FakeConfig(
+          dynamicConfig: DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+          ),
+        ),
         cache: CacheService.inMemory(),
         buildBucketClient: mockBuildBucketClient,
         githubChecksUtil: mockGithubChecksUtil,
@@ -545,6 +554,79 @@
       expect(userData.checkRunId, 456);
       expect(userData.guardCheckRunId, isNull);
     });
+
+    test(
+      'does not update dashboard checks when unified flow is disabled',
+      () async {
+        final pullRequest = generatePullRequest(
+          id: 1,
+          repo: 'flutter',
+          headSha: 'headsha123',
+        );
+
+        final buildTarget = generateTarget(
+          1,
+          properties: {'os': 'abc'},
+          slug: RepositorySlug.full('flutter/flutter'),
+          name: 'Linux foo',
+        );
+
+        // Disable Unified Check Run Flow but provide a guard (unexpected but should be handled)
+        luci = LuciBuildService(
+          config: FakeConfig(
+            dynamicConfig: DynamicConfig(
+              unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+            ),
+          ),
+          cache: CacheService.inMemory(),
+          buildBucketClient: mockBuildBucketClient,
+          githubChecksUtil: mockGithubChecksUtil,
+          pubsub: pubSub,
+          gerritService: gerritService,
+          firestore: firestore,
+        );
+
+        final checkRunGuard = generateCheckRun(1234, name: 'Guard');
+
+        when(
+          mockGithubChecksUtil.createCheckRun(any, any, any, any),
+        ).thenAnswer((_) async => generateCheckRun(456, name: 'Linux foo'));
+
+        await expectLater(
+          luci.scheduleTryBuilds(
+            pullRequest: pullRequest,
+            targets: [buildTarget],
+            engineArtifacts: EngineArtifacts.builtFromSource(
+              commitSha: pullRequest.head!.sha!,
+            ),
+            dashboardChecks: checkRunGuard, // Pass guard even though disabled
+          ),
+          completion([isTarget.hasName('Linux foo')]),
+        );
+
+        // Should NOT update dashboard checks
+        verifyNever(
+          mockGithubChecksUtil.updateCheckRun(
+            any,
+            any,
+            any,
+            status: anyNamed('status'),
+            conclusion: anyNamed('conclusion'),
+          ),
+        );
+
+        // Should create individual check run because unified flow is disabled
+        verify(
+          mockGithubChecksUtil.createCheckRun(
+            any,
+            RepositorySlug.full('flutter/flutter'),
+            'headsha123',
+            'Linux foo',
+          ),
+        ).called(1);
+      },
+    );
+
     test(
       'reRequests check run for re-run failed checks when failedJobs is 0',
       () async {
@@ -571,7 +653,9 @@
         luci = LuciBuildService(
           config: FakeConfig(
             githubClient: mockGithubClient,
-            dynamicConfig: DynamicConfig(),
+            dynamicConfig: DynamicConfig(
+              unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+            ),
           ),
           cache: CacheService.inMemory(),
           buildBucketClient: mockBuildBucketClient,
@@ -646,7 +730,9 @@
         luci = LuciBuildService(
           config: FakeConfig(
             githubClient: mockGithubClient,
-            dynamicConfig: DynamicConfig(),
+            dynamicConfig: DynamicConfig(
+              unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+            ),
           ),
           cache: CacheService.inMemory(),
           buildBucketClient: mockBuildBucketClient,
diff --git a/app_dart/test/service/scheduler_test.dart b/app_dart/test/service/scheduler_test.dart
index e67bab0..8cfd86a 100644
--- a/app_dart/test/service/scheduler_test.dart
+++ b/app_dart/test/service/scheduler_test.dart
@@ -76,9 +76,10 @@
           Config.flutterSlug,
           Config.packagesSlug,
         },
-        maxFilesChangedForSkippingEnginePhaseValue: 0,
       );
-      config.dynamicConfig = DynamicConfig();
+      config.dynamicConfig = DynamicConfig(
+        unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+      );
 
       fakeContentAwareHash = FakeContentAwareHashService(config: config);
 
@@ -92,8 +93,6 @@
           any,
           any,
           output: anyNamed('output'),
-          conclusion: anyNamed('conclusion'),
-          detailsUrl: anyNamed('detailsUrl'),
         ),
       ).thenAnswer((Invocation invocation) async {
         return generateCheckRun(
@@ -674,7 +673,9 @@
         final mockGithubClient = MockGitHub();
         config = FakeConfig(
           githubService: mockGithubService,
-          dynamicConfig: DynamicConfig(),
+          dynamicConfig: DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+          ),
         );
         scheduler = Scheduler(
           githubService: config.githubService ?? FakeGithubService(),
@@ -727,7 +728,6 @@
             any,
             any,
             output: anyNamed('output'),
-            detailsUrl: anyNamed('detailsUrl'),
           ),
         ).thenAnswer((_) async {
           return CheckRun.fromJson(const <String, dynamic>{
@@ -757,16 +757,9 @@
             output: anyNamed('output'),
           ),
         );
-        // Verifies Dashboard Checks was created
+        // Verfies Linux A was created
         verify(
-          mockGithubChecksUtil.createCheckRun(
-            any,
-            any,
-            any,
-            Config.kDashboardCheckName,
-            output: anyNamed('output'),
-            detailsUrl: anyNamed('detailsUrl'),
-          ),
+          mockGithubChecksUtil.createCheckRun(any, any, any, any),
         ).called(1);
       });
 
@@ -1624,6 +1617,15 @@
           test(
             'ignores default check runs that have no side effects',
             () async {
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'abc123',
+                stage: CiStage.fusionTests,
+                tasks: ['foo', 'bar'],
+                checkRunGuard: '{}',
+              );
+
               for (final ignored in Scheduler.kCheckRunsToIgnore) {
                 expect(
                   await scheduler.processCheckRunCompleted(
@@ -1636,14 +1638,584 @@
                       checkRunId: 1,
                       checkSuiteId: 668083231,
                       headBranch: 'master',
+                      isUnifiedCheckRun: false,
                     ),
                   ),
                   isTrue,
                 );
               }
+
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging.hasCheckRuns({
+                    'foo': TaskConclusion.scheduled,
+                    'bar': TaskConclusion.scheduled,
+                  }),
+                ]),
+              );
             },
           );
 
+          test('ignores invalid conclusions', () async {
+            final document = await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'abc123',
+              stage: CiStage.fusionTests,
+              tasks: ['Bar bar'],
+              checkRunGuard: '{}',
+            );
+
+            firestore.failOnWriteDocument(document);
+
+            expect(
+              await scheduler.processCheckRunCompleted(
+                PresubmitCompletedJob(
+                  name: 'Bar bar',
+                  sha: 'abc123',
+                  slug: createGithubRepository().slug(),
+                  status: TaskStatus.succeeded,
+                  isMergeGroup: false,
+                  checkRunId: 1,
+                  checkSuiteId: 668083231,
+                  headBranch: 'master',
+                  isUnifiedCheckRun: false,
+                ),
+              ),
+              isFalse,
+            );
+
+            expect(
+              firestore,
+              existsInStorage(CiStaging.metadata, [
+                isCiStaging.hasCheckRuns({'Bar bar': TaskConclusion.scheduled}),
+              ]),
+            );
+
+            verifyNever(
+              mockGithubChecksUtil.updateCheckRun(
+                any,
+                any,
+                any,
+                status: anyNamed('status'),
+                conclusion: anyNamed('conclusion'),
+                output: anyNamed('output'),
+              ),
+            );
+          });
+
+          test('does not complete with remaining tests', () async {
+            await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'abc123',
+              stage: CiStage.fusionEngineBuild,
+              tasks: ['Foo foo', 'Bar bar'],
+              checkRunGuard: '{}',
+            );
+
+            expect(
+              await scheduler.processCheckRunCompleted(
+                PresubmitCompletedJob(
+                  name: 'Bar bar',
+                  sha: 'abc123',
+                  slug: createGithubRepository().slug(),
+                  status: TaskStatus.succeeded,
+                  isMergeGroup: false,
+                  checkRunId: 1,
+                  checkSuiteId: 668083231,
+                  headBranch: 'master',
+                  isUnifiedCheckRun: false,
+                ),
+              ),
+              isFalse,
+            );
+
+            expect(
+              firestore,
+              existsInStorage(CiStaging.metadata, [
+                isCiStaging.hasCheckRuns({
+                  'Foo foo': TaskConclusion.scheduled,
+                  'Bar bar': TaskConclusion.success,
+                }),
+              ]),
+            );
+
+            verifyNever(
+              mockGithubChecksUtil.updateCheckRun(
+                any,
+                any,
+                any,
+                status: anyNamed('status'),
+                conclusion: anyNamed('conclusion'),
+                output: anyNamed('output'),
+              ),
+            );
+          });
+
+          // The merge guard is not closed until both engine build and tests
+          // complete and are successful.
+          // This behavior is explained here:
+          // https://github.com/flutter/flutter/issues/159898#issuecomment-2597209435
+          test(
+            'failed tests neither unlock merge queue guard nor schedule test stage',
+            () async {
+              await PrCheckRuns.initializeDocument(
+                firestoreService: firestore,
+                pullRequest: pullRequest,
+                checks: [createGithubCheckRun(name: 'Bar bar')],
+              );
+
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'abc123',
+                stage: CiStage.fusionEngineBuild,
+                tasks: ['Bar bar'],
+                checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+              );
+
+              expect(
+                await scheduler.processCheckRunCompleted(
+                  PresubmitCompletedJob(
+                    name: 'Bar bar',
+                    sha: 'abc123',
+                    slug: createGithubRepository().slug(),
+                    status: TaskStatus.succeeded,
+                    isMergeGroup: false,
+                    checkRunId: 1,
+                    checkSuiteId: 668083231,
+                    headBranch: 'master',
+                    isUnifiedCheckRun: false,
+                  ),
+                ),
+                isTrue,
+              );
+
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging.hasCheckRuns({'Bar bar': TaskConclusion.success}),
+                ]),
+              );
+
+              verifyNever(
+                mockGithubChecksUtil.updateCheckRun(
+                  any,
+                  any,
+                  any,
+                  status: anyNamed('status'),
+                  conclusion: anyNamed('conclusion'),
+                  output: anyNamed('output'),
+                ),
+              );
+            },
+          );
+
+          test('schedules tests after engine stage', () async {
+            final githubService = config.githubService = MockGithubService();
+            final githubClient = MockGitHub();
+            when(githubService.github).thenReturn(githubClient);
+            when(
+              githubService.searchIssuesAndPRs(
+                any,
+                any,
+                sort: anyNamed('sort'),
+                pages: anyNamed('pages'),
+              ),
+            ).thenAnswer((_) async => [generateIssue(42)]);
+
+            final pullRequest = generatePullRequest();
+            when(
+              githubService.getPullRequest(any, any),
+            ).thenAnswer((_) async => pullRequest);
+            getFilesChanged.cannedFiles = ['abc/def'];
+            when(
+              mockGithubChecksUtil.listCheckSuitesForRef(
+                any,
+                any,
+                ref: anyNamed('ref'),
+              ),
+            ).thenAnswer(
+              (_) async => [
+                // From check_run.check_suite.id in [checkRunString].
+                generateCheckSuite(668083231),
+              ],
+            );
+
+            ciYamlFetcher.setCiYamlFrom(singleCiYaml, engine: fusionCiYaml);
+            final luci = MockLuciBuildService();
+            when(
+              luci.scheduleTryBuilds(
+                targets: anyNamed('targets'),
+                pullRequest: anyNamed('pullRequest'),
+                engineArtifacts: anyNamed('engineArtifacts'),
+                dashboardChecks: anyNamed('dashboardChecks'),
+                mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                stage: anyNamed('stage'),
+              ),
+            ).thenAnswer((inv) async {
+              return [];
+            });
+
+            final gitHubChecksService = MockGithubChecksService();
+            when(
+              gitHubChecksService.githubChecksUtil,
+            ).thenReturn(mockGithubChecksUtil);
+            when(
+              gitHubChecksService.findMatchingPullRequest(any, any, any),
+            ).thenAnswer((inv) async {
+              return pullRequest;
+            });
+
+            // Cocoon creates a Firestore document to track the tasks in the
+            // test stage.
+
+            scheduler = Scheduler(
+              githubService: config.githubService ?? FakeGithubService(),
+              cache: cache,
+              config: config,
+              getFilesChanged: getFilesChanged,
+              githubChecksService: gitHubChecksService,
+              ciYamlFetcher: ciYamlFetcher,
+              luciBuildService: luci,
+              contentAwareHash: fakeContentAwareHash,
+              firestore: firestore,
+              bigQuery: bigQuery,
+            );
+
+            await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'testSha',
+              stage: CiStage.fusionEngineBuild,
+              tasks: ['Bar bar'],
+              checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+            );
+
+            expect(
+              await scheduler.processCheckRunCompleted(
+                PresubmitCompletedJob(
+                  name: 'Bar bar',
+                  sha: 'testSha',
+                  slug: createGithubRepository().slug(),
+                  status: TaskStatus.succeeded,
+                  isMergeGroup: false,
+                  checkRunId: 1,
+                  checkSuiteId: 668083231,
+                  headBranch: 'master',
+                  isUnifiedCheckRun: false,
+                ),
+              ),
+              isTrue,
+            );
+
+            verify(
+              gitHubChecksService.findMatchingPullRequest(
+                Config.flutterSlug,
+                'testSha',
+                668083231,
+              ),
+            ).called(1);
+
+            expect(
+              firestore,
+              existsInStorage(CiStaging.metadata, [
+                isCiStaging.hasStage(CiStage.fusionEngineBuild).hasCheckRuns({
+                  'Bar bar': TaskConclusion.success,
+                }),
+                isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+                  'Linux A': TaskConclusion.scheduled,
+                  'Linux Z': TaskConclusion.scheduled,
+                  'Linux engine_presubmit': TaskConclusion.scheduled,
+                }),
+              ]),
+            );
+
+            verifyNever(
+              mockGithubChecksUtil.updateCheckRun(
+                any,
+                any,
+                any,
+                status: anyNamed('status'),
+                conclusion: anyNamed('conclusion'),
+                output: anyNamed('output'),
+              ),
+            );
+
+            final result = verify(
+              luci.scheduleTryBuilds(
+                targets: captureAnyNamed('targets'),
+                pullRequest: captureAnyNamed('pullRequest'),
+                engineArtifacts: anyNamed('engineArtifacts'),
+                dashboardChecks: anyNamed('dashboardChecks'),
+                mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                stage: anyNamed('stage'),
+              ),
+            );
+            expect(result.callCount, 1);
+            final captured = result.captured;
+            expect(captured[0], hasLength(3));
+            // see the blend of fusionCiYaml and singleCiYaml
+            expect(captured[0][0].name, 'Linux A');
+            expect(captured[0][1].name, 'Linux Z');
+            expect(captured[0][2].name, 'Linux engine_presubmit');
+            expect(captured[1], pullRequest);
+          });
+
+          test(
+            'processCheckRunCompleted not failed when check suite id is 0',
+            () async {
+              final githubService = config.githubService = MockGithubService();
+              final githubClient = MockGitHub();
+              when(githubService.github).thenReturn(githubClient);
+              when(
+                githubService.searchIssuesAndPRs(
+                  any,
+                  any,
+                  sort: anyNamed('sort'),
+                  pages: anyNamed('pages'),
+                ),
+              ).thenAnswer((_) async => [generateIssue(42)]);
+
+              final pullRequest = generatePullRequest();
+              when(
+                githubService.getPullRequest(any, any),
+              ).thenAnswer((_) async => pullRequest);
+              getFilesChanged.cannedFiles = ['abc/def'];
+              when(
+                mockGithubChecksUtil.listCheckSuitesForRef(
+                  any,
+                  any,
+                  ref: anyNamed('ref'),
+                ),
+              ).thenAnswer(
+                (_) async => [
+                  // From check_run.check_suite.id in [checkRunString].
+                  generateCheckSuite(668083231),
+                ],
+              );
+
+              ciYamlFetcher.setCiYamlFrom(singleCiYaml, engine: fusionCiYaml);
+              final luci = MockLuciBuildService();
+              when(
+                luci.scheduleTryBuilds(
+                  targets: anyNamed('targets'),
+                  pullRequest: anyNamed('pullRequest'),
+                  engineArtifacts: anyNamed('engineArtifacts'),
+                  dashboardChecks: anyNamed('dashboardChecks'),
+                  mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                  stage: anyNamed('stage'),
+                ),
+              ).thenAnswer((inv) async {
+                return [];
+              });
+
+              final gitHubChecksService = MockGithubChecksService();
+              when(
+                gitHubChecksService.githubChecksUtil,
+              ).thenReturn(mockGithubChecksUtil);
+              when(
+                gitHubChecksService.findMatchingPullRequest(any, any, any),
+              ).thenAnswer((inv) async {
+                return pullRequest;
+              });
+
+              // Cocoon creates a Firestore document to track the tasks in the
+              // test stage.
+
+              scheduler = Scheduler(
+                githubService: config.githubService ?? FakeGithubService(),
+                cache: cache,
+                config: config,
+                getFilesChanged: getFilesChanged,
+                githubChecksService: gitHubChecksService,
+                ciYamlFetcher: ciYamlFetcher,
+                luciBuildService: luci,
+                contentAwareHash: fakeContentAwareHash,
+                firestore: firestore,
+                bigQuery: bigQuery,
+              );
+
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'testSha',
+                stage: CiStage.fusionEngineBuild,
+                tasks: ['Bar bar'],
+                checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+              );
+
+              expect(
+                await scheduler.processCheckRunCompleted(
+                  PresubmitCompletedJob(
+                    name: 'Bar bar',
+                    sha: 'testSha',
+                    slug: createGithubRepository().slug(),
+                    status: TaskStatus.succeeded,
+                    isMergeGroup: false,
+                    checkRunId: 1,
+                    checkSuiteId: 0,
+                    headBranch: 'master',
+                    isUnifiedCheckRun: false,
+                  ),
+                ),
+                isTrue,
+              );
+
+              verify(
+                gitHubChecksService.findMatchingPullRequest(
+                  Config.flutterSlug,
+                  'testSha',
+                  0,
+                ),
+              ).called(1);
+
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging.hasStage(CiStage.fusionEngineBuild).hasCheckRuns({
+                    'Bar bar': TaskConclusion.success,
+                  }),
+                  isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+                    'Linux A': TaskConclusion.scheduled,
+                    'Linux Z': TaskConclusion.scheduled,
+                    'Linux engine_presubmit': TaskConclusion.scheduled,
+                  }),
+                ]),
+              );
+
+              verifyNever(
+                mockGithubChecksUtil.updateCheckRun(
+                  any,
+                  any,
+                  any,
+                  status: anyNamed('status'),
+                  conclusion: anyNamed('conclusion'),
+                  output: anyNamed('output'),
+                ),
+              );
+
+              final result = verify(
+                luci.scheduleTryBuilds(
+                  targets: captureAnyNamed('targets'),
+                  pullRequest: captureAnyNamed('pullRequest'),
+                  engineArtifacts: anyNamed('engineArtifacts'),
+                  dashboardChecks: anyNamed('dashboardChecks'),
+                  mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                  stage: anyNamed('stage'),
+                ),
+              );
+              expect(result.callCount, 1);
+              final captured = result.captured;
+              expect(captured[0], hasLength(3));
+              // see the blend of fusionCiYaml and singleCiYaml
+              expect(captured[0][0].name, 'Linux A');
+              expect(captured[0][1].name, 'Linux Z');
+              expect(captured[0][2].name, 'Linux engine_presubmit');
+              expect(captured[1], pullRequest);
+            },
+          );
+
+          test('tracks test check runs in firestore', () async {
+            final githubService = config.githubService = MockGithubService();
+            final githubClient = MockGitHub();
+            final luci = MockLuciBuildService();
+            final gitHubChecksService = MockGithubChecksService();
+
+            when(githubService.github).thenReturn(githubClient);
+            when(
+              gitHubChecksService.githubChecksUtil,
+            ).thenReturn(mockGithubChecksUtil);
+
+            scheduler = Scheduler(
+              githubService: config.githubService ?? FakeGithubService(),
+              cache: cache,
+              config: config,
+              getFilesChanged: getFilesChanged,
+              githubChecksService: gitHubChecksService,
+              ciYamlFetcher: ciYamlFetcher,
+              luciBuildService: luci,
+              contentAwareHash: fakeContentAwareHash,
+              firestore: firestore,
+              bigQuery: bigQuery,
+            );
+
+            await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'testSha',
+              stage: CiStage.fusionEngineBuild,
+              tasks: [],
+              checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+            );
+
+            await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'testSha',
+              stage: CiStage.fusionTests,
+              tasks: ['Bar bar'],
+              checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+            );
+
+            expect(
+              await scheduler.processCheckRunCompleted(
+                PresubmitCompletedJob(
+                  name: 'Bar bar',
+                  sha: 'testSha',
+                  slug: createGithubRepository().slug(),
+                  status: TaskStatus.succeeded,
+                  isMergeGroup: false,
+                  checkRunId: 1,
+                  checkSuiteId: 668083231,
+                  headBranch: 'master',
+                  isUnifiedCheckRun: false,
+                ),
+              ),
+              isTrue,
+            );
+
+            // The first invocation looks in the fusionEngineBuild stage, which
+            // returns "missing" result.
+            expect(
+              firestore,
+              existsInStorage(CiStaging.metadata, [
+                isCiStaging
+                    .hasStage(CiStage.fusionEngineBuild)
+                    .hasCheckRuns(isEmpty),
+                isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+                  'Bar bar': TaskConclusion.success,
+                }),
+              ]),
+            );
+
+            // Because tests completed, and completed successfully, the guard is
+            // unlocked, allowing the PR to land.
+            verify(
+              mockGithubChecksUtil.updateCheckRun(
+                any,
+                argThat(equals(RepositorySlug('flutter', 'flutter'))),
+                argThat(
+                  predicate<CheckRun>((arg) {
+                    expect(arg.name, 'GUARD TEST');
+                    return true;
+                  }),
+                ),
+                status: argThat(
+                  equals(CheckRunStatus.completed),
+                  named: 'status',
+                ),
+                conclusion: argThat(
+                  equals(CheckRunConclusion.success),
+                  named: 'conclusion',
+                ),
+                output: anyNamed('output'),
+              ),
+            ).called(1);
+          });
+
           test(
             'writes failure comment if moving to next phase fails',
             () async {
@@ -1816,6 +2388,421 @@
             );
           });
 
+          test(
+            'does not fail the merge queue guard when a test check run fails (presubmit)',
+            () async {
+              final githubService = config.githubService = MockGithubService();
+              final githubClient = MockGitHub();
+              final luci = MockLuciBuildService();
+              final gitHubChecksService = MockGithubChecksService();
+
+              when(githubService.github).thenReturn(githubClient);
+              when(
+                gitHubChecksService.githubChecksUtil,
+              ).thenReturn(mockGithubChecksUtil);
+
+              scheduler = Scheduler(
+                githubService: config.githubService ?? FakeGithubService(),
+                cache: cache,
+                config: config,
+                getFilesChanged: getFilesChanged,
+                githubChecksService: gitHubChecksService,
+                ciYamlFetcher: ciYamlFetcher,
+                luciBuildService: luci,
+                contentAwareHash: fakeContentAwareHash,
+                firestore: firestore,
+                bigQuery: bigQuery,
+              );
+
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'testSha',
+                stage: CiStage.fusionEngineBuild,
+                tasks: [],
+                checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+              );
+
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'testSha',
+                stage: CiStage.fusionTests,
+                tasks: ['Bar bar'],
+                checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+              );
+
+              expect(
+                await scheduler.processCheckRunCompleted(
+                  PresubmitCompletedJob(
+                    name: 'Bar bar',
+                    sha: 'testSha',
+                    slug: createGithubRepository().slug(),
+                    status: TaskStatus.failed,
+                    isMergeGroup: false,
+                    checkRunId: 1,
+                    checkSuiteId: 668083231,
+                    headBranch: 'master',
+                    isUnifiedCheckRun: false,
+                  ),
+                ),
+                isTrue,
+              );
+
+              // The first invocation looks in the fusionEngineBuild stage, which
+              // returns "missing" result.
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging
+                      .hasStage(CiStage.fusionEngineBuild)
+                      .hasCheckRuns(isEmpty),
+                  isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+                    'Bar bar': TaskConclusion.failure,
+                  }),
+                ]),
+              );
+
+              // The test stage completed, but with failures. The merge queue
+              // guard should stay open to prevent the pull request from landing.
+              verifyNever(
+                mockGithubChecksUtil.updateCheckRun(
+                  any,
+                  any,
+                  any,
+                  status: anyNamed('status'),
+                  conclusion: anyNamed('conclusion'),
+                  output: anyNamed('output'),
+                ),
+              );
+            },
+          );
+
+          test(
+            'fails the merge queue guard when a test check run fails (merge group)',
+            () async {
+              final githubService = config.githubService = MockGithubService();
+              final githubClient = MockGitHub();
+              final luci = MockLuciBuildService();
+              final gitHubChecksService = MockGithubChecksService();
+
+              when(githubService.github).thenReturn(githubClient);
+              when(
+                gitHubChecksService.githubChecksUtil,
+              ).thenReturn(mockGithubChecksUtil);
+
+              scheduler = Scheduler(
+                githubService: config.githubService ?? FakeGithubService(),
+                cache: cache,
+                config: config,
+                getFilesChanged: getFilesChanged,
+                githubChecksService: gitHubChecksService,
+                ciYamlFetcher: ciYamlFetcher,
+                luciBuildService: luci,
+                contentAwareHash: fakeContentAwareHash,
+                firestore: firestore,
+                bigQuery: bigQuery,
+              );
+
+              const headBranch =
+                  'gh-readonly-queue/master/pr-15-c9affbbb12aa40cb3afbe94b9ea6b119a256bebf';
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'testSha',
+                stage: CiStage.fusionEngineBuild,
+                tasks: ['Bar bar'],
+                checkRunGuard: checkRunFor(
+                  name: 'GUARD TEST',
+                  headBranch: headBranch,
+                ),
+              );
+
+              expect(
+                await scheduler.processCheckRunCompleted(
+                  PresubmitCompletedJob(
+                    name: 'Bar bar',
+                    sha: 'testSha',
+                    slug: createGithubRepository().slug(),
+                    status: TaskStatus.failed,
+                    isMergeGroup: true,
+                    checkRunId: 1,
+                    checkSuiteId: 668083231,
+                    headBranch: headBranch,
+                    isUnifiedCheckRun: false,
+                  ),
+                ),
+                isTrue,
+              );
+
+              // The first invocation looks in the fusionEngineBuild stage, which
+              // returns "missing" result.
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging.hasStage(CiStage.fusionEngineBuild).hasCheckRuns({
+                    'Bar bar': TaskConclusion.failure,
+                  }),
+                ]),
+              );
+
+              // The test stage completed, but with failures. The merge queue
+              // guard should stay open to prevent the pull request from landing.
+              verify(
+                mockGithubChecksUtil.updateCheckRun(
+                  any,
+                  any,
+                  any,
+                  status: anyNamed('status'),
+                  conclusion: CheckRunConclusion.failure,
+                  output: anyNamed('output'),
+                ),
+              ).called(1);
+
+              expect(fakeContentAwareHash.completedShas, [
+                (commitSha: 'testSha', successful: false),
+              ]);
+            },
+          );
+
+          test('closes merge queue guard in merge group success', () async {
+            final githubService = config.githubService = MockGithubService();
+            final githubClient = MockGitHub();
+            final luci = MockLuciBuildService();
+            final gitHubChecksService = MockGithubChecksService();
+
+            when(githubService.github).thenReturn(githubClient);
+            when(
+              gitHubChecksService.githubChecksUtil,
+            ).thenReturn(mockGithubChecksUtil);
+
+            scheduler = Scheduler(
+              githubService: config.githubService ?? FakeGithubService(),
+              cache: cache,
+              config: config,
+              getFilesChanged: getFilesChanged,
+              githubChecksService: gitHubChecksService,
+              ciYamlFetcher: ciYamlFetcher,
+              luciBuildService: luci,
+              contentAwareHash: fakeContentAwareHash,
+              firestore: firestore,
+              bigQuery: bigQuery,
+            );
+
+            const headBranch =
+                'gh-readonly-queue/master/pr-15-c9affbbb12aa40cb3afbe94b9ea6b119a256bebf';
+            await CiStaging.initializeDocument(
+              firestoreService: firestore,
+              slug: Config.flutterSlug,
+              sha: 'testSha',
+              stage: CiStage.fusionEngineBuild,
+              tasks: ['Bar bar'],
+              checkRunGuard: checkRunFor(
+                name: 'GUARD TEST',
+                headBranch: headBranch,
+              ),
+            );
+
+            expect(
+              await scheduler.processCheckRunCompleted(
+                PresubmitCompletedJob(
+                  name: 'Bar bar',
+                  sha: 'testSha',
+                  slug: createGithubRepository().slug(),
+                  status: TaskStatus.succeeded,
+                  isMergeGroup: true,
+                  checkRunId: 1,
+                  checkSuiteId: 668083231,
+                  headBranch: headBranch,
+                  isUnifiedCheckRun: false,
+                ),
+              ),
+              isTrue,
+            );
+
+            // The first invocation looks in the fusionEngineBuild stage, which
+            // returns "missing" result.
+            expect(
+              firestore,
+              existsInStorage(CiStaging.metadata, [
+                isCiStaging.hasStage(CiStage.fusionEngineBuild).hasCheckRuns({
+                  'Bar bar': TaskConclusion.success,
+                }),
+              ]),
+            );
+
+            // The test stage completed, but with failures. The merge queue
+            // guard should stay open to prevent the pull request from landing.
+            verify(
+              mockGithubChecksUtil.updateCheckRun(
+                any,
+                any,
+                any,
+                status: anyNamed('status'),
+                conclusion: CheckRunConclusion.success,
+                output: anyNamed('output'),
+              ),
+            ).called(1);
+
+            expect(fakeContentAwareHash.completedShas, [
+              (commitSha: 'testSha', successful: true),
+            ]);
+          });
+
+          test(
+            'schedules tests after engine stage - with pr caching',
+            () async {
+              final githubService = config.githubService = MockGithubService();
+              final githubClient = MockGitHub();
+              when(githubService.github).thenReturn(githubClient);
+              when(
+                githubService.searchIssuesAndPRs(
+                  any,
+                  any,
+                  sort: anyNamed('sort'),
+                  pages: anyNamed('pages'),
+                ),
+              ).thenAnswer((_) async => [generateIssue(42)]);
+
+              final pullRequest = generatePullRequest();
+              when(
+                githubService.getPullRequest(any, any),
+              ).thenAnswer((_) async => pullRequest);
+              getFilesChanged.cannedFiles = ['abc/def'];
+              when(
+                mockGithubChecksUtil.listCheckSuitesForRef(
+                  any,
+                  any,
+                  ref: anyNamed('ref'),
+                ),
+              ).thenAnswer(
+                (_) async => [
+                  // From check_run.check_suite.id in [checkRunString].
+                  generateCheckSuite(668083231),
+                ],
+              );
+
+              await PrCheckRuns.initializeDocument(
+                firestoreService: firestore,
+                checks: [generateCheckRun(1, name: 'Bar bar')],
+                pullRequest: pullRequest,
+              );
+
+              ciYamlFetcher.setCiYamlFrom(singleCiYaml, engine: fusionCiYaml);
+              final luci = MockLuciBuildService();
+              when(
+                luci.scheduleTryBuilds(
+                  targets: anyNamed('targets'),
+                  pullRequest: anyNamed('pullRequest'),
+                  engineArtifacts: anyNamed('engineArtifacts'),
+                  dashboardChecks: anyNamed('dashboardChecks'),
+                  mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                  stage: anyNamed('stage'),
+                ),
+              ).thenAnswer((inv) async {
+                return [];
+              });
+
+              final gitHubChecksService = MockGithubChecksService();
+              when(
+                gitHubChecksService.githubChecksUtil,
+              ).thenReturn(mockGithubChecksUtil);
+
+              scheduler = Scheduler(
+                githubService: config.githubService ?? FakeGithubService(),
+                cache: cache,
+                config: config,
+                githubChecksService: gitHubChecksService,
+                getFilesChanged: getFilesChanged,
+                ciYamlFetcher: ciYamlFetcher,
+                luciBuildService: luci,
+                contentAwareHash: fakeContentAwareHash,
+                firestore: firestore,
+                bigQuery: bigQuery,
+              );
+
+              await CiStaging.initializeDocument(
+                firestoreService: firestore,
+                slug: Config.flutterSlug,
+                sha: 'testSha',
+                stage: CiStage.fusionEngineBuild,
+                tasks: ['Bar bar'],
+                checkRunGuard: checkRunFor(name: 'GUARD TEST'),
+              );
+
+              expect(
+                await scheduler.processCheckRunCompleted(
+                  PresubmitCompletedJob(
+                    name: 'Bar bar',
+                    sha: 'testSha',
+                    slug: createGithubRepository().slug(),
+                    status: TaskStatus.succeeded,
+                    isMergeGroup: false,
+                    checkRunId: 1,
+                    checkSuiteId: 668083231,
+                    headBranch: 'master',
+                    isUnifiedCheckRun: false,
+                  ),
+                ),
+                isTrue,
+              );
+
+              verifyNever(
+                gitHubChecksService.findMatchingPullRequest(any, any, any),
+              );
+
+              expect(
+                firestore,
+                existsInStorage(CiStaging.metadata, [
+                  isCiStaging.hasStage(CiStage.fusionEngineBuild).hasCheckRuns({
+                    'Bar bar': TaskConclusion.success,
+                  }),
+                  isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+                    'Linux A': TaskConclusion.scheduled,
+                    'Linux Z': TaskConclusion.scheduled,
+                    'Linux engine_presubmit': TaskConclusion.scheduled,
+                  }),
+                ]),
+              );
+
+              verifyNever(
+                mockGithubChecksUtil.updateCheckRun(
+                  any,
+                  any,
+                  any,
+                  status: anyNamed('status'),
+                  conclusion: anyNamed('conclusion'),
+                  output: anyNamed('output'),
+                ),
+              );
+
+              final result = verify(
+                luci.scheduleTryBuilds(
+                  targets: captureAnyNamed('targets'),
+                  pullRequest: captureAnyNamed('pullRequest'),
+                  engineArtifacts: anyNamed('engineArtifacts'),
+                  dashboardChecks: anyNamed('dashboardChecks'),
+                  mergeQueueGuard: anyNamed('mergeQueueGuard'),
+                  stage: anyNamed('stage'),
+                ),
+              );
+              expect(result.callCount, 1);
+              final captured = result.captured;
+              expect(captured[0], hasLength(3));
+              // see the blend of fusionCiYaml and singleCiYaml
+              expect(captured[0][0].name, 'Linux A');
+              expect(captured[0][1].name, 'Linux Z');
+              expect(captured[0][2].name, 'Linux engine_presubmit');
+              expect(
+                captured[1],
+                isA<PullRequest>().having(
+                  (p) => p.number,
+                  'number',
+                  pullRequest.number,
+                ),
+              );
+            },
+          );
           // end of group
         });
       });
@@ -1909,7 +2896,6 @@
               any,
               captureAny,
               output: captureAnyNamed('output'),
-              detailsUrl: anyNamed('detailsUrl'),
             ),
           ).captured,
           <Object?>[
@@ -1929,6 +2915,9 @@
               summary:
                   'If this check is stuck pending, push an empty commit to retrigger the checks',
             ),
+            'Linux A',
+            null,
+            // Linux runIf is not run as this is for tip of tree and the files weren't affected
           ],
         );
       });
@@ -1937,7 +2926,9 @@
         'creates presubmit_guard document for flutter/packages when unified check run flow is enabled',
         () async {
           getFilesChanged.cannedFiles = ['README.md'];
-          config.dynamicConfig = DynamicConfig();
+          config.dynamicConfig = DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+          );
 
           when(
             mockGithubChecksUtil.createCheckRun(
@@ -1996,7 +2987,9 @@
         'unlocks merge group for cocoon when unified check run flow is enabled',
         () async {
           getFilesChanged.cannedFiles = ['README.md'];
-          config.dynamicConfig = DynamicConfig();
+          config.dynamicConfig = DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+          );
 
           when(
             mockGithubChecksUtil.createCheckRun(
@@ -2063,7 +3056,7 @@
           final lockResult = await scheduler.lockMergeGroupChecks(
             Config.flutterSlug,
             'sha123',
-            isPresubmit: true,
+            isUnifiedCheckRun: true,
           );
 
           expect(lockResult.dashboardChecks.name, Config.kDashboardCheckName);
@@ -2157,7 +3150,9 @@
           final fakeConfig = FakeConfig(
             githubService: mockGithubService,
             githubClient: MockGitHub(),
-            dynamicConfig: DynamicConfig(),
+            dynamicConfig: DynamicConfig(
+              unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+            ),
           );
           scheduler = Scheduler(
             githubService: fakeConfig.githubService ?? FakeGithubService(),
@@ -2192,7 +3187,6 @@
                 any,
                 captureAny,
                 output: captureAnyNamed('output'),
-                detailsUrl: anyNamed('detailsUrl'),
               ),
             ).captured,
             <Object?>[
@@ -2212,12 +3206,13 @@
                 summary:
                     'If this check is stuck pending, push an empty commit to retrigger the checks',
               ),
+              'Linux A',
+              null,
+              // runIf requires a diff in dev, so an error will cause it to be triggered
+              'Linux runIf',
+              null,
             ],
           );
-          final guards = await firestore.query(PresubmitGuard.collectionId, {});
-          expect(guards, isNotEmpty);
-          final guard = PresubmitGuard.fromDocument(guards.first);
-          expect(guard.jobs.keys, containsAll(['Linux A', 'Linux runIf']));
         },
       );
 
@@ -2238,7 +3233,6 @@
                 any,
                 captureAny,
                 output: captureAnyNamed('output'),
-                detailsUrl: anyNamed('detailsUrl'),
               ),
             ).captured,
             <Object?>[
@@ -2282,7 +3276,14 @@
               output: anyNamed('output'),
             ),
           ).captured,
-          <Object?>[CheckRunStatus.completed, CheckRunConclusion.success],
+          <Object?>[
+            CheckRunStatus.completed,
+            CheckRunConclusion.success,
+            CheckRunStatus.completed,
+            CheckRunConclusion.success,
+            CheckRunStatus.completed,
+            CheckRunConclusion.success,
+          ],
         );
       });
 
@@ -2314,6 +3315,11 @@
 
         expect(capturedUpdates, <(String, CheckRunStatus, CheckRunConclusion)>[
           (
+            Config.kDashboardCheckName,
+            CheckRunStatus.completed,
+            CheckRunConclusion.success,
+          ),
+          (
             'ci.yaml validation',
             CheckRunStatus.completed,
             CheckRunConclusion.failure,
@@ -2335,7 +3341,12 @@
               output: anyNamed('output'),
             ),
           ).captured,
-          <Object?>[CheckRunStatus.completed, CheckRunConclusion.failure],
+          <Object?>[
+            CheckRunStatus.completed,
+            CheckRunConclusion.success,
+            CheckRunStatus.completed,
+            CheckRunConclusion.failure,
+          ],
         );
       });
 
@@ -2433,7 +3444,6 @@
             any,
             any,
             output: anyNamed('output'),
-            detailsUrl: anyNamed('detailsUrl'),
           ),
         ).thenAnswer((inv) async {
           final slug = inv.positionalArguments[1] as RepositorySlug;
@@ -2457,7 +3467,9 @@
           githubService: mockGithubService,
           githubClient: MockGitHub(),
           maxFilesChangedForSkippingEnginePhaseValue: 0,
-          dynamicConfig: DynamicConfig(),
+          dynamicConfig: DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+          ),
         );
         scheduler = Scheduler(
           githubService: fakeConfig.githubService ?? FakeGithubService(),
@@ -2482,7 +3494,6 @@
             any,
             captureAny,
             output: captureAnyNamed('output'),
-            detailsUrl: anyNamed('detailsUrl'),
           ),
         ).captured;
         stdout.writeAll(results);
@@ -2508,7 +3519,7 @@
           mockGithubChecksUtil.updateCheckRun(
             any,
             Config.flutterSlug,
-            checkRuns[2],
+            checkRuns[1],
             status: argThat(equals(CheckRunStatus.completed), named: 'status'),
             conclusion: argThat(
               equals(CheckRunConclusion.success),
@@ -2528,16 +3539,6 @@
             output: anyNamed('output'),
           ),
         );
-        verifyNever(
-          mockGithubChecksUtil.updateCheckRun(
-            any,
-            Config.flutterSlug,
-            checkRuns[1],
-            status: anyNamed('status'),
-            conclusion: anyNamed('conclusion'),
-            output: anyNamed('output'),
-          ),
-        );
       });
     });
 
@@ -3125,7 +4126,9 @@
           githubService: mockGithubService,
           githubClient: MockGitHub(),
           maxFilesChangedForSkippingEnginePhaseValue: 29,
-          dynamicConfig: DynamicConfig(),
+          dynamicConfig: DynamicConfig(
+            unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: false),
+          ),
         );
         scheduler = Scheduler(
           githubService: fakeConfig.githubService ?? FakeGithubService(),
@@ -3207,18 +4210,18 @@
           'Linux analyze',
         ], reason: 'Should skip Linux engine_build');
 
-        final guards = await firestore.query(PresubmitGuard.collectionId, {});
-        final engineGuard = guards
-            .map(PresubmitGuard.fromDocument)
-            .firstWhere((g) => g.stage == CiStage.fusionEngineBuild);
-        expect(engineGuard.jobs, isEmpty);
-        final testsGuard = guards
-            .map(PresubmitGuard.fromDocument)
-            .firstWhere((g) => g.stage == CiStage.fusionTests);
-        expect(testsGuard.jobs, {
-          'Linux A': TaskStatus.waitingForBackfill,
-          'Linux analyze': TaskStatus.waitingForBackfill,
-        });
+        expect(
+          firestore,
+          existsInStorage(CiStaging.metadata, [
+            isCiStaging
+                .hasStage(CiStage.fusionEngineBuild)
+                .hasCheckRuns(isEmpty),
+            isCiStaging.hasStage(CiStage.fusionTests).hasCheckRuns({
+              'Linux A': TaskConclusion.scheduled,
+              'Linux analyze': TaskConclusion.scheduled,
+            }),
+          ]),
+        );
       });
 
       // Regression test for https://github.com/flutter/flutter/issues/167124.
@@ -3303,7 +4306,9 @@
 
         // Enable fusion
         ciYamlFetcher.setCiYamlFrom(singleCiYaml, engine: fusionCiYaml);
-        config.dynamicConfig = DynamicConfig();
+        config.dynamicConfig = DynamicConfig(
+          unifiedCheckRunFlow: UnifiedCheckRunFlow(useForAll: true),
+        );
 
         final userData = PresubmitUserData(
           commit: CommitRef(
diff --git a/cipd_packages/device_doctor/lib/src/health.dart b/cipd_packages/device_doctor/lib/src/health.dart
index 0ea948f..1b65880 100644
--- a/cipd_packages/device_doctor/lib/src/health.dart
+++ b/cipd_packages/device_doctor/lib/src/health.dart
@@ -17,7 +17,7 @@
 Future<HealthCheckResult> closeIosDialog({
   ProcessManager pm = const LocalProcessManager(),
   String? deviceId,
-  platform.Platform pl = const platform.Platform(),
+  platform.Platform pl = const platform.LocalPlatform(),
   String infraDialog = 'infra-dialog',
 }) async {
   var dialogDir = dir(path.dirname(Platform.script.path), 'tool', infraDialog);
@@ -36,16 +36,15 @@
     // By default the above command relies on automatic code signing, while on devicelab machines
     // it should utilize manual code signing as that is more stable. Below overwrites the code
     // signing config if one exists in the environment.
-    if (pl.nativePlatform!.environment['FLUTTER_XCODE_CODE_SIGN_STYLE'] !=
-        null) {
+    if (pl.environment['FLUTTER_XCODE_CODE_SIGN_STYLE'] != null) {
       command.add(
-        "CODE_SIGN_STYLE=${pl.nativePlatform!.environment['FLUTTER_XCODE_CODE_SIGN_STYLE']}",
+        "CODE_SIGN_STYLE=${pl.environment['FLUTTER_XCODE_CODE_SIGN_STYLE']}",
       );
       command.add(
-        "DEVELOPMENT_TEAM=${pl.nativePlatform!.environment['FLUTTER_XCODE_DEVELOPMENT_TEAM']}",
+        "DEVELOPMENT_TEAM=${pl.environment['FLUTTER_XCODE_DEVELOPMENT_TEAM']}",
       );
       command.add(
-        "PROVISIONING_PROFILE_SPECIFIER=${pl.nativePlatform!.environment['FLUTTER_XCODE_PROVISIONING_PROFILE_SPECIFIER']}",
+        "PROVISIONING_PROFILE_SPECIFIER=${pl.environment['FLUTTER_XCODE_PROVISIONING_PROFILE_SPECIFIER']}",
       );
     }
     final proc = await pm.start(command, workingDirectory: dialogDir.path);
diff --git a/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart b/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
index a888200..fff64d3 100644
--- a/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
+++ b/cipd_packages/device_doctor/lib/src/ios_debug_symbol_doctor.dart
@@ -64,7 +64,7 @@
     this.processManager = const LocalProcessManager(),
     Logger? loggerOverride,
     this.fs = const LocalFileSystem(),
-    this.platform = const Platform(),
+    this.platform = const LocalPlatform(),
   }) : logger = loggerOverride ?? Logger.root {
     argParser
       ..addOption(
@@ -197,7 +197,7 @@
   /// Xcode will regenerate this folder and symbols for connected devices
   /// when Xcode is opened.
   void _deleteSymbols() {
-    final home = platform.nativePlatform!.environment['HOME'];
+    final home = platform.environment['HOME'];
     if (home == null) {
       logger.warning('\$HOME path was not found');
       return;
diff --git a/cipd_packages/device_doctor/test/src/health_test.dart b/cipd_packages/device_doctor/test/src/health_test.dart
index 9495be2..50954ee 100644
--- a/cipd_packages/device_doctor/test/src/health_test.dart
+++ b/cipd_packages/device_doctor/test/src/health_test.dart
@@ -8,7 +8,6 @@
 import 'package:device_doctor/src/utils.dart';
 import 'package:mockito/mockito.dart';
 import 'package:platform/platform.dart' as platform;
-import 'package:platform/testing.dart';
 import 'package:test/test.dart';
 
 import 'utils.dart';
@@ -37,7 +36,7 @@
       when(
         pm.start(any, workingDirectory: anyNamed('workingDirectory')),
       ).thenAnswer((_) => Future.value(proc));
-      final platform.Platform pl = TestPlatform.native(
+      final platform.Platform pl = platform.FakePlatform(
         environment: <String, String>{
           'FLUTTER_XCODE_CODE_SIGN_STYLE': 'Manual',
           'FLUTTER_XCODE_DEVELOPMENT_TEAM': 'S8QB4VV633',
diff --git a/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart b/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
index 4387ec3..4c91f65 100644
--- a/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
+++ b/cipd_packages/device_doctor/test/src/ios_debug_symbol_doctor_test.dart
@@ -11,7 +11,7 @@
 import 'package:file/memory.dart';
 import 'package:logging/logging.dart';
 import 'package:mockito/mockito.dart';
-import 'package:platform/testing.dart';
+import 'package:platform/platform.dart';
 
 import 'package:test/test.dart';
 
@@ -102,9 +102,8 @@
       logger = TestLogger();
       fs = MemoryFileSystem();
       fs.directory(xcworkspacePath).createSync(recursive: true);
-      platform = TestPlatform.native(
-        environment: <String, String>{'HOME': '/User/username'},
-      );
+      platform = MockPlatform();
+      platform.environment['HOME'] = '/User/username';
     });
 
     test('diagnose logs output of xcdevice list', () async {
diff --git a/cipd_packages/device_doctor/test/src/utils.dart b/cipd_packages/device_doctor/test/src/utils.dart
index 4d15aeb..d308810 100644
--- a/cipd_packages/device_doctor/test/src/utils.dart
+++ b/cipd_packages/device_doctor/test/src/utils.dart
@@ -8,8 +8,14 @@
 
 import 'package:logging/logging.dart';
 import 'package:mockito/mockito.dart';
+import 'package:platform/platform.dart';
 import 'package:process/process.dart';
 
+class MockPlatform extends Mock implements Platform {
+  @override
+  Map<String, String> environment = <String, String>{};
+}
+
 class MockProcessManager extends Mock implements ProcessManager {
   @override
   Future<Process> start(
diff --git a/packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart b/packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart
index fc81f5a..9b6601b 100644
--- a/packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart
+++ b/packages/cocoon_integration_test/lib/src/fakes/fake_firestore_service.dart
@@ -469,11 +469,8 @@
           'simulate a backend failure.',
         );
       }
-      final statusCode = result.any((r) => r.code == 9)
-          ? HttpStatus.conflict
-          : 500;
       throw DetailedApiRequestError(
-        statusCode,
+        500,
         'The transaction was aborted:\n'
         '${result.where((r) => r.code != 0).map((r) => r.message).join('\n')}',
       );
diff --git a/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart b/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart
index 85ff525..8d4568a 100644
--- a/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart
+++ b/packages/cocoon_integration_test/lib/src/utilities/mocks.mocks.dart
@@ -5731,13 +5731,13 @@
     _i7.RepositorySlug? slug,
     String? headSha, {
     String? detailsUrl,
-    required bool? isPresubmit,
+    required bool? isUnifiedCheckRun,
   }) =>
       (super.noSuchMethod(
             Invocation.method(
               #lockMergeGroupChecks,
               [slug, headSha],
-              {#detailsUrl: detailsUrl, #isUnifiedCheckRun: isPresubmit},
+              {#detailsUrl: detailsUrl, #isUnifiedCheckRun: isUnifiedCheckRun},
             ),
             returnValue: _i13.Future<_i16.CheckRunLockResult>.value(
               _FakeCheckRunLockResult_58(
@@ -5745,7 +5745,10 @@
                 Invocation.method(
                   #lockMergeGroupChecks,
                   [slug, headSha],
-                  {#detailsUrl: detailsUrl, #isUnifiedCheckRun: isPresubmit},
+                  {
+                    #detailsUrl: detailsUrl,
+                    #isUnifiedCheckRun: isUnifiedCheckRun,
+                  },
                 ),
               ),
             ),
@@ -5782,7 +5785,7 @@
           as _i13.Future<void>);
 
   @override
-  _i13.Future<void> unlockCheckRun(
+  _i13.Future<void> unlockMergeQueueGuard(
     _i7.RepositorySlug? slug,
     String? headSha,
     _i7.CheckRun? lock,
diff --git a/packages/cocoon_integration_test/test/fake_firestore_service_test.dart b/packages/cocoon_integration_test/test/fake_firestore_service_test.dart
index 043f3d2..e0d149e 100644
--- a/packages/cocoon_integration_test/test/fake_firestore_service_test.dart
+++ b/packages/cocoon_integration_test/test/fake_firestore_service_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io';
-
 import 'package:cocoon_integration_test/testing.dart';
 import 'package:cocoon_server_test/test_logging.dart';
 import 'package:cocoon_service/src/service/firestore.dart';
@@ -526,7 +524,7 @@
           isA<g.DetailedApiRequestError>().having(
             (e) => e.status,
             'status',
-            HttpStatus.conflict,
+            500,
           ),
         ),
       );