orchestrata_ultimate.factory.projection.completeness
Reference › orchestrata_ultimate › factory › projection › completeness
completeness is the pre-run projection meta-check of ADR-0006 (SPEC-033 row B5): incomplete projection is a gate error, and in factory mode it fails closed (ADR-0002). A caller derives the RequiredSet with required_predicates from analyzer, then calls assert_projection_complete with that set and the collection of predicates it is about to project into Prolog. If any required extensional predicate is missing, the function raises IncompleteProjection, which carries the list of missing PredId values; it is never a warning or a silent pass. projection_manifest returns a JSON-ready snapshot of what was required, for gate provenance. The module delivers the contract only; adopting it at each gate is a separate reviewed change. The scripts.factory_projection CLI imports it, and tests/factory/test_projection_completeness.py tests it.
At a glance
| Source | src/orchestrata_ultimate/factory/projection/completeness.py |
| Lines of code | 75 |
| Classes | 1 |
| Functions | 2 |
| Imports (internal) | orchestrata_ultimate.factory.projection.analyzer |
| Imported by | scripts.factory_projection |
| Tests that import it | tests/factory/test_projection_completeness.py |
Class diagram
Dependency diagram
API
Classes
IncompleteProjection
Bases: Exception · Line 31
Raised when provided omits an extensional predicate a rulebase's rules consult -- the ADR-0006 fail-closed gate error.
| Method | Signature | Summary |
|---|---|---|
__init__ |
__init__(missing: list[PredId]) -> None |
Functions
| Function | Signature | Summary |
|---|---|---|
assert_projection_complete |
assert_projection_complete(required: RequiredSet, provided: Collection[PredId]) -> None |
Raise :class:IncompleteProjection if any required.extensional predicate is absent from provided. |
projection_manifest |
projection_manifest(required: RequiredSet) -> dict[str, list[str]] |
JSON-able snapshot of WHAT was required, for gate provenance (persisted alongside the verdict, per the brief -- "gates can persist WHAT was projected alongside the verdict"). |
Source
"""Projection-completeness pre-run meta-check (B5, ADR-0006).
ADR-0006's decision: "a meta-check asserts projection completeness before
the rulebase runs; incomplete projection is a gate error, and in factory
mode that fails closed (ADR-0002)". This module IS that meta-check.
The CALLER runs :func:`assert_projection_complete` before consulting the
rulebase, passing the derived :class:`~.analyzer.RequiredSet`
(:func:`~.analyzer.required_predicates`) and the collection of predicates it
is about to project into Prolog. A missing extensional predicate raises
:class:`IncompleteProjection` -- fail-closed, never a warning, never a
silent pass.
B5 wiring: per-gate adoption is a separate, reviewed change. This module
delivers the CONTRACT (call ``assert_projection_complete`` with your derived
required set + your projected fact collection before you `consult`/query);
it does not itself touch the existing per-gate assertion call sites (the
code that actually knows the fact store, per ADR-0005's ground-fact
discipline) -- see the package docstring's wiring note.
"""
from __future__ import annotations
from collections.abc import Collection
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from orchestrata_ultimate.factory.projection.analyzer import PredId, RequiredSet
class IncompleteProjection(Exception):
"""Raised when ``provided`` omits an extensional predicate a rulebase's
rules consult -- the ADR-0006 fail-closed gate error.
``missing`` lists every absent ``PredId``, in the same order as the
exception message, so a caller can report or retry against a specific
predicate without re-parsing the message text.
"""
def __init__(self, missing: list[PredId]) -> None:
self.missing = missing
named = ", ".join(str(p) for p in missing)
super().__init__(
f"projection incomplete -- missing extensional predicate(s): {named}"
)
def assert_projection_complete(
required: RequiredSet, provided: Collection[PredId]
) -> None:
"""Raise :class:`IncompleteProjection` if any ``required.extensional``
predicate is absent from ``provided``.
Intensional predicates (defined by clauses in the rulebase itself) are
never demanded from ``provided`` -- they need no fact projection, only
the rulebase's own source, which the caller already `consult`s.
"""
provided_set = set(provided)
missing = sorted(
(pred for pred in required.extensional if pred not in provided_set),
key=str,
)
if missing:
raise IncompleteProjection(missing)
def projection_manifest(required: RequiredSet) -> dict[str, list[str]]:
"""JSON-able snapshot of WHAT was required, for gate provenance
(persisted alongside the verdict, per the brief -- "gates can persist
WHAT was projected alongside the verdict")."""
return {
"intensional": sorted(str(pred) for pred in required.intensional),
"extensional": sorted(str(pred) for pred in required.extensional),
"builtins": sorted(str(pred) for pred in required.builtins),
}