github / github/spec-kit

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

未关闭
#4,065 15 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Python
星标
137k
派生
12.3k
平均合并
2 天 12 小时
30 天内合并 PR
159

描述

### 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`).

贡献指南

打开贡献指南

调研方向

从 PR #4066 开始,将更改与 templates/spec-template.md、templates/tasks-template.md、templates/checklist-template.md 以及 issue 中提到的五个命令文件进行比较。检查 taskstoissues.md 中的正则表达式和现有的 converge.md 规则,然后验证未来的标识符保持稳定,并且能够识别四位数的任务 ID,同时不追溯性地更改现有工件。

由索引模型根据 Issue 内容生成。

评估

技术栈
markdown
领域
developer-experience, tooling
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
描述清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。