Files
graph-requirements-planner/backend/app/quality.py
ANDREW HOSFORD 0e8978f48c Update project files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 11:59:48 -05:00

55 lines
2.0 KiB
Python

from .models import RequirementNode, NodeType
from .schemas import QualityReport
def validate_requirement(node: RequirementNode, children: list[RequirementNode]) -> QualityReport:
"""Run quality gates on a requirement node.
Quality gates:
1. Traceable — auto-calculated: has parent (non-pillar) + description
2. Measurable — user toggle (manually set by the user)
3. Consistent — user toggle (manually set by the user)
4. Single-purpose — user toggle (manually set by the user)
"""
errors: list[str] = []
warnings: list[str] = []
# 1. Traceable — auto-calculated
traceable = True
if node.node_type != NodeType.pillar:
if not node.parent_id:
errors.append("Orphaned node — must be assigned a parent for traceability")
traceable = False
if not node.description:
warnings.append("Missing description — hard to trace how this serves parent")
else:
if not node.description:
warnings.append("Pillar should have a description explaining its purpose")
# 2. Measurable — user toggle, but forced false without test_spec
measurable = bool(node.measurable)
if not node.acceptance_criteria:
warnings.append("Missing acceptance criteria")
if not node.test_spec:
errors.append("Missing test specification (GIVEN/WHEN/THEN) — cannot be measurable")
measurable = False
# 3. Consistent — user toggle
consistent = bool(node.consistent)
# 4. Single-purpose — user toggle, but warn on heuristic
single_purpose = bool(node.single_purpose)
title_lower = node.title.lower()
if " and " in title_lower and " and " not in title_lower.split("(")[0]:
warnings.append("Title contains 'and' — may serve multiple purposes")
return QualityReport(
traceable=traceable,
measurable=measurable,
consistent=consistent,
single_purpose=single_purpose,
errors=errors,
warnings=warnings,
valid=len(errors) == 0,
)