Skip to content

Library Trash (the Trash part of phase 1 of 01-sources-and-folders): taking it, if it is free #2375

Open

Description

@ybai08

Taking it, if it is free: the Library Trash, phase 4a of 01-sources-and-folders.md. It is the first line of Known gaps in docs/architecture/documents.md: "Deleting a folder is permanent; the Trash is designed, not built."

What is on dev (36c42457b)

  • 0025_source_roots_and_folders already has folders.state with trashed and deleting, plus trash_kind and trashed_at.
  • source_scope/resolve.py and the agent's thread_folder/mirror_path.py already leave out trashed and deleting subtrees.
  • The tree's delete still goes to DELETE /folders/{id} (folders/delete_folder.py) and DELETE /documents/{id}, both permanent.
  • There is no trash.py, purge.py, /trash route or blob_tombstones yet.

Plan. Three PRs against dev, each built to the proposal as written:

  1. Move to Trash and Restore (modules/folders/trash.py, POST /trash, GET /trash, POST /trash/{folder_id}/restore):
    • A folder is marked trashed in place.
    • Loose documents go into one "Deleted {date} {time}" wrapper per source folder.
    • The subtree's pending and processing rows are cancelled in the same transaction.
    • Filed artifacts pass versions.guard_delete first.
    • Restore handles the " (restored)" rename and the re-queue at PRIORITY_BULK.
    • FOLDERS events carry the ids.
  2. Purge (purge.py, DELETE /trash/{folder_id}, DELETE /trash):
    • Every subtree is set to deleting first. Documents are then removed in batches of up to 500, each in its own transaction, then folders deepest first.
    • A blob_tombstones table (a new plain migration) gets a row for each documents/<id>/ and artifacts/<id>/ directory as it is removed.
    • orphan_directories.py::sweep_tombstones runs at start.
    • An hourly lifespan task purges entries older than 30 days.
  3. Frontend:
    • The Trash row at the end of the Library, with counts, size and purge date. Each entry has Restore and Delete now, plus Empty Trash.
    • The tree's delete moves rows to the Trash with an Undo toast. DELETE /documents/{id} keeps its permanent meaning for plugins.
    • This PR moves the Trash part of the design into docs/architecture/documents.md and removes the Known gaps line.

Each backend PR comes with tests for its steps from the proposal: scope exclusion at once, restore intact, a cancelled job no-oping at begin_job, batch size, deepest-first order, and a tombstone kept when a directory cannot be removed. Linked roots (4b) are out of scope.

Two questions before I start

  • Is anyone already on this, or is it planned on your side?
  • The proposal's status is in-progress. Do you want anything changed in the Trash section first, such as the 30-day estimate or the "Deleted {date} {time}" wrapper name, or should I build it as written?

Activity

  1. changed the title [-]Library Trash (phase 4a of 01-sources-and-folders): taking it, if it is free[/-] [+]Library Trash (the Trash part of phase 1 of 01-sources-and-folders): taking it, if it is free[/+] on Nov 4, 2026
  2. ybai08 commented on Nov 4, 2026

    @ybai08
    ContributorAuthor

    A correction to my title and first line: in the proposal's Phases table, the Trash ("Trash, restore, batched purge and tombstone sweep") is part of phase 1, Folders in the Library. Phase 4a is "Link a folder: scan and reconcile". I had taken "phases 4a and 4b" from the status line near the top, which reads "The Trash and linking a folder on disk (phases 4a and 4b) are designed, not built". That line and the table disagree; I can fix the status line in the first PR if you like.

    The rest of the plan and the two questions above are unchanged: is the Trash free to take, and should it be built as the proposal describes it?

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions