Skip to content

fix(bundler): let catalog remove delete a project source overriding a built-in - #4533

Open
jawwad-ali wants to merge 1 commit into
github:mainfrom
jawwad-ali:fix/catalog-remove-project-override
Open

fix(bundler): let catalog remove delete a project source overriding a built-in#4533
jawwad-ali wants to merge 1 commit into
github:mainfrom
jawwad-ali:fix/catalog-remove-project-override

Conversation

@jawwad-ali

Copy link
Copy Markdown
Contributor

Problem

remove_source refuses any built-in id before looking at what the project config actually holds:

if target in _BUILTIN_IDS:
    raise BundlerError(
        f"'{target}' is a built-in default source and cannot be deleted "
        "(add a same-id source to override it instead)."
    )

The error message documents the supported override workflow — and the same guard then makes that override permanent.

Reproduction on current main (c173bf1)

built-in ids : ['community', 'default']
under test   : community

add_source   -> OK (documented override). stored: ['community']
remove_source-> REFUSED: 'community' is a built-in default source and cannot be
                deleted (add a same-id source to override it instead).
STILL STORED : ['community']   <-- user cannot undo their own override

The user follows the advice in the error message, then finds there is no CLI path back. The only remedy is hand-editing the very config file bundle catalog exists to manage.

Fix

Refuse a built-in id only when there is nothing project-scoped to remove:

catalogs = _read(project_root)
if target in _BUILTIN_IDS and not any(c.get("id") == target for c in catalogs):
    raise BundlerError(...)

A project-scoped entry is the user's own file and is theirs to delete; removing it simply restores the built-in default.

After the fix:

1. override then remove              -> OK. remaining: []
2. remove builtin with NO override   -> still refused: '...is a built-in default source...'
3. remove unknown id                 -> refused: No project-scoped catalog source matching 'never-added' was found.

Verification

  • Fail-before / pass-after: 1 new-vs-baseline failure with the source reverted to upstream/main → passing with the fix.
  • A companion test pins that deleting the built-in default itself (no override present) is still refused, so the guard is narrowed rather than removed.
  • The pre-existing CLI guard tests/contract/test_bundle_cli.py::test_catalog_remove_builtin_is_refused runs against a project with no such entry and still passes unchanged — verified directly.
  • Scoped regression over tests/unit: 537 passed vs a clean-main baseline of 535 passed, with the same 2 pre-existing failures and none new.
  • uvx ruff@0.15.0 check src tests → clean

Behaviour change, disclosed: exactly one previously-failing input now succeeds — catalog remove <builtin-id> when the project config genuinely contains an entry with that id. That is the defect being fixed. Nothing that previously succeeded changes.


Written with assistance from Claude Code. Bug found, reproduced, and verified by me on current main.

🤖 Generated with Claude Code

… a built-in

`remove_source` refused any built-in id before looking at what the project
config actually held:

    if target in _BUILTIN_IDS:
        raise BundlerError(
            f"'{target}' is a built-in default source and cannot be deleted "
            "(add a same-id source to override it instead)."
        )

That message documents the override workflow -- and the same guard then made
the override permanent. Reproduced on main:

    add_source   -> OK (documented override). stored: ['community']
    remove_source-> REFUSED: 'community' is a built-in default source and
                    cannot be deleted (add a same-id source to override it
                    instead).
    STILL STORED : ['community']

The user could not undo their own project-scoped entry through the CLI at all;
the only way back was hand-editing the config the command exists to manage.

Now the built-in id is refused only when there is no project-scoped entry to
remove. Deleting the user's own entry simply restores the built-in default.

The existing CLI guard (tests/contract/test_bundle_cli.py
test_catalog_remove_builtin_is_refused) runs against a project with no such
entry and still passes unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jawwad-ali
jawwad-ali requested a review from mnriem as a code owner September 11, 2026 16:10
@mnriem mnriem added the triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review label Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-nice-to-have Verdict: evidence-backed fix or greenlit feature — land after review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants