# scratch-dirs — hidden, tracked, always cleaned up

## Why this exists

Every scratch directory is a promise to clean up. Untracked scratch dirs are how
workspaces fill with `new` folders, extracted tarballs, and mystery dumps —
invisible because they are mixed in with real work. The contract:

1. **Hidden** — always `.scratch` (dot-prefixed), so it never appears in
   directory listings, tab-completion, glob sweeps, or git status.
2. **Named** — one dir per task, named for the task, not `tmp` or `new`.
3. **Tracked** — a manifest records what exists and why, so cleanup never
   depends on memory.
4. **Deleted** — removed when its use is complete, or the user is asked.
   Nothing survives a task silently.

## Creating a scratch dir

Default location: inside the task working context — the repo or directory the
work is about, as a hidden dir:

    <workdir>/.scratch/<task-name>/

Rules:

- **Dot-prefixed always.** `.scratch`, never `scratch` — a visible scratch
  dir reads as real content to humans and globbing tools alike.
- **One dir per task, task-named:** `.scratch/values-diff-20261011`,
  `.scratch/tarball-inspect`. Never a bare `.scratch` dumping ground shared
  across unrelated tasks.
- **Never inside a path a build or package step sweeps** (a chart templates dir,
  a repo dir that gets `.tgz`-packaged, a synced/stfolder path). If the
  workdir is sweep-risky, use `~/.dsh/tmp-<task-name>/` instead — that
  pattern is already established in this DSH home.
- **Tracked:** append a manifest entry to `~/.dsh/.scratch-manifest.json`
  whenever a scratch dir outlives its immediate command:

```json
{ "path": "/abs/path/.scratch/values-diff-20261011", "task": "docker-bump diff",
  "created": "2026-10-11T12:50:00-04:00" }
```

## The cleanup decision (delete vs ask)

The default is **auto-delete**: when the task that needed the dir completes,
delete it in the same breath as the final step, and say so. Do not defer.

**Ask instead of deleting** when any of these hold:

- The dir contains output the user might want to keep (a report, a rendered
  diff, an artifact produced by an agent).
- The task ended abnormally (killed mid-run, errored partway) — contents may
  hold diagnostic value.
- The contents came from the user (uploaded files, pasted data) rather than
  being generated by the work.
- Deletion would need to reach outside the dir you created.

When asking, give the path, size, and a one-line contents summary, and offer:
delete / keep / move somewhere durable. Never delete user-sourced content
without asking.

## Session-end sweep

When a task or session is wrapping up:

1. Check the manifest plus a quick `find . -maxdepth 3 -name .scratch -type d`
   over the workdirs touched this session.
2. Report any survivors to the user with the ask-or-delete rule above.
3. Delete manifest entries for dirs that no longer exist.

## Failure modes this prevents

- **Visible scratch clutter** — `scratch/`, `tmp/`, `new/` folders polluting
  repos and confusing glob-based tooling.
- **Orphaned extraction dirs** — tarballs unpacked next to their source and
  forgotten because the task moved on.
- **Swept-into-build scratch** — scratch content silently packaged into a
  chart tgz or committed because it sat inside a swept path.
- **Silent survival** — a cleanup that "will happen later" with no reminder
  mechanism. If auto-delete cannot run, the ask does.

## Relationship to other skills

- `guard-uncommitted-work` — before any agent or cleanup step runs git state
  operations, that skill gates first; never let scratch cleanup eat
  uncommitted work.
- `memory-curation` — durable memory hygiene is a different concern; scratch
  dirs are throwaway by contract, memory is kept by design.