Skip to content

[Hackathon] fix(plan): same-key accept retries fail after staging is cleared #658

Open

Description

@sanaro99

Verified against (commit SHA or released version)

CLI v0.15.0, commit d61e6dfc400f5e88ee34ac799c5496ac5c5a7751, Linux, Node v22.23.3. Reproduced with the real built runPlanAccept and HTTP client, injected HTTP responses, fake credentials, and temporary directories. No TestSprite service calls or credits were used. Backend receipt replay was simulated, not verified against a live account.

Discord Username / User ID

sanaro99

What does this improvement do?

Restore the advertised safe-retry behavior of test plan accept --idempotency-key. After an acceptance clears staging, a second invocation with the same key fails locally before it can ask the server to replay the original receipt.

This matters when a developer or coding agent loses the acceptance response: tests may already have been created, but repeating the same command cannot recover their case keys. The error points toward generating proposals again instead of recovering the committed acceptance.

The confirmed defect is the client-side retry barrier and misleading recovery guidance. This report does not establish duplicate creation, duplicate billing, or loss of created tests.

Details / implementation notes

Reproduction

Given a project with two staged proposals, accept them with a fixed key:

testsprite test plan accept --project p_example --idempotency-key accept-build-42 --output json

Repeat the exact command after acceptance clears staging. The command performs GET /projects/p_example/plans, sees no proposals, and exits 6 with PRECONDITION_FAILED, reason nothing_staged. It never sends a second POST /projects/p_example/plans/accept or its idempotency key. Repeating with an explicit --only prop_1 selection has the same problem.

The offline reproduction exercised three cases:

Scenario First invocation Same-key retry Requests across both
Accept all proposals Returns two case keys Exit 6, nothing staged GET, POST, GET
Accept one proposal Returns one case key Exit 6, nothing staged GET, POST, GET
Accept one, lose response after commit Response read fails; fixture retains receipt Exit 6, nothing staged GET, POST, GET

All three assertions passed. The fixture stores the accepted request and receipt under the supplied key and can replay it, but the CLI never reaches that endpoint on the second invocation. The first two cases establish the defect without requiring a transport failure; the third illustrates recovery impact.

Source evidence

Expected behavior and fix direction

Confirm the service's receipt-replay contract during triage, then let a retry recover the original acceptance result without requiring the accepted proposals to remain staged. Preserve the original project, key and exact selected IDs, plus any metadata needed to reconstruct the output.

For accept-all, the original ID list cannot be reconstructed from empty staging. A CLI-only approach may need an intent record saved before dispatch; an existing server lookup could be preferable if available. Please agree that mechanism before implementation. An explicit same-key retry must not silently select proposals generated after the original acceptance.

Do not simply remove the guard and send only: []: the documented client contract says that empty list means rejecting everything and clearing staging. Keep genuine first-attempt empty-staging validation and key/body mismatch protection.

Focused regression coverage

  • All-proposal and subset acceptance followed by a same-key retry.
  • A committed acceptance whose response is lost.
  • New proposals staged before the old operation is retried.
  • Reusing a key with different selection/project intent.
  • A genuinely new request with empty staging.
  • Correct recovery output, including the original case keys, without a second creation.

Suggested severity: P2, for broken recovery and automation.

Duplicate check: Public open/closed issue and open-PR searches for plan acceptance, nothing_staged, retries, receipts and idempotency found no matching report or implementation. #492 concerns changing keys on batch run triggers; #431 concerns response-body transport retries; #516 concerns generation resumption. This report concerns a subsequent acceptance invocation being rejected before dispatch, including after a normally successful first invocation.

AI assistance: Codex assisted with public source inspection, the offline reproduction and drafting. No live backend behavior beyond the public client contract is asserted.

Confirmations

  • I have searched existing issues and this is not a duplicate.
  • I have provided my Discord identity above for reward coordination.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions