Skip to content

disk-hygiene: add a gated managed-state lane with a bundled owner registry #4006

Description

@kyle-sexton

Drafted by an AI agent from an operator-confirmed interview (run 20260908-home-d1).

Parent

Parent: #4004. Refs #3855 (the proportionality decision carrier) and #3860 (the managed-state exclusion). This resolves the operator side of #3855 without touching engine containment, and it is the concrete shape #3860 asks for.

Problem

The engine is correct to refuse managed state. It is not correct that refusing it is the end of the interaction.

On this run the engine deleted 726 bytes of unmanaged residue. Roughly 60 GB of reclaimable-by-its-owner state was identified alongside it, and every one of those handoffs was composed by the model, one command at a time, with nothing shipped to draw on:

Location Owner Size Read-only result Native cleanup, hand-composed during the run
AppData\Local\Docker Docker Desktop (running) 103.1 GB docker system df: 23.4 GB of 30.4 GB images reclaimable, 0.9 GB of 3.0 GB build cache docker image prune, docker builder prune
AppData\Local\NVIDIA NVIDIA driver 32.2 GB n/a Disk Cleanup "DirectX Shader Cache", or the shader-cache size setting
AppData\Roaming\Cursor Cursor IDE (running) 20.8 GB n/a in-app cache clearing, backups retention
.codex OpenAI Codex CLI 5.63 GB archived_sessions 3.77 GB, logs_2.sqlite 1.51 GB Codex history/retention config
.cache\chezmoi chezmoi 808 MB chezmoi doctor clean no cache command; httpcache re-downloads on next apply
.pulumi Pulumi 3.260.0 325 MB pulumi about clean; github plugin 6.14.0 and 6.15.0 installed pulumi plugin ls, then pulumi plugin rm for the unused version

Six of roughly twenty such entries. The read-only probes (docker system df, pulumi about, chezmoi doctor, dotnet nuget locals all --list, ollama list) all had to be recalled and authored per run, and each cost a permission prompt. The next run starts from zero again.

What to build

A gated managed-state lane beside the engine lane, not inside it.

A bundled owner registry maps a known path to:

  • the owning product,
  • the product's read-only / dry-run command,
  • the product's destructive native command,
  • the platforms each applies on.

The engine lane is unchanged: it still deletes only unmanaged residue, and it still never deletes managed state. The managed lane never deletes either. It reports the owner and offers the owner's own commands.

Design constraints

  • Containment is untouched. This lane adds no deletion capability to the engine. It emits and, under approval, runs the owner's command. Nothing here changes what the engine itself may remove.
  • Read-only and destructive are different gates. A dry-run command may be offered freely. The destructive command runs only under the same tier-and-exact-list approval as the engine lane — same ceremony, same exact-path enumeration, same fresh preview.
  • Tool presence is checked before either command is offered. The run's own shape shows why: .aws, .biome and .gitbook were disposable precisely because the owning tool was absent from PATH. Offering aws configure for an absent AWS CLI is noise.
  • A registry entry is a hint, never authorization. The same rule the engine already applies to filename hints applies here: a path matching a registry entry is a starting point for an owner claim, not proof of one.
  • An unmatched managed-looking path stays a coverage gap. The run recorded several AppData\Local directories that look like leftovers of uninstalled games with nothing matching under Program Files, and correctly did not triage them further, because Steam/Epic/GOG libraries often live on another drive. That posture must survive: unknown means unknown, not "probably safe".
  • The registry ships with the plugin and is inspectable. An operator must be able to read what the component believes about a path without running it.

Acceptance criteria

  • A bundled owner registry exists, is inspectable as data, and maps path patterns to owner, read-only command, destructive command, and platform.
  • A managed-state match is reported with its owner and its read-only command, and the read-only command's output is surfaced in the report.
  • The destructive command is offered only behind the same tier-and-exact-list approval the engine lane uses, demonstrated by a test that shows the approval path is shared, not parallel.
  • A registry entry whose owning tool is not present on the machine is reported as absent-tool and does not offer commands.
  • A managed-looking path with no registry match is reported as a coverage gap, not as clean and not as removable.
  • The engine lane's eligibility rules are unchanged by this work, demonstrated by a test.
  • scripts/affected-tests.sh --run selects and passes the suites mapped to the changed files.

Out of scope

Activity

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

    priority: mediumReal value, no hard deadline; normal backlog flow.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions