""" Edge relationship-name constants for the FALSIFY belief graph. These strings are passed as ``relationship_name`` to ``graph_engine.add_edge(...)`` and used as ``edge_types`` filters in ``get_neighborhood(...)``. They are re-exported from :mod:`falsify.models` as well; this module is the single source of truth. Edge semantics (see REQUIREMENTS.md §1.1) ----------------------------------------- - ``DEPENDS_ON`` : Conclusion -> Evidence. THE forward-propagation rail. A Conclusion depends on the Evidence it rests on. ``edge_properties = {"critical": bool}``. - ``SUPPORTS`` : Evidence -> Hypothesis. Evidence corroborates a hypothesis. ``edge_properties = {"weight": float}``. - ``REFUTES`` : Evidence -> Hypothesis. Evidence contradicts a hypothesis. ``edge_properties = {"weight": float}``. - ``SUPERSEDES`` : Evidence(new) -> Evidence(old). Written when a new fact back-dates / overrides an old evidence node. ``edge_properties = {"confidence": float}``. """ DEPENDS_ON = "depends_on" # Non-critical dependency variant. Criticality is encoded in the relationship NAME # because some graph backends (e.g. Ladybug) do not round-trip edge *properties* — # a name always persists, an edge property may not. So a plain ``depends_on`` edge is # treated as critical by default, and ``depends_on_soft`` is the explicit non-critical # form. (For in-memory/tests, an explicit ``{"critical": bool}`` property still wins.) DEPENDS_ON_SOFT = "depends_on_soft" SUPPORTS = "supports" REFUTES = "refutes" # ``CONTRADICTS`` kept as an alias for the refutes edge (spec used both names). CONTRADICTS = REFUTES SUPERSEDES = "supersedes" #: All dependency edge relationship names (critical + soft). DEPENDENCY_EDGE_TYPES = [DEPENDS_ON, DEPENDS_ON_SOFT] #: Edge types traversed when checking whether a node still feeds a live consumer. CONSUMER_EDGE_TYPES = [DEPENDS_ON, DEPENDS_ON_SOFT, SUPPORTS] def is_critical_dependency(rel: str, props: dict | None = None) -> bool: """Return whether a dependency edge is *critical*. An explicit ``critical`` edge property wins when present (used by in-memory tests). Otherwise criticality is inferred from the relationship name: ``depends_on`` is critical by default, ``depends_on_soft`` is not. This makes correctness independent of whether the backend persists edge properties. """ props = props or {} if "critical" in props: return bool(props["critical"]) if rel == DEPENDS_ON_SOFT: return False return rel == DEPENDS_ON # depends_on => critical by default # Edge types traversed during forward refutation propagation. PROPAGATION_EDGE_TYPES = [DEPENDS_ON, DEPENDS_ON_SOFT, SUPPORTS] __all__ = [ "DEPENDS_ON", "DEPENDS_ON_SOFT", "SUPPORTS", "REFUTES", "CONTRADICTS", "SUPERSEDES", "DEPENDENCY_EDGE_TYPES", "CONSUMER_EDGE_TYPES", "PROPAGATION_EDGE_TYPES", "is_critical_dependency", ]