diff --git a/askcc/functions.py b/askcc/functions.py index d5473cd..1bda66b 100644 --- a/askcc/functions.py +++ b/askcc/functions.py @@ -299,12 +299,17 @@ def _run_project_verification(cwd: Path) -> VerificationResult: def _has_acceptance_criteria(body: str) -> bool: - """Check for an acceptance criteria section with checklist items.""" - match = re.search(r"#{2,}\s+acceptance\s+criteria", body, re.IGNORECASE) + """Check for an acceptance criteria section with checklist items. + + The section ends at the next heading at the same level or higher (fewer #s), + so deeper sub-headings (e.g. ### inside an ## section) stay part of it. + """ + match = re.search(r"(#{2,})\s+acceptance\s+criteria", body, re.IGNORECASE) if not match: return False + heading_level = len(match.group(1)) section_start = match.end() - next_heading = re.search(r"\n#{2,}\s+", body[section_start:]) + next_heading = re.search(rf"\n#{{1,{heading_level}}}\s+", body[section_start:]) section = body[section_start : section_start + next_heading.start()] if next_heading else body[section_start:] return bool(re.search(r"-\s*\[[\sx]\]", section)) diff --git a/pyproject.toml b/pyproject.toml index f0f700e..f1f4719 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "askcc" -version = "0.2.6" +version = "0.2.7" description = "A one-shot cc cli executor" authors = [{ name = "mknt", email = "shane.cousins@gmail.com" }] readme = "README.md" diff --git a/tests/test_askcc.py b/tests/test_askcc.py index 7cf4a69..68bc945 100644 --- a/tests/test_askcc.py +++ b/tests/test_askcc.py @@ -610,6 +610,31 @@ def test_h3_heading(self): body = "### Acceptance Criteria\n- [ ] Works with h3\n" assert _has_acceptance_criteria(body) is True + def test_h2_section_with_h3_subheadings(self): + body = ( + "## Acceptance Criteria\n\n" + "### Core Responder Abstraction\n" + "- [ ] Responder ABC defined\n" + "- [ ] validate_input pass-through\n\n" + "### Guardrail\n" + "- [ ] LLMGuardrail class defined\n" + ) + assert _has_acceptance_criteria(body) is True + + def test_h2_section_with_h3_subheadings_then_other_h2(self): + body = ( + "## Acceptance Criteria\n\n### Group A\n- [ ] Item one\n\n## Other Section\n- [ ] Should not be counted\n" + ) + assert _has_acceptance_criteria(body) is True + + def test_h3_section_with_h4_subheadings(self): + body = "### Acceptance Criteria\n\n#### Subgroup\n- [ ] Item under h4\n" + assert _has_acceptance_criteria(body) is True + + def test_h3_section_terminated_by_sibling_h3(self): + body = "### Acceptance Criteria\nPlain text with no checklist.\n\n### Other\n- [ ] Wrong section\n" + assert _has_acceptance_criteria(body) is False + class TestHasDependenciesSection: def test_dependencies_heading(self): diff --git a/uv.lock b/uv.lock index 0177694..2f73f54 100644 --- a/uv.lock +++ b/uv.lock @@ -4,7 +4,7 @@ requires-python = "==3.14.*" [[package]] name = "askcc" -version = "0.2.6" +version = "0.2.7" source = { editable = "." } [package.dev-dependencies]