Artifact 29f0efc3338c14eb87085cd87591d01d78ae1feac8b3f6ab7f5a2533ac01a7db:
- File
src/sim/faulty_dir.zig
-
2026-07-20 04:21:55
— part of check-in
[0cea021cf9]
on branch h2-checkout-dst
— sim: working-tree crash-recovery DST sweep for update
Add sim/faulty_dir.zig, a decorator std.Io that cuts a run at a seeded mutating-op boundary the way a power loss does: the crashing write persists at most a torn prefix and every later mutation is a frozen no-op, so the checkout layer's own recovery moves no byte. Crash-point enumeration follows TigerBeetle's storage-fault-injection lineage, ported to the directory surface update.zig and checkout.zig write through.
Add sim/checkout_sweep.zig: it materializes a check-in, replays an A-to-B update.applyCheckin under a crash at every reachable cut, reopens, and asserts unmanaged files are preserved, the checkout record names only a complete target, and the tree recovers to the target via the undo journal. Joins the dst gate per seed at bounded cuts; the soak walks every boundary.
Finding: update.writePayload writes working files in place (createFile truncate, write, sync), not through the atomic write-temp+fsync+rename that checkout.write, the managed set, and the undo journal use. A crash mid-write can leave a file matching neither its pre- nor its post-image. The sweep pins this; a working-tree write-journal is the fix. (user: dmestas, size: 13665) [annotate] [blame] [check-ins using]
-
2026-07-20 04:28:24
— part of check-in
[5401ce245f]
on branch trunk
— Merge h2-checkout-dst: crash-test the working tree, and a finding it surfaces
The working tree -- the one place a version-control tool can lose a user's data -- had no crash simulation; only the log store did. A new faulty directory layer tears and freezes writes at a seeded crash point, and a sweep replays an update across every crash cut, reopens, and checks four invariants. Three hold: an untracked file the update must preserve is never touched, a crashed update recovers to its target through the undo journal, and the checkout record never names a check-in whose tree did not finish materializing. The fourth does not, and that is the point of the harness: the payload write lands in place rather than through the write-temp-and-rename the metadata already uses, so a crash mid-write can leave a managed file spliced from old and new bytes -- torn, but recoverable. The gate runs the three that hold; the fourth is pinned by a test asserting the splice IS produced, so it flips the day the write is made atomic. Crash-point enumeration follows TigerBeetle's storage model. (user: dmestas, size: 13665) [annotate] [blame] [check-ins using]
-
2026-07-20 04:21:55
— part of check-in
[0cea021cf9]
on branch h2-checkout-dst
— sim: working-tree crash-recovery DST sweep for update