The maintenance sequence I use for small systems contains an awkwardly manual step. After the reports are gathered and before any cleanup happens, I read the candidates and decide what not to touch.
It would be easy to automate. The inputs are structured. Old images, unused volumes, stale local artifacts, and retired configuration fragments can all be ranked by age or apparent reachability. A script can print a convincing list in seconds. It can also be confidently wrong about the one artifact I’ll need when a rollback stops being theoretical.
So the collection is automatic and the deletion isn't.
That boundary came from walking the workflow end to end, not from a general suspicion of automation. The first phase gathers facts that are tedious and safe to repeat. It lists candidates, records sizes, traces references from active configuration, and notes the last observed use where that evidence exists. It doesn't hide items that fail one of those lookups. An unknown reference becomes part of the review instead of quietly earning the same score as an unused object.
The output lands as a dated text report. I want a boring artifact that can be searched, compared with the previous run, and opened without the tool that produced it. A dashboard would be prettier, but this is occasional work. I don't need to maintain an application so I can avoid reading a file.
Then I review the report in context. Is the related service actually retired, or merely stopped? Does the current configuration still name the artifact? Is there an older rollback path that assumes it exists? Is the storage pressure real enough to justify removing it now? Those aren't impossible questions for software. They’re questions whose inputs extend beyond the filesystem and change too irregularly to make a trustworthy rule cheap.
I mark each candidate as keep, remove, or investigate. “Investigate” matters. Without it, uncertainty gets forced into the two categories most convenient for a script. Keep forever wastes space. Remove now can waste an evening. A third state lets the review stay honest without blocking obvious cleanup.
The manual step changes the economics
Automation pays when a stable decision can be exercised many times. The collection phase fits. Paths can be enumerated, references can be checked, and output can be regenerated without harm. My judgment phase is low-frequency and consequence-heavy. It depends on recent changes, future plans, and whether I’m willing to give up a fallback.
Encoding all of that would require a durable inventory of intent: why an artifact exists, which recovery path uses it, when that path expires, and who can retire it. Such an inventory could be worthwhile in a larger environment. In a small one, maintaining it might cost more than reading the report carefully. Worse, a half-maintained inventory would make the deletion rule look safer than it was.
There’s also value in friction. Deletion should feel different from observation. I don't want a cleanup job to acquire destructive authority because the read-only half has behaved well for months. Reliable collection proves reliable collection. It doesn't prove the classification captures every reason to retain an object.
After review, a separate command accepts only the explicitly marked removal set. It prints the resolved targets again and refuses unresolved entries. I don't pass a broad directory or a wildcard. The command creates a final manifest before making changes, and the report records what actually happened. If a target changed between review and execution, it stops rather than expanding the interpretation of my approval.
That last detail keeps the manual boundary useful. A human click isn't magic. If the execution step can reinterpret the decision, then I’ve only moved ambiguity behind a confirmation prompt. The reviewed object and the acted-on object have to be the same.
The whole sequence is slower than unattended cleanup. It’s also faster than doing everything by hand. Collection, comparison, formatting, and execution are exactly the parts software handles well. I spend my attention on the small set of candidates where history and intent matter.
I use the same division in a few other maintenance tasks. Scripts find expiring material, drift, oversized paths, and records that don't match expected structure. They prepare commands and group the easy cases. I keep the final call when the operation is hard to reverse, the policy is still moving, or the exception rate is high enough that “automatic” would mostly mean “surprising in batches.”
This isn't a claim that destructive work should never be automated. Mature systems can have strong lifecycles, retention policies, quarantine periods, and tested recovery. When those mechanisms exist, a person approving every item can become theater. But I won't invent that maturity with a cron schedule.
My test is practical: can I explain the rule completely, supply its inputs reliably, and recover from a wrong decision at acceptable cost? If not, I automate the preparation and leave the decision exposed.
The report still occasionally contains an obvious candidate I’m tempted to let the script remove next time. I haven't taken that shortcut. Reading one extra line is cheap. Reconstructing why a supposedly unused artifact mattered is not.