Reuse previously-resolved prompt values on re-sync#339
Merged
Conversation
- Load state.resolvedValues as priors into Configurator.resolveAllValues; partition declared prompts into reusable (input/valid-select) vs new, always re-run script/fileDetect - Interactive gate offers a single 'Reuse N values? [Y/n]' when all prompts are reusable; non-interactive and --customize paths bypass the gate (silent reuse / force re-ask with priors as defaults) - Thread priorValues through PromptExecutor, CrossPackPromptResolver, and ProjectConfigContext so Enter-to-accept defaults mirror stored answers
There was a problem hiding this comment.
Pull request overview
Improves the mcs sync/re-sync experience by reusing previously resolved prompt values (stored in project state) to avoid re-asking unchanged prompts, including seeding select UIs from prior answers.
Changes:
- Thread
priorValuesthroughProjectConfigContext, sync strategies, and prompt execution paths; prefer prior values over declared defaults forinput/select. - Add prompt partitioning + reuse gating logic in
Configurator.resolveAllValues, and seedCLIOutput.singleSelectwith aninitialIndex. - Add/extend unit + integration tests covering reuse, new prompts, select invalidation, non-interactive behavior, and
--customize.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/MCSTests/TestHelpers.swift | Adds MockPromptTechPack to simulate prompt resolution with priors in tests. |
| Tests/MCSTests/PromptExecutorTests.swift | Adds tests for priorValue behavior (select w/ nil options, script ignoring prior). |
| Tests/MCSTests/LifecycleIntegrationTests.swift | Adds end-to-end lifecycle coverage for reuse/new prompts/select invalidation/customize. |
| Tests/MCSTests/CrossPackPromptResolverTests.swift | Adds unit tests for partitionDeclaredPrompts. |
| Sources/mcs/TechPack/TechPack.swift | Extends ProjectConfigContext with priorValues. |
| Sources/mcs/TechPack/PromptDefinition.swift | Adds PromptOption.index(of:in:) helper for select seeding. |
| Sources/mcs/Sync/SyncStrategy.swift | Updates makeConfigContext to accept priorValues. |
| Sources/mcs/Sync/ProjectSyncStrategy.swift | Propagates priorValues into project-scope config context. |
| Sources/mcs/Sync/GlobalSyncStrategy.swift | Propagates priorValues into global-scope config context. |
| Sources/mcs/Sync/CrossPackPromptResolver.swift | Adds declared-prompt collection + partitioning and supports priors in shared resolution. |
| Sources/mcs/Sync/Configurator.swift | Implements reuse gating + seeding from prior values during resolve phase. |
| Sources/mcs/ExternalPack/PromptExecutor.swift | Adds priorValue(s) plumbing and uses priors as defaults/selection seeds. |
| Sources/mcs/ExternalPack/ExternalPackAdapter.swift | Forwards context.priorValues into prompt execution. |
| Sources/mcs/Core/CLIOutput.swift | Adds initialIndex support to singleSelect (interactive + fallback). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix collectDeclaredPrompts dropping duplicate-key declarations — select-option validation now sees all packs' options, so a prior from pack B no longer re-prompts when pack A happened to win dedup - Treat select with nil/empty options as reusable when a prior exists (matches executor fallback) - Hide prior values in the interactive gate listing (prompts frequently hold API keys); downgrade non-interactive info line to dimmed
…eclarations - Replace 'any unconstrained declaration wins' with intersection semantic: if any pack constrains the select value, the prior must satisfy that constraint — matches resolveSharedPrompts, which presents the merged constrained option list - Add two regression tests covering the mixed case (prior inside vs outside constraints)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Mask prior-value defaults in promptInline's hint — add maskDefault flag so re-prompts (--customize, user-declined gate) show "press Enter to keep existing value" instead of echoing the stored secret to the terminal - Thread real pre-sync resolvedValues into the configureProject hook context (was hardcoded to empty); snapshot before resolveAllValues overwrites state - Apply masking at every prior-backed promptInline call: executeInput, resolveSharedPrompts text-input fallback, undeclared-placeholder loop
This was referenced Apr 21, 2026
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
Second
mcs syncruns no longer re-ask every pack prompt. Values from the previous sync (already persisted in.claude/.mcs-projectfor doctor's sake) now short-circuit the prompt executors. With multiple packs each declaring several prompts, re-sync after a pack update is a one-keystroke operation.Changes
Configurator.resolveAllValuesloadsstate.resolvedValuesas priors, then partitions declared prompts into reusable (input + valid select) and newly-declared sets.Reuse N values? [Y/n]gate. Interactive + new prompts added → skip gate, info line, ask only the new ones. Non-interactive (--pack/--all/no TTY) → silently reuse.--customize→ force re-ask with priors surfacing as per-prompt defaults.scriptandfileDetectprompts always re-execute.selectpriors are invalidated when the stored value is no longer in the pack's options (common after a pack update).priorValuesthroughProjectConfigContext,PromptExecutor.execute/executeAll, andCrossPackPromptResolver.resolveSharedPrompts.CLIOutput.singleSelectgainedinitialIndexso stored select values seed the cursor.PromptOption.index(of:in:)centralizes the option-lookup.CrossPackPromptResolver.collectDeclaredPromptsandpartitionDeclaredPrompts— live alongside the existing walk-pack-declarations code.Test plan
swift testpasses locally (1057 tests, 121 suites)swiftformat --lint .andswiftlintpass without violationsmcs sync,mcs doctor)Checklist for engine changes
LifecycleIntegrationTests.PromptValueReuseLifecycleTests, 5 cases covering happy path, new prompts, select invalidation, silent non-interactive,--customize)