> $subjectOutcomes * @param list $uncoveredTypes * @return array{ * run_outcome: string, * operation_outcome: string, * counts: array> * } */ public function summarize( array $subjectOutcomes, int $driftFindingsCount, bool $warningsRecorded, bool $resumeTokenPresent = false, array $uncoveredTypes = [], ): array { $counts = [ 'by_reason' => [], 'by_category' => [], 'by_actionability' => [], 'by_readiness_impact' => [], ]; $verifiedSubjectCount = 0; $blockingSubjectCount = 0; $failedSubjectCount = 0; foreach ($subjectOutcomes as $outcome) { $outcome = $outcome instanceof CompareSubjectOutcome ? $outcome->toArray() : $outcome; if (! is_array($outcome)) { continue; } $reason = $this->nonEmptyString($outcome['reason'] ?? null); $category = $this->nonEmptyString($outcome['category'] ?? null); $actionability = $this->nonEmptyString($outcome['actionability'] ?? null); $readinessImpact = $this->nonEmptyString($outcome['readiness_impact'] ?? null); $this->increment($counts['by_reason'], $reason); $this->increment($counts['by_category'], $category); $this->increment($counts['by_actionability'], $actionability); $this->increment($counts['by_readiness_impact'], $readinessImpact); if (in_array($category, [CompareResultCategory::Verified->value, CompareResultCategory::DriftDetected->value], true)) { $verifiedSubjectCount++; } if (in_array($readinessImpact, [CompareResultReadinessImpact::CustomerBlocker->value, CompareResultReadinessImpact::InternalBlocker->value], true)) { $blockingSubjectCount++; } if ($category === CompareResultCategory::Failed->value) { $failedSubjectCount++; } } foreach ($counts as &$bucket) { ksort($bucket); } unset($bucket); $hasWarnings = $warningsRecorded || $resumeTokenPresent || $uncoveredTypes !== []; $runOutcome = $this->runOutcome( driftFindingsCount: $driftFindingsCount, verifiedSubjectCount: $verifiedSubjectCount, blockingSubjectCount: $blockingSubjectCount, failedSubjectCount: $failedSubjectCount, hasWarnings: $hasWarnings, ); return [ 'run_outcome' => $runOutcome->value, 'operation_outcome' => in_array($runOutcome, [CompareRunOutcome::Completed, CompareRunOutcome::CompletedWithDrift], true) ? OperationRunOutcome::Succeeded->value : OperationRunOutcome::PartiallySucceeded->value, 'counts' => $counts, ]; } private function runOutcome( int $driftFindingsCount, int $verifiedSubjectCount, int $blockingSubjectCount, int $failedSubjectCount, bool $hasWarnings, ): CompareRunOutcome { if ($failedSubjectCount > 0 && $verifiedSubjectCount === 0 && $driftFindingsCount === 0) { return CompareRunOutcome::Failed; } if ($blockingSubjectCount > 0 && $verifiedSubjectCount === 0 && $driftFindingsCount === 0) { return CompareRunOutcome::Blocked; } if ($hasWarnings || $blockingSubjectCount > 0 || $failedSubjectCount > 0) { return CompareRunOutcome::Partial; } return $driftFindingsCount > 0 ? CompareRunOutcome::CompletedWithDrift : CompareRunOutcome::Completed; } /** * @param array $counts */ private function increment(array &$counts, ?string $key): void { if ($key === null) { return; } $counts[$key] = ($counts[$key] ?? 0) + 1; } private function nonEmptyString(mixed $value): ?string { if (! is_string($value) || trim($value) === '') { return null; } return trim($value); } }