An extension alias can shadow a core command; `_validate_install_conflicts` only checks installed extensions
- Lenguaje dominante
- Python
- Estrellas
- 137k
- Forks
- 12.3k
- Merge medio
- 2 d 12 h
- PR fusionados (30 d)
- 159
Descripción
### 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.*
Guía de contribución
Línea de trabajo
Start in src/specify_cli/extensions/__init__.py by reading EXTENSION_COMMAND_NAME_PATTERN, the core-namespace guard, _validate_install_conflicts, and _get_installed_command_name_map. Trace how ExtensionManifest validation and ExtensionManager.install_from_directory handle aliases, then inspect _load_core_command_names and _FALLBACK_CORE_COMMAND_NAMES. Done means the chosen core-alias policy is enforced or documented and a test pins that decision.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- cli
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Activo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 55/100