Skip to content

fix(presets): use _repo_root() for bundled-core source-checkout fallback (#3086)#3091

Merged
mnriem merged 3 commits into
github:mainfrom
mnriem:mnriem-fix-3086-bundled-core-fallback-repo-root
Jun 22, 2026
Merged

fix(presets): use _repo_root() for bundled-core source-checkout fallback (#3086)#3091
mnriem merged 3 commits into
github:mainfrom
mnriem:mnriem-fix-3086-bundled-core-fallback-repo-root

Conversation

@mnriem

@mnriem mnriem commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Assessment and fix for #3086.

The issue claims specify init not copying templates/commands/ into .specify/templates/commands/ causes wrap-strategy presets to fail. That root cause is incorrect: PresetResolver has an explicit Priority‑5 fallback (_find_bundled_core, plus the matching tier‑5 branch in resolve()) specifically designed to locate the core base layer when .specify/templates/commands/ is absent. The missing copy is a layout/cosmetic gap, not a functional one.

However, while verifying, I found a real bug that does break wrap presets — but only in source/editable installs, and for a different reason:

Both fallbacks computed the repo root as Path(__file__).parent.parent.parent. After presets.py was moved to presets/__init__.py (#2826), that chain is one level short — it resolves to src/ and looks for src/templates/commands/<cmd>.md, which never exists. So the base layer was never found.

Wheel installs were unaffected because they take the core_pack branch.

Fix

Use the shared _repo_root() helper (from _assets.py) in both resolve() and _find_bundled_core() instead of a hand-rolled .parent chain, so the path stays correct regardless of module nesting.

Tests

  • Added two regression tests asserting the bundled-core fallback resolves speckit.implement via both collect_all_layers() and resolve() when .specify/templates/commands/ has no matching file.
  • Full preset suite (312 tests) passes.

Why not the issue's suggested fix

Copying templates/commands/ into .specify/templates/commands/ during specify init touches the core SDD install/manifest/upgrade flow to solve a non-problem (the fallback already covers wheel installs). This PR keeps the change isolated to the preset resolver and does not alter the SDD process.

Refs #3086

The tier-5 fallback in PresetResolver.resolve() and
_find_bundled_core() computed the repo root as
Path(__file__).parent.parent.parent. After presets.py was moved to
presets/__init__.py (github#2826) that chain is one level short, resolving
to src/ and looking for src/templates/commands/<cmd>.md, which never
exists. As a result, wrap-strategy presets found no core base layer in
source/editable installs.

Use the shared _repo_root() helper so both fallbacks resolve against
the actual repo-root templates/ tree. Wheel installs were unaffected
(core_pack path), so this only impacts source/editable checkouts.

Refs github#3086

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 22, 2026 16:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes preset resolver tier-5 (“bundled core”) fallback for source/editable installs by using the shared _repo_root() helper (instead of a brittle Path(__file__).parent... chain), and adds regression tests for #3086 to ensure wrap-strategy presets can always locate the core base layer even when .specify/templates/commands/ is empty.

Changes:

  • Update PresetResolver.resolve() tier-5 fallback to use specify_cli._repo_root() for repo-root template lookup in source checkouts.
  • Update PresetResolver._find_bundled_core() to use the same _repo_root() helper for consistent layer collection behavior.
  • Add regression tests covering tier-5 fallback behavior for collect_all_layers() and resolve() when no matching core command exists in .specify/templates/commands/.
Show a summary per file
File Description
src/specify_cli/presets/__init__.py Switch tier-5 repo-root fallback path computation to shared _repo_root() in both resolve() and _find_bundled_core().
tests/test_presets.py Add regression tests for bundled-core fallback resolution paths when .specify/templates/commands/ has no matching command file.

Copilot's findings

Tip

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

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

Comment thread tests/test_presets.py Outdated
A prior edit accidentally removed the
def test_resolve_extension_command_via_manifest_skips_oserror_manifests
line, orphaning its body inside the new bundled-core test. Restore the
test definition so pytest collects it again.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mnriem

mnriem commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

Good catch — the def test_resolve_extension_command_via_manifest_skips_oserror_manifests line had been dropped, orphaning that test's body inside test_resolve_command_falls_back_to_bundled_core. Restored the definition in c52ee42; pytest now collects it again (suite goes 312 → 313, all green).

Posted on behalf of @mnriem by GitHub Copilot CLI (model: Claude Opus 4.8).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot's findings

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

Comment thread tests/test_presets.py Outdated
The two tier-5 fallback regression tests exercise collect_all_layers()
and resolve(), not resolve_core(), so they belong in TestPresetResolver
rather than TestResolveCore. Relocate them for clearer suite navigation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mnriem

mnriem commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

Moved both tier-5 fallback regression tests out of TestResolveCore and into TestPresetResolver in 129514c, since they exercise collect_all_layers() and resolve() rather than resolve_core(). Suite still green (313 passing).

Posted on behalf of @mnriem by GitHub Copilot CLI (model: Claude Opus 4.8).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new

@mnriem mnriem merged commit 79a34b8 into github:main Jun 22, 2026
11 checks passed
@mnriem mnriem deleted the mnriem-fix-3086-bundled-core-fallback-repo-root branch June 22, 2026 16:33
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