github / github/spec-kit

[Feature]: Stable, block-allocated identifiers (FR/SC/T/CHK) so edits never force a renumber

Abierto
#4,065 15 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
137k
Forks
12.3k
Merge medio
2 d 12 h
PR fusionados (30 d)
159

Descripción

### Problem Statement

`FR-###`, `SC-###`, `T###` and `CHK###` are **references**, not just labels. Once a spec exists, its identifiers get cited from `plan.md`, `tasks.md` dependency lines, checklist items (`[Spec §FR-001]`), `analyze.md` findings tables, `converge.md` source-refs, the GitHub issue titles created by `/speckit.taskstoissues`, commit messages, and PR review comments.

But the templates and commands tell agents to allocate them **densely and sequentially**:

- `templates/commands/tasks.md:160` — "**Task ID**: Sequential number (T001, T002, T003...) in execution order"
- `templates/commands/checklist.md:258` — "globally incrementing IDs starting at CHK001"
- `templates/checklist-template.md:45` — "Items are numbered sequentially for easy reference"
- `templates/spec-template.md` — `FR-001`…`FR-007`, `SC-001`…`SC-004` run as one dense sequence

Dense + sequential means **any insertion or deletion forces a renumber**, and a renumber silently invalidates every citation elsewhere. This shows up in practice in several ways:

1. **Cross-artifact reference rot.** Insert `FR-004` into an existing spec and every later FR shifts. `checklists/requirements.md`, `plan.md`, and any open PR comment now point at the wrong requirement. Nothing errors — the references just quietly mean something else.
2. **Token cost, twice over.** Adding one task at position 10 of a 50-task file rewrites 40 task lines plus every dependency reference (`depends on T012, T013`) and every summary block. Deleting a task is worse: the renumber-and-re-reference pass is pure waste, and it contaminates the agent's context with a diff that carries no information.
3. **Agents get it wrong at scale.** [#1497](https://github.com/github/spec-kit/issues/1497) reported exactly this: after deleting three tasks from a 100-task file the task lines were renumbered "more or less correctly" but the `By Type: … (T009-T021, T036-T039, T046-T049)` summaries went out of sync and were hard to repair.
4. **It contradicts a rule the repo already has.** `templates/commands/converge.md:77` forbids the agent to "rewrite, renumber, reorder, or delete any existing task", and `:219` says "Never reuse or renumber existing IDs." That invariant is exactly right — but it currently only applies to convergence tasks, while the dense allocation scheme in `tasks.md` / `spec-template.md` / `checklist.md` actively pushes agents in the opposite direction everywhere else.

#1497 was closed as stale rather than rejected on the merits, so the underlying problem is still live.

### Proposed Solution

Make identifiers permanent, and allocate them sparsely enough that they can stay permanent.

**1. Identifiers are permanent references.** Never renumber an existing identifier. A removed item's number is retired, not reused, and the hole it leaves is never closed. Gaps are the expected steady state, not damage to repair. (This is `converge.md`'s existing rule, promoted to a general invariant.)

**2. Allocate in 1000-blocks per group, stepping by 10 within the group.** Each group — an FR category, a task phase, a checklist category — starts at the next multiple of 1000; items step by 10 inside it:

```markdown
## Phase 1: Setup
- [ ] T1000 Create project structure per implementation plan
- [ ] T1010 Initialize [language] project with [framework] dependencies
- [ ] T1020 [P] Configure linting and formatting tools

## Phase 2: Foundational
- [ ] T2000 Setup database schema and migrations framework
- [ ] T2010 [P] Implement authentication/authorization framework
```

The two levels of spacing do different jobs:

- **Step 10 → insert in position.** A task that belongs between `T1010` and `T1020` becomes `T1015`. It sits where it should in the document, IDs stay ascending, and nothing after it moves. This is the case a per-group block alone does *not* solve.
- **1000-blocks → groups are independent.** Appending to Phase 1 takes `T1030`; Phase 2 is untouched. Adding a whole phase takes the next unused thousand.
- **Deletion → do nothing.** Remove the line and stop. No renumber, no re-reference pass, no context churn.

For an ungrouped list, the same step-10 rule applies from `1000`.

Concretely:

- `templates/spec-template.md` — FR samples grouped by category (`FR-1000`, `FR-1010`, … / `FR-2000`, …); SC follows the same scheme; both carry the rule in a template comment
- `templates/tasks-template.md` — sample tasks renumbered per phase; the `## Format` section documents block, step, insert, and delete
- `templates/checklist-template.md` — `CHK1000` / `CHK2000` per category; the closing note changes from "numbered sequentially for easy reference" to "stable references — do not renumber"
- `templates/commands/{specify,clarify,tasks,checklist,converge}.md` — generation rules updated to allocate, insert, and preserve accordingly

**One dependent fix.** With four-digit IDs, `templates/commands/taskstoissues.md:67` breaks: it matches issue titles with `` `\bT\d{3}\b` `` — *exactly* three digits — so given `T1000` the trailing `\b` cannot fall between two digits and there is no match at all. Those tasks are silently neither deduplicated nor converted into issues. This is already reachable today, independent of this proposal ([#3866](https://github.com/github/spec-kit/issues/3866)): `converge.md` formats IDs with `T{M+1:03d}`, and `03d` is a floor rather than a cap. Widening to `` `\bT\d{3,}\b` `` is a prerequisite here, and recording the contract in `converge.md` keeps producer and consumer from drifting apart again.

### Alternatives Considered

- **Hierarchical IDs (`T1.1`, `T1.2`) — the [#1497](https://github.com/github/spec-kit/issues/1497) proposal.** Solves the same insertion problem, but changes the ID *shape*. Every consumer that assumes `T\d+` breaks: `taskstoissues.md`'s regex and issue titles, `converge.md`'s `T{M+1:03d}` formatting, `analyze.md`'s tables, and any existing `tasks.md` in the wild. Inserting between `T1.2` and `T1.3` also still needs a sub-level (`T1.2.1`), so IDs grow unboundedly rather than staying uniform. Numeric blocks keep the existing `T####` shape and every existing consumer keeps working.
- **100-blocks with step 1** (`T100`, `T101` / `T200`). Shorter IDs and solves append/delete, but not positional insert — a task belonging between `T101` and `T102` has no free number, so it either renumbers or lands out of order.
- **100-blocks with step 10** (`T100`, `T110`). Solves both, but caps a group at ~10 items before it overflows into the next block; task phases routinely exceed that.
- **Do nothing / tell agents "try not to renumber".** Roughly the status quo, and #1497's report shows agents renumber anyway when the surrounding template models dense sequential allocation. The template has to make the correct behaviour the path of least resistance.
- **Renumber, but auto-update references.** Requires a reference index across `spec.md`, `plan.md`, `tasks.md`, checklists, and *external* systems (GitHub issues, PR comments) that no tool can reach. Not feasible for the external half.

### Component

Spec templates (BDD, Testing Strategy, etc.)

### AI Agent (if applicable)

All agents

### Additional Context

I've been running this convention locally (constitution rule + patched templates and command prompts) and it removed the renumbering churn entirely.

PR implementing the above: #4066. Existing artifacts are not retroactively renumbered — the rule applies going forward. Full test suite is unchanged by the diff (13 failed / 6616 passed both with and without it; the 13 are pre-existing branch-slug and template-composition failures on `main`).

Guía de contribución

Abrir la guía de contribución

Línea de trabajo

Start with PR #4066 and compare the changes against templates/spec-template.md, templates/tasks-template.md, templates/checklist-template.md, and the five command files named in the issue. Check the taskstoissues.md regex and existing converge.md rule, then verify that future identifiers remain stable and four-digit task IDs are recognized without retroactively changing existing artifacts.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
markdown
Área
developer-experience, tooling
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Bien especificado
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.