Add 'mcs update' multi-scope refresh command#346
Conversation
- New 'mcs update' fetches latest pack contents and re-applies the existing configured set across global and current-project scopes; '--all-projects' fans out to every project tracked in the index after interactive confirmation - Soft-deprecates 'mcs pack update' and 'mcs sync --update' with warnings, and redirects pack-update hint strings (sync/doctor/check-updates and the SessionStart hook) to 'mcs update' - Skips the interactive "Reuse these values?" gate during update so prior prompt answers are reused silently while genuinely new prompts still execute
There was a problem hiding this comment.
Pull request overview
Adds a new top-level mcs update command to refresh already-configured packs across scopes (global + project), consolidating the “fetch” + “re-apply” workflow and deprecating mcs pack update / mcs sync --update messaging accordingly.
Changes:
- Introduces
mcs updatewith scope selection (--global,--project,--all-projects) and--dry-run, plus anUpdateScopeResolverto enumerate target scopes. - Adds “silent prior value reuse” support in
Configuratorfor update runs, while keeping new prompts interactive. - Updates CLI/docs and user-facing hints (UpdateChecker output, deprecation warnings) to point users at
mcs update.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/cli.md | Documents mcs update and marks older update flows as deprecated. |
| docs/architecture.md | Updates lockfile semantics documentation to reflect mcs update and deprecations. |
| Tests/MCSTests/UpdateScopeResolverTests.swift | Adds unit tests for scope resolution behavior. |
| Sources/mcs/Sync/UpdateScopeResolver.swift | New resolver to select global/project/everywhere scope runs; prunes stale index entries. |
| Sources/mcs/Sync/LockfileOperations.swift | Reuses shortSHA helper for consistent update output formatting. |
| Sources/mcs/Sync/Configurator.swift | Adds reusePriorValuesSilently path to skip the “Reuse these values?” gate during update. |
| Sources/mcs/ExternalPack/PackRegistryFile.swift | Adds shortSHA convenience accessor for display. |
| Sources/mcs/Core/UpdateChecker.swift | Updates “available updates” hints to recommend mcs update. |
| Sources/mcs/Core/Telemetry.swift | Adds telemetry enum case for the new command. |
| Sources/mcs/Core/ProjectIndex.swift | Adds isGlobal/url helpers for sentinel-aware index handling. |
| Sources/mcs/Commands/UpdateCommand.swift | New command implementing update → reapply → lockfile phases across selected scopes. |
| Sources/mcs/Commands/SyncCommand.swift | Adds deprecation warning for mcs sync --update. |
| Sources/mcs/Commands/PackCommand.swift | Adds deprecation warning for mcs pack update and updates follow-up guidance. |
| Sources/mcs/CLI.swift | Registers UpdateCommand as a top-level subcommand. |
| CLAUDE.md | Updates quick-reference command list for the new verb + deprecations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- '--pack' now filters both fetch and re-apply; previously the re-apply phase still touched all configured packs in each scope, causing 'configureProject' hooks to run for unrelated packs - Pack IDs tracked in state but unloadable from the registry now emit a per-ID warning instead of being silently dropped - 'ProjectState' is the source of truth for whether a scope has configured packs; the project-index entry is no longer required, avoiding no-op behavior when sync's best-effort index write previously failed
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Remove --pack: filtering subset through Configurator.configure() treated un-targeted packs as removals and silently uninstalled them; the engine is a convergence engine, not a subset refresher - mcs update now always refreshes the full configured set per scope; --global, --project, --all-projects, --dry-run remain - Un-deprecate mcs pack update: it does something mcs update cannot (fetch a single pack's registry entry without applying), useful for pack authors and CI workflows; the two verbs cleanly separate orchestration from registry management
- '--project' error message now reports the resolved target path (path arg or cwd) instead of always the cwd, so failures with an explicit path argument are diagnosable - Sort pack IDs before resolving to TechPack instances so the order passed to Configurator (and therefore CLAUDE/settings/hook composition) is deterministic across runs
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Users with packs configured in both global and project scopes had to run two separate commands to pick up upstream pack updates ("I ran sync, why is my other scope still stale?"). This adds a single
mcs updateverb that fetches the latest pack contents and re-applies the existing configured set across every scope the user is in.Changes
mcs updaterefreshes configured packs across the global scope and the current project's scope in one invocation, with trust prompts handled by the existing pack-update pipeline.--global,--project, and--dry-runscope the refresh;--all-projectsfans out to every project recorded in the project index after listing them and asking for interactive confirmation.mcs sync(Y/n gate) ormcs sync --customize.mcs update.generate-lockfileinstead of force-writing the way--updatedoes, and runs only on project scopes.cdormcs sync.mcs sync --updateprints a one-line deprecation warning and continues to work for one release. The "available pack updates" hint shown by sync/doctor/check-updates and the SessionStart hook now points atmcs update.--all-projectsmode (the only mode that consumes the result) and does not write to disk during--dry-run.mcs pack updateis not deprecated — it stays as the surgical "registry-only fetch" verb for pack authors and CI.Test plan
mcs updatefrom the project — expect both scopes to refresh in a single invocation with no second command needed.mcs update --dry-runfrom the same project — expect a preview only; the project index is not rewritten even if it contained stale entries.generate-lockfileto its three states (true,false, unset) and runmcs updatein each — expect lockfile written, silent skip, and a drift warning respectively.mcs update— expect the pack to be skipped from re-apply that run, with the prompt re-firing on the next invocation.mcs update --all-projectsinteractively — expect a list including both the global scope and each project, then a default-No confirmation; running it again under--dry-runshould preview without writing.mcs sync --update— expect the deprecation warning followed by its existing behavior.mcs update --global ~/some/path— expect a warning that the positional path is ignored under--global.Checklist for engine changes
CLAUDE.md,docs/cli.md,docs/architecture.md)