Skip to content

fix(presets): treat an unreadable core template as missing - #3961

Open
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/core-template-decode
Open

fix(presets): treat an unreadable core template as missing#3961
marcelsafin wants to merge 2 commits into
github:mainfrom
marcelsafin:fix/core-template-decode

Conversation

@marcelsafin

Copy link
Copy Markdown
Contributor

Description

_substitute_core_template() reads the resolved core template with a bare read_text(), so one corrupted project-owned override in .specify/templates/commands/ crashes the whole wrap-strategy command registration with a raw UnicodeDecodeError. Both callers (CommandRegistrar.register_pack and _register_commands) are unguarded here — even though register_pack already skips an unreadable preset source with a warning a few lines above the call.

Fix: treat an unreadable core template like a missing one — warn and return the body unchanged with empty frontmatter — matching the function's documented no-core contract ("Both are unchanged / empty when … the core template file does not exist").

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest (6,310 passed, 176 skipped)
  • New regression test test_substitute_core_template_unreadable_core_treated_as_missing (fails on main, passes with fix)
  • ruff check src tests clean

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Implemented autonomously by GitHub Copilot CLI (model: Claude Fable 5) under human direction; TDD (failing test first), full suite and lint verified locally. Commit includes Assisted-by/Co-authored-by trailers.

_substitute_core_template() read the resolved core template with a bare
read_text(), so one corrupted project-owned override in
.specify/templates/commands/ crashed the whole wrap-strategy command
registration with a raw UnicodeDecodeError. Both callers
(CommandRegistrar.register_pack and _register_commands) are unguarded
here, even though register_pack already skips an unreadable preset
source with a warning a few lines above the call.

Treat an unreadable core template like a missing one — warn and return
the body unchanged with empty frontmatter — matching the function's
documented no-core contract.

Assisted-by: GitHub Copilot (model: claude-fable-5, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 19:56
@marcelsafin
marcelsafin requested a review from mnriem as a code owner August 3, 2026 19:56

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

Handles unreadable core templates without crashing preset command registration.

Changes:

  • Warns and falls back when core templates cannot be read or decoded.
  • Adds regression coverage and updates the function contract.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/specify_cli/presets/__init__.py Handles unreadable core templates safely.
tests/test_presets.py Tests invalid UTF-8 fallback behavior.

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

Comment thread tests/test_presets.py Outdated
Review follow-up: use pytest.warns so removing or changing the promised
warning fails the test.

Assisted-by: GitHub Copilot (model: claude-fable-5, autonomous)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 3, 2026 20:13

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/specify_cli/presets/init.py:214

  • CommandRegistrar has no register_pack method; the guarded caller is register_commands, while the other direct caller is PresetManager._register_skills. Referencing the nonexistent method makes this rationale difficult to verify.
    # the wrap-strategy callers already skip an unreadable preset source with
    # a warning (CommandRegistrar.register_pack).

tests/test_presets.py:10732

  • This rationale names nonexistent CommandRegistrar.register_pack and says both callers skip unreadable preset sources. The actual call sites are register_commands (guarded) and _register_skills (whose source read is unguarded), so the regression explanation is inaccurate.
        The wrap-strategy callers (``CommandRegistrar.register_pack`` and
        ``_register_commands``) skip an unreadable preset source with a

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