fix(workflows): refuse overlay add that would overwrite a different overlay - #4141
Open
jawwad-ali wants to merge 1 commit into
Open
fix(workflows): refuse overlay add that would overwrite a different overlay#4141jawwad-ali wants to merge 1 commit into
overlay add that would overwrite a different overlay#4141jawwad-ali wants to merge 1 commit into
Conversation
… overlay Overlay identity in this module is the manifest `id`, not the filename — `_find_overlay_file`'s own docstring says so, and a whole test class asserts it. So `.specify/workflows/overlays/wf/lint.yml` can legitimately contain `id: format`. When `_find_overlay_file` finds no file carrying the incoming overlay's id, the fallback target is derived purely from the filename and committed onto unconditionally, with no check for who already lives there: BEFORE: lint.yml holds id='format' add exit: 0 AFTER : lint.yml holds id='lint' -> the format overlay is GONE backups left: none The loss is permanent: `_commit_workflow_file` renames the victim to a `.bak` and the success path then discards that backup. Exit code 0, no warning — a silent loss of exactly the project-local customization overlays exist to protect. Refuse instead. The guard fires only for a *different* id, so updating an overlay in place and creating a new file both still work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Overlay identity in this module is the manifest
id, not the filename._find_overlay_filesays so in its own docstring:…and
TestOverlayFilenameVsManifestIdexists to assert it. So.specify/workflows/overlays/wf/lint.ymllegitimately containingid: formatis a supported state.But when
_find_overlay_filefinds no file carrying the incoming overlay's id,workflow_overlay_addfalls back to a target derived purely from the filename:…and commits onto it unconditionally, never checking who already lives there.
Reproduction on current
main(bf88c9f)lint.ymlholds theformatoverlay; thenspecify workflow overlay addan unrelated overlay whose id happens to belint:The loss is permanent:
_commit_workflow_filerenames the victim to a.bak, and_discard_committed_backup_file(backup)on the success path deletes that backup. Exit code 0, no warning.This is a silent loss of a project-local customization — the exact thing overlays exist to protect (
docs/reference/workflows.md: "project overlays in.specify/workflows/overlays/<id>/are preserved").Fix
Before committing to the filename-derived fallback, read the occupant and refuse if it is a different overlay. Returning
Noneis this function's existing failure contract; the CLI wrapper turns it intotyper.Exit(1)._read_overlay,err_consoleand_escape_markupare all already available in this module — no new imports.Narrowly scoped. The guard fires only when the occupant's id differs. Verified all three paths:
Verification
priority: 3) is byte-intact with no stray.bak; an in-place update still works; a fresh add still works.tests/workflows: no new failures vs a clean-mainbaseline captured onbf88c9f9(10 pre-existing, Windows symlink-privilege).uvx ruff@0.15.0 check src tests→ cleanWritten with assistance from Claude Code. Bug found, reproduced, and verified by me on current
main.