Skip to content

protocol: non-atomic multi-store writes in handoff and bounty paths #227

@windoliver

Description

@windoliver

Summary

Two critical protocol paths write to multiple stores without transactional guarantees, risking inconsistent state on partial failure.

1. Handoff creation on non-SQLite stores

contributeOperation in src/core/operations/contribute.ts has two code paths for handoff creation:

  • Atomic path: When the store supports putWithCowrite (duck-typed SQLite), handoff creation runs inside the same transaction as the contribution write. Safe.
  • Non-atomic path: When putWithCowrite is not available (e.g., Nexus HTTP stores), the contribution is written first, then handoff creation runs separately. If handoff creation fails, the contribution exists but downstream agents never get notified.

The non-atomic path also writes debug output to /tmp/grove-debug.log — operational noise in library code.

2. Bounty claim is two separate store calls

claimBountyOperation in src/core/operations/bounty.ts calls:

  1. claimStore.claimOrRenew(claim) — creates the claim
  2. bountyStore.claimBounty(bountyId, claim.claimId) — updates the bounty

If step 2 fails, we have a dangling claim with no corresponding bounty update. Manual repair required.

Proposed fixes

Short term

  • Wrap the non-atomic handoff path in try/catch with rollback (delete the contribution if handoff creation fails)
  • Add a claimBountyAtomic that either wraps both calls in a single SQLite transaction or uses a compensating action pattern
  • Remove the /tmp/grove-debug.log write

Long term

  • Consider a saga pattern for multi-store operations
  • Or ensure all store combinations support a "co-write" primitive

Files

  • src/core/operations/contribute.ts — non-atomic handoff branch
  • src/core/operations/bounty.tsclaimBountyOperation

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions