init commit
This commit is contained in:
54
backend/app/quality.py
Normal file
54
backend/app/quality.py
Normal file
@@ -0,0 +1,54 @@
|
||||
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("Non-pillar node must have a parent (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,
|
||||
)
|
||||
Reference in New Issue
Block a user