Skip to content

Prompts should be skippable when their components aren't selected #356

Description

@bguidolim

Problem

PromptDefinition (Sources/mcs/TechPack/PromptDefinition.swift) has no condition field, and CrossPackPromptResolver.collectDeclaredPrompts (Sources/mcs/Sync/CrossPackPromptResolver.swift:20-25) gathers prompts per pack, not per selected component:

packs.flatMap { $0.declaredPrompts(context: context) }

So a prompt is asked even when every component that consumes its placeholder was deselected via mcs sync --customize, and the answer goes nowhere. Harmless with one or two packs, increasingly irritating as packs accumulate prompts.

Sketch

Add an optional requiredBy: [String] (component ids) to PromptDefinition:

prompts:
  - key: KB_GATE_MODE
    type: select
    requiredBy: [hook-gate-turn, hook-gate-record, hook-gate-check]

Skip the prompt when none of the listed ids are in the selected set; keep asking when requiredBy is absent (current behavior).

Insertion point: ProjectConfigContext is already threaded into declaredPrompts(context:) and is currently under-used — implementations read only isGlobalScope from it. Carrying the selected-component set on the context is cheaper than changing the collectDeclaredPrompts signature. The selection is known at Configurator.resolveAllValues (Configurator.swift:645).

Two details to settle before starting

1. Placeholder fallback is bigger than it looks. ConfiguratorSupport.scanForUndeclaredPlaceholders (called at Configurator.swift:695) takes packs, not the selected component set — so it scans deselected components' files too. A requiredBy-skipped prompt would then be re-asked as a raw Set value for KB_GATE_MODE inline prompt even when nothing selected uses it, which is strictly worse than today's behavior.

Narrowing that scan to selected components is therefore part of this work, not a follow-up — and it needs care: the scan is load-bearing as the safety net for emitWarnings: false substitution, and covers three artifact families (copyPackFile sources, settingsMerge file sources, mcpServer env/command/args).

Alternative worth considering: treat a requiredBy mismatch — a placeholder used by a component not listed in requiredBy — as an authoring error at mcs pack validate time. It's statically detectable and avoids the runtime question entirely.

2. Prior values. A skipped prompt must leave any stored prior untouched rather than clearing it, so re-enabling the component later doesn't lose the answer.

Validation to add

Every id in requiredBy must exist in the pack's components — catches typos and renames at mcs pack validate time.

Tests

Tests/MCSTests/CrossPackPromptResolverTests.swift:

  • prompt with requiredBy and no listed component selected → not asked
  • prompt with requiredBy and one listed component selected → asked
  • prompt without requiredBy → asked (regression guard)
  • skipped prompt leaves prior value intact across a re-sync
  • requiredBy referencing an unknown component id → validation error

Metadata

Metadata

Assignees

No one assigned

    Labels

    P5BacklogenhancementNew feature or requestideaFuture idea — not planned yet

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions