Skip to content

rename-lane: the four-file rename is still not crash-atomic, deferred from #158 #224

Open

Description

@brettheap

#158 asked for the rename's handoff stamp to be hardened and for "broader four-file crash recovery" to be assessed separately. This issue is that separate assessment. No issue tracked it until now.

What #212 made atomic, and what it did not

Atomic now: the Rule 3 RENAMED from … stamp. rename-lane writes the stamped copy to an exclusive mktemp file beside the handoff, in its resolved directory, copies the handoff's mode onto it with cp -p, and replaces the handoff with mv -f. A SIGKILL or power loss at any point leaves the handoff whole: either the old bytes or the stamped bytes, never a truncated file. cleanup removes the temporary file on handled exits.

Still not crash-atomic: the rename itself. Its four moves are separate filesystem operations, made in this order:

  1. the object log is moved to lanes/log/<new>.md and the RENAMED line is appended;
  2. the handoff is moved and stamped;
  3. a row is appended to lanes/aliases.tsv;
  4. the register row is rewritten.

They become one change only at the commit. rename_undo restores them on a handled failure (exit or INT/TERM), but a SIGKILL or power loss runs no trap. A crash between two moves therefore leaves the checkout half-renamed: for example, the log already under <new> while the row still says <old>. A second rename-lane cannot finish that state, because its own refusal reads the moved log as another lane's ("lane '' has no row and this checkout already carries … an object log under that name"). Recovery is by hand.

rename_undo's own restores are also in-place redirects: cat snapshot > target for the log, the handoff, the alias table and the register. A crash during a rollback can therefore truncate any of them. The register's redirect is deliberate, because of the symlink hazard in lanes-edit.sh's header (a redirect follows the ~/projects/<estate>/LANES.md link where mv would detach it), so any answer for the register has to keep following that link.

A fix has to decide how a crashed rename is detected and finished or undone on the next run. One option is an intent record written before the first move, which a later rename-lane or lane-start reads. That decision is the scope here. It does not extend to more single-file atomicity.

A rolled-back MOVED handoff loses its mode (found in #212's review, also on main)

When a rename that moved the handoff rolls back, rename_undo runs rm -f "$RL_H_NEW" and then cat -- "$RL_SNAP/handoff" > "$RL_H_OLD". That creates a new file at the default umask mode, so a 0640 handoff comes back as 0644. The object log's restore (rm -f "$RL_LOG_NEW", then cat … > "$RL_LOG_OLD") follows the same shape. The bytes are restored exactly; the mode is not. f87fd5a behaves the same way.

A stale sentence that is fenced for another branch

docs/README-lanes.md:~4202–4206 still says "Legacy lane rename is an explicit publication exception … Its existing four-file transaction uses EXIT rollback, including stamp write failures; it is not crash atomic across those files." After #212 the stamp is no longer an exception to atomic publication; only the four-file rename is still not crash-atomic. That region (README-lanes.md from ~:3830 on) is reserved for lane openRepoTools-3's unpublished branch feat/triad-lane-tooling, so #212 left it alone. #212 corrected the same claim in skills/handoff/SKILL.md.

Filed by lane openRepoTools-4 from the review of #212.

🤖 Generated with Claude Code

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