Skip to content

refactor: unified deployed_files manifest — safe integration lifecycle #164

@danielmeppiel

Description

@danielmeppiel

Problem

APM deploys files into developer-curated directories (.github/prompts/, .github/skills/, .claude/agents/, etc.) — spaces developers actively manage by hand. The current integration system can destroy user-authored primitives in several ways:

  1. HookIntegrator uses shutil.rmtree() on .github/hooks/scripts/ and .claude/hooks/ — unconditionally wiping all content including user scripts
  2. SkillIntegrator (legacy path) deletes all skill directories not matching installed packages — destroying user-authored skills
  3. Suffix naming pollution (-apm.prompt.md, -apm.agent.md) — users have complained about the naming convention
  4. No collision detection — APM silently overwrites user files with the same name (instructions, skills)
  5. apm prune removes packages from apm_modules/ but leaves stale integrated files in .github/ and .claude/

Solution: Unified deployed_files Manifest

Generalize the lockfile-based ownership tracking to ALL integrators. A single deployed_files field in apm.lock records every file path APM deployed:

dependencies:
  microsoft/code-review:
    version: "1.0.0"
    resolved: "https://github.com/microsoft/code-review"
    deployed_files:
      - .github/prompts/security-audit.prompt.md
      - .github/agents/reviewer.agent.md
      - .github/skills/code-review/
      - .github/hooks/pre-commit.json
      - .github/hooks/scripts/code-review/lint.sh
      - .claude/agents/reviewer.md
      - .claude/commands/security-audit.md

Behavior Changes

Install:

  • Deploy with clean filenames (no -apm suffix)
  • Skip + warn if file exists and is not in any package's deployed_files (user-authored)
  • --force flag to overwrite user files explicitly
  • Record all deployed paths in deployed_files

Uninstall:

  • Remove only files listed in the uninstalled package's deployed_files
  • No globs, no rmtree of entire directories, no guessing

Prune:

  • After removing orphaned packages from apm_modules/, also remove their deployed_files from .github/ and .claude/

Migration

  • Old -apm files are removed by existing sync logic on first install
  • New clean-named files deployed and tracked in deployed_files
  • Old lockfiles without deployed_files treated as "nothing managed" (safe default)

Scope

  • deployed_files field in LockedDependency (replaces deployed_skills)
  • All 6 integrators: record deployed paths, manifest-based cleanup
  • Remove -apm suffix — deploy with clean filenames
  • Collision detection: skip + warn, --force to override
  • Fix HookIntegrator destructive rmtree calls
  • Fix SkillIntegrator legacy fallback
  • Prune cleans stale integrated files
  • Backwards compatibility with old lockfiles

Blocks #112 (InstructionIntegrator PR #162 will rebase on this)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions