Skip to content

feat(presets): Composition strategies (prepend, append, wrap) for templates, commands, and scripts#2133

Merged
mnriem merged 33 commits intomainfrom
copilot/add-composition-strategies-to-presets
Apr 23, 2026
Merged

feat(presets): Composition strategies (prepend, append, wrap) for templates, commands, and scripts#2133
mnriem merged 33 commits intomainfrom
copilot/add-composition-strategies-to-presets

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 8, 2026

Presets can now augment lower-priority templates instead of only fully replacing them. A new optional strategy field in preset.yml controls how content is composed across the priority stack.

provides:
  templates:
    - type: "template"
      name: "spec-template"
      file: "templates/spec-addendum.md"
      strategy: "append"  # new field; default: "replace"
Strategy Behavior Templates Commands Scripts
replace Full replacement (existing default)
prepend Insert before lower-priority content
append Insert after lower-priority content
wrap {CORE_TEMPLATE} / $CORE_SCRIPT placeholder substitution

Multiple composing presets chain recursively (e.g. security prepend + compliance append → header + core + footer).

Python resolver (src/specify_cli/presets.py)

  • VALID_PRESET_STRATEGIES / VALID_SCRIPT_STRATEGIES constants; validation in _validate() rejects prepend/append for scripts
  • PresetResolver._collect_all_layers() — walks full priority stack, reads strategy from each preset manifest
  • PresetResolver.resolve_content() — bottom-up composition across layers
  • PresetManager._register_commands() — composes command content before writing to agent directories

Shell resolvers

  • resolve_template_content() in scripts/bash/common.sh
  • Resolve-TemplateContent in scripts/powershell/common.ps1

CLI

  • specify preset resolve shows composition chain when non-replace strategies are present

Documentation

  • presets/scaffold/preset.yml — strategy field docs and composition examples
  • presets/README.md — composition strategies section; moved implemented items out of future considerations
  • presets/ARCHITECTURE.md — strategy table and content resolution function references

Tests

  • 26 new tests: strategy validation (valid/invalid/script restrictions), resolve_content() for each strategy × type, multi-preset chaining, override precedence, separator behavior, _collect_all_layers() ordering

Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 20:55
Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 21:05
Comment thread src/specify_cli/presets.py Fixed
Copilot AI requested review from Copilot and removed request for Copilot April 8, 2026 21:08
Copilot AI changed the title [WIP] Add composition strategies for templates, commands, and scripts feat(presets): Composition strategies (prepend, append, wrap) for templates, commands, and scripts Apr 8, 2026
Copilot AI requested a review from mnriem April 8, 2026 21:09
Copilot AI review requested due to automatic review settings April 20, 2026 18:51
@mnriem mnriem force-pushed the copilot/add-composition-strategies-to-presets branch from 00edba1 to fa04828 Compare April 20, 2026 18:53
@mnriem mnriem review requested due to automatic review settings April 20, 2026 18:54
@mnriem mnriem marked this pull request as ready for review April 20, 2026 19:02
Copilot AI review requested due to automatic review settings April 20, 2026 19:02
Copy link
Copy Markdown
Contributor

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

Adds composition strategies to the preset system so higher-priority presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts instead of always fully replacing them.

Changes:

  • Introduces strategy validation in preset manifests and a new Python composition resolver (_collect_all_layers() + resolve_content()).
  • Updates command registration to attempt composing command content before writing into agent directories.
  • Adds shell (bash/PowerShell) “resolve composed content” helpers plus docs and extensive new tests for strategy behavior.
Show a summary per file
File Description
tests/test_presets.py Adds strategy validation + composition resolver unit tests (including multi-preset chaining).
src/specify_cli/presets.py Adds strategy constants/validation, command composition during registration, and composition-aware resolution APIs.
src/specify_cli/init.py Enhances specify preset resolve output to show the composition chain when applicable.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent to compose template layers using strategies.
scripts/bash/common.sh Adds resolve_template_content to compose template layers using strategies.
presets/scaffold/preset.yml Documents the new strategy field and shows composition examples.
presets/README.md Documents strategy semantics, supported combinations, and chaining behavior.
presets/ARCHITECTURE.md Documents strategy table and where composition resolution is implemented across runtimes.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 8/8 changed files
  • Comments generated: 8

Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/presets.py Outdated
Comment thread scripts/bash/common.sh
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Comment thread presets/scaffold/preset.yml
Comment thread presets/README.md
Copy link
Copy Markdown
Contributor

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

Adds composition strategies to the preset system so higher-priority presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts instead of always fully replacing them.

Changes:

  • Introduces strategy validation in preset manifests and adds Python composition resolution across the full priority stack.
  • Updates command registration to write composed command content before registering with agent directories; adds CLI output to display a composition chain.
  • Adds bash/PowerShell template-content composition helpers, documentation updates, and a large set of new tests.
Show a summary per file
File Description
src/specify_cli/presets.py Adds strategy validation, layer collection, composed content resolver, and command registration changes to use composed content.
src/specify_cli/__init__.py Enhances specify preset resolve output to display a composition chain.
scripts/bash/common.sh Adds resolve_template_content() to compose template content in bash using the same strategy concepts.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent to compose template content in PowerShell.
presets/scaffold/preset.yml Documents the new strategy field and provides composition examples.
presets/README.md Documents composition strategies and supported combinations; updates future-considerations list.
presets/ARCHITECTURE.md Adds strategy table and references to the new composition resolution functions.
tests/test_presets.py Adds extensive coverage for strategy validation, composition behavior, chaining, and layer collection ordering.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 8/8 changed files
  • Comments generated: 3

Comment thread src/specify_cli/__init__.py Outdated
Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py Outdated
Copy link
Copy Markdown
Contributor

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

Adds composition strategies to the preset resolution stack so higher-priority presets can augment lower-priority templates/commands/scripts instead of only replacing them, with consistent behavior across Python + shell helpers and updated CLI/docs/tests.

Changes:

  • Introduces strategy support (replace/prepend/append/wrap) in preset manifests and implements bottom-up content composition in PresetResolver.
  • Updates command registration/removal flows to write/register composed command content and attempts to reconcile commands after uninstall.
  • Adds shell equivalents for composed template resolution, expands CLI preset resolve output, and updates preset documentation and test suite.
Show a summary per file
File Description
src/specify_cli/presets.py Validates strategy, collects full priority layers, composes content, and updates command registration/removal behavior.
src/specify_cli/__init__.py Enhances specify preset resolve output to display top layer and (optionally) a composition chain.
tests/test_presets.py Adds composition strategy validation and resolver behavior tests (including chaining and override precedence).
scripts/bash/common.sh Adds resolve_template_content() to compose template content via strategy metadata.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent to compose template content via strategy metadata.
presets/scaffold/preset.yml Documents the new strategy field and provides composition examples.
presets/README.md Documents composition strategies and supported type/strategy combinations.
presets/ARCHITECTURE.md Documents composition strategy semantics and points to resolution implementations.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/presets.py:658

  • In the composed branch of _reconcile_composed_commands, if not composed: continue will skip re-registration when the composed result is an empty string. Use an explicit is None check so empty-but-valid content still gets written and registered.
                composed = resolver.resolve_content(cmd_name, "command")
                if not composed:
                    continue
  • Files reviewed: 8/8 changed files
  • Comments generated: 5

Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/__init__.py Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Copilot AI review requested due to automatic review settings April 20, 2026 20:45
- Fix context_note type to Optional[str]
- Wrap shutil.rmtree in try/except during install rollback
- Separate override-backed skills from core/extension in _reconcile_skills
Copy link
Copy Markdown
Contributor

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

This PR adds composition strategies to preset-provided templates/commands/scripts so higher-priority presets can augment (prepend/append/wrap) lower-priority content instead of only replacing it, with updates across the Python resolver, agent command registration, CLI output, shell helpers, docs, and tests.

Changes:

  • Add strategy validation in PresetManifest and implement full-stack layer collection + bottom-up composition in PresetResolver (replace, prepend, append, wrap; scripts restricted to replace/wrap).
  • Update command registration/reconciliation to write composed command content into .composed/ and keep agent directories consistent after install/remove.
  • Add shell equivalents for template composition and update docs + tests to cover strategies and chaining behavior.
Show a summary per file
File Description
src/specify_cli/presets.py Adds strategy validation, introduces collect_all_layers() + resolve_content(), and updates install/remove to reconcile composed commands/skills.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() to support reconciliation without clobbering SKILL-based agents.
src/specify_cli/__init__.py Updates specify preset resolve to show layer chains and composition warnings.
scripts/bash/common.sh Adds resolve_template_content() for composed template resolution and filters disabled presets.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent and Python discovery helper; filters disabled presets.
tests/test_presets.py Replaces older wrap-lifecycle tests with strategy validation + composition behavior tests.
presets/scaffold/preset.yml Documents strategy field and composition examples for preset authors.
presets/README.md Adds user-facing “Composition Strategies” documentation and updates future-considerations section.
presets/ARCHITECTURE.md Documents strategy semantics and points to resolver implementations.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 3

Comment thread scripts/bash/common.sh Outdated
Comment thread src/specify_cli/presets.py Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Rewrite bash and PowerShell composition loops to find the effective
base replace layer first (scanning bottom-up, skipping non-replace
layers below it), then compose only from the base upward. This
prevents evaluation of irrelevant lower layers (e.g. a wrap with
no placeholder below a replace) and matches resolve_content behavior.
Copy link
Copy Markdown
Contributor

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

Adds multi-layer composition strategies to the preset resolution stack so higher-priority presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts instead of always fully replacing them.

Changes:

  • Adds strategy validation in PresetManifest and implements stack-aware layering + bottom-up composition via PresetResolver.collect_all_layers() / resolve_content().
  • Updates command registration to write/register composed command outputs and adds reconciliation logic to keep agent outputs correct after install/remove.
  • Updates CLI (preset resolve), shell resolvers (bash/pwsh), and preset documentation; replaces wrap-focused tests with strategy/composition tests.
Show a summary per file
File Description
tests/test_presets.py Reworks tests to cover strategy validation, layering order, and composed output behaviors.
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, content composition, install/remove reconciliation, command/core stem resolution.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() helper to support reconciliation without clobbering SKILL.md agents.
src/specify_cli/init.py Enhances specify preset resolve output to show composition chain when applicable.
scripts/powershell/common.ps1 Adds template composition resolver and improves preset-enabled filtering; introduces Python discovery helper.
scripts/bash/common.sh Adds template composition resolver and improves preset-enabled filtering.
presets/scaffold/preset.yml Documents strategy field usage and provides composition examples for preset authors.
presets/README.md Documents composition strategies and updates future-considerations section accordingly.
presets/ARCHITECTURE.md Documents strategy semantics and points to new content-resolution functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 3

Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py
Comment thread scripts/powershell/common.ps1
…as cleanup

- Warn when no Python 3 found in PS1 and presets use composition strategies
- Apply post_process_skill_content integration hook when restoring
  override-backed skills so agent-specific flags are preserved
- Unregister command aliases alongside primary name when composition
  fails to prevent orphaned alias files
Copy link
Copy Markdown
Contributor

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

This PR adds composition strategies to the preset system so presets can augment lower-priority templates/commands/scripts (prepend/append/wrap) instead of only fully replacing them. It extends the Python resolver to compose content across the full priority stack, updates command registration to write composed outputs, and adds shell-side template composition helpers for parity in bootstrap scripts.

Changes:

  • Add strategy validation to preset manifests and implement layered composition via PresetResolver.collect_all_layers() + PresetResolver.resolve_content().
  • Replace wrap-specific replay logic with generalized post-install/remove reconciliation for commands and skills.
  • Update CLI + docs to explain strategies; add extensive tests; add bash/PowerShell template composition helpers.
Show a summary per file
File Description
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, content composition, and install/remove reconciliation.
src/specify_cli/agents.py Adds a non-skill-agent-only registration path used by reconciliation.
src/specify_cli/__init__.py Enhances specify preset resolve output to show composition chains.
tests/test_presets.py Reworks tests toward strategy validation + composition behaviors and reconciliation expectations.
scripts/bash/common.sh Adds resolve_template_content() and respects disabled presets when reading registry.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent, Python 3 discovery, and respects disabled presets.
presets/scaffold/preset.yml Documents strategy usage and examples for new behavior.
presets/README.md Adds a “Composition Strategies” section and updates future-considerations.
presets/ARCHITECTURE.md Documents strategies + points to resolution functions across implementations.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/specify_cli/presets.py
Read aliases from preset manifest before deleting pack_dir so alias
command files are included in unregistration and reconciliation.
Comment thread src/specify_cli/presets.py Fixed
Copy link
Copy Markdown
Contributor

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

Adds content composition strategies to the preset system so higher-priority presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts rather than only replacing them, and updates the resolver, CLI, shell helpers, docs, and tests accordingly.

Changes:

  • Introduces strategy validation in PresetManifest and implements multi-layer composition via PresetResolver.collect_all_layers() + PresetResolver.resolve_content().
  • Updates command registration to write/register composed command content and adds post-install/remove reconciliation to keep agent outputs consistent across install/remove order.
  • Extends Bash/PowerShell template resolution with a composition-capable content resolver and updates docs + tests to cover strategy behavior.
Show a summary per file
File Description
src/specify_cli/presets.py Adds strategy validation, layer collection, content composition, and reconciliation logic for commands/skills.
src/specify_cli/agents.py Adds helper to register commands for non-skill agents (used during reconciliation).
src/specify_cli/__init__.py Updates specify preset resolve to display composition chains and warn on composition errors.
scripts/bash/common.sh Filters disabled presets and adds resolve_template_content() for strategy-based template composition.
scripts/powershell/common.ps1 Adds Python3 detection, filters disabled presets, and adds Resolve-TemplateContent for composed template content.
tests/test_presets.py Replaces wrap-replay tests with comprehensive composition strategy tests (validation, composition, chaining, ordering, removal reconciliation).
presets/scaffold/preset.yml Documents the new strategy field and provides composition examples in the scaffold.
presets/README.md Documents composition strategies and updates the “future considerations” section accordingly.
presets/ARCHITECTURE.md Documents strategy behavior and points to the new resolution/composition entry points.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 3

Comment thread src/specify_cli/presets.py Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
Change base-finding to scan from highest priority downward to find the
nearest replace layer, then compose only layers above it. Prevents
evaluation of irrelevant lower layers (e.g. a wrap without placeholder
below a higher-priority replace) across Python, bash, and PowerShell.
Copy link
Copy Markdown
Contributor

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

Adds preset-level composition strategies so higher-priority presets can augment lower-priority templates/commands/scripts instead of only fully replacing them, and updates registration/reconciliation so agent-facing command files reflect the current priority stack.

Changes:

  • Introduces strategy validation in preset.yml and implements layered composition via PresetResolver.collect_all_layers() + resolve_content().
  • Updates command registration and post-install/remove reconciliation to write composed command outputs (including .composed/ artifacts) and keep agent directories in sync.
  • Adds/updates shell resolvers and documentation, and substantially expands preset composition test coverage.
Show a summary per file
File Description
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, composition, and install/remove reconciliation changes.
src/specify_cli/agents.py Adds helper to register commands for non-skill agents (used by reconciliation).
src/specify_cli/__init__.py Enhances specify preset resolve to show layer stack and composition chain.
scripts/bash/common.sh Adds template composition resolver and ensures disabled presets are skipped.
scripts/powershell/common.ps1 Adds Python3 detection + template composition resolver and skips disabled presets.
tests/test_presets.py Adds tests for strategy validation, composition semantics, chaining, and layer ordering.
presets/scaffold/preset.yml Documents strategy usage and examples in scaffold preset.
presets/README.md Documents composition strategies and updates “future considerations”.
presets/ARCHITECTURE.md Documents strategy table and references the new resolution/composition functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/specify_cli/__init__.py Outdated
Show only contributing layers (base and above) in preset resolve
output, matching resolve_content top-down semantics. Layers below
the effective base are omitted since they do not contribute.
Copy link
Copy Markdown
Contributor

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

Adds content composition strategies to the preset system so higher-priority presets can prepend/append/wrap lower-priority templates/commands (instead of only full replacement), with resolver + CLI visibility and cross-platform parity.

Changes:

  • Introduces strategy validation in PresetManifest and implements layered resolution/composition via PresetResolver.collect_all_layers() + resolve_content().
  • Updates command registration to materialize composed command content into preset-local .composed/ and reconciles agent outputs on install/remove.
  • Adds Bash/PowerShell template composition helpers and updates preset docs/scaffold + expands tests for strategy behavior.
Show a summary per file
File Description
src/specify_cli/presets.py Core implementation: strategy validation, layered collection, composed resolution, and install/remove reconciliation for agent command outputs/skills.
tests/test_presets.py Adds/updates tests for strategy validation, resolve_content(), collect_all_layers(), chaining behavior, and removal reconciliation.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() to support reconciliation without clobbering SKILL.md agents.
src/specify_cli/__init__.py Enhances specify preset resolve output to show composition chain and composition warnings.
scripts/bash/common.sh Adds resolve_template_content() and filters disabled presets when reading .registry.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent and a Python 3 locator to parse YAML strategies where available.
presets/scaffold/preset.yml Documents strategy options + examples in the scaffold preset manifest.
presets/README.md Documents composition strategies and supported matrix; removes “future consideration” text for implemented features.
presets/ARCHITECTURE.md Documents strategy behavior and points to the new resolution/composition functions across implementations.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

scripts/bash/common.sh:414

  • Same as above: in the Python used to sort presets for composition, meta.get('enabled', True) will throw if a registry entry’s value isn’t a dict. Skipping non-dict metas (isinstance check) avoids falling back to unordered directory scans just because one registry entry is corrupted.
        data = json.load(f)
    presets = data.get('presets', {})
    for pid, meta in sorted(presets.items(), key=lambda x: x[1].get('priority', 10)):
        if meta.get('enabled', True) is not False:
            print(pid)
except Exception:
  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Comment thread src/specify_cli/presets.py
Comment thread scripts/bash/common.sh Outdated
- Add isinstance(meta, dict) guard in bash registry parsing so corrupted
  entries are skipped instead of breaking priority ordering
- Only use convention-based file lookup when the manifest does not list
  the requested template, making preset.yml authoritative and preventing
  stray on-disk files from creating unintended layers
Copy link
Copy Markdown
Contributor

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

Adds preset composition strategies so higher-priority presets can augment lower-priority templates/commands/scripts (prepend/append/wrap) rather than only fully replacing them, and updates resolution/registration tooling to understand and display the full composition chain.

Changes:

  • Add strategy validation to preset.yml entries and implement bottom-up composition via PresetResolver.collect_all_layers() + resolve_content().
  • Update preset install/remove to reconcile composed command outputs (and skill outputs) so on-disk agent command files reflect the current priority stack, independent of install order.
  • Add shell helpers (bash + PowerShell) for template composition, expand CLI preset resolve output, update docs, and add extensive tests.
Show a summary per file
File Description
tests/test_presets.py Replaces wrap-replay tests with strategy validation + composition/resolution + reconciliation coverage.
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, content composition, and command/skill reconciliation on install/remove.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() to support reconciliation without clobbering SKILL.md agents.
src/specify_cli/init.py Enhances specify preset resolve to show composition chains and warn on composition errors.
scripts/powershell/common.ps1 Adds Python 3 discovery helper and Resolve-TemplateContent for composed template output.
scripts/bash/common.sh Adds resolve_template_content() and improves preset sorting to respect enabled.
presets/scaffold/preset.yml Documents strategy usage and provides composition examples.
presets/README.md Documents composition strategies and updates future-considerations section accordingly.
presets/ARCHITECTURE.md Documents strategy semantics and points to new resolution functions across Python/shell implementations.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 2

Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py
mnriem added 2 commits April 22, 2026 19:01
…text_note

- Update resolve() preset tier to consult manifest file paths before
  convention-based lookup, matching collect_all_layers behavior
- Use exact extension context_note format matching extensions.CommandRegistrar
- Update test to declare template in manifest (authoritative manifest)
…patibility

resolve() is the existing public API used by shell scripts and other
callers. Changing it to manifest-authoritative breaks backward compat
for presets that rely on convention-based file lookup. Only the new
collect_all_layers/resolve_content path uses manifest-authoritative
logic.
Copy link
Copy Markdown
Contributor

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

Adds first-class preset composition strategies so presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts instead of only replacing them, and updates the CLI/docs/tests to reflect the new behavior.

Changes:

  • Add strategy validation to preset manifests and implement bottom-up layer composition via PresetResolver.collect_all_layers() + resolve_content().
  • Update command registration to support composed command content and introduce reconciliation logic after install/remove to ensure agent outputs reflect the current priority stack.
  • Add shell (bash/PowerShell) template-content composition helpers, update preset resolve output, and expand documentation/tests.
Show a summary per file
File Description
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, content composition, command/skill reconciliation during preset lifecycle.
tests/test_presets.py Adds coverage for strategy validation, resolve_content behavior, multi-layer chaining, and removal reconciliation.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() to support reconciliation without clobbering SKILL.md layouts.
src/specify_cli/__init__.py Enhances specify preset resolve to display composition chains and composition warnings.
scripts/bash/common.sh Adds resolve_template_content() (templates) and improves registry sorting to ignore disabled presets.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent (templates), Python 3 discovery helper, and ignores disabled presets.
presets/scaffold/preset.yml Documents strategy field and provides composition examples in the scaffold.
presets/README.md Documents composition strategies and updates “future considerations”.
presets/ARCHITECTURE.md Adds strategy table and references to the composition resolution functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/specify_cli/presets.py
Skip composition in _register_commands when a higher-priority replace
layer already wins for the command. Register the raw file instead and
let reconciliation write the correct final content.
Copy link
Copy Markdown
Contributor

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

Adds preset “composition strategies” so higher-priority presets can augment lower-priority templates/commands/scripts (prepend/append/wrap) instead of only fully replacing them, and updates resolution/registration paths to produce the correct composed outputs across installs/removals.

Changes:

  • Introduces manifest validation + Python-side composition stack building (collect_all_layers) and bottom-up content composition (resolve_content) for templates/commands/scripts.
  • Reworks command registration to pre-compose when appropriate and adds reconciliation on install/remove to keep agent outputs consistent with the active priority stack (including skills handling).
  • Extends Bash/PowerShell template resolution to support composition for templates, and updates docs + tests accordingly.
Show a summary per file
File Description
src/specify_cli/presets.py Core implementation: strategy validation, layered resolution, content composition, and post-install/remove reconciliation for commands/skills.
src/specify_cli/agents.py Adds helper to register commands for non-skill agents (used during reconciliation).
src/specify_cli/__init__.py Enhances specify preset resolve output to show composition chains and composition warnings.
scripts/bash/common.sh Adds resolve_template_content() to compose template content in shell environments.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent and Python3 discovery to support template composition in PowerShell.
tests/test_presets.py Replaces legacy wrap replay tests with validation + composition + layering + reconciliation coverage.
presets/scaffold/preset.yml Documents the new strategy field and provides composition examples.
presets/README.md Adds user-facing documentation for composition strategies and supported combinations.
presets/ARCHITECTURE.md Documents strategy semantics and points to the new resolution/composition entrypoints.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/presets.py:961

  • _reconcile_skills() also re-reads the preset registry from disk via a new PresetRegistry instance. This is additional filesystem/JSON parsing work on every reconcile and duplicates state already available as self.registry. Consider using self.registry.list_by_priority() (optionally memoized) to reduce overhead and keep a single source of truth for registry state.
        # Cache registry once to avoid repeated filesystem reads
        presets_by_priority = list(
            PresetRegistry(self.presets_dir).list_by_priority()
        ) if self.presets_dir.exists() else []
  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py Outdated
Comment thread scripts/bash/common.sh Outdated
Comment thread scripts/powershell/common.ps1 Outdated
- Emit PyYAML-missing warning once per function call in bash/PS1 instead
  of per-preset to avoid spamming stderr
- Use self.registry.list_by_priority() in reconciliation methods instead
  of constructing new PresetRegistry instances to avoid redundant I/O
  and potential consistency issues
Copy link
Copy Markdown
Contributor

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

Adds composition strategies to the preset system so higher-priority presets can augment lower-priority templates/commands/scripts (prepend/append/wrap) rather than only fully replacing them, with corresponding resolver/registration updates and documentation.

Changes:

  • Introduces strategy validation in PresetManifest and adds bottom-up composition via PresetResolver.collect_all_layers() + resolve_content().
  • Updates preset command installation/removal to reconcile composed command outputs (and skill outputs) based on the full priority stack.
  • Adds shell helpers for template composition, enhances specify preset resolve output, and updates docs + tests.
Show a summary per file
File Description
tests/test_presets.py Replaces wrap-only lifecycle tests with comprehensive composition strategy tests (validation, chaining, ordering, reconciliation).
src/specify_cli/presets.py Core implementation: strategy validation, layered collection, composed content resolution, command/skill reconciliation on install/remove.
src/specify_cli/agents.py Adds a non-skill-agent registration helper to support reconciliation without clobbering SKILL.md layouts.
src/specify_cli/init.py Updates specify preset resolve to display layer chain and warn on composition errors.
scripts/powershell/common.ps1 Adds template composition resolver and a Python 3 discovery helper; respects enabled presets.
scripts/bash/common.sh Filters disabled presets when reading registry and adds template composition resolver function.
presets/scaffold/preset.yml Documents the new strategy field and provides composition examples.
presets/README.md Adds a “Composition Strategies” section and removes the previously “future” composition item.
presets/ARCHITECTURE.md Documents strategy semantics and points to the new composition resolution functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/presets.py:2927

  • resolve_content() returns the top layer verbatim when its strategy is replace. For template_type == 'command', that means any strategy key (or other internal-only metadata) present in the command frontmatter will be returned unchanged, even though later in this method you explicitly strip strategy when composing commands.

To make behavior consistent, consider parsing command frontmatter even in the top-level replace fast-path and removing strategy (and applying the same frontmatter inheritance rules, if needed) before returning the content.

        # If the top (highest-priority) layer is replace, it wins entirely —
        # lower layers are irrelevant regardless of their strategies.
        if layers[0]["strategy"] == "replace":
            return layers[0]["path"].read_text(encoding="utf-8")

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/specify_cli/presets.py
Composed output already strips strategy from frontmatter (resolve_content
pops it). Raw file registration preserves legacy frontmatter strategy
for backward compat; reconciliation corrects the final state.
Copy link
Copy Markdown
Contributor

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

This PR introduces preset “composition strategies” so higher-priority presets can augment lower-priority templates/commands/scripts (prepend/append/wrap) instead of only fully replacing them, and updates resolution/registration logic plus docs and tests accordingly.

Changes:

  • Add strategy validation in PresetManifest and implement layered resolution + bottom-up composition via PresetResolver.collect_all_layers() / resolve_content().
  • Update command registration to pre-compose command content when needed and add install/remove reconciliation so agent outputs reflect the current priority stack.
  • Add shell (bash/pwsh) template composition resolvers, update CLI output for preset resolve, and expand documentation + test coverage.
Show a summary per file
File Description
tests/test_presets.py New tests for strategy validation, layered collection, composition behavior, and reconciliation.
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, content composition, and command/skill reconciliation.
src/specify_cli/agents.py Add helper to register commands for non-skill agents (used by reconciliation).
src/specify_cli/init.py Update preset resolve CLI to show composition chain and warnings.
scripts/powershell/common.ps1 Add template composition resolver with manifest strategy parsing (via Python/PyYAML when available).
scripts/bash/common.sh Add template composition resolver and ensure disabled presets are skipped.
presets/scaffold/preset.yml Document strategy field and examples in scaffold preset.
presets/README.md Document composition strategies and update “future considerations”.
presets/ARCHITECTURE.md Describe composition strategies and reference new resolver functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/presets.py Outdated
Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py
Copy link
Copy Markdown
Contributor

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

Adds first-class preset composition strategies so presets can augment lower-priority templates/commands/scripts instead of only replacing them, and updates resolver/CLI/docs/tests accordingly.

Changes:

  • Introduces strategy validation in PresetManifest and implements stack-wide layer collection + bottom-up resolve_content() composition.
  • Updates preset command registration to pre-compose when needed and adds post-install/remove reconciliation to keep agent outputs aligned with the current priority stack.
  • Extends Bash/PowerShell template resolution helpers for composition, and updates preset documentation + tests.
Show a summary per file
File Description
src/specify_cli/presets.py Adds strategy validation, layer collection, composed content resolution, and command/skill reconciliation logic.
src/specify_cli/agents.py Adds register_commands_for_non_skill_agents() helper used by reconciliation.
src/specify_cli/__init__.py Updates specify preset resolve to display composition chains using collected layers.
scripts/bash/common.sh Adds resolve_template_content() (templates) and improves preset ordering by priority + enabled filtering.
scripts/powershell/common.ps1 Adds Resolve-TemplateContent + Python discovery helper; filters disabled presets.
tests/test_presets.py Replaces wrap-replay tests with strategy/composition/layering/reconciliation coverage.
presets/scaffold/preset.yml Documents strategy and provides examples.
presets/README.md Documents composition strategies and updates “future considerations”.
presets/ARCHITECTURE.md Describes strategies and points to new resolution functions.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment thread src/specify_cli/presets.py
Comment thread scripts/bash/common.sh
Comment thread scripts/powershell/common.ps1
Comment thread tests/test_presets.py
Reject absolute paths and parent directory traversal (..) in the
manifest-declared file field before joining with the preset directory.
Matches the Python-side validation in PresetManifest._validate().
Copy link
Copy Markdown
Contributor

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

Note

Copilot was unable to run its full agentic suite in this review.

Adds composition strategies to preset resolution so higher-priority presets can augment (prepend/append/wrap) lower-priority templates/commands/scripts instead of always fully replacing them.

Changes:

  • Introduces strategy validation in preset manifests and bottom-up composition via PresetResolver.collect_all_layers() + resolve_content().
  • Updates command registration to pre-compose where appropriate and adds install/remove reconciliation to keep agent outputs correct across priority changes.
  • Extends shell resolvers and documentation to describe/implement composition behavior; adds/updates unit tests.
Show a summary per file
File Description
tests/test_presets.py Adds tests for strategy validation and composition behavior across types and layering.
src/specify_cli/presets.py Core implementation: strategy validation, layer collection, composed resolution, and reconciliation on install/remove.
src/specify_cli/agents.py Adds helper to register commands for non-skill agents (used by reconciliation).
src/specify_cli/init.py Enhances specify preset resolve output to display composition chain and warnings.
scripts/powershell/common.ps1 Adds template composition resolver and filters disabled presets in registry ordering.
scripts/bash/common.sh Filters disabled presets and adds template composition resolver.
presets/scaffold/preset.yml Documents strategy usage and composition examples in scaffold preset.
presets/README.md Documents composition strategies and supported combinations.
presets/ARCHITECTURE.md Documents strategy table and where resolution/composition is implemented.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 9/9 changed files
  • Comments generated: 4

Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py
Comment thread src/specify_cli/presets.py
Comment thread tests/test_presets.py
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.

feat(presets): Composition strategies (prepend, append, wrap) for templates, commands, and scripts

3 participants