Category: spec-conformance Severity: minor
Location: arcp-runtime/src/main/java/dev/arcp/runtime/session/SessionLoop.java:473-486
Spec: ARCP v1.1 §7.2
What
Replay uses prior.budget().snapshot(), which reflects budget already decremented by cost metrics since acceptance, so a duplicate submit with the same idempotency_key can return a budget map that differs from the original job.accepted. §7.2 requires the runtime return the same job.accepted payload for a repeated key with identical parameters.
Evidence
private void emitReplayAccepted(JobRecord prior, @Nullable TraceId traceId) {
Map<String, BigDecimal> budgetSnapshot = prior.budget().snapshot();
JobAccepted accepted =
new JobAccepted(
prior.jobId(),
prior.resolvedAgent(),
prior.lease(),
prior.constraints().expiresAt() != null ? prior.constraints() : null,
budgetSnapshot.isEmpty() ? null : budgetSnapshot,
nullableWireCredentials(prior),
prior.createdAt(),
traceId);
Proposed fix
Persist the initial budget map produced at acceptance and replay that captured payload verbatim, rather than recomputing from live counters.
Acceptance criteria
Category: spec-conformance Severity: minor
Location:
arcp-runtime/src/main/java/dev/arcp/runtime/session/SessionLoop.java:473-486Spec: ARCP v1.1 §7.2
What
Replay uses
prior.budget().snapshot(), which reflects budget already decremented by cost metrics since acceptance, so a duplicate submit with the sameidempotency_keycan return abudgetmap that differs from the originaljob.accepted. §7.2 requires the runtime return the samejob.acceptedpayload for a repeated key with identical parameters.Evidence
Proposed fix
Persist the initial budget map produced at acceptance and replay that captured payload verbatim, rather than recomputing from live counters.
Acceptance criteria
idempotency_keyreturns ajob.acceptedwhosebudgetequals the budget returned by the original acceptance, regardless of intervening spend.