You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Name the sources in --purge's "Leaving N workspace(s)" list, and say what removing the cache costs the survivors.
The smallest high-value change on this map, and #452 argued why it is worth its own ticket: principle 2 is satisfied far more cheaply by the user can see it and decide than by reclaiming anything, and this is the one screen where somebody is actually deciding.
Two changes:
The leaving list prints workspace ids and never sources. A user looking at pythontemplate and my-hand-made-workspace cannot tell which is a dl <path> workspace whose clone is theirs and which is a hand-made one. Print the source beside the id.
Add a sentence that removing the cache drops what devlaunch knew about the survivors. This matters more after #456: the per-workspace markers live in the cache, so a purge that leaves foreign workspaces standing also destroys the records naming their volumes, and their volumes then become exactly the orphans Orphaned volumes with no surviving record #451 declined to reclaim.
Cost, already scoped: one golden in rust/dl/tests/lifecycle.rs and a paragraph in docs/cleanup.md. No em or en dashes in docs/ (test_docs_prose.py).
Deliberately not in scope: the dl --ls degradation under a moved repos_dir, which waits on whether repos_dir is supported at all.
breadcrumb: unblocked by #460, and smaller than when it was filed.
The dl --ls degradation this ticket deferred needs no build work at all. repos_dir is being retired (#467), which makes is_devlaunch_clone's containment test complete, so the devlaunch:false / SIZE - / unsaved:null case stops being a bug to fix and becomes unrepresentable. Re-blocked on that ticket rather than on the decision, so the ordering is explicit.
What remains is the original first half only, and one of its three examples goes with the retired key: print the source beside the id in the leaving list, and add the sentence about what removing the cache costs the survivors. That second half matters more after #456, since the per-workspace markers live in the cache.
breadcrumb: scope note and a second blocker, both from #459.
The purge figure folds into this ticket. It is the same golden (PURGE_PLAN, rust/dl/tests/lifecycle.rs:751) and the same docs/cleanup.md paragraph as the leaving-list change already here, so two PRs over one prompt would be waste.
How it must be computed, because the obvious route is wrong. Not by reusing prune_plan: that weighs only clones it removes and only worktrees inside clones it keeps, and purge's set is the union of both exclusions. It is a walk over <cache_dir>/repos — cache_dir, per R1, never the retired repos_dir — under run_if_lock_free, because prune_plan's per-repo lock is an unbounded wait while purge_all_data takes no lock at all, so a blocking report would be stricter than the deletion it precedes. And the figure is not a usize: 0 would mean both "nothing at risk" and "could not weigh", which is devlaunch#171's shipped bug one level up.
Blocked on #446 as well as #467, because the count is only worth printing once the clone-level guard can see nested agent worktrees. Today it cannot, and a figure derived from the blind probe would read "0" over 104.5 GB of unsaved work, which is worse than printing nothing.
If that reach does not land, the escape hatch from #459 applies instead: print no count, and make the current position explicit in docs/cleanup.md and #455's row as "the confirmation, and nothing else", with the reason beside it.
breadcrumb: unblocked by #467 (PR #481), and the review there handed this ticket a concrete case it must cover rather than a general aspiration.
Reproduced: seed a devpod workspace whose localFolder is <retired repos_dir>/blooop/devlaunch/devlaunch-main-3j1t, which is exactly what a pre-#467dl left on any machine that set the key. dl --purge -y prints
Leaving 1 workspace(s) devlaunch did not create:
- devlaunch-main-3j1t
an opaque id with no path, while the same run deletes the metadata.json record that last pointed at the tree. commands.rs:801 never opens dl's records, so #467's migration notice does not fire on this path either. It is not permanent silence, since the notice returns on the next records-opening command while the key remains, but --purge is the one command whose promise is nothing left, and this is a tree it neither removes nor names.
Two things this ticket now owns, then: naming the source beside each left workspace (its original scope), and deciding whether the retired-key notice belongs on the purge path. #467 deliberately left the second alone because printing it there means editing what a purge says about what it leaves, which is this ticket's surface.
Also from #467: this ticket's first bullet loses the clause "which is devlaunch's own under a moved repos_dir", since a configuration can no longer place a clone anywhere. The stranded-by-a-prior-build case above replaces it, and is narrower and real.
Claimed 2026-08-29: build in progress from an interactive session (agent in an isolated worktree), managed by session devlaunch-2b as part of closing out map #444. PR to follow. If you are another session looking at this ticket, pick a different one.
Both halves of the remaining scope, plus the decision #467 handed over.
The source beside the id, from describe_source -- the same reading dl --ls's SOURCE column uses, so the two surfaces cannot describe one workspace differently. The unreadable-source arm is printed as devpod's object and said to be one, rather than sitting after a colon looking like a path.
What the cache costs the survivors, in two sentences under the list: they keep working, and a clone an older dl placed outside the cache is named only by a record inside it, so dl <ws> rm afterwards takes the workspace and leaves the tree. Not a claim about volumes, because those names are read from workspace_result.json under DEVPOD_HOME, which a purge does not touch. The doc comment on the constant is where Keep devlaunch's own copy of the volume names, and reclaim from it #456 will change that sentence.
The retired-key notice does belong on this path, answered yes. It reads config.toml directly rather than opening dl's records: opening them runs the cache migration, which would write records into the tree the command is about to remove and into one an aborted purge was asked to leave alone. Where a workspace still opens such a clone the list names the path; where none does, the notice is the only mention that tree gets.
#481's reproduced case is a fixture (--stranded-clone) and a test: the plan names the path, the notice is on stderr, and after -y the tree is still standing while its record is gone, which is what the new sentences warn about.
Not in scope and not attempted: the purge figure from #459, still blocked on #446.
Activity
blooop commentedon Aug 25, 2026
breadcrumb: unblocked by #460, and smaller than when it was filed.
The
dl --lsdegradation this ticket deferred needs no build work at all.repos_diris being retired (#467), which makesis_devlaunch_clone's containment test complete, so thedevlaunch:false/SIZE -/unsaved:nullcase stops being a bug to fix and becomes unrepresentable. Re-blocked on that ticket rather than on the decision, so the ordering is explicit.What remains is the original first half only, and one of its three examples goes with the retired key: print the source beside the id in the leaving list, and add the sentence about what removing the cache costs the survivors. That second half matters more after #456, since the per-workspace markers live in the cache.
blooop commentedon Aug 25, 2026
breadcrumb: scope note and a second blocker, both from #459.
The purge figure folds into this ticket. It is the same golden (
PURGE_PLAN,rust/dl/tests/lifecycle.rs:751) and the samedocs/cleanup.mdparagraph as the leaving-list change already here, so two PRs over one prompt would be waste.How it must be computed, because the obvious route is wrong. Not by reusing
prune_plan: that weighs only clones it removes and only worktrees inside clones it keeps, and purge's set is the union of both exclusions. It is a walk over<cache_dir>/repos—cache_dir, per R1, never the retiredrepos_dir— underrun_if_lock_free, becauseprune_plan's per-repo lock is an unbounded wait whilepurge_all_datatakes no lock at all, so a blocking report would be stricter than the deletion it precedes. And the figure is not ausize: 0 would mean both "nothing at risk" and "could not weigh", which is devlaunch#171's shipped bug one level up.Blocked on #446 as well as #467, because the count is only worth printing once the clone-level guard can see nested agent worktrees. Today it cannot, and a figure derived from the blind probe would read "0" over 104.5 GB of unsaved work, which is worse than printing nothing.
If that reach does not land, the escape hatch from #459 applies instead: print no count, and make the current position explicit in
docs/cleanup.mdand #455's row as "the confirmation, and nothing else", with the reason beside it.blooop commentedon Aug 25, 2026
breadcrumb: unblocked by #467 (PR #481), and the review there handed this ticket a concrete case it must cover rather than a general aspiration.
Reproduced: seed a devpod workspace whose
localFolderis<retired repos_dir>/blooop/devlaunch/devlaunch-main-3j1t, which is exactly what a pre-#467dlleft on any machine that set the key.dl --purge -yprintsan opaque id with no path, while the same run deletes the
metadata.jsonrecord that last pointed at the tree.commands.rs:801never opens dl's records, so #467's migration notice does not fire on this path either. It is not permanent silence, since the notice returns on the next records-opening command while the key remains, but--purgeis the one command whose promise is nothing left, and this is a tree it neither removes nor names.Two things this ticket now owns, then: naming the source beside each left workspace (its original scope), and deciding whether the retired-key notice belongs on the purge path. #467 deliberately left the second alone because printing it there means editing what a purge says about what it leaves, which is this ticket's surface.
Also from #467: this ticket's first bullet loses the clause "which is devlaunch's own under a moved
repos_dir", since a configuration can no longer place a clone anywhere. The stranded-by-a-prior-build case above replaces it, and is narrower and real.blooop commentedon Aug 29, 2026
Claimed 2026-08-29: build in progress from an interactive session (agent in an isolated worktree), managed by session devlaunch-2b as part of closing out map #444. PR to follow. If you are another session looking at this ticket, pick a different one.
blooop commentedon Aug 29, 2026
breadcrumb: built in #515.
Both halves of the remaining scope, plus the decision #467 handed over.
describe_source-- the same readingdl --ls'sSOURCEcolumn uses, so the two surfaces cannot describe one workspace differently. The unreadable-source arm is printed as devpod's object and said to be one, rather than sitting after a colon looking like a path.dlplaced outside the cache is named only by a record inside it, sodl <ws> rmafterwards takes the workspace and leaves the tree. Not a claim about volumes, because those names are read fromworkspace_result.jsonunderDEVPOD_HOME, which a purge does not touch. The doc comment on the constant is where Keep devlaunch's own copy of the volume names, and reclaim from it #456 will change that sentence.config.tomldirectly rather than opening dl's records: opening them runs the cache migration, which would write records into the tree the command is about to remove and into one an aborted purge was asked to leave alone. Where a workspace still opens such a clone the list names the path; where none does, the notice is the only mention that tree gets.#481's reproduced case is a fixture (
--stranded-clone) and a test: the plan names the path, the notice is on stderr, and after-ythe tree is still standing while its record is gone, which is what the new sentences warn about.Not in scope and not attempted: the purge figure from #459, still blocked on #446.