v0.2.0 — wt-snapshot: capture a worktree before anyone deletes it
v0.2.0 — wt-snapshot: capture a worktree before anyone deletes it
The weekly cleanup report kept finding worktree remnants because "may I delete
this?" had no safe answer. bin/wt-snapshot gives it one: it captures a dirty or
not-reconstructible worktree into a commit object under
refs/worktree-snapshots// in the main repository, so
deletion becomes reversible. The tool never deletes anything itself.
- captures tracked dirty changes, untracked files, and the configured ignored
path set (e.g. .omc/) through a temporary index; the user's HEAD, index and
config are never touched and identity is passed explicitly per git call - a clean worktree at a reachable HEAD is an explicit no-op, so noise is never
snapshotted - CK_WTSNAP_SECRET_SCAN_CMD, when set, sees every captured byte before anything
is written; a hit aborts with the scanner's status and leaves refs and the
object store untouched - restore rebuilds the worktree including the ignored set; prune lists expired
refs and deletes nothing
Evidence for the two properties that matter most, measured on this head:
extended-attribute content cannot smuggle bytes past the scanner (payload holds
0 LIBARCHIVE.xattr records and 0 plain hits for a probe secret placed in an
xattr), and a staged submodule pointer is captured rather than reported as a
no-op (restored index gitlink oid matches the source exactly). A plain-file
secret aborts with exit 17 leaving loose-object count unchanged at 3 and no ref
written. Payload verification is pinned from both directions: an injected
unlisted member aborts with exit 70, and neutralising the member-type
comparison turns exactly one case red.
Suite on this head: 29 passed in tests/test_wt_snapshot.sh, all seven suites
green. Review: 4 rounds, 3 seats each round (Grok 4.6, Kimi K3, Muse Spark 1.2)
— two MAJORs found and closed in rounds 3 and 4, final round GO / GO-WITH-MINOR
/ GO.