github / github/spec-kit

An extension alias can shadow a core command; `_validate_install_conflicts` only checks installed extensions

Fermée
#4,555 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub
bug-assess severity-medium triage-nice-to-have
Langage dominant
Python
Étoiles
137k
Forks
12.3k
Merge moyen
2 j 12 h
PR mergées (30 j)
159

Description

### Problem Statement

`_validate_install_conflicts` is documented as rejecting installs that "would shadow core or installed extension commands", but it only checks installed **extensions**. Core command names are never in the map it consults, so an extension can claim a core command name as an **alias** and install successfully.

Split out of #4421 at a maintainer's request, so that stage 1 (#4488) stays additive and no core-validation change is smuggled into it.

### Reproduction

`main` at `d848fb4`. A manifest whose command carries `speckit.taskstoissues` — a live core command — as an alias:

```yaml
schema_version: "1.0"
extension:
id: probe
name: "Probe"
version: "1.0.0"
description: "probe"
requires:
speckit_version: ">=0.2.0"
provides:
commands:
- name: speckit.probe.taskstoissues
file: commands/cmd.md
aliases: ["speckit.taskstoissues"] # core command name
```

Result:

```
1) manifest validation:
ACCEPTED — aliases: [['speckit.taskstoissues']]
2) install into a project (core taskstoissues exists):
ACCEPTED — installed: probe
```

Both stages accept it, with the core command present in the same project.

### Cause

Two gaps that line up:

1. **Aliases are not pattern-checked.** `EXTENSION_COMMAND_NAME_PATTERN` and the core-namespace guard in `src/specify_cli/extensions/__init__.py` apply to *primary* command names only. A primary `speckit.taskstoissues` is correctly rejected (it fails the two-segment pattern, and an extension `id` equal to a core command name is rejected separately) — but an alias goes through neither check.

2. **The conflict check does not know about core.** `_get_installed_command_name_map` walks `self.registry` — installed extensions — so core command names never appear in the map that `_validate_install_conflicts` compares against. Confirmed by inspection: the function references `self.registry` and nothing that loads core command names (`_load_core_command_names` / `_FALLBACK_CORE_COMMAND_NAMES`).

So the docstring describes a guarantee ("shadow core or installed extension commands") that is only half implemented.

### Impact

A community extension can claim a core command's name as an alias and shadow it. This is most likely to bite during the #4421 migration, where the whole point of stage 1 is that `speckit.taskstoissues` and `speckit.github.taskstoissues` coexist without either shadowing the other — but it applies to any core command, not just this one.

The bundled `github` extension in #4488 deliberately registers no alias, and has a test pinning that. Worth being explicit that this is currently **author discipline, not an enforced invariant** — which is the reason to file this separately rather than rely on the convention holding.

### Suggested Fix

Either:

- extend the core-namespace guard to aliases as well as primary names, and include core command names in the map `_validate_install_conflicts` consults; or
- if shadowing core via an alias is intended to be allowed (an override mechanism), narrow the docstring to describe what is actually checked.

Whichever way it goes, a test should pin the decision — an install that claims `speckit.taskstoissues` as an alias currently passes silently either way.

### Component

Specify CLI (initialization, commands)

---

*Disclosure: I used an AI assistant (Claude Code, model Claude Opus 5) to investigate this and draft this report. The results above came from running the probe manifest through `ExtensionManifest` and `ExtensionManager.install_from_directory` against `main`; I reviewed the findings before filing.*

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Commencez dans src/specify_cli/extensions/__init__.py par lire EXTENSION_COMMAND_NAME_PATTERN, la protection de l’espace de noms core, _validate_install_conflicts et _get_installed_command_name_map. Suivez la manière dont la validation de ExtensionManifest et ExtensionManager.install_from_directory gère les alias, puis examinez _load_core_command_names et _FALLBACK_CORE_COMMAND_NAMES. C’est terminé lorsque la politique choisie pour les alias core est appliquée ou documentée et qu’un test fige cette décision.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
cli
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
55/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.