orchestrata_ultimate.verification.requirements.prolog_generator

Reference › orchestrata_ultimate › verification › requirements › prolog_generator

PrologGenerator renders a list of Constraint objects as Prolog source text. generate writes a module header named auto_verification that exports every non-empty predicate with arity 1, followed by one clause per constraint produced by generate_predicate. A performance constraint becomes a clause that requires a number no greater than the expected value; a quality constraint with a numeric expectation requires a number at least the expected value; other quality constraints, and all security and functional constraints, become a fact that holds for the atom true. The constraint description is emitted as a comment. validate_syntax is a line-by-line sanity check (comment lines are skipped, clause lines must end in a period or comma, and so on), not a Prolog parse. The module is separate from the rulebase that ConstraintEvaluator queries, and has no importers inside the package. Constraints usually come from the requirements parser.

At a glance

Source src/orchestrata_ultimate/verification/requirements/prolog_generator.py
Lines of code 104
Classes 1
Functions 0
Imports (internal) orchestrata_ultimate.core.base.traces, orchestrata_ultimate.verification.types
Imported by none
Tests that import it tests/verification/requirements/test_prolog_generator.py, tests/verification/test_prolog_generator.py, tests/verification/test_requirements.py, tests/verification/test_small_modules.py

Class diagram

Class diagram orchestrata_ultimate.verification.requirements.prolog_generator

Dependency diagram

Dependency diagram orchestrata_ultimate.verification.requirements.prolog_generator

API

Classes

PrologGenerator

Decorators: traces(spec='035', story='US-001', reqs=['REQ-035-US-001-008', 'REQ-035-US-001-009', 'REQ-035-US-001-016', 'REQ-035-US-… · Line 28

Generates Prolog predicates from constraints.

Method Signature Summary
generate generate(constraints: list[Constraint]) -> str Generate Prolog code for all constraints.
generate_predicate generate_predicate(constraint: Constraint) -> str Generate a single Prolog predicate for a constraint.
validate_syntax validate_syntax(prolog_code: str) -> bool Basic syntax validation for generated Prolog.

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/src/orchestrata_ultimate/verification/requirements/prolog_generator.py

"""Convert Constraint objects into Prolog predicates."""

# Spec: 035 - Verification Agent

import logging

from orchestrata_ultimate.core.base.traces import traces
from orchestrata_ultimate.verification.types import Constraint, ConstraintType

logger = logging.getLogger(__name__)


@traces(
    spec="035",
    story="US-001",
    reqs=[
        "REQ-035-US-001-008",
        "REQ-035-US-001-009",
        "REQ-035-US-001-016",
        "REQ-035-US-001-017",
        "REQ-035-US-001-023",
        "REQ-035-US-002-008",
        "REQ-035-US-002-011",
        "REQ-035-US-002-014",
        "REQ-035-US-002-019",
    ],
)
class PrologGenerator:
    """Generates Prolog predicates from constraints."""

    @traces(spec="035", story="US-001", reqs=["REQ-035-US-001-023"])
    def generate(self, constraints: list[Constraint]) -> str:
        """Generate Prolog code for all constraints."""
        lines = [
            "%% Auto-generated verification predicates.",
            ":- module(auto_verification, [",
        ]
        exports = [f"    {c.predicate}/1" for c in constraints if c.predicate]
        lines.append(",\n".join(exports))
        lines.append("]).")
        lines.append("")
        for constraint in constraints:
            if constraint.predicate:
                lines.append(self.generate_predicate(constraint))
                lines.append("")
        return "\n".join(lines)

    @traces(
        spec="035", story="US-001", reqs=["REQ-035-US-001-008", "REQ-035-US-002-011"]
    )
    def generate_predicate(self, constraint: Constraint) -> str:
        """Generate a single Prolog predicate for a constraint."""
        pred = constraint.predicate
        expected = constraint.expected

        if constraint.type == ConstraintType.PERFORMANCE:
            return (
                f"%% {constraint.description}\n"
                f"{pred}(Value) :- number(Value), Value =< {expected}."
            )
        elif constraint.type == ConstraintType.QUALITY:
            if isinstance(expected, (int, float)):
                return (
                    f"%% {constraint.description}\n"
                    f"{pred}(Value) :- number(Value), Value >= {expected}."
                )
            return f"%% {constraint.description}\n{pred}(true)."
        elif constraint.type == ConstraintType.SECURITY:
            return f"%% {constraint.description}\n{pred}(true)."
        else:
            return f"%% {constraint.description}\n{pred}(true)."

    @traces(
        spec="035",
        story="US-001",
        reqs=[
            "REQ-035-US-001-009",
            "REQ-035-US-001-017",
            "REQ-035-US-002-008",
            "REQ-035-US-002-014",
            "REQ-035-US-002-019",
        ],
    )
    def validate_syntax(self, prolog_code: str) -> bool:
        """Basic syntax validation for generated Prolog."""
        lines = prolog_code.strip().split("\n")
        for line in lines:
            stripped = line.strip()
            if not stripped or stripped.startswith("%"):
                continue
            if stripped.startswith(":-"):
                if not stripped.endswith(".") and not stripped.endswith(","):
                    return False
            elif stripped.endswith("."):
                continue
            elif stripped.endswith(","):
                continue
            elif stripped.endswith("]):"):
                continue
            elif stripped.startswith("]):"):
                continue
            else:
                return False
        return True