agentleFS
selamy-labsselamy-labs/agent-skills/skills/ephemeral-workspace-lifecycle/SKILL.md

ephemeral-workspace-lifecycle

Skill0 starsChanged 5 days agoMITView on GitHub

Use when creating, inheriting, handing off, or cleaning a temporary worktree, clone, task directory, build output, or local cache. Give every ephemeral resource an owner and terminal cleanup contract, preserve dirty work, and prevent scratch storage from exhausting its host.

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. About 0 are common, 16 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈16

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Treat ephemeral resources as leases.

    line 8
  2. Distinctive:

    Do not apply one deletion policy to everything called a workspace or cache.

    line 13
  3. Distinctive:

    Use a canonical managed scratch root.

    line 30
  4. Distinctive:

    Create the path with permissions that prevent another user from replacing the resource or its manifest.

    line 36
  5. Distinctive:

    Check free space on every backing filesystem that will receive a workspace, output base, or cache.

    line 38
  6. Very specific:

    Treat language temporary-directory APIs and /tmp as placement mechanisms, not lifecycle managers.

    line 41
  7. Distinctive:

    Prefer a separate quota-controlled filesystem for high-churn workspaces and local build caches.

    line 45
  8. Distinctive:

    Use explicit states rather than interpreting age as task state:

    line 51
  9. Distinctive:

    Before removal, atomically claim the resource for reaping and require every task reference to be in a terminal state.

    line 64
  10. Distinctive:

    Run every gate immediately before mutation while holding the reaper claim:

    line 100
  11. Distinctive:

    Use the resource-specific contract below.

    line 111
  12. Distinctive:

    Treat ignored files as work, so any output retains the worktree.

    line 132
  13. Very specific:

    Do not use --force or repository-wide git worktree prune in unattended per-resource cleanup.

    line 157
  14. Distinctive:

    When no native operation exists, delete only the exact canonical output path recorded in the manifest with the common containment gates.

    line 184
  15. Distinctive:

    If native GC is unavailable, alert and design a cache-specific reaper.

    line 190
  16. Distinctive:

    Run cleanup on authoritative terminal task transitions and as a periodic safety net.

    line 195
  17. Very specific:

    Remove verified terminal-removable exclusive resources immediately.

    line 198
  18. Distinctive:

    Keep an allowlist of managed roots and resource classes, dry-run output, an append-only audit log, and mutual exclusion between admission …

    line 203
  19. Distinctive:

    Do not claim the task fully complete while its ephemeral resources have no verified disposition.

    line 217

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Ephemeral Workspace Lifecycle

Treat ephemeral resources as leases. Cleanup is part of task completion unless a named owner intentionally retains the state.

Classify Before Creating

Do not apply one deletion policy to everything called a workspace or cache.

ResourceOwnership proofAutomatic removal authorityRemoval method
Linked Git worktreeTask manifest plus matching git worktree list --porcelain entryOnly after the task is terminal, the tree is clean, and its exact commit is durably recoverablegit worktree remove for the validated path
Full temporary cloneExclusive task manifest at a canonical managed pathOnly after the task is terminal, the clone is clean, and every local commit is durably reachable from a freshly verified remoteVCS-aware inspection followed by contained directory removal
Exclusive task directoryUnpredictable per-task ID, creator UID, and canonical path in the manifestOnly after the task is terminal and every nested resource has its own safe dispositionDescriptor-relative, no-symlink contained removal
Per-task build output or cacheExact output path and owning task in the manifestOnly after no process or active task references itTool-native clean or garbage collection; contained removal only when the tool has no native operation
Shared or global cacheHost policy and cache-manager identity, never a single task manifestNever as part of task teardownCache-native size/age GC, quota, or eviction under a host-wide lock

An exclusively owned workspace may be deleted as one task resource only when every nested resource is also exclusive to that task. Shared caches, credential stores, tool installations, registries, logs, and user state are separate resources even when they appear below a convenient parent path.

At Creation

  • Use a canonical managed scratch root. Resolve and record both the root and resource paths before creating anything; reject paths outside the root, symlinked roots, mount crossings, and reused ownership markers.
  • Record a random task/workspace ID, creator UID, task owner, repository, branch or commit, resource class, canonical path, creation time, heartbeat, protected state, and terminal cleanup rule.
  • Create the path with permissions that prevent another user from replacing the resource or its manifest.
  • Check free space on every backing filesystem that will receive a workspace, output base, or cache. Stop admitting new build-heavy work below the host's hard watermark.
  • Treat language temporary-directory APIs and /tmp as placement mechanisms, not lifecycle managers. Record the resource before launching the worker; do not depend on process exit, reboot, or an operating-system temp reaper.

Prefer a separate quota-controlled filesystem for high-churn workspaces and local build caches. A full scratch volume may fail a task; it must not make the host root filesystem unhealthy.

Registry State

Use explicit states rather than interpreting age as task state:

active -> terminal-removable -> removed
active -> terminal-retained
terminal-retained -> terminal-removable -> removed

The task owner or authoritative task system performs the terminal transition. A missing heartbeat or old modification time is not a terminal transition. Reconcile orphaned active records with the task system; retain and alert when that proof is unavailable.

Before removal, atomically claim the resource for reaping and require every task reference to be in a terminal state. After removal, replace the live registry entry with an immutable tombstone containing the path, resource ID, terminal evidence, removal time, and bytes reclaimed. A tombstone is audit history, not a live reference, so it does not prevent removal or keep a lease active.

Finalization Ownership

The controller that allocates a resource owns its final disposition. Register an exit observer before launching the worker and invoke the terminal lifecycle on success, merge or close, cancellation, iteration exhaustion, ordinary client exit, and handled failure. Do not make the worker process the sole owner of cleanup.

A worker finally block, defer, shutdown hook, or temporary-directory context is a useful fast path, but OOM, SIGKILL, host loss, and client crashes can bypass it. After a worker exits, the controller must reconcile any resource still marked active; the periodic reaper remains a backstop for controller loss. Every path ends as removed, retained, or blocked with evidence.

At Handoff

Either remove the resource or record:

  • why it must remain
  • who owns the next action
  • the exact canonical path and current branch, commit, or task
  • whether it is dirty or contains unpushed work
  • an expiry or next-review time
  • whether each nested cache/output is exclusive or shared

An unowned path with no expiry is a leak.

Common Safety Gates

Run every gate immediately before mutation while holding the reaper claim:

  1. Re-resolve the managed root and candidate without following a final symlink. Require the expected root, creator UID, resource ID, filesystem, and direct containment relationship to still match the manifest.
  2. Refuse symlinked roots, candidates, unknown nested mounts, path traversal, ownership mismatches, missing/malformed manifests, and probe errors.
  3. Confirm no live process, open file, current working directory, heartbeat, lock, or nonterminal task registry entry references the candidate.
  4. Preserve durable artifacts, useful logs, handoff evidence, dirty state, and commits before reclaiming rebuildable data.
  5. Use the resource-specific contract below. Never replace a failed native cleanup with an unconditional recursive delete.
  6. Record the resource ID, exact path, safety evidence, bytes reclaimed, reason, and before/after free space in an append-only audit sink.

Resource-Specific Removal

Linked Git worktree

From the shared repository, confirm that the candidate is the exact canonical path reported by git worktree list --porcelain. Run every Git safety probe as the resource-owning UID, never as a privileged controller. Use a trusted absolute Git executable and sanitized environment; disable system/global configuration and executable integrations with GIT_CONFIG_NOSYSTEM=1, GIT_CONFIG_GLOBAL=/dev/null, -c core.fsmonitor=false, and -c core.hooksPath=/dev/null. Sanitize PATH, GIT_EXEC_PATH, and dynamic loader variables too. Fail closed if the privilege drop or sanitization is unavailable.

Enumerate tracked, untracked, and ignored descendants with git status --porcelain=v1 --untracked-files=all --ignored=traditional. Treat ignored files as work, so any output retains the worktree. Clean a generated output only through its separate resource-specific contract, then re-run the status probe; never infer that an ignored path is rebuildable from its name. Also inspect git ls-files -v. Retain the worktree when it has lowercase status tags (assume-unchanged), an S tag (skip-worktree), or other hidden index state; do not silently clear those flags. Re-run both probes immediately before removal and retain on unknown or remaining content. Refresh the trusted remote and prove the exact worktree commit is reachable from the intended durable remote ref; an unrelated merged PR number is not proof.

A squash or rebase merge does not make the original task HEAD reachable from the destination branch. Before deleting that worktree or its task branch, preserve the exact HEAD in either a protected archival ref on the trusted remote or a Git bundle stored outside every ephemeral root. Verify the archival ref or bundle enumerates that exact commit and can restore it, then record its location, commit, verification result, and retention policy in the terminal evidence. Fail closed if archival creation or verification fails. The same archival step is required whenever deleting a remote task branch would invalidate the only reachability proof.

cd <main-repository>
git worktree remove <canonical-workspace>

Do not use --force or repository-wide git worktree prune in unattended per-resource cleanup. Pruning scans registrations that are outside the validated resource and may only run as a separate repository maintenance operation with its own ownership and safety checks.

Full temporary clone

Require a clean tracked and untracked status and enumerate every local ref and commit that is not reachable from the freshly fetched trusted remote. Retain the clone if fetch, reachability, submodule, nested-repository, or object-health checks fail. Remove it only by an implementation that anchors traversal to an already-open managed-root directory, rejects symlinks and mount crossings, and cannot escape through path replacement.

Exclusive task directory

Require the unpredictable resource ID and creator UID from the protected manifest. Inventory nested repositories, mounts, sockets, outputs, and caches; apply the matching contract to each. Remove the directory only when the inventory contains no unknown or shared resource. Use descriptor-relative deletion that does not follow symlinks and re-check the directory identity immediately before unlinking it.

Build outputs and caches

For a per-task output base or cache, use the build tool's shutdown, clean, expunge, or garbage collector after verifying that no live process uses it. When no native operation exists, delete only the exact canonical output path recorded in the manifest with the common containment gates.

For shared/global caches, task completion may release a reference but must not delete the cache tree. Use the cache manager's native GC under a host-wide lock with a size budget, minimum free-space target, and protected active entries. If native GC is unavailable, alert and design a cache-specific reaper; do not generalize the workspace recursive-delete path.

Scheduled Reaping

Run cleanup on authoritative terminal task transitions and as a periodic safety net.

  • Remove verified terminal-removable exclusive resources immediately.
  • Reconcile stale active leases with the task system; never infer terminal state from age alone.
  • Alert on dirty, protected, retained, unknown-owner, shared, or probe-failed resources.
  • Keep an allowlist of managed roots and resource classes, dry-run output, an append-only audit log, and mutual exclusion between admission and reaping.
  • Trigger GC before a filesystem is critical. Check the actual backing filesystems, not only /.

Done

Report one of:

  • removed: resource ID, canonical path, tombstone, and native/contained cleanup evidence
  • retained: owner, reason, dirty/protected state, and expiry
  • blocked: failed safety probe and the next action

Do not claim the task fully complete while its ephemeral resources have no verified disposition.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.