Repository navigation
Description
Summary
Watched installs can accumulate a separate repository checkout for each selected commit. Removing both the watch and its installed skill leaves those snapshots behind. There is no explicit retention or pruning contract in the current cache implementation.
Code evidence at 5d4987b:
Sources/Core/RuntimeService.swift:802materializes a commit-specific checkout when the source checkout differs from the selected reviewed/baseline commit;:808uses.agent/cache/watch-installs.Sources/Core/ProcessRunner.swift:106names snapshots using identity and commit prefix;:120clones a repository with a working tree and.git.Sources/Core/WatchLedger.swift:370removes the watch record only;Sources/Core/Installer.swift:249handles installed files/lock entries, with no snapshot reclamation path.
Use Case
Long-lived watches can leave many snapshots as reviewed commits advance. Each snapshot contains a working tree, including files outside the selected skill, as well as Git metadata. Local Git clones may share object storage through hard links; this report does not assume every snapshot duplicates every object byte.
Reproduction / current-state verification
Executed at 5d4987b.
Run in Bash after cd "<checkout>" && swift build, replacing <checkout> with the absolute path of the checkout at this revision. Use a fresh reproduction directory. The commands isolate HOME, agent configuration, and XDG_*, and remove their fixture root on exit.
set -eu
checkout="<checkout>"
skill_bin="$checkout/.build/debug/skill"
repro_root="$checkout/.build/issue-repro-watch-cache"
mkdir -p "$repro_root/home" "$repro_root/tmp" "$repro_root/project"
trap 'rm -rf "$repro_root"' EXIT
isolated() {
env -i PATH="$PATH" HOME="$repro_root/home" \
CODEX_HOME="$repro_root/home/.codex" \
CLAUDE_CONFIG_DIR="$repro_root/home/.claude" \
XDG_CONFIG_HOME="$repro_root/home/.config" \
XDG_STATE_HOME="$repro_root/home/.local/state" \
XDG_CACHE_HOME="$repro_root/home/.cache" TMPDIR="$repro_root/tmp" \
GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
GIT_AUTHOR_NAME=Fixture [email protected] \
GIT_COMMITTER_NAME=Fixture [email protected] \
"$@"
}
skill() { isolated "$skill_bin" "$@"; }
write_skill() {
mkdir -p "$1"
printf -- '---\nname: %s\ndescription: Reproduction fixture\n---\n%s\n' "$2" "$3" > "$1/SKILL.md"
}
cd "$repro_root/project"
write_skill "$repro_root/source/skills/demo" demo A
isolated git init -q -b main "$repro_root/source"
isolated git -C "$repro_root/source" add .
isolated git -C "$repro_root/source" commit -qm A
skill add "$repro_root/source" --watch-only --skill demo --agent codex
write_skill "$repro_root/source/skills/demo" demo B
isolated git -C "$repro_root/source" add .
isolated git -C "$repro_root/source" commit -qm B
skill add "$repro_root/source" --skill demo --agent codex
skill review check "$repro_root/source" --watch --path skills/demo
skill review done "$repro_root/source" --watch --path skills/demo --note reviewed
write_skill "$repro_root/source/skills/demo" demo C
isolated git -C "$repro_root/source" add .
isolated git -C "$repro_root/source" commit -qm C
skill add "$repro_root/source" --skill demo --agent codex
skill remove "$repro_root/source" --watch
skill remove demo --agent codex
isolated python3 - <<'CODE'
from pathlib import Path
cache=Path('.agent/cache/watch-installs')
print('retained checkouts:', sum((p/'.git').exists() for p in cache.iterdir()))
print('retained skill bodies:', sorted((p/'skills/demo/SKILL.md').read_text().splitlines()[-1] for p in cache.iterdir()))
CODEObserved output (relevant lines; temporary paths shortened to <temp>):
watched source path skills/demo
recorded done source
removed source
Removing demo
removed <temp>/project/.agents/skills/demo
retained checkouts: 2
retained skill bodies: ['A', 'B']
Environment: Apple Swift 6.4, macOS 27.0.1 (26A434), arm64; CLI 0.2.1; validation date 2026-10-17.
Proposed Behavior
The maintainer should choose a bounded retention/pruning policy and its trigger: automatic reclamation, an explicit cleanup command, or both. Preserve snapshots still required by current installations or review state.
Completion checks:
- Exercise several reviewed commits and verify the chosen retention bound or explicit cleanup behavior.
- Removing all consumers makes the snapshots eligible for reclamation.
- Active installation source paths and review baselines remain usable after pruning.
- Document the policy and validate it with
swift test.
Tradeoffs
Reusing an existing identity/commit snapshot is useful and already happens. Pruning must account for stored source paths and offline restore/review needs; blindly deleting every old directory could break health checks. A cheaper snapshot representation is optional, not a prerequisite for defining ownership and retention.
Compatibility Notes
This is a cache lifecycle proposal, not a claim that existing snapshot retention violates a published limit. No retention limit or deletion timing is assumed.
Related: #7 covers restore semantics, #9 covers preview writes, and #10 covers watch scope. Retention should follow the accepted scope model without reopening those issues. No duplicate found.
Activity