Skip to content

feat(assignments): add recoverable claim leases - #86

Merged
chicoxyzzy merged 2 commits into
mainfrom
feat/assignment-claim-leases
Jul 22, 2026
Merged

feat(assignments): add recoverable claim leases#86
chicoxyzzy merged 2 commits into
mainfrom
feat/assignment-claim-leases

Conversation

@chicoxyzzy

Copy link
Copy Markdown
Member

Summary

  • add server-issued, renewable pre-start assignment claim leases with 128-bit fencing IDs
  • require the current fence for MCP prepare, release, progress, and completion mutations
  • add explicit expired-claim recovery that requeues coordination state without touching running host execution
  • persist fences in memory, SQLite, and snapshot v2 while retaining safe v1 import support
  • expose recovery state through capabilities, fallback text, operations, health, activity, and the MCP App

Why

Atomic assignment transitions prevented double claims, but a host crash after assignments.claim could still strand work indefinitely. Expiry alone would be unsafe because a stale worker could mutate a later claim generation.

This change leases only the pre-start claimed reservation and fences every later worker lifecycle write. Once work starts, the lease expiry is retired and Cairnline continues to treat runtime recovery as host-owned.

Contract and migration

  • assignments.claim now returns claim.id, acquired_at, and expires_at in structured content, with the ID also present in fallback text.
  • assignments.prepare and assignments.release take claim_id instead of claimed_by; assignments.update_status and assignments.complete require it.
  • assignments.renew_claim and assignments.recover_claim are new.
  • The public Store interface adds leased/fenced methods, so custom stores must implement them.
  • Snapshot version 2 persists claim generations. Version 1 imports remain supported as unleased host-authoritative history.
  • Existing trusted Go host-authority methods remain available, preserving the current Hecate integration boundary.

Safety properties

  • claim IDs use fail-closed 128-bit cryptographic randomness and are concurrency fences, not credentials
  • renewal never shortens an existing lease and does not reorder assignment activity
  • exact-expiry mutations conflict; explicit recovery is atomic and clears prepared execution/context references
  • expiry never requeues or cancels running, awaiting_approval, or awaiting_review work
  • malformed claim states are rejected before memory, SQLite, or snapshot writes

Validation

  • go build ./...
  • go test -count=1 ./...
  • go vet ./...
  • go test -race -count=1 -timeout 10m ./...
  • bun run build
  • bun run typecheck
  • bun run test
  • bun run lint
  • bun run format:check
  • headless Chromium MCP App verification under the production CSP

@chicoxyzzy
chicoxyzzy marked this pull request as ready for review July 22, 2026 22:18
@chicoxyzzy
chicoxyzzy merged commit 99ad37e into main Jul 22, 2026
2 checks passed
@chicoxyzzy
chicoxyzzy deleted the feat/assignment-claim-leases branch July 22, 2026 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant