Skip to content

Commit fb7dc0c

Browse files
authored
Fix duplicate step numbering in specify command (#3647)
* fix: correct specify step numbering Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous)
1 parent a5560fc commit fb7dc0c

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

templates/commands/specify.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ Given that feature description, do this:
139139
7. Identify Key Entities (if data involved)
140140
8. Return: SUCCESS (spec ready for planning)
141141
142-
6. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
142+
7. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
143143
144-
7. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
144+
8. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria:
145145
146146
a. **Create Spec Quality Checklist**: Generate a checklist file at `SPECIFY_FEATURE_DIRECTORY/checklists/requirements.md` using the checklist template structure with these validation items:
147147
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Regression tests for top-level step numbering in specify.md."""
2+
3+
import re
4+
from pathlib import Path
5+
6+
REPO_ROOT = Path(__file__).parent.parent
7+
SPECIFY_TEMPLATE = REPO_ROOT / "templates" / "commands" / "specify.md"
8+
MAIN_LIST_START = "Given that feature description, do this:"
9+
MAIN_LIST_END = "## Mandatory Post-Execution Hooks"
10+
11+
12+
def _main_execution_ordinals(text: str) -> list[int]:
13+
"""Extract top-level ordinals from the main execution flow."""
14+
_, start, execution_flow = text.partition(MAIN_LIST_START)
15+
execution_flow, end, _ = execution_flow.partition(MAIN_LIST_END)
16+
if not start or not end:
17+
return []
18+
19+
return [
20+
int(match.group(1))
21+
for line in execution_flow.splitlines()
22+
if (match := re.match(r"^(\d+)\. ", line))
23+
]
24+
25+
26+
def test_main_execution_list_has_no_duplicate_ordinals():
27+
"""The main execution list must not reuse a step number."""
28+
ordinals = _main_execution_ordinals(SPECIFY_TEMPLATE.read_text(encoding="utf-8"))
29+
duplicates = {ordinal for ordinal in ordinals if ordinals.count(ordinal) > 1}
30+
31+
assert not duplicates, f"Duplicate top-level ordinals found: {sorted(duplicates)}"
32+
33+
34+
def test_main_execution_list_is_sequential():
35+
"""The main execution list must run from 1 through N without gaps."""
36+
ordinals = _main_execution_ordinals(SPECIFY_TEMPLATE.read_text(encoding="utf-8"))
37+
38+
assert ordinals, "Could not find the main execution list in specify.md"
39+
assert ordinals == list(range(1, 9))

0 commit comments

Comments
 (0)