'Run never started', self::StaleRunning => 'Run stopped reporting progress', self::InfrastructureTimeoutOrAbandonment => 'Infrastructure ended the run', self::QueueFailureBridge => 'Queue failure was reconciled', self::AdapterOutOfSync => 'Lifecycle was reconciled from related records', }; } public function shortExplanation(): string { return match ($this) { self::StaleQueued => 'The run stayed queued past its lifecycle window and was marked failed.', self::StaleRunning => 'The run stayed active past its lifecycle window and was marked failed.', self::InfrastructureTimeoutOrAbandonment => 'Queue infrastructure ended the job before normal completion could update the run.', self::QueueFailureBridge => 'The platform bridged a queue failure back to the owning run and marked it failed.', self::AdapterOutOfSync => 'A related restore record reached terminal truth before the operation run was updated.', }; } public function actionability(): string { return match ($this) { self::AdapterOutOfSync => 'non_actionable', default => 'retryable_transient', }; } /** * @return array */ public function nextSteps(): array { return match ($this) { self::AdapterOutOfSync => [ NextStepOption::instruction('Review the related restore record before deciding whether to run the workflow again.'), ], default => [ NextStepOption::instruction('Review worker health and logs before retrying this operation.'), ], }; } public function defaultMessage(): string { return $this->shortExplanation(); } /** * @param array $context */ public function toReasonResolutionEnvelope(string $surface = 'detail', array $context = []): ReasonResolutionEnvelope { return new ReasonResolutionEnvelope( internalCode: $this->value, operatorLabel: $this->operatorLabel(), shortExplanation: $this->shortExplanation(), actionability: $this->actionability(), nextSteps: $this->nextSteps(), showNoActionNeeded: false, diagnosticCodeLabel: $this->value, ); } }