Skip to content

feat(destroy): remove an environment and reclaim what it holds - #45

Merged
olamide226 merged 2 commits into
mainfrom
feat/avr-destroy
Aug 1, 2026
Merged

feat(destroy): remove an environment and reclaim what it holds#45
olamide226 merged 2 commits into
mainfrom
feat/avr-destroy

Conversation

@olamide226

Copy link
Copy Markdown
Owner

Implements task 30 / REQ-5.6–5.8 — the gap found while preparing for a public release.

Why

Every other lifecycle verb already existed:

Verb Before Now
create / start implicit on first avr unchanged
stop avr stop, --all unchanged
idle-stop automatic unchanged
reset destroy + recreate unchanged
remove nothing avr destroy

avr reset destroys and immediately recreates. avr isolate off reaches only the current project's machine, and only from inside that project's directory. So reclaiming an environment's disk meant limactl delete — the backend-management model REQ-1.5 exists to prevent.

Behaviour

avr destroy              # this directory's environment
avr destroy --all        # every environment avar manages
avr destroy --orphaned   # isolated environments whose project directory is gone
avr destroy --yes        # skip the confirmation

--orphaned is the one that could not be done any other way. Once a project directory is deleted, avr isolate off cannot be run — it needs you to stand in the directory. Those environments were unreachable and accumulated forever. They are matched through avar's own records (which project an isolated machine serves is bookkeeping no backend can be asked), and each is named by its project:

Destroying Ubuntu 24.04 · arm64 for /Users/olamide/orphan-a…
Destroying Ubuntu 24.04 · arm64 for /Users/olamide/orphan-b…

Without that, several orphans of the same distro print the same sentence repeatedly, and REQ-5.8 requires naming the project each belonged to.

Confirmation is proportionate. A single environment is confirmed by typing its name — identical to avr reset, so the two read the same. --all wants the word all, because removing everything should not be one keystroke. --orphaned takes a yes: those projects are already deleted and the list has just been shown.

Only isolated machines can be orphaned. A shared machine serves every project at once, so no single directory disappearing makes it unwanted, and a base machine serves future clones.

A bug the tests caught

readLine first used fmt.Fscanln, which stops at whitespace. Environment labels contain spaces (Ubuntu 24.04 · arm64), so it compared the answer against only its first word and no correct answer would ever have been accepted. Now reads a whole line.

Requirements covered

REQ Criterion How
5.6 Remove the current environment, confirm, --yes bypass, host files unaffected runDestroy default scope
5.7 --all removes every environment, reports the count scopeAll
5.8 --orphaned removes isolated environments whose project is gone, naming each project orphanedMachines + environmentOf
PROP-10 Host project files never affected e2e writes from host and guest, checks both survive a destroy

Verification

make build / lint / tidy-check    pass
go test -race ./...               all packages pass
go test -tags e2e -run TestDestroy  2 passed (17.1s) against real Lima

Also exercised by hand: created two isolated environments, deleted both project directories, and confirmed --orphaned found and removed exactly those two while leaving the shared and base machines alone.

tasks.md checkbox 30 is left unticked per the working agreement — it is ticked when this merges.

Every other lifecycle verb existed already — create, start, stop, idle-stop,
reset — and removal did not, so an environment could be created but never
deliberately removed. avr reset destroys and immediately recreates; avr isolate
off reaches only the current project's machine and only from inside that
project's directory. A user wanting the disk back had to run limactl, which is
the model REQ-1.5 exists to prevent.

avr destroy removes the environment for the current directory. --all removes
every one avar manages. --orphaned removes isolated environments whose project
directory no longer exists, which nothing else can reach: isolate off must be
run from a directory that has been deleted. Records and the SSH host entry go
with the machine.

Confirmation is proportionate to what is at stake. A single environment is
confirmed by typing its name, exactly as reset asks, so the two read the same.
--all wants the word "all", because removing everything should not be one
keystroke. --orphaned takes a yes: those projects are already gone and the list
has just been shown.

Host project files are never affected — they are shared, never copied — and the
e2e test proves it by writing from both host and guest and checking both
survive.

Requirements: REQ-5.6, REQ-5.7, REQ-5.8
Properties: PROP-10
Four review passes over the destroy command. Two findings were defects rather
than cleanups.

environmentOf formatted the selector directly instead of using
environmentLabel, which guards the case where a machine's selector could not be
recovered. avarOwned lists on the name prefix alone — deliberately, so a machine
left by a crash mid-create stays visible — and such a machine rendered as
"  · ". The single-environment path then asks the user to type that label, so
the environment could never be destroyed: exactly the machines most in need of
it.

The live-session warning read MachineStatus.Sessions, which no provider
populates — cmd/status.go counts from avar's own records, because a backend has
no idea what an avr session is. The check was always false. It now counts from
the store, and the summary says when destroying would take somebody else's
terminal with it.

Cleanups: one confirmByTyping helper on App replaces destroy's readLine and
reset's confirmReset, settling two divergent EOF policies on the safer one; one
forgetMachine replaces the record and SSH-host removals that were always called
as a pair; the record and project reads became one transaction; and the
redundant sort, counter, scope-tracking variable and duplicated test went.

Grammar: "3 environments no longer has its project directory" now agrees.

Property 10 is widened from "Reset scoping" to all destructive operations and
validates 5.6-5.8. It was quantified over avr reset alone and this work cited
it anyway, which is the failure docs/lessons.md already records.

README moves destroy out of the roadmap and into the command table: it said the
command was not implemented, which this branch makes false.

Requirements: REQ-5.6, REQ-5.7, REQ-5.8, REQ-1.5
Properties: PROP-10
@olamide226
olamide226 merged commit bc8cc03 into main Aug 1, 2026
2 checks passed
@olamide226
olamide226 deleted the feat/avr-destroy branch August 1, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant