## Summary - add shared governance artifact truth presentation and badge taxonomy - integrate artifact-truth messaging across baseline, evidence, tenant review, review pack, and operation run surfaces - add focused regression coverage and spec artifacts for artifact truth semantics ## Testing - not run in this step Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #188
138 lines
4.5 KiB
PHP
138 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support\Ui\GovernanceArtifactTruth;
|
|
|
|
use App\Support\Badges\BadgeSpec;
|
|
|
|
final readonly class ArtifactTruthEnvelope
|
|
{
|
|
/**
|
|
* @param array<int, ArtifactTruthDimension> $dimensions
|
|
*/
|
|
public function __construct(
|
|
public string $artifactFamily,
|
|
public string $artifactKey,
|
|
public int $workspaceId,
|
|
public ?int $tenantId,
|
|
public ?string $executionOutcome,
|
|
public string $artifactExistence,
|
|
public string $contentState,
|
|
public string $freshnessState,
|
|
public ?string $publicationReadiness,
|
|
public string $supportState,
|
|
public string $actionability,
|
|
public string $primaryLabel,
|
|
public ?string $primaryExplanation,
|
|
public ?string $diagnosticLabel,
|
|
public ?string $nextActionLabel,
|
|
public ?string $nextActionUrl,
|
|
public ?int $relatedRunId,
|
|
public ?string $relatedArtifactUrl,
|
|
public array $dimensions = [],
|
|
public ?ArtifactTruthCause $reason = null,
|
|
) {}
|
|
|
|
public function primaryDimension(): ?ArtifactTruthDimension
|
|
{
|
|
foreach ($this->dimensions as $dimension) {
|
|
if ($dimension instanceof ArtifactTruthDimension && $dimension->isPrimary()) {
|
|
return $dimension;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function primaryBadgeSpec(): BadgeSpec
|
|
{
|
|
$dimension = $this->primaryDimension();
|
|
|
|
return $dimension?->badgeSpec() ?? \App\Support\Badges\BadgeSpec::unknown();
|
|
}
|
|
|
|
public function nextStepText(): string
|
|
{
|
|
if (is_string($this->nextActionLabel) && trim($this->nextActionLabel) !== '') {
|
|
return $this->nextActionLabel;
|
|
}
|
|
|
|
return match ($this->actionability) {
|
|
'none' => 'No action needed',
|
|
'optional' => 'Review recommended',
|
|
default => 'Action required',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @return array{
|
|
* artifactFamily: string,
|
|
* artifactKey: string,
|
|
* workspaceId: int,
|
|
* tenantId: ?int,
|
|
* executionOutcome: ?string,
|
|
* artifactExistence: string,
|
|
* contentState: string,
|
|
* freshnessState: string,
|
|
* publicationReadiness: ?string,
|
|
* supportState: string,
|
|
* actionability: string,
|
|
* primaryLabel: string,
|
|
* primaryExplanation: ?string,
|
|
* diagnosticLabel: ?string,
|
|
* nextActionLabel: ?string,
|
|
* nextActionUrl: ?string,
|
|
* relatedRunId: ?int,
|
|
* relatedArtifactUrl: ?string,
|
|
* dimensions: array<int, array{
|
|
* axis: string,
|
|
* state: string,
|
|
* label: string,
|
|
* classification: string,
|
|
* badgeDomain: ?string,
|
|
* badgeState: ?string
|
|
* }>,
|
|
* reason: ?array{
|
|
* reasonCode: ?string,
|
|
* translationArtifact: ?string,
|
|
* operatorLabel: ?string,
|
|
* shortExplanation: ?string,
|
|
* diagnosticCode: ?string,
|
|
* nextSteps: array<int, string>
|
|
* }
|
|
* }
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'artifactFamily' => $this->artifactFamily,
|
|
'artifactKey' => $this->artifactKey,
|
|
'workspaceId' => $this->workspaceId,
|
|
'tenantId' => $this->tenantId,
|
|
'executionOutcome' => $this->executionOutcome,
|
|
'artifactExistence' => $this->artifactExistence,
|
|
'contentState' => $this->contentState,
|
|
'freshnessState' => $this->freshnessState,
|
|
'publicationReadiness' => $this->publicationReadiness,
|
|
'supportState' => $this->supportState,
|
|
'actionability' => $this->actionability,
|
|
'primaryLabel' => $this->primaryLabel,
|
|
'primaryExplanation' => $this->primaryExplanation,
|
|
'diagnosticLabel' => $this->diagnosticLabel,
|
|
'nextActionLabel' => $this->nextActionLabel,
|
|
'nextActionUrl' => $this->nextActionUrl,
|
|
'relatedRunId' => $this->relatedRunId,
|
|
'relatedArtifactUrl' => $this->relatedArtifactUrl,
|
|
'dimensions' => array_values(array_map(
|
|
static fn (ArtifactTruthDimension $dimension): array => $dimension->toArray(),
|
|
array_filter(
|
|
$this->dimensions,
|
|
static fn (mixed $dimension): bool => $dimension instanceof ArtifactTruthDimension,
|
|
),
|
|
)),
|
|
'reason' => $this->reason?->toArray(),
|
|
];
|
|
}
|
|
}
|