Skip to content

Reuse previously-resolved prompt values on re-sync#339

Merged
bguidolim merged 4 commits intomainfrom
bruno/reuse-prompt-values
Apr 21, 2026
Merged

Reuse previously-resolved prompt values on re-sync#339
bguidolim merged 4 commits intomainfrom
bruno/reuse-prompt-values

Conversation

@bguidolim
Copy link
Copy Markdown
Collaborator

Summary

Second mcs sync runs no longer re-ask every pack prompt. Values from the previous sync (already persisted in .claude/.mcs-project for 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.resolveAllValues loads state.resolvedValues as priors, then partitions declared prompts into reusable (input + valid select) and newly-declared sets.
  • Interactive + only-reusable → single 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.
  • script and fileDetect prompts always re-execute. select priors are invalidated when the stored value is no longer in the pack's options (common after a pack update).
  • Threaded priorValues through ProjectConfigContext, PromptExecutor.execute/executeAll, and CrossPackPromptResolver.resolveSharedPrompts. CLIOutput.singleSelect gained initialIndex so stored select values seed the cursor. PromptOption.index(of:in:) centralizes the option-lookup.
  • New helpers CrossPackPromptResolver.collectDeclaredPrompts and partitionDeclaredPrompts — live alongside the existing walk-pack-declarations code.

Test plan

  • swift test passes locally (1057 tests, 121 suites)
  • 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.PromptValueReuseLifecycleTests, 5 cases covering happy path, new prompts, select invalidation, silent non-interactive, --customize)

- 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
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 priorValues through ProjectConfigContext, sync strategies, and prompt execution paths; prefer prior values over declared defaults for input/select.
  • Add prompt partitioning + reuse gating logic in Configurator.resolveAllValues, and seed CLIOutput.singleSelect with an initialIndex.
  • 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.

Comment thread Sources/mcs/Sync/Configurator.swift
Comment thread Sources/mcs/Sync/CrossPackPromptResolver.swift
Comment thread Sources/mcs/Sync/Configurator.swift
Comment thread Sources/mcs/Sync/Configurator.swift Outdated
- 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)
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

Comment thread Sources/mcs/Sync/Configurator.swift Outdated
Comment thread Sources/mcs/ExternalPack/PromptExecutor.swift Outdated
Comment thread Sources/mcs/Sync/CrossPackPromptResolver.swift Outdated
- 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
@bguidolim bguidolim merged commit 6c84b0b into main Apr 21, 2026
4 checks passed
@bguidolim bguidolim deleted the bruno/reuse-prompt-values branch April 21, 2026 12:12
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.

2 participants