Skip to content

Transaction journal for multi-file lifecycle mutations (crash safety) #38

Description

@xantorres

Problem

Multi-file lifecycle commands (rk close, rk start, rk cancel, rk reopen) apply mutations as sequential await calls with no journal. A crash or SIGKILL between writes leaves the project in a partially-mutated state.

rk close mutation sequence (highest risk):

Step File Change
1 sprints/S-NNN.md status: shipped, closed_at, end_sha
2 reviews/R-NNN.md end_sha backfill (optional)
3 queues/<lane>.md remove slot
4 .repokernel/registry.json refreshRegistry

A crash after step 1 leaves status: shipped but the slot still present in the queue — detectable via SHIPPED_SPRINT_IN_QUEUE and fixable via rk fix --apply. A crash between steps 1 and 3 during rk start (sprint becomes active before queue updates) has no automated repair path.

Current mitigations

  • rk fix --apply repairs SHIPPED_SPRINT_IN_QUEUE and CANCELLED_SPRINT_IN_QUEUE
  • rk registry --write regenerates a stale registry
  • Re-running commands is partially idempotent

Proposed solution: transaction journal

Write a .git/repokernel/journal/<op-id>.pending.json file before the first mutation, with each step's completedAt updated atomically after it completes. A matching <op-id>.done sentinel is written after the final step.

On rk recover --apply, scan for .pending.json files without a .done sentinel and either forward-complete or roll back the partial operation.

See docs/internals/crash-recovery.md for full design: journal schema, recovery protocol, options table, and phased implementation plan.

Implementation phases

  • 2a Journal write for rk close
  • 2b Journal write for rk start, rk cancel, rk reopen
  • 2c rk recover --apply forward-completion path
  • 2d Rollback support

Related

  • DUPLICATE_REVIEW_ID handler in fix.ts (lines 637–659) is dead code — loadProject short-circuits before runValidators when duplicate IDs exist. Should be removed or the graph-phase error handling refactored to allow fix.ts to see the finding. Track separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions