Integrations Guide (v0.6.0 SCM)

This guide explains how to integrate ZeroProofML’s Signed Common Meadow (SCM) semantics with common ML stacks.

The key contract in v0.6.0: - Use (and/or a boolean mask) to represent singular/domain-error states. - Keep the payload numeric and treat the mask as the “special value” channel.

Installing backends

ZeroProofML keeps backends optional.

From PyPI:

pip install "zeroproofml[torch]"  # PyTorch integration
pip install "zeroproofml[jax]"    # JAX integration

From a repo checkout:

pip install -e ".[torch]"  # PyTorch integration
pip install -e ".[jax]"    # JAX integration

You can also run a minimal integration check without pytest:

.venv/bin/python scripts/smoke_integrations.py

Python / NumPy

Ingesting external floats

Use the IEEE bridge to collapse NaN/Inf to at the boundary:

from zeroproofml.utils.ieee_bridge import from_ieee

v = from_ieee(float("inf"))  # -> ⊥

Vectorised arithmetic (payload + mask)

Use the scm_*_numpy helpers in zeroproofml.scm.ops:

import numpy as np
from zeroproofml.scm.ops import scm_mul_numpy

payload = np.array([1.0, 2.0, 3.0])
mask = np.array([False, True, False])  # mark ⊥

out, out_mask = scm_mul_numpy(payload, payload, mask, mask)

PyTorch

SCM rational heads

SCMRationalLayer returns an explicit bottom mask:

import torch
from zeroproofml.layers import SCMRationalLayer

layer = SCMRationalLayer(3, 2)  # degrees (P, Q)
y, bottom = layer(torch.randn(128))

Use bottom for: - coverage metrics (1 - bottom.float().mean()) - inference decoding (NaN sentinel or explicit rejection) - rejection loss inputs (zeroproofml.losses.rejection_loss)

Loss wiring pattern

Most training loops follow: 1) model returns (y, bottom_mask) (or projective tuple outputs) 2) compute fit loss on decoded values 3) add SCM regularisers (margin/sign/rejection) using zeroproofml.losses.SCMTrainingLoss

JAX

The v0.6.0 core provides vectorised SCM ops for JAX via scm_*_jax (payload + mask). Projective tuple tooling is implemented in zeroproofml.autodiff.projective for the conceptual contract; for high-performance JAX training, treat it as a reference implementation and port the same mask/threshold logic into your JIT-ed code.

Export / tooling

  • is exported as IEEE NaN by default (zeroproofml.utils.ieee_bridge) so standard tooling can ignore/reject invalid predictions.
  • Keep raw bottom_mask alongside payloads if you need to distinguish “model refused” vs “numerically NaN” in downstream systems.

Minimal bundle service decision

A minimal REST service around validated ONNX bundles is worthwhile as an optional integration surface for non-ROS consumers, but it should stay a thin adapter over load_onnx_runtime_bundle(...) and remain outside the base install dependencies. gRPC is deferred until a concrete deployment needs binary tensor transport, streaming, or a maintained protobuf contract. See docs/29_rest_grpc_bundle_service_decision.md.

Triton-style inference-server decision

Triton or a similar inference server is useful as a downstream deployment recipe after the ONNX Runtime bundle path is stable, but it should not become a first-party runtime path or base dependency yet. A future recipe should convert validated bundles into a model-repository layout, preserve metadata.json as the strict-inference semantic sidecar, and smoke-test decoded, bottom_mask, and gap_mask parity against load_onnx_runtime_bundle(...). Add Triton containers, CI, or client code only after a deployment needs dynamic batching, multi-model hosting, GPU scheduling, standardized server metrics, or an existing Triton/KServe-compatible serving platform. See docs/30_triton_inference_server_decision.md.

ROS 2 beta companion path

The planned first-party ROS 2 beta stays in this repository under integrations/ros2/ as an optional companion workspace. The root pyproject.toml stays ROS-free; colcon / ament metadata, launch files, and ROS-specific tests live under that workspace instead. See docs/26_ros2_repo_layout_decision.md for the recorded layout decision. The bootstrap src/zeroproofml_ros/ package is an ament_python bridge that currently re-exports the stable Python strict-inference and ONNX runtime surfaces so the first ROS node can reuse them directly. The companion workspace now also ships the ROS-only zeroproofml_msgs package at src/zeroproofml_msgs/ with msg/StrictInferenceResult.msg, carrying flattened decoded payloads, merged bottom_mask / gap_mask, bundle and schema metadata, threshold metadata, and optional stable provenance slots (fault_mask + semantic_bottom_mask or bottom_provenance). The recorded bundle-loading decision for that first node is params-first: the node should take a startup bundle_dir ROS parameter and defer any reload service until a later lifecycle-managed path exists. The first implementation now lives at integrations/ros2/src/zeroproofml_ros/zeroproofml_ros/strict_inference_node.py as the strict_inference_node entry point: it subscribes to std_msgs/msg/Float64MultiArray, publishes zeroproofml_msgs/msg/StrictInferenceResult, and emits diagnostic_msgs/msg/DiagnosticArray summaries while reusing the root ONNX runtime helpers. It also publishes a standard std_msgs/msg/Float64MultiArray telemetry vector on telemetry_topic for Foxglove/PlotJuggler-style plots; the vector follows VISUALIZATION_TELEMETRY_FIELDS, covering batch mask counts, running mask rates, explicit per-batch bottom/gap/provenance rates, n_updates, and fallback metrics including fallback_rate, fault_fallback_rate, semantic_fallback_rate, plus routing counts/rates with missing optional fields as NaN. If the loaded bundle records fallback_policy_id="route_to_analytic_solver", those diagnostics also expose fallback-routing counts/rates plus provenance-aware route-vs-reject fields when available. For named exports outside the live ROS graph, the same ROS package also exposes build_visualization_telemetry_row(...) and write_visualization_telemetry_csv(...), which flatten those telemetry fields into the stable VISUALIZATION_TELEMETRY_EXPORT_FIELDS CSV order for PlotJuggler or other CSV-based tooling. The same ROS package exposes build_workspace_heatmap_marker_overlay(...) and build_workspace_heatmap_marker_array_message(...) so summaries from plot_workspace_rate_heatmaps(...) can be published as RViz visualization_msgs/msg/MarkerArray CUBE_LIST overlays for RR-style workspace debugging. For per-sample spatial interpretation in the RR IK path, build_rr_ik_result_marker_overlay(...) and build_rr_ik_result_marker_array_message(...) render the current arm pose, requested displacement, and accepted end-effector solution as RViz markers from a strict-inference result payload. The strict-inference input/result topics accept a qos_preset parameter: low_latency_control uses keep-last depth 1, best-effort, volatile QoS for control loops, and offline_batch_replay uses keep-last depth 1000, reliable, volatile QoS for deterministic rosbag or batch replay. For deployments that need lifecycle orchestration, the same package now also provides integrations/ros2/src/zeroproofml_ros/zeroproofml_ros/lifecycle_strict_inference_node.py as the lifecycle_strict_inference_node entry point; it keeps the same strict inference bundle/message contract while moving bundle loading to on_configure and gating input processing on lifecycle activation. See docs/27_ros2_bundle_loading_decision.md. For the first domain-specific launch path, integrations/ros2/src/zeroproofml_ros/launch/rr_ik_strict_inference.launch.py plus config/rr_ik_strict_inference.yaml wire the reference robotics RR IK bundle onto /rr_ik/strict_inference/* topics, including /rr_ik/strict_inference/telemetry, and zeroproofml_ros.rr_ik_demo provides a deterministic one-sample smoke run for that same bundle contract. The companion rr_ik_strict_inference_graph.launch.py example composes the strict-inference node with a one-shot RR IK sample publisher plus result and telemetry echo subscribers, giving a concrete small graph that users can replace with their own planner, controller, rosbag replay, Foxglove, PlotJuggler, or monitoring nodes. The companion package also includes the non-robotics offline launch path integrations/ros2/src/zeroproofml_ros/launch/dose_offline_batch.launch.py with config/dose_offline_batch.yaml and demo/dose_offline_batch_input.yaml, defaulting DOSE-style batch replay to offline_batch_replay QoS on /dose/offline_batch/* topics, including /dose/offline_batch/telemetry. For middleware stability, the first beta currently validates only rmw_cyclonedds_cpp (CycloneDDS) via the launch default, package dependency, container images, and CI jobs; widening to a second RMW is deferred until that Humble/Jazzy path is stable. See docs/28_ros2_rmw_selection_decision.md. For reproducible ROS environments, the companion workspace now also ships integrations/ros2/containers/manifest.json plus ros2_humble_cpu.Dockerfile and ros2_jazzy_cpu.Dockerfile, covering Humble/Jammy and Jazzy/Noble CPU images that preinstall onnxruntime, the root zeroproofml checkout, and a built colcon workspace overlay. Treat any ROS 2 Kilted usage as experimental/manual-only until the existing Humble/Jazzy coverage is stable; it is not part of the shipped container manifest or CI matrix yet.