makeExplanationReasonEnvelope([ 'internalCode' => 'review_publish_blocked', 'operatorLabel' => 'Publication blocked', 'shortExplanation' => 'A required approval or prerequisite is missing for this review.', 'trustImpact' => TrustworthinessLevel::Unusable->value, 'absencePattern' => 'blocked_prerequisite', 'nextSteps' => [\App\Support\ReasonTranslation\NextStepOption::instruction('Resolve review blockers before publication.')], ]); $truth = $this->makeArtifactTruthEnvelope([ 'executionOutcome' => 'blocked', 'artifactExistence' => 'created_but_not_usable', 'contentState' => 'missing_input', 'actionability' => 'required', 'primaryLabel' => 'Artifact not usable', 'primaryExplanation' => 'The review exists, but it is blocked from publication.', 'nextActionLabel' => 'Resolve review blockers before publication', ], $reason); $explanation = app(OperatorExplanationBuilder::class)->fromArtifactTruthEnvelope($truth, [ new CountDescriptor('Publish blockers', 2, CountDescriptor::ROLE_RELIABILITY_SIGNAL, 'resolve before publish'), ]); expect($explanation->family)->toBe(ExplanationFamily::BlockedPrerequisite) ->and($explanation->evaluationResult)->toBe('unavailable') ->and($explanation->trustworthinessLevel)->toBe(TrustworthinessLevel::Unusable) ->and($explanation->dominantCauseLabel)->toBe('Publication blocked') ->and($explanation->dominantCauseExplanation)->toContain('missing for this review') ->and($explanation->nextActionText)->toBe('Resolve review blockers before publication') ->and($explanation->countDescriptors)->toHaveCount(1); }); it('keeps trustworthy artifact truth separate from no-action guidance', function (): void { $truth = $this->makeArtifactTruthEnvelope([ 'executionOutcome' => 'succeeded', 'artifactExistence' => 'created', 'contentState' => 'trusted', 'freshnessState' => 'current', 'actionability' => 'none', 'primaryLabel' => 'Trustworthy artifact', 'primaryExplanation' => 'The artifact is ready for the intended operator task.', ]); $explanation = app(OperatorExplanationBuilder::class)->fromArtifactTruthEnvelope($truth, [ new CountDescriptor('Findings', 3, CountDescriptor::ROLE_EVALUATION_OUTPUT), ]); expect($explanation->family)->toBe(ExplanationFamily::TrustworthyResult) ->and($explanation->evaluationResult)->toBe('full_result') ->and($explanation->trustworthinessLevel)->toBe(TrustworthinessLevel::Trustworthy) ->and($explanation->nextActionText)->toBe('No action needed') ->and($explanation->coverageStatement)->toContain('sufficient'); });