Clearing the fleet's four leftover agents returned 404 on every one. They had
been soft-deleted back in June — correctly invisible in the UI ever since — and
`agents::get` filters `deleted_at IS NULL`, so `workspace_agent` could not find
them. Every route uses it, including `batch-delete`, the one that exists to
HARD-purge. So a soft-deleted agent was unreachable from the application
entirely and its row stayed forever.
`get_any` sees them, and only the purge path uses it: hiding soft-deleted rows
is right for every read, and wrong for the one operation whose whole job is
removing them. Written with `query_as` rather than the checked macro so it does
not force an offline-cache regeneration on every machine that builds this.
`fleet-reset.sh` now uses `batch-delete` for agents rather than
`DELETE /api/claws/{id}`. The latter is a SOFT delete, so pointing a reset
script at it would have quietly added to the pile it was meant to clear.
Co-Authored-By: Claude Opus 5 <[email protected]>
For a clean slate before a UI session, and for the thing that keeps being true
here: deleting a row has never deleted a directory. A full harness run leaves
~35 missions, each with a repo checkout and a runtime-data tree, on the smallest
disk in the fleet. There are 125 rows and 117 directories right now.
Deletes through the API, never with SQL. `missions::delete` tears down the
per-mission runtime container, hard-purges the FK graph in order, and removes
the workspace directory — falling back to a root purge for the files the
per-mission daemon leaves as root. A `DELETE FROM missions` skips all three and
orphans every one of them, which is how the orphans got there.
Then it checks, because rows gone is not bytes back and every incarnation of
this cleanup has managed the first while silently failing the second: it names
each directory left without a row, and counts root-owned residue separately
because that is the specific way it fails.
Refuses outright while any mission is RUNNING. Yanking a live mission's checkout
leaves a VM writing into a directory that no longer exists, and the symptom is a
phase that hangs rather than one that fails. Verified: it stopped exactly there
against the in-flight harness.
Dry by default; `--yes` to act; `KEEP=<substring>` to spare some.
Co-Authored-By: Claude Opus 5 <[email protected]>