Problem
When a file is renamed inside an APM package (e.g., a prompt file my-command.prompt.md → my-new-command.prompt.md), running apm install generates the new target files but leaves the old ones on disk as stale artifacts.
Steps to reproduce
- Have a package with a prompt file my-command.prompt.md
- Run apm install — files are deployed to .claude/commands/my-command.md, .opencode/commands/my-command.md, .github/prompts/my-command.prompt.md
- Rename the source to my-new-command.prompt.md
- Run apm install again
Expected: Old files (my-command.md, my-command.prompt.md) are removed, new files (my-new-command.md, my-new-command.prompt.md) are created.
Actual: Both old and new files exist on disk. The old files must be manually deleted.
Why this happens
The install loop writes the new deployed_files list to the lockfile, overwriting the previous one — but never computes the diff between old and new to remove orphaned files. The existing detect_orphans() in drift.py only operates at the package level (is the package still in apm.yml?), not at the file level within a package.
Suggested approach
The infrastructure is already in place — apm.lock.yaml tracks deployed_files per dependency. During apm install, for each package:
- Read the old deployed_files from the existing lockfile
- Integrate the package (existing logic)
- Collect the new deployed_files
- Compute stale = old - new
- Delete stale files from disk
This would cover renames, deleted prompts, and any other case where a package's output file set changes between installs.
Problem
When a file is renamed inside an APM package (e.g., a prompt file my-command.prompt.md → my-new-command.prompt.md), running apm install generates the new target files but leaves the old ones on disk as stale artifacts.
Steps to reproduce
Expected: Old files (my-command.md, my-command.prompt.md) are removed, new files (my-new-command.md, my-new-command.prompt.md) are created.
Actual: Both old and new files exist on disk. The old files must be manually deleted.
Why this happens
The install loop writes the new deployed_files list to the lockfile, overwriting the previous one — but never computes the diff between old and new to remove orphaned files. The existing detect_orphans() in drift.py only operates at the package level (is the package still in apm.yml?), not at the file level within a package.
Suggested approach
The infrastructure is already in place — apm.lock.yaml tracks deployed_files per dependency. During apm install, for each package:
This would cover renames, deleted prompts, and any other case where a package's output file set changes between installs.