$nextSteps */ public function __construct( public ?string $reasonCode, public ?string $translationArtifact, public ?string $operatorLabel, public ?string $shortExplanation, public ?string $diagnosticCode, public string $trustImpact, public ?string $absencePattern, public array $nextSteps = [], public ?string $ownerLayer = null, public ?string $ownerNamespace = null, public ?string $platformReasonFamily = null, ) {} public static function fromReasonResolutionEnvelope( ?ReasonResolutionEnvelope $reason, ?string $translationArtifact = null, ): ?self { if (! $reason instanceof ReasonResolutionEnvelope) { return null; } return new self( reasonCode: $reason->internalCode, translationArtifact: $translationArtifact, operatorLabel: $reason->operatorLabel, shortExplanation: $reason->shortExplanation, diagnosticCode: $reason->diagnosticCode(), trustImpact: $reason->trustImpact, absencePattern: $reason->absencePattern, nextSteps: array_values(array_map( static fn (NextStepOption $nextStep): string => $nextStep->label, $reason->nextSteps, )), ownerLayer: $reason->ownerLayer(), ownerNamespace: $reason->ownerNamespace(), platformReasonFamily: $reason->platformReasonFamily(), ); } public function toReasonResolutionEnvelope(): ReasonResolutionEnvelope { $reasonOwnership = null; $family = is_string($this->platformReasonFamily) ? PlatformReasonFamily::tryFrom($this->platformReasonFamily) : null; if (is_string($this->ownerLayer) && trim($this->ownerLayer) !== '' && is_string($this->ownerNamespace) && trim($this->ownerNamespace) !== '' && $family instanceof PlatformReasonFamily) { $reasonOwnership = new ReasonOwnershipDescriptor( ownerLayer: trim($this->ownerLayer), ownerNamespace: trim($this->ownerNamespace), reasonCode: $this->reasonCode ?? 'artifact_truth_reason', platformReasonFamily: $family, ); } return new ReasonResolutionEnvelope( internalCode: $this->reasonCode ?? 'artifact_truth_reason', operatorLabel: $this->operatorLabel ?? 'Operator attention required', shortExplanation: $this->shortExplanation ?? 'Technical diagnostics are available for this result.', actionability: $this->absencePattern === 'true_no_result' ? 'non_actionable' : 'prerequisite_missing', nextSteps: array_map( static fn (string $label): NextStepOption => NextStepOption::instruction($label), $this->nextSteps, ), diagnosticCodeLabel: $this->diagnosticCode, trustImpact: $this->trustImpact !== '' ? $this->trustImpact : TrustworthinessLevel::LimitedConfidence->value, absencePattern: $this->absencePattern, reasonOwnership: $reasonOwnership, ); } /** * @return array{ * reasonCode: ?string, * translationArtifact: ?string, * operatorLabel: ?string, * shortExplanation: ?string, * diagnosticCode: ?string, * trustImpact: string, * absencePattern: ?string, * nextSteps: array, * ownerLayer: ?string, * ownerNamespace: ?string, * platformReasonFamily: ?string * } */ public function toArray(): array { return [ 'reasonCode' => $this->reasonCode, 'translationArtifact' => $this->translationArtifact, 'operatorLabel' => $this->operatorLabel, 'shortExplanation' => $this->shortExplanation, 'diagnosticCode' => $this->diagnosticCode, 'trustImpact' => $this->trustImpact, 'absencePattern' => $this->absencePattern, 'nextSteps' => $this->nextSteps, 'ownerLayer' => $this->ownerLayer, 'ownerNamespace' => $this->ownerNamespace, 'platformReasonFamily' => $this->platformReasonFamily, ]; } }