github / github/spec-kit

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

Cerrado
#4,555 1 comentario 0 reacciones 0 asignados Ver en GitHub
bug-assess severity-medium triage-nice-to-have
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

Abrir la 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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.