From b69f3725fbf0afd13c23d4980b08588d7a48c5a0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Jul 2026 18:06:55 +0000 Subject: [PATCH] Fix specify-step-self-reference: renumber duplicate step 6 in specify.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the remediation from the bug assessment on issue #2407. The top-level numbered list in templates/commands/specify.md had two consecutive items both labelled 6. — the execution-flow step (line 117) and the write-spec step (line 142). This caused the Specification Quality Validation section to be numbered 7 when it should be 8, which led to a self-referencing 'proceed to step 7' instruction inside step 7 itself. Changes: - Line 142: 6. Write the specification → 7. Write the specification - Line 144: 7. Specification Quality Validation → 8. Specification Quality Validation - Add regression test tests/test_specify_template_numbering.py that asserts the main execution list is sequential with no duplicates Refs #2407 Assisted-by: GitHub Copilot (model: claude-sonnet-4.6, autonomous) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- templates/commands/specify.md | 4 +- tests/test_specify_template_numbering.py | 59 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/test_specify_template_numbering.py diff --git a/templates/commands/specify.md b/templates/commands/specify.md index e32fd48971..54151e8b42 100644 --- a/templates/commands/specify.md +++ b/templates/commands/specify.md @@ -139,9 +139,9 @@ Given that feature description, do this: 7. Identify Key Entities (if data involved) 8. Return: SUCCESS (spec ready for planning) -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. +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. -7. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria: +8. **Specification Quality Validation**: After writing the initial spec, validate it against quality criteria: 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: diff --git a/tests/test_specify_template_numbering.py b/tests/test_specify_template_numbering.py new file mode 100644 index 0000000000..21b50fb624 --- /dev/null +++ b/tests/test_specify_template_numbering.py @@ -0,0 +1,59 @@ +"""Regression test for duplicate top-level step numbers in specify.md. + +Covers #2407: two consecutive items were both labelled ``6.``, which caused +a self-referencing ``proceed to step 7`` inside the section already numbered 7. +""" + +import re +from pathlib import Path + +REPO_ROOT = Path(__file__).parent.parent +SPECIFY_MD = REPO_ROOT / "templates" / "commands" / "specify.md" + + +def _main_execution_ordinals(text: str) -> list[int]: + """Return ordinals from the main execution list (items 1-N at column 0). + + The file contains several distinct numbered lists; we only care about the + primary execution steps that span the first ~250 lines and whose first item + starts with ``1. **Generate``. + """ + ordinals: list[int] = [] + in_main_list = False + for line in text.splitlines(): + m = re.match(r"^(\d+)\. ", line) + if m: + n = int(m.group(1)) + if n == 1 and not in_main_list: + # Start of the main execution list + in_main_list = True + ordinals = [n] + elif in_main_list: + if n == 1: + # A new list restarts — stop here + break + ordinals.append(n) + return ordinals + + +def test_no_duplicate_top_level_ordinals(): + """The main numbered list in specify.md must have no duplicate ordinals.""" + text = SPECIFY_MD.read_text(encoding="utf-8") + ordinals = _main_execution_ordinals(text) + duplicates = [n for n in ordinals if ordinals.count(n) > 1] + assert not duplicates, ( + f"Duplicate top-level ordinals found in templates/commands/specify.md: " + f"{sorted(set(duplicates))}" + ) + + +def test_main_execution_list_is_sequential(): + """The main execution steps must run 1, 2, 3, … without gaps or duplicates.""" + text = SPECIFY_MD.read_text(encoding="utf-8") + ordinals = _main_execution_ordinals(text) + assert ordinals, "Could not find the main execution list in specify.md" + expected = list(range(1, len(ordinals) + 1)) + assert ordinals == expected, ( + f"Main execution steps are not sequential in templates/commands/specify.md. " + f"Got: {ordinals}, expected: {expected}" + )