ISSUE-372: Warn when global sync duplicates project-installed packs - #381
Merged
Conversation
- Fires only for packs newly entering the global scope, so re-syncs and `mcs update` stay silent - Warning text lives in a pure function, since `CLIOutput` has no capture seam for tests - `dryRunSummary` returns its additions set so the dry-run path reuses one diff Claude-Session: https://claude.ai/code/session_01MkBJdGBUoZ2aRtchjaKXMN
There was a problem hiding this comment.
🟡 Changes recommended
The warning is currently emitted before the removal confirmation gate, so it can print (and read the index) even when the sync is cancelled and no duplication is actually created.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds an informational warning to mcs sync --global (and its dry-run flow) when a pack newly entering the global scope is already installed in tracked projects, so users are alerted that hooks/skills will run twice until the project-scoped copy is removed.
Changes:
- Introduces
ConfiguratorSupport.projectDuplicationWarningandwarnProjectDuplicationto compute and emit a stable, testable warning message from the project index. - Wires the warning into global-scope
configureanddryRunflows, keyed on scope additions (transition-based) to keep repeated global syncs andmcs updatequiet. - Adds unit + integration coverage for overlap detection, stale paths, dry-run behavior, second-sync silence, and unreadable index handling.
File summaries
| File | Description |
|---|---|
| Tests/MCSTests/SyncCommandTests.swift | Unit tests for the warning line generation (sorting, filtering global sentinel, stale paths, multi-pack header). |
| Tests/MCSTests/LifecycleIntegrationTests.swift | Integration scenarios validating warning emission, non-mutation of project index entries, dry-run behavior, and unreadable index degradation. |
| Sources/mcs/Sync/ConfiguratorSupport.swift | Implements warning computation + scoped emission helper; updates dryRunSummary to return additions for reuse. |
| Sources/mcs/Sync/Configurator.swift | Hooks warning emission into dry-run plan output and global configure flow. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Cancelling at "Proceed with removal?" returned before installing, so the warning could describe duplicates that were never created - Also avoids reading the project index on the cancelled path Claude-Session: https://claude.ai/code/session_01MkBJdGBUoZ2aRtchjaKXMN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Installing a pack globally when projects already have it locally duplicates its hooks and skills — the global and project copies register as distinct settings entries, so both fire. #370 blocks the reverse direction, and the doctor check from #371 only runs inside an affected project, so today this duplication is created silently and surfaces only when you next happen to work in each affected project.
mcs sync --globalnow names those projects at the moment it creates the duplication, and points at the existingmcs doctor --fixremediation. Informational only — it never blocks or prompts.Closes #372
Changes
mcs sync --globaland everymcs updatestay silent.~/.mcs/projects.yamldegrades to a notice rather than failing the sync.Test plan
swift testpasses locallyswiftformat --lint .andswiftlintpass without violationsmcs sync,mcs doctor)Left unchecked deliberately: the CLI resolves its home directory in a way that ignores a
HOMEoverride, so a manual run cannot be sandboxed away from real~/.mcsstate. Covered by integration tests instead — global sync, dry run, a second sync, the no-overlap case, and an unreadable index.Checklist for engine changes
LifecycleIntegrationTestsorDoctorRunnerIntegrationTests)https://claude.ai/code/session_01MkBJdGBUoZ2aRtchjaKXMN