Skip to content

Remove, delete, prune and compact: branch.remove, project.delete, branch.prune, store.compact #511

Open

Description

@yifanxuaaa

Answers #411 and is #446 A8. Owner direction (2026-10-30): no automatic compaction. Space comes back only through explicit SDK calls.

The full spec is core/docs/issues/511/README.md on the PR #507 branch (issue506-store-backends-remote). It builds on the #506 Store model, where runtime.project.remove was renamed runtime.project.delete on 2026-10-30.

The four calls

Call What it does Frees space
branch.remove(name, { confirm }) Hides a Branch in one row update. It leaves every listing at once; fork, merge, publish and mount refuse it. Refused for main (ReservedName) and while a Workspace is mounted on it (MountsActive). no, waits for compact
project.delete(name, { confirm, store, stopSandboxes, … }) A project alone in its Store: deleted with its volume, as today. In a shared Store: proposed to hide in one row update (D2), instead of today's history-sized delete inside the writer. alone: yes; shared: at compact
branch.prune(name, { confirm }) Keeps every Commit's record and ID, but gives up the file trees of the Branch's own intermediate Commits. Its head, Layer sources, fork points (merge bases) and merge parents stay whole. Reading a pruned Commit's files fails Pruned. no, waits for compact
store.compact(name, { confirm, dryRun, stopSandboxes }) With the Store closed, marks what visible Branches, Layers and unpruned Commits use, delta bases and pooled inode rows included. Copies only that into a new file, verifies it, and swaps it in as pull does. dryRun reports exact savings. SQLite only for now. yes, the only one

Each call is one attempt, with no retry. The CLI gets the same verbs.

Why removal can't simply delete

  • Stored data is shared and can't be changed or deleted in place.
    • Packs are trigger-immutable, and read_immutable depends on that.
    • Each pack is written by one Save, then reused by later Commits of any project through dedup and delta bases. Delta bases are referenced only by ID, possibly across projects.
  • History is shared too. Forks share Commits; merges and Layers point into other Branches.
  • Branch names can't be reused safely as-is, because a Branch's ID is derived from its name (BranchId::named). See D1.
  • No Store table records mounts, and some roots live outside the Store: mounted bases, in-flight Saves and reads, macOS NFS exports (raised by jiangkoumo on layerfs rm/compact: retire Branches and reclaim unreachable Store history #411). Compact therefore requires the Store closed, which covers all of them.

Findings (diagnostic, one read-only sample, 2026-10-30)

r2-examples-clone: 251.2 MB file, 818 Commits, 410 Branches Frees up to
Remove the 384 Branches with no Commits of their own, then compact 5.2 MB
Remove depot_2.implementation (4 own Commits), then compact 94.6 MB
Remove all 410 Branches (main kept), then compact 105.1 MB
Delete the project, then compact 237.4 MB
Prune all 548 intermediate Commits, then compact 176.4 MB (loose bound)
  • Dedup is already strong: 260.5 GB of files across all Commits become 688 MB after dedup and 237.4 MB on disk.
  • History rows cost about 0.7 KB per Commit (0.55 MB in all). The space is in file data, much of it in a few Commits and in intermediate trees.
  • Bounds: these are upper bounds from per-Commit "stored first" attribution. Compact's dry run gives the exact figure.

Builds on

Owner decisions

  • D1 · Reuse of a removed Branch's name. Recommended: new Branches get a generation in their ID (format change). Alternative: refuse reuse while the tombstone exists.
  • D2 · project.delete in a shared Store hides instead of deleting rows (recommended).
  • D3 · Writers check at admission that their open file is still the Store's (inode), else Replaced. Recommended; it also closes pull's opener race.
  • D4 · PostgreSQL compact later. Remove, delete and prune work on PostgreSQL now.
  • D5 · A pruned Commit keeps change counts and bytes, not a full path list (recommended).
  • D6 · Schema version bump (removed_ms, deleted_ms, pruned_ms, partial unique indexes, change summary) with a one-time upgrade on open.
  • D7 · Allow removing a Branch that another Branch forked from (recommended).

Done when

  • the four calls, CLI verbs and Connect actions (Remove…, Delete…, Prune history…, Compact… with a dry run) are built;
  • on a fixture Store (cross-project dedup, a cross-project delta base, a fork sharing Commits, a merge, Layers, pruned Commits, pooled leaves), every kept Commit and Layer reads identically after compact, merge bases are unchanged, and the dry run equals the real run;
  • remove, delete and prune each take one short write;
  • measured on copies of r2-examples-clone and services under the agent measurement policy: exact bytes freed against the bounds above, and compact's wall time.

Out of scope: automatic collection, in-place sweep, PostgreSQL compaction, remote-side compaction (push the compacted file), and pruning main's Layers.

Activity

  1. changed the title [-]Delete, prune and compact: branch.delete, project.delete, branch.prune, store.compact[/-] [+]Remove, delete, prune and compact: branch.remove, project.delete, branch.prune, store.compact[/+] on Oct 30, 2026
  2. added 2 commits that reference this issue on Oct 30, 2026
  3. Mola-maker commented on Nov 1, 2026

    @Mola-maker
    Member

    感谢提出这个 issue,也感谢 AI 协作工具在整个排查过程中做的分析 🙏

    对 AI agent 的使用来说,这个问题的解决会直接改善 agent 清理分支和回收存储的完整生命周期管理。

    两点建议:

    1. 动手修改前请先实测:在真实环境(Linux WSL2/ext4 或原生)复现 issue 描述的行为,把复现命令与输出贴出来,确认问题在最新 main 上仍然存在。
    2. 实现等 LayerFS 2.0 发布:2.0 roadmap(LayerFS 2.0 roadmap #446)已在推进,建议把修复/功能实现排进 2.0 的计划里,当前阶段先冻结讨论与实测证据,避免在旧基线上做出之后需要重做的改动。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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