v0.2 slice 2: tombstones, peer delete propagation, plan/sync UX #2

Merged
erik merged 1 commit from worktree-v0.2-2 into main 2026-05-26 16:50:42 +00:00
Owner

Tombstones + safer deletes:

  • New tombstones cache table (migration 0002) with state.TombstoneRow, CacheTombstone, HasTombstone, DeleteFiles.
  • Local deletes now build and PUT an explicit tombstone object at roots//tombstones/_.json before the manifest write; rows are dropped from state on success. fswalk.deletedPass preserves the previous sha/size/target so previous_sha256 is populated.
  • Peer tombstones are enumerated, fetched, verified, and applied per the safety table: clean local with matching sha removes the file and prunes empty parent dirs; diverged local becomes a conflict-skip warning. Cached for idempotency.

Decider rewrites (internal/download/decide.go):

  • ActionLocalWins (generalised from ActionLocalDeleteWins) covers deleted rows and locally-modified rows: a tombstone or upload will propagate, the peer entry is treated as stale.
  • Clean rows with peer-sha mismatch now ActionDownload when the peer manifest is newer, ActionAlreadyPresent when older. Version skew is judged by comparing PeerEntry.PeerCreatedAt against LocalView.LatestLocalManifestCreatedAt.

New subcommand dropbear clean [--remote] [--confirmed] :

  • Removes .dropbear/ locally; with --remote, lists and deletes every object under the configured root prefix. Other roots in the same bucket are untouched.
  • Requires interactive confirmation unless --confirmed is passed.
  • objectstore.Store gained DeleteObject(ctx, key) (s3 + fake).

UX improvements:

  • dropbear plan enumerates peer heads by default and surfaces incoming download/conflict-skip rows; --local-only skips the network. Peer-enumeration failures degrade to a warning rather than failing the command.
  • sync human output now lists each file involved (one line per upload/download/tombstone/apply) and the summary line shows tombstone counts.
  • Sync JSON gained tombstone_id, tombstoned_count, applied_tombstone_count, tombstone_conflicts_skipped.

Tests:

  • New integration tests: tombstone propagation, directory delete + parent prune, modify-after-download, version-skew, peer-side dropbear clean.
  • Decider table updated to reflect the new clean+modified-with-stale-peer semantics.

Wiki:

  • wiki/PROJECT.md "Where We Are" + "Recent Changes" updated; "Last reviewed" rolled to 2026-05-26.

Carve-outs deferred to later slices: archive-only/never-delete rule (slice 4), tombstone preview in plan, baseline-sha for concurrent-edit detection.

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

Tombstones + safer deletes: - New tombstones cache table (migration 0002) with state.TombstoneRow, CacheTombstone, HasTombstone, DeleteFiles. - Local deletes now build and PUT an explicit tombstone object at roots/<rootID>/tombstones/<ts>_<deviceID>.json before the manifest write; rows are dropped from state on success. fswalk.deletedPass preserves the previous sha/size/target so previous_sha256 is populated. - Peer tombstones are enumerated, fetched, verified, and applied per the safety table: clean local with matching sha removes the file and prunes empty parent dirs; diverged local becomes a conflict-skip warning. Cached for idempotency. Decider rewrites (internal/download/decide.go): - ActionLocalWins (generalised from ActionLocalDeleteWins) covers deleted rows and locally-modified rows: a tombstone or upload will propagate, the peer entry is treated as stale. - Clean rows with peer-sha mismatch now ActionDownload when the peer manifest is newer, ActionAlreadyPresent when older. Version skew is judged by comparing PeerEntry.PeerCreatedAt against LocalView.LatestLocalManifestCreatedAt. New subcommand dropbear clean [--remote] [--confirmed] <path>: - Removes .dropbear/ locally; with --remote, lists and deletes every object under the configured root prefix. Other roots in the same bucket are untouched. - Requires interactive confirmation unless --confirmed is passed. - objectstore.Store gained DeleteObject(ctx, key) (s3 + fake). UX improvements: - dropbear plan enumerates peer heads by default and surfaces incoming download/conflict-skip rows; --local-only skips the network. Peer-enumeration failures degrade to a warning rather than failing the command. - sync human output now lists each file involved (one line per upload/download/tombstone/apply) and the summary line shows tombstone counts. - Sync JSON gained tombstone_id, tombstoned_count, applied_tombstone_count, tombstone_conflicts_skipped. Tests: - New integration tests: tombstone propagation, directory delete + parent prune, modify-after-download, version-skew, peer-side dropbear clean. - Decider table updated to reflect the new clean+modified-with-stale-peer semantics. Wiki: - wiki/PROJECT.md "Where We Are" + "Recent Changes" updated; "Last reviewed" rolled to 2026-05-26. Carve-outs deferred to later slices: archive-only/never-delete rule (slice 4), tombstone preview in plan, baseline-sha for concurrent-edit detection. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
v0.2 slice 2: tombstones, peer delete propagation, plan/sync UX
All checks were successful
Validate / validate (push) Successful in 38s
Validate / validate (pull_request) Successful in 37s
e9bd9bc1f0
Tombstones + safer deletes:
- New tombstones cache table (migration 0002) with state.TombstoneRow, CacheTombstone, HasTombstone, DeleteFiles.
- Local deletes now build and PUT an explicit tombstone object at roots/<rootID>/tombstones/<ts>_<deviceID>.json before the manifest write; rows are dropped from state on success. fswalk.deletedPass preserves the previous sha/size/target so previous_sha256 is populated.
- Peer tombstones are enumerated, fetched, verified, and applied per the safety table: clean local with matching sha removes the file and prunes empty parent dirs; diverged local becomes a conflict-skip warning. Cached for idempotency.

Decider rewrites (internal/download/decide.go):
- ActionLocalWins (generalised from ActionLocalDeleteWins) covers deleted rows and locally-modified rows: a tombstone or upload will propagate, the peer entry is treated as stale.
- Clean rows with peer-sha mismatch now ActionDownload when the peer manifest is newer, ActionAlreadyPresent when older. Version skew is judged by comparing PeerEntry.PeerCreatedAt against LocalView.LatestLocalManifestCreatedAt.

New subcommand dropbear clean [--remote] [--confirmed] <path>:
- Removes .dropbear/ locally; with --remote, lists and deletes every object under the configured root prefix. Other roots in the same bucket are untouched.
- Requires interactive confirmation unless --confirmed is passed.
- objectstore.Store gained DeleteObject(ctx, key) (s3 + fake).

UX improvements:
- dropbear plan enumerates peer heads by default and surfaces incoming download/conflict-skip rows; --local-only skips the network. Peer-enumeration failures degrade to a warning rather than failing the command.
- sync human output now lists each file involved (one line per upload/download/tombstone/apply) and the summary line shows tombstone counts.
- Sync JSON gained tombstone_id, tombstoned_count, applied_tombstone_count, tombstone_conflicts_skipped.

Tests:
- New integration tests: tombstone propagation, directory delete + parent prune, modify-after-download, version-skew, peer-side dropbear clean.
- Decider table updated to reflect the new clean+modified-with-stale-peer semantics.

Wiki:
- wiki/PROJECT.md "Where We Are" + "Recent Changes" updated; "Last reviewed" rolled to 2026-05-26.

Carve-outs deferred to later slices: archive-only/never-delete rule (slice 4), tombstone preview in plan, baseline-sha for concurrent-edit detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
erik merged commit ed8fa8149c into main 2026-05-26 16:50:42 +00:00
erik deleted branch worktree-v0.2-2 2026-05-26 16:50:42 +00:00
Sign in to join this conversation.
No description provided.