Category: spec-conformance Severity: major
Location: src/Errors/ErrorPayload.php:79-98
Spec: ARCP v1.1 §12
What
§12: 'Error payloads carry a retryable boolean. LEASE_EXPIRED and BUDGET_EXHAUSTED MUST be returned with retryable: false.' Because the constructor defaults retryable to null and toArray suppresses null, any caller building new ErrorPayload('LEASE_EXPIRED', '...') emits a wire envelope without the required boolean.
Evidence
public function toArray(): array
{
$out = [
'code' => $this->code,
'message' => $this->message,
];
if ($this->retryable !== null) {
$out['retryable'] = $this->retryable;
}
...
}
Proposed fix
When retryable is null at construction, derive it from ErrorCode::tryFrom($code)?->defaultRetryable() and always emit the field. Hard-code retryable=false for LEASE_EXPIRED and BUDGET_EXHAUSTED, retryable=true for INTERNAL_ERROR.
Acceptance criteria
Category: spec-conformance Severity: major
Location:
src/Errors/ErrorPayload.php:79-98Spec: ARCP v1.1 §12
What
§12: 'Error payloads carry a retryable boolean. LEASE_EXPIRED and BUDGET_EXHAUSTED MUST be returned with retryable: false.' Because the constructor defaults retryable to null and toArray suppresses null, any caller building
new ErrorPayload('LEASE_EXPIRED', '...')emits a wire envelope without the required boolean.Evidence
Proposed fix
When retryable is null at construction, derive it from ErrorCode::tryFrom($code)?->defaultRetryable() and always emit the field. Hard-code retryable=false for LEASE_EXPIRED and BUDGET_EXHAUSTED, retryable=true for INTERNAL_ERROR.
Acceptance criteria