Skip to content

[Lease] Crash consistency between git mutation and lease record #136

Description

@rmems

Current owner handoff — integration-first scope checkpoint (2026-09-22)

Active implementation is draft PR #203, branch cursor/lease-crash-consistency-2079, existing Cursor session bc-f8aa5137-6d0f-4ac2-a7e2-5129f27d2079. #185/#198 are preserved salvage sources, not three independent implementations to keep polishing. Continue only this current session/thread; no replacement PR or new worker.

HOLD architecture expansion; preserve and stabilize the retained binding core. Grok's OSS Position Audit recommends that writ retain binding job ownership, register-only CheckoutRef identity, handoff generations/envelope, and a single native authoritative ownership ledger. It explicitly does not select Foremerge as the default backend; semantic-conflict analysis and generic transport are optional integration candidates. Do not replace the ownership database, install sidecars, or remove working code based solely on the audit.

Within #203, retain useful crash-recovery/non-resurrection/WIP-preservation and generation-matched-handoff code/tests. Fix demonstrable bounded correctness or current-main integration problems, but do not expand messaging, semantic detection, remote coordination, supervision, or managed checkout lifecycle just to finish the old roadmap. Before a large refactor, identify the smallest binding core and the existing call boundaries that can become replaceable ports; report a concrete keep/adapt/defer map and review blockers here. A new abstraction should be justified by an actual integration, not speculative extensibility.

RM-1412/#202 is being steered in its existing session to verify and repair cross-process live-checkout ownership atomicity; consume that invariant/test after coordination rather than creating another fix. Preserve current main's status/watchlist consumers and unknown-state semantics. Advisory path overlap must not become a universal write veto; backend failure must never silently grant duplicate ownership or seize WIP. Distinguish optional advisory-service degradation from unavailable binding authority.

Keep draft and preserve branch/history/attribution. Normal assigned-branch fetch/integration/testing/commits/push for bounded fixes are permitted. No merge, repository-settings change, new session, bulk deletion, or broad dependency migration is requested. Report exact head, supported behavior, meaningful test evidence and outstanding decisions; green analyzers alone do not settle the architecture.


Note

Current planning lives in Linear: #136
GitHub remains the source / PR / review / checks surface. This issue is a compatibility/history mirror, not a second required backlog.
The attached GitHub milestone M1 — Hook enforcement (v0.3.0) is legacy taxonomy from an older architecture; current planning milestone is writ — Collaboration MVP in Linear.

Current Cursor owner direction — 2026-09-21

This is the shared-state foundation for the collaboration-first product. Preserve the existing #185/#198 branches and history; do not restart from scratch.

Key correction: PR #199 retired writ-owned worktree creation/removal. Revise #185 so crash consistency applies to registration/ownership of harness-created checkouts, not a writ-owned git worktree add lifecycle. Keep the useful SQLite, operation identity, reconciliation, tombstone, TTL/heartbeat, and crash tests. Then reconcile #198's same-host claims/messages/handoff layer on top.

Path overlap on different branches is advisory/negotiated; duplicate live task ownership must not happen silently. Normal assigned-branch merge/rebase/cherry-pick is allowed. GitHub remains the remote protected-branch merge authority. No new database, Python orchestrator, universal shell classifier, GitHub issue twin, or duplicate Cursor session.

Revision note — after RM-1711 / PR #199

Draft PR #185 predates the harness-owned-checkout change and still couples its prepare/reconcile protocol to writ-owned git worktree add. Treat #185 as a salvage branch, not merge-ready as-is: keep the SQLite state, operation identity, reconciliation, tombstone, TTL, and crash-test primitives that still apply, but revise the mutation boundary around registration/ownership of harness-created checkouts. Draft PR #198 remains valuable for the same-host coordination/message/handoff layer; reconcile it after the retained #185 substrate is compatible with PR #199.

Restored — 2026-09-21

This issue was unintentionally canceled when the obsolete Phase-1 enforcement parent was canceled. The work is still aligned with #1: crash-safe ownership plus the same-host coordination/handoff substrate. Preserve the existing branches and draft PRs #185 and #198; do not restart implementation from scratch.

Current-session steering — 2026-09-19

Follow the new collaboration-first direction in #1. Preserve and finish the useful crash-consistency work already on this session's branch; do not expand universal no-merge enforcement.

Own the minimal shared coordination/message/handoff contract, reusing the existing Rust/SQLite primitives. Allow independent worker processes to announce task/agent/branch identity and intended paths, report overlaps/blockers, request help, and acknowledge a handoff. Record enough identity/version information to distinguish stale messages and stale ownership from live state; do not treat TTL expiry alone as permission to overwrite WIP. Declared path overlap on distinct branches is advisory and negotiated, not an automatic repo-wide write veto.

RM-145 owns guidance/integration policy; RM-127 owns consuming state for visibility. Coordinate the small shared contract with them before divergent schemas appear. Independent cloud sessions use the shared Linear threads now, not separate local SQLite files. Prove a local runtime slice with two separate processes/worktrees using one shared store, an overlap/help/handoff round trip, and paused-worker recovery. Keep this additive follow-up separate from an already-reviewed crash-recovery diff; no distributed-service rewrite or duplicate agent launch.

This implementation direction supersedes conflicting historical enforcement-first prose below. It does not authorize merging a PR, changing repository settings, or discarding either worker's work.


Important

Product goal (2026-09-05): writ (formerly worktrees-hives) is the enforcement and admission-control layer for agent fleets. Task assignment is commoditized — Claude Code agent teams, /batch, Cursor /multitask and Codex already assign and isolate work. What nothing enforces is safe concurrent writing, and nothing arbitrates contention — whether a second agent may take a path or a work item already taken. writ enforces at the git mutation boundary through Claude Code hooks (a PreToolUse exit 2 cannot be overridden, even by another hook's permissionDecision: "allow"), leases worktrees it did not create, and never merges. Prefer work that hardens that boundary over creating worktrees or re-implementing task assignment.

Why this survived the pivot

The original framing was Python LabJobManager.allocate persisting a PENDING record before calling wh worktree create, with a crash window between Rust mutation and Python promotion. python/ is deleted in Phase 3, so that specific code is going away.

The defect is not. It reappears verbatim in the hook path:

  1. WorktreeCreate fires. writ verifies the exact base and Claude Code creates the worktree.
  2. The process dies before the lease row is committed.
  3. A later session sees a real worktree and branch with no lease row — it cannot prove who owns it, cannot distinguish a complete prior allocation from partial or foreign state, and (per [Hook] Verified worktree reuse so hooks can reattach a reclaimed branch #141's rules) must fail closed on reuse.

TTL and heartbeat, planned for the lease store in #124, solve the opposite window — an orphaned lease whose owner died. They do not solve a mutation with no lease. Both halves are needed, and this issue owns the second.

Scope

Crash consistency between the git mutation and the lease record.

  • Persist the requested source identity before mutation, retaining enough immutable identity to distinguish a symbolic request from the exact commit that was resolved.
  • Close the resolve/mutate/commit gap with either a durable operation journal or an explicit prepare/reserve protocol that persists the canonical start commit before mutation.
  • Provide a Rust-owned inspection operation reporting derived path, symbolic branch ref, branch commit, worker HEAD, registration state, repository identity, and operation identity without mutating or adopting anything.
  • Define deterministic outcomes: promote when every identity matches; retry only when it is proven no mutation occurred; retain a needs-attention state for partial or conflicting evidence.
  • Never delete a branch, worktree, registration, or path unless ownership by this transaction is proven.
  • Do not use ambient HEAD, current checkout state, or a moved symbolic ref to reconstruct the original requested commit.
  • fix_cycles (see [writ] Advisory change-growth budgets for collaborative agents #167) is the only accumulated lease counter; every other budget dimension is derived from the resolved canonical start commit and is crash-safe by construction. This protocol therefore covers exactly one counter, and a crash between an increment and the mutation it authorized must neither double-count nor lose it.

Acceptance criteria

  • A crash before mutation is detected and retryable without permanently reserving the identity.
  • A crash after branch creation, after registration, after filesystem creation, and after full success is independently injected and reconciled at each boundary.
  • A fully matching interrupted allocation is promoted with its exact canonical start commit.
  • Conflicting branch/ref/HEAD/registration/path evidence stays fail-closed and is surfaced without destructive cleanup.
  • The persisted record distinguishes requested symbolic identity, resolved canonical commit, and operation identity.
  • Concurrent reconciliation and teardown cannot resurrect a released or tombstoned lease.
  • TTL expiry (orphaned lease, live worktree) and this case (live worktree, missing lease) are both covered and clearly distinguished.
  • Cargo fmt, Clippy with warnings denied, and Rust workspace tests pass.

Scope boundaries

Owns crash consistency of the lease record. Does not implement general branch resume (#141), fork-object import (#134), path-race hardening (#127), or merge behavior. Must not weaken exact-base or unproven-reuse fail-closed rules.

Relationships

Activity

  1. self-assigned this
    on Aug 30, 2026
  2. linear-code commented on Aug 30, 2026

    @linear-code
    Contributor
  3. moved this from Backlog to Ready in Autonomous Software Engineeringon Aug 30, 2026
  4. 19 remaining items

  5. rmems commented on Sep 15, 2026

    @rmems
    OwnerAuthor

    Crash-consistent lease prepare/inspect/reconcile is on cursor/lease-crash-consistency-32fa at 86dc2da.

    writ worktree create now persists requested symbolic identity, resolved canonical start commit, and an operation id before git mutation. Inspect is read-only. Reconcile promotes a fully matching interrupt, retries a proven no-mutation crash, and keeps partial/conflicting residuals fail-closed without cleanup. Released/tombstoned rows cannot be resurrected; TTL expiry is distinct from a live worktree with no lease. fix_cycles uses the same prepare/commit protocol.

    Agent: Cursor Grok 4.6

  6. rmems commented on Sep 19, 2026

    @rmems
    OwnerAuthor

    Crash-consistency recovered on cursor/lease-crash-consistency-32fa @ ea6cf100ebf14ec1ef10917325ae45ffc59e0ac2 (PR #185). Collaboration messages/handoff will land on stacked cursor/lease-coord-handoff-32fa in the same leases.db (coord_claims + coord_messages). No second store, no remote merge, no GitHub settings change.

    Agent: Cursor Grok 4.6

  7. reopened this on Sep 21, 2026
  8. rmems commented on Sep 21, 2026

    @rmems
    OwnerAuthor

    Salvage of this issue after #199 is on draft PR #203 (cursor/lease-crash-consistency-2079 @ ba4e236). Crash consistency now applies to harness-owned checkout registration, not writ-owned git worktree add. Same-host coord/handoff from #198 is on the same leases.db.

    Native gates passed on that SHA. #185/#198 history was used as the salvage source and is not discarded.

    Agent: Cursor Grok 4.6

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

Metadata

Metadata

Assignees

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions