Skip to content

ISSUE-373: Regression test: 'mcs update' must not remove both-scope packs - #383

Merged
bguidolim merged 1 commit into
mainfrom
bruno/ISSUE-373-update-reapply-regression-test
Sep 2, 2026
Merged

ISSUE-373: Regression test: 'mcs update' must not remove both-scope packs#383
bguidolim merged 1 commit into
mainfrom
bruno/ISSUE-373-update-reapply-regression-test

Conversation

@bguidolim

Copy link
Copy Markdown
Collaborator

Summary

Closes #373. mcs update re-applies each scope's already-configured pack set, so the global-pack block from #370 never reaches it and a pack installed in both scopes survives. That safety was a property of where the update path sourced its list, not something any test asserted, and an earlier --pack iteration broke exactly this by filtering the list. This pins it.

While writing the test I found that the same re-apply path drops skipped packs (fetch failed, trust declined, missing from registry) from the list, which unconfigures them when a scope holds two or more packs. Filed as #382; not fixed here.

Changes

  • The per-scope re-apply body becomes an internal static helper so a sandboxed test can drive the real resolver → configure chain instead of mirroring it. It takes the whole scope run so the pack list and strategy provably come from the same scope. Production behavior is unchanged.
  • New lifecycle test installs a hook pack in both scopes, deletes the project hook, re-applies via --project and bare mcs update, and asserts the pack is still configured in both scopes and the hook was restored (proving the re-apply ran rather than returned early).

Test plan

  • swift test passes locally
  • swiftformat --lint . and swiftlint pass without violations
  • Affected commands verified with a real pack (e.g. mcs sync, mcs doctor)

Manual: with a pack in both scopes, run mcs update --project and mcs update → expect the pack still listed in the project's .claude/.mcs-project and its artifacts intact.

Checklist for engine changes
  • Integration tests updated for new features (LifecycleIntegrationTests or DoctorRunnerIntegrationTests)

https://claude.ai/code/session_01MkBJdGBUoZ2aRtchjaKXMN

…th scopes

- Extract the per-scope re-apply into UpdateCommand.reapplyScope so a sandboxed test can drive the real resolver → configure chain
- Add a lifecycle test that installs a pack in both scopes, re-applies via --project and bare update, and asserts the pack and its hook survive
- Add LifecycleTestBed.globalState() alongside projectState()

Claude-Session: https://claude.ai/code/session_01MkBJdGBUoZ2aRtchjaKXMN

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The re-apply implementation still filters out skipped/unresolved packs before calling Configurator.configure(confirmRemovals: false), which can silently unconfigure packs and delete artifacts.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds an end-to-end regression test to ensure mcs update’s per-scope “re-apply” phase cannot accidentally remove a pack that is installed in both global + project scopes, and refactors the update implementation to make that re-apply path directly testable from the integration suite.

Changes:

  • Extracts the per-scope update re-apply logic into a new UpdateCommand.reapplyScope static helper so integration tests can drive the real resolver → configurator chain in a sandboxed environment.
  • Adds a lifecycle integration test that installs the same hook pack in both scopes, deletes the project hook artifact, runs the update re-apply flow, and asserts both-scope configuration + artifact restoration.
  • Adds a LifecycleTestBed.globalState() convenience accessor for reading sandboxed global state.
File summaries
File Description
Sources/mcs/Commands/UpdateCommand.swift Extracts re-apply logic into a static helper to enable targeted, sandboxed integration testing.
Tests/MCSTests/LifecycleIntegrationTests.swift Adds an integration regression test ensuring both-scope packs survive update re-apply and restores a removed hook artifact.
Review details
  • Files reviewed: 2/2 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.

Comment on lines +346 to 350
var packs: [any TechPack] = []
for packID in run.configuredPackIDs.subtracting(skippedPackIDs).sorted() {
guard let pack = registry.pack(for: packID) else {
output.warn(" \(packID): tracked in state but missing from pack registry — skipping. Run 'mcs pack add' to restore it.")
continue
@bguidolim
bguidolim merged commit 1b9b6a9 into main Sep 2, 2026
5 checks passed
@bguidolim
bguidolim deleted the bruno/ISSUE-373-update-reapply-regression-test branch September 2, 2026 18:54
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.

Regression test: 'mcs update' must not remove packs installed in both scopes

2 participants