TenantAtlas/tests/Feature/Concerns/BuildsOperatorExplanationFixtures.php
ahmido 1f0cc5de56 feat: implement operator explanation layer (#191)
## Summary
- add the shared operator explanation layer with explanation families, trustworthiness semantics, count descriptors, and centralized badge mappings
- adopt explanation-first rendering across baseline compare, governance operation run detail, baseline snapshot presentation, tenant review detail, and review register rows
- extend reason translation, artifact-truth presentation, fallback ops UX messaging, and focused regression coverage for operator explanation semantics

## Testing
- vendor/bin/sail bin pint --dirty --format agent
- vendor/bin/sail artisan test --compact tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/Operations/OperationRunBlockedExecutionPresentationTest.php
- vendor/bin/sail artisan test --compact

## Notes
- Livewire v4 compatible
- panel provider registration remains in bootstrap/providers.php
- no destructive Filament actions were added or changed in this PR
- no new global-search behavior was introduced in this slice

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #191
2026-03-24 11:24:33 +00:00

68 lines
3.5 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Concerns;
use App\Support\ReasonTranslation\NextStepOption;
use App\Support\ReasonTranslation\ReasonResolutionEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthCause;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\OperatorExplanation\TrustworthinessLevel;
trait BuildsOperatorExplanationFixtures
{
/**
* @param array<string, mixed> $overrides
*/
protected function makeExplanationReasonEnvelope(array $overrides = []): ReasonResolutionEnvelope
{
$nextSteps = $overrides['nextSteps'] ?? [NextStepOption::instruction('Review the recorded prerequisite before retrying.')];
return new ReasonResolutionEnvelope(
internalCode: (string) ($overrides['internalCode'] ?? 'operator.explanation.test'),
operatorLabel: (string) ($overrides['operatorLabel'] ?? 'Operator attention required'),
shortExplanation: (string) ($overrides['shortExplanation'] ?? 'TenantPilot recorded a missing prerequisite for this workflow.'),
actionability: (string) ($overrides['actionability'] ?? 'prerequisite_missing'),
nextSteps: is_array($nextSteps) ? $nextSteps : [],
showNoActionNeeded: (bool) ($overrides['showNoActionNeeded'] ?? false),
diagnosticCodeLabel: $overrides['diagnosticCodeLabel'] ?? 'operator.explanation.test',
trustImpact: (string) ($overrides['trustImpact'] ?? TrustworthinessLevel::Unusable->value),
absencePattern: $overrides['absencePattern'] ?? 'blocked_prerequisite',
);
}
/**
* @param array<string, mixed> $overrides
*/
protected function makeArtifactTruthEnvelope(
array $overrides = [],
?ReasonResolutionEnvelope $reason = null,
): ArtifactTruthEnvelope {
return new ArtifactTruthEnvelope(
artifactFamily: (string) ($overrides['artifactFamily'] ?? 'test_artifact'),
artifactKey: (string) ($overrides['artifactKey'] ?? 'test_artifact:1'),
workspaceId: (int) ($overrides['workspaceId'] ?? 1),
tenantId: $overrides['tenantId'] ?? 1,
executionOutcome: $overrides['executionOutcome'] ?? 'completed',
artifactExistence: (string) ($overrides['artifactExistence'] ?? 'created'),
contentState: (string) ($overrides['contentState'] ?? 'trusted'),
freshnessState: (string) ($overrides['freshnessState'] ?? 'current'),
publicationReadiness: $overrides['publicationReadiness'] ?? null,
supportState: (string) ($overrides['supportState'] ?? 'normal'),
actionability: (string) ($overrides['actionability'] ?? 'none'),
primaryLabel: (string) ($overrides['primaryLabel'] ?? 'Trustworthy artifact'),
primaryExplanation: $overrides['primaryExplanation'] ?? 'The artifact can be used for the intended operator task.',
diagnosticLabel: $overrides['diagnosticLabel'] ?? null,
nextActionLabel: $overrides['nextActionLabel'] ?? null,
nextActionUrl: $overrides['nextActionUrl'] ?? null,
relatedRunId: $overrides['relatedRunId'] ?? null,
relatedArtifactUrl: $overrides['relatedArtifactUrl'] ?? null,
dimensions: [],
reason: $reason instanceof ReasonResolutionEnvelope
? ArtifactTruthCause::fromReasonResolutionEnvelope($reason, 'test_artifact')
: null,
);
}
}