Skip to content

fix: preserve registered integration skills during extension update - #5005

Open
chelsealong wants to merge 2 commits into
github:mainfrom
chelsealong:fix/codex-spec-kit-5002
Open

chelsealong wants to merge 2 commits into
github:mainfrom
chelsealong:fix/codex-spec-kit-5002

Conversation

@chelsealong

Copy link
Copy Markdown
Contributor

Description

Fixes #5002. Updating an extension now refreshes commands and native skills for integrations recorded in its previous registry entry, including a non-default Codex integration. An integration with no prior registration remains untouched.

Testing

  • Regression test: failed before the fix because the Codex SKILL.md was deleted; both positive and negative cases pass after the fix.
  • .venv/bin/python -m pytest tests/specify_cli/extensions/test_command_update.py tests/specify_cli/extensions/test_command_update_transaction.py tests/specify_cli/extensions/test_command_update_artifacts.py -q — 61 passed.
  • .venv/bin/specify --help and git diff --check — passed.
  • Ruff reports 20 findings in the touched files; the unchanged files report the same 20 findings.

AI Disclosure

  • I used AI assistance.

AI disclosure: Codex (GPT-6, autonomous mode) investigated the issue and generated the code and regression test. No human review is claimed.

@chelsealong
chelsealong requested a review from mnriem as a code owner October 17, 2026 10:36
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Oct 18, 2026
@mnriem
mnriem requested a max review from Copilot October 19, 2026 12:52

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.

🟡 Changes recommended

Secondary registration can overwrite the active integration’s skills when output directories are shared.

2 open issues
What changed in this PR

Preserves extension commands and native skills for previously registered integrations during updates, addressing #5002.

Changes:

  • Refreshes previously registered non-default integrations.
  • Includes their outputs in transactional backups.
  • Adds positive and negative Codex regression cases.

AI disclosure: GitHub Copilot (model unknown, autonomous) generated this review for the requester.

File Description
tests/​specify_cli/​extensions/​test_command_update.py Tests preservation of registered Codex skills and exclusion of unregistered integrations.
src/​specify_cli/​extensions/​_command_update_transaction.py Expands backups and restores secondary integration registrations after installation.

Review effort: Max

Comment on lines +410 to +414
command_targets = manager._command_registration_targets()
for agent_name, cmd_names in registered_commands.items():
if cmd_names and agent_name in registrar.AGENT_CONFIGS:
command_targets.setdefault(
agent_name,
@mnriem

mnriem commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback

@mnriem mnriem added the author-awaiting Waiting on author response label Oct 19, 2026
Assisted-by: Codex (model: GPT-6, autonomous)
Copilot AI max review requested due to automatic review settings November 15, 2026 11:52
@chelsealong

Copy link
Copy Markdown
Contributor Author

Thank you for both findings. Commit 3542570 reuses the refreshed command list when integrations share a skills directory, preserving the active integration’s rendering. Secondary integrations now retain the normal output-directory and project-marker checks.

The new CLI regressions cover shared Codex/Zed output, a deleted output directory, a removed Hermes project marker, and failure after secondary registration has overwritten an existing candidate and created new alias files. The rollback test checks byte-for-byte restoration, removal of the new directories, and equality with the original registry entry. Removing the expanded backup inventory makes that test fail with leftover files. The three affected suites pass all 93 tests, and the CLI help entry point succeeds.

Posted on behalf of chelsealong. Codex (model GPT-6, autonomous) implemented the follow-up, ran the tests, and drafted this summary.

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.

🟡 Changes recommended

Secondary-integration updates can overwrite existing user files and delete their only backups during cleanup, creating a data-loss risk.

8 open issues
3 previously missed issues

In code that hasn't changed since last review

Medium severity Apply refresh eligibility checks to historical backup targets

src/​specify_cli/​extensions/​_command_update_transaction.py:419

Historical targets bypass the output-directory and detect_dir checks used by the refresh pass, so a removed Hermes marker can make an unrelated hard-linked skill at a new alias abort the entire update. Apply those checks before adding secondary backup targets, while preserving the manager's active recovery targets and the backups of previously registered files.

AI-generated for the review requester by GitHub Copilot (model unknown, autonomous mode).

Medium severity Preserve previously registered Copilot skills during integration changes

src/​specify_cli/​extensions/​_command_update_transaction.py:570

An extension previously used by Copilot in --skills mode is tracked only in registered_skills, so updating after integration use claude still deletes its Copilot skills. Capture the previously owned skill roots before removal and refresh those integrations in their original skills mode.

AI-generated for the review requester by GitHub Copilot (model unknown, autonomous mode).

Medium severity Refresh persisted generic registrations when inactive

src/​specify_cli/​extensions/​_command_update_transaction.py:580

After integration use claude, the registrar omits generic from AGENT_CONFIGS, so this filter drops a prior generic registration even though removal has deleted its hash-owned command files. Resolve the persisted generic directory and refresh its commands and ownership hashes even when generic is inactive.

AI-generated for the review requester by GitHub Copilot (model unknown, autonomous mode).

1 resolved since last review

Review effort: Max

Comment on lines +617 to +619
registrar.register_commands_for_all_agents(
manifest, manager.extensions_dir / extension_id,
project_root, only_agent=agent_name,
Comment on lines +577 to +580
missing_agents = [
agent_name for agent_name, cmd_names in registered_commands.items()
if cmd_names and agent_name not in refreshed_commands
and agent_name in registrar.AGENT_CONFIGS
Comment on lines +599 to +603
if config.get("extension") == "/SKILL.md":
for refreshed_agent, commands in refreshed_commands.items():
refreshed_config = registrar.AGENT_CONFIGS[refreshed_agent]
if (
refreshed_config.get("extension") == "/SKILL.md"
Comment on lines +616 to +621
refreshed_commands.update(
registrar.register_commands_for_all_agents(
manifest, manager.extensions_dir / extension_id,
project_root, only_agent=agent_name,
)
)
# An update replaces an existing installation. Keep the
# integrations that held commands before removal, even
# when they are not the current default integration.
if registered_commands:
Comment on lines +599 to +600
if config.get("extension") == "/SKILL.md":
for refreshed_agent, commands in refreshed_commands.items():
Comment on lines +446 to +447
@pytest.mark.parametrize("case", ["shared", "missing-output", "missing-marker", "rollback"])
def test_update_secondary_registration_safeguards(self, tmp_path, monkeypatch, case):

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-awaiting Waiting on author response triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: extension update removes extension skills of non-default integrations

3 participants