Skip to content

fix(workflows): remove the catalog source shown at the listed index - #4870

Merged
mnriem merged 1 commit into
github:mainfrom
kartsan03:fix/workflow-catalog-remove-index
Oct 7, 2026
Merged

mnriem merged 1 commit into
github:mainfrom
kartsan03:fix/workflow-catalog-remove-index

Conversation

@kartsan03

Copy link
Copy Markdown
Contributor

Description

specify workflow catalog remove <index> and specify workflow step catalog remove <index> take the index "from 'catalog list'" (help text and docs/reference/workflows.md). The list is sorted by priority, with SPECKIT_*_CATALOG_URL taking over entirely when set, but remove_catalog() pops that index from the raw project YAML. So:

  • with priorities that don't match file order, remove 0 deletes a different source than the one listed at [0], and reports success;
  • with the environment override set, the list shows only env-override, and remove 0 deletes a project source that wasn't listed at all.

The bundle catalog had a similar catalog remove mismatch, fixed in #4533. This is the same kind of bug in the workflow and step catalogs.

The fix makes remove_catalog() in both catalog modules parse the project file with the same validation and stable priority sort that list uses, keeping each entry's original position, then remove that entry. While the environment override is active, removal is refused before anything is written. The missing-file error is unchanged, and the range check counts listed entries. A config that list rejects is now rejected by remove too, instead of having a raw row popped. The reference docs and workflows/README.md now say the index is the listed one and that environment-provided sources can't be removed this way.

Repro (no catalog is downloaded; example.invalid URLs are never fetched):

specify init catalog-remove-repro --integration codex --ignore-agent-tools --non-interactive
cd catalog-remove-repro
cat > .specify/workflow-catalogs.yml <<'YAML'
catalogs:
  - name: team
    url: https://example.invalid/team.json
    priority: 10
    install_allowed: true
  - name: review
    url: https://example.invalid/review.json
    priority: 1
    install_allowed: true
YAML
cp .specify/workflow-catalogs.yml .specify/step-catalogs.yml
specify workflow catalog list          # [0] review, [1] team
specify workflow catalog remove 0
specify workflow step catalog list     # [0] review, [1] team
specify workflow step catalog remove 0
# then, with one project source left:
SPECKIT_WORKFLOW_CATALOG_URL=https://example.invalid/ci.json specify workflow catalog list   # [0] env-override
SPECKIT_WORKFLOW_CATALOG_URL=https://example.invalid/ci.json specify workflow catalog remove 0
Command main (d3ab820) This PR
workflow catalog remove 0 ✓ Catalog source 'team' removed, review left ✓ Catalog source 'review' removed, team left
workflow step catalog remove 0 ✓ Step catalog source 'team' removed, review left ✓ Step catalog source 'review' removed, team left
remove 0 with SPECKIT_WORKFLOW_CATALOG_URL set removes the remaining project source, exit 0 exit 1, project file unchanged

With the fix, the last row prints:

Error: The active catalog comes from SPECKIT_WORKFLOW_CATALOG_URL. Unset that
variable to remove a project catalog source.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

New tests: parametrized over both catalogs in tests/test_workflows.py::TestWorkflowCatalog (listed position with priority reorder, equal-priority ties, duplicate names and skipped blank-URL rows; bounds checked against listed entries; env-override refusal with unchanged bytes; blank override ignored; configs that list rejects), plus a priority-reorder and an env-override CLI test in each test_command_remove.py, using real config files.

With only src/ reverted to main, 22 tests fail, all of them new; the other 115 pass, including the new negative-index and blank-override controls. With the fix, all 137 tests in the catalog suites pass.

Full suite on Linux, Python 3.13.15: 9572 passed, 265 skipped (uv run pytest, 5m28s). uvx ruff@0.15.0 check src tests passes, and markdownlint passes on both changed Markdown files.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: Two agents, both autonomous. Codex CLI (model: gpt-6-astra, reasoning effort xhigh, autonomous, sandboxed and offline) found the bug while auditing the catalog removal paths, wrote the reproduction, and generated the fix, tests and docs changes. Claude Code (model: claude-opus-5-5, autonomous) picked this fix from the candidates, reviewed the diff and cut it down (it dropped new error messages for user-level and built-in sources that weren't needed for this bug), reran the tests against main and the fix, ran the full suite and lint, and drafted this description. Commits carry Assisted-by: trailers.

`workflow catalog remove <index>` and `workflow step catalog remove <index>`
take the index from `catalog list`, which is priority-ordered, but popped
that index from the raw project YAML. With priorities set, remove deleted a
different source; with SPECKIT_*_CATALOG_URL set, it deleted a project source
the list never showed.

Parse the project config with the same validation and priority sort as the
list, keep each entry's original position, and remove that entry. Refuse
removal while the environment override is active, before any write.

Assisted-by: Codex CLI (model: gpt-6-astra, autonomous)
Assisted-by: Claude Code (model: claude-opus-5-5, autonomous)
@kartsan03
kartsan03 requested a review from mnriem as a code owner October 7, 2026 19:24
@mnriem
mnriem requested a balanced review from Copilot October 7, 2026 20:20

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.

🟢 Approval recommended

The implementation aligns removal with listing behavior and includes comprehensive positive, negative, and regression coverage.

0 open findings

What changed in this PR

Fixes workflow and step catalog removal so indices match priority-ordered catalog listings, consistent with the bundle catalog fix in #4533.

Changes:

  • Retains original YAML positions while sorting catalog entries.
  • Prevents removal while environment overrides are active.
  • Adds regression coverage and clarifies documentation.
File Description
src/​specify_cli/​workflows/​catalog/​_domain.py Corrects workflow catalog removal.
src/​specify_cli/​workflows/​step/​catalog/​_domain.py Corrects step catalog removal.
tests/​test_workflows.py Covers ordering, validation, bounds, and overrides.
tests/​specify_cli/​workflows/​catalog/​test_command_remove.py Adds workflow CLI regressions.
tests/​specify_cli/​workflows/​step/​catalog/​test_command_remove.py Adds step CLI regressions.
docs/​reference/​workflows.md Documents removal semantics.
workflows/​README.md Clarifies listed indices and environment sources.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@mnriem
mnriem merged commit ad4296d into github:main Oct 7, 2026
15 checks passed
@mnriem

mnriem commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Thank you!

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.

3 participants