Skip to content

[#278] Namespace copyPackFile destinations with pack ID subdirectory#280

Merged
bguidolim merged 4 commits intomainfrom
bruno/278-namespace-copypackfile-destinations
Mar 24, 2026
Merged

[#278] Namespace copyPackFile destinations with pack ID subdirectory#280
bguidolim merged 4 commits intomainfrom
bruno/278-namespace-copypackfile-destinations

Conversation

@bguidolim
Copy link
Copy Markdown
Collaborator

Summary

Prevents cross-pack file collisions by namespacing copyPackFile destinations with the pack identifier as a subdirectory prefix. When two packs define the same destination filename, they now install to distinct paths (e.g., .claude/hooks/pack-a/lint.sh vs .claude/hooks/pack-b/lint.sh).

Changes

  • Prepend <pack-identifier>/ to copyPackFile destinations in ExternalPackAdapter.convertInstallAction, covering all five CopyFileType cases (hooks, skills, commands, agents, generic)
  • Memoize ExternalPackAdapter.components as a stored property computed once at init
  • Add projectHookCommand/globalHookCommand helpers to LifecycleTestBed, replacing 9 hand-assembled hook command string literals
  • Add CrossPackCollisionTests integration test verifying two packs with same hook filename coexist and removal is independent

Test plan

  • swift test passes locally (866 tests)
  • swiftformat --lint . and swiftlint pass without violations
  • Affected commands verified with a real pack (e.g. mcs sync, mcs doctor)
Checklist for engine changes
  • Integration tests updated for new features (LifecycleIntegrationTests or DoctorRunnerIntegrationTests)
  • New file write/copy/delete paths use PathContainment.safePath() and handle the nil (escape) case

Closes #278

…rectory

- Prepend pack identifier as subdirectory to copyPackFile destinations in ExternalPackAdapter, preventing cross-pack file collisions
- Update existing adapter test assertions to expect namespaced paths
- Add integration test verifying two packs with same hook filename coexist and removal is independent
- Memoize ExternalPackAdapter.components as a stored property computed once at init
- Add projectHookCommand/globalHookCommand helpers to LifecycleTestBed
- Replace 9 hand-assembled hook command string literals with helper calls
- Skip pack-id subdirectory prefix for .skill file type to avoid double nesting that breaks Claude Code skill discovery
- Skills use directory-based identity (.claude/skills/<name>/SKILL.md) — an extra nesting level makes them invisible
- Add inline comment explaining why skills are excluded from destination namespacing
- Remove unused globalHookCommand helper from LifecycleTestBed
@bguidolim bguidolim enabled auto-merge (squash) March 24, 2026 11:12
@bguidolim bguidolim merged commit b27a10c into main Mar 24, 2026
4 checks passed
@bguidolim bguidolim deleted the bruno/278-namespace-copypackfile-destinations branch March 24, 2026 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Namespace copyPackFile destinations with composed pack ID to prevent cross-pack collisions

1 participant