context) ? $run->context : []; $storedTranslation = $this->storedOperationRunTranslation($context); if ($storedTranslation !== null) { $storedEnvelope = ReasonResolutionEnvelope::fromArray($storedTranslation); if ($storedEnvelope instanceof ReasonResolutionEnvelope) { $nextSteps = $this->operationRunNextSteps($context); if ($storedEnvelope->nextSteps === [] && $nextSteps !== []) { return $storedEnvelope->withNextSteps($nextSteps); } return $storedEnvelope; } } $contextReasonCode = data_get($context, 'execution_legitimacy.reason_code') ?? data_get($context, 'reason_code') ?? data_get($context, 'baseline_compare.reason_code'); if (is_string($contextReasonCode) && trim($contextReasonCode) !== '') { return $this->translateOperationRunReason(trim($contextReasonCode), $surface, $context); } $failureReasonCode = data_get($run->failure_summary, '0.reason_code'); if (! is_string($failureReasonCode) || trim($failureReasonCode) === '') { return null; } $failureReasonCode = trim($failureReasonCode); if (! $this->isDirectlyTranslatableOperationReason($failureReasonCode)) { return null; } $envelope = $this->translateOperationRunReason($failureReasonCode, $surface, $context); if (! $envelope instanceof ReasonResolutionEnvelope) { return null; } if ($envelope->nextSteps !== []) { return $envelope; } $legacyNextSteps = $this->operationRunNextSteps($context); return $legacyNextSteps !== [] ? $envelope->withNextSteps($legacyNextSteps) : $envelope; } /** * @param array $context * @return array|null */ private function storedOperationRunTranslation(array $context): ?array { $storedTranslation = $context['reason_translation'] ?? data_get($context, 'baseline_compare.reason_translation'); return is_array($storedTranslation) ? $storedTranslation : null; } /** * @param array $context * @return array */ private function operationRunNextSteps(array $context): array { $nextSteps = $context['next_steps'] ?? data_get($context, 'baseline_compare.next_steps'); return is_array($nextSteps) ? NextStepOption::collect($nextSteps) : []; } /** * @param array $context */ private function translateOperationRunReason( string $reasonCode, string $surface, array $context, ): ?ReasonResolutionEnvelope { return $this->reasonTranslator->translate($reasonCode, surface: $surface, context: $context); } private function isDirectlyTranslatableOperationReason(string $reasonCode): bool { if ($reasonCode === ProviderReasonCodes::UnknownError) { return false; } return ProviderReasonCodes::isKnown($reasonCode) || ExecutionDenialReasonCode::tryFrom($reasonCode) instanceof ExecutionDenialReasonCode || LifecycleReconciliationReason::tryFrom($reasonCode) instanceof LifecycleReconciliationReason || TenantOperabilityReasonCode::tryFrom($reasonCode) instanceof TenantOperabilityReasonCode || RbacReason::tryFrom($reasonCode) instanceof RbacReason; } public function forProviderReason( Tenant $tenant, string $reasonCode, ?ProviderConnection $connection = null, string $surface = 'detail', ): ?ReasonResolutionEnvelope { return $this->reasonTranslator->translate( reasonCode: $reasonCode, artifactKey: ProviderReasonTranslator::ARTIFACT_KEY, surface: $surface, context: [ 'tenant' => $tenant, 'connection' => $connection, ], ); } public function forTenantOperabilityReason( TenantOperabilityReasonCode|string|null $reasonCode, string $surface = 'detail', ): ?ReasonResolutionEnvelope { $normalizedCode = $reasonCode instanceof TenantOperabilityReasonCode ? $reasonCode->value : $reasonCode; return $this->reasonTranslator->translate( reasonCode: $normalizedCode, artifactKey: ReasonTranslator::TENANT_OPERABILITY_ARTIFACT, surface: $surface, ); } public function forRbacReason(RbacReason|string|null $reasonCode, string $surface = 'detail'): ?ReasonResolutionEnvelope { $normalizedCode = $reasonCode instanceof RbacReason ? $reasonCode->value : $reasonCode; return $this->reasonTranslator->translate( reasonCode: $normalizedCode, artifactKey: ReasonTranslator::RBAC_ARTIFACT, surface: $surface, ); } /** * @param array $context */ public function forArtifactTruth( ?string $reasonCode, string $surface = 'detail', array $context = [], ): ?ReasonResolutionEnvelope { return $this->reasonTranslator->translate( reasonCode: $reasonCode, artifactKey: self::GOVERNANCE_ARTIFACT_TRUTH_ARTIFACT, surface: $surface, context: $context, ); } public function diagnosticCode(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->diagnosticCode(); } public function primaryLabel(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->operatorLabel; } public function shortExplanation(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->shortExplanation; } public function dominantCauseLabel(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->operatorLabel; } public function dominantCauseExplanation(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->shortExplanation; } public function trustImpact(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->trustImpact; } public function absencePattern(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->absencePattern; } public function guidance(?ReasonResolutionEnvelope $envelope): ?string { return $envelope?->guidanceText(); } /** * @return array */ public function bodyLines(?ReasonResolutionEnvelope $envelope, bool $includeGuidance = true): array { return $envelope?->toBodyLines($includeGuidance) ?? []; } }