createdAt = new \DateTimeImmutable(); } // Factory Methods public static function builder(int $taskId, string $executor, AssigneeType $executorType): TaskResultBuilder { return new TaskResultBuilder($taskId, $executor, $executorType); } // Getters - Only for necessary access public function id(): ?int { return $this->id; } public function taskId(): int { return $this->taskId; } public function assignmentId(): ?int { return $this->assignmentId; } public function executor(): string { return $this->executor; } public function executorType(): AssigneeType { return $this->executorType; } public function modelName(): ?string { return $this->modelName; } public function request(): ?string { return $this->request; } public function response(): ?string { return $this->response; } public function duration(): ExecutionDuration { return $this->duration; } public function metrics(): ExecutionMetrics { return $this->metrics; } public function status(): ResultStatus { return $this->status; } public function errorMessage(): ?string { return $this->errorMessage; } public function createdAt(): \DateTimeImmutable { return $this->createdAt; } // Setter only for infrastructure (persistence) public function setId(int $id): void { $this->id = $id; } // Domain Logic public function isSuccess(): bool { return $this->status === ResultStatus::SUCCESS; } public function hasError(): bool { return $this->status === ResultStatus::ERROR; } public function hasModel(): bool { return $this->modelName !== null; } public function summary(): string { $parts = [ $this->executor, $this->status->label(), ]; if ($this->modelName !== null) { $parts[] = "({$this->modelName})"; } return implode(' - ', $parts); } // Legacy getters for backward compatibility (deprecated) public function getId(): ?int { return $this->id; } public function getTaskId(): int { return $this->taskId; } public function getAssignmentId(): ?int { return $this->assignmentId; } public function getExecutor(): string { return $this->executor; } public function getExecutorType(): AssigneeType { return $this->executorType; } public function getModelName(): ?string { return $this->modelName; } public function getRequest(): ?string { return $this->request; } public function getResponse(): ?string { return $this->response; } public function getRequestTimestamp(): \DateTimeImmutable { return $this->duration->requestedAt(); } public function getResponseTimestamp(): ?\DateTimeImmutable { return $this->duration->respondedAt(); } public function getDurationMs(): ?int { return $this->duration->durationMs(); } public function getTokensInput(): ?int { return $this->metrics->tokens()->input(); } public function getTokensOutput(): ?int { return $this->metrics->tokens()->output(); } public function getTokensTotal(): ?int { return $this->metrics->tokens()->total(); } public function getCostUsd(): ?float { return $this->metrics->costUsd(); } public function getStatus(): string { return $this->status->value; } public function getErrorMessage(): ?string { return $this->errorMessage; } public function getCreatedAt(): \DateTimeImmutable { return $this->createdAt; } public function toArray(): array { return [ 'id' => $this->id, 'task_id' => $this->taskId, 'assignment_id' => $this->assignmentId, 'executor' => $this->executor, 'executor_type' => $this->executorType->value, 'model_name' => $this->modelName, 'request' => $this->request, 'response' => $this->response, 'request_timestamp' => $this->requestTimestamp->format('Y-m-d H:i:s.u'), 'response_timestamp' => $this->responseTimestamp?->format('Y-m-d H:i:s.u'), 'duration_ms' => $this->durationMs, 'tokens_input' => $this->tokensInput, 'tokens_output' => $this->tokensOutput, 'tokens_total' => $this->tokensTotal, 'cost_usd' => $this->costUsd, 'status' => $this->status, 'error_message' => $this->errorMessage, 'created_at' => $this->createdAt->format('Y-m-d H:i:s.u'), ]; } public static function fromArray(array $data): self { $result = new self(); if (isset($data['id'])) { $result->setId((int) $data['id']); } if (isset($data['task_id'])) { $result->setTaskId((int) $data['task_id']); } if (isset($data['assignment_id'])) { $result->setAssignmentId((int) $data['assignment_id']); } if (isset($data['executor'])) { $result->setExecutor($data['executor']); } if (isset($data['executor_type'])) { $result->executorType = AssigneeType::from($data['executor_type']); } if (isset($data['model_name'])) { $result->setModelName($data['model_name']); } if (isset($data['request'])) { $result->request = $data['request']; } if (isset($data['response'])) { $result->response = $data['response']; } if (isset($data['request_timestamp'])) { $result->setRequestTimestamp(new \DateTimeImmutable($data['request_timestamp'])); } if (isset($data['response_timestamp'])) { $result->setResponseTimestamp(new \DateTimeImmutable($data['response_timestamp'])); } if (isset($data['duration_ms'])) { $result->setDurationMs((int) $data['duration_ms']); } if (isset($data['tokens_input'])) { $result->tokensInput = (int) $data['tokens_input']; } if (isset($data['tokens_output'])) { $result->tokensOutput = (int) $data['tokens_output']; } if (isset($data['tokens_total'])) { $result->tokensTotal = (int) $data['tokens_total']; } if (isset($data['cost_usd'])) { $result->setCostUsd((float) $data['cost_usd']); } if (isset($data['status'])) { $result->status = $data['status']; } if (isset($data['error_message'])) { $result->errorMessage = $data['error_message']; } if (isset($data['created_at'])) { $result->setCreatedAt(new \DateTimeImmutable($data['created_at'])); } return $result; } }