Skip to content

Reactor semantic admission

scpn_control.reactor_semantic_admission is CONTROL's portable, deterministic gate for reactor semantic evidence owned by SCPN-PHASE-ORCHESTRATOR. It admits a handoff only for review. It never grants actuation authority and never creates, imports, forwards, or serializes a control action.

Boundary and ownership

The exchange has three distinct owners:

  1. SCPN-FUSION-CORE produces canonical model-evidence bytes with the physical values, units, simulation clock, calibration declaration, numerical refinement uncertainty, and provenance.
  2. SCPN-PHASE-ORCHESTRATOR verifies those bytes, resolves reactor identity through its U0 registry, and assigns nonphase bounded-feature semantics.
  3. SCPN-CONTROL consumes SPO's canonical handoff bytes and emits a sealed admission decision.

The MIF merge-compression lane preserves the same authority separation through a dedicated contract. SCPN-MIF-CORE owns pulsed FRC merge/compression lifecycle and source evidence, SPO owns the frc_compression_mif carrier assignment, and CONTROL independently admits the resulting bytes for review. This lane is not the uncompressed field_reversed_configuration identity and does not transfer ownership to the separate SCPN-FRC-CORE project.

CONTROL calls the public SPO handoff_from_bytes function directly. It does not vendor the schema, decode a looser JSON representation, copy sibling source, or construct its own reactor registry.

The dedicated cross-project test carries only the exact 12,073-byte immutable FUSION evidence fixture, with its producer commit, evidence commit, and SHA-256 recorded beside it. It does not import a sibling checkout or add a local-path dependency. The fixture is passed through the installed SPO adapter and then through this public CONTROL API. SPO 1.3.1 is the first supported public package version carrying the required decoder; standard installation therefore resolves scpn-phase-orchestrator>=1.3.1,<1.4 rather than the older 1.2.0 wheel.

Deterministic policy

Every admission call supplies a ReactorSemanticAdmissionPolicy containing:

  • the exact expected handoff SHA-256;
  • the expected FUSION schema, 40-character producer revision, and embedded source-envelope SHA-256;
  • an explicit ClockReference with domain, kind, epoch, and timestamp;
  • inclusive evidence-age and calibration-age limits in nanoseconds;
  • complete calibration-ID and transfer-function-ID allowlists; and
  • optional degraded-validity-reason and degraded-quality-flag allowlists.

No wall clock is read. Empty degradation allowlists reject degraded evidence. Observable validity VALID and quality VALID pass. DEGRADED passes only when every declared reason or flag is allowlisted. Observable validity UNKNOWN, STALE, OUT_OF_DISTRIBUTION, UNOBSERVABLE, or INVALID, and observable quality UNKNOWN or INVALID, always reject.

The semantic records are different from the observable descriptors. For this transport exchange, every semantic record is intentionally a bounded_feature with phase validity UNOBSERVABLE, quality UNKNOWN, the noncyclic_transport_evidence flag, zero phase confidence and observability, and no phase fields. This is the expected statement that no cyclic phase was declared. It does not make a valid transport observable unusable. The UNKNOWN regime is likewise expected because no regime classifier was supplied.

Example

from pathlib import Path

from scpn_phase_orchestrator.reactor_semantics import ClockKind, ClockReference
from scpn_control.reactor_semantic_admission import (
    ReactorSemanticAdmissionPolicy,
    admission_decision_to_bytes,
    admit_reactor_semantic_handoff,
)

handoff_bytes = Path("reactor-semantic-handoff.json").read_bytes()
expected_handoff_sha256 = Path("reactor-semantic-handoff.sha256").read_text().strip()
expected_source_revision = Path("fusion-source-revision.txt").read_text().strip()
expected_source_envelope_sha256 = Path("fusion-source-envelope.sha256").read_text().strip()
policy = ReactorSemanticAdmissionPolicy(
    expected_handoff_sha256=expected_handoff_sha256,
    expected_source_schema="scpn-fusion-core.torax-runtime-review-envelope.v1",
    expected_source_revision=expected_source_revision,
    expected_source_envelope_sha256=expected_source_envelope_sha256,
    reference_clock=ClockReference(
        domain="simulation_monotonic",
        kind=ClockKind.SIMULATION_MONOTONIC,
        epoch="scenario_start",
        timestamp_ns=20_000_000,
        sample_rate_hz=100.0,
        latency_s=0.0,
        picosecond_offset=0,
        synchronized_to=None,
    ),
    max_evidence_age_ns=0,
    max_calibration_age_ns=20_000_000,
    allowed_calibration_ids=frozenset(
        {"fusion.torax.simulation_declared_units.v1"}
    ),
    allowed_transfer_function_ids=frozenset(
        {"fusion.torax.identity_projection.v1"}
    ),
)

decision = admit_reactor_semantic_handoff(handoff_bytes, policy=policy)
portable_decision = admission_decision_to_bytes(decision)

The output schema is scpn-control.reactor-semantic-admission.v1 version 1.0.0. It contains the admitted or rejected state, review_only=true, actionable=false, the explicit check timestamp, safely decoded identities, sorted unique refusal codes, a decision digest, and an outer payload seal. Decoder failures leave upstream identity fields null rather than copying caller expectations into evidence.

MIF merge-compression policy

MIFReactorSemanticAdmissionPolicy is deliberately separate from the FUSION transport policy. It pins the exact handoff and embedded source-envelope digests, MIF producer revision and schema, event and context IDs, SPO registry version and digest, complete observation clock, closed observable and semantic sets, numerical-phase IDs, producer provenance attributes, freshness limits, calibration and transfer allowlists, and minimum numerical observability, confidence, and uncertainty bounds.

The package facade exports both MIF names without promoting them to the root scpn_control namespace:

from scpn_control.reactor_semantic_admission import (
    MIFReactorSemanticAdmissionPolicy,
    admit_mif_reactor_semantic_handoff,
)

The runtime dependency uses the public-index range scpn-phase-orchestrator>=1.3.1,<1.4. CI and reproducibility locks select the immutable SPO 1.3.1 release at source commit c2a7581d58819060806c6f173da941c822103695. The non-yanked PyPI wheel has SHA-256 c2d7c0a5c0ad47f420fee02e54ccc28122bf8d128eb3b80ca51ba5f034320274; the PyPI and GitHub Release sdist has SHA-256 c0318a85931eef3fba6615bb5ff587c749c5a83c766504d10cdf7f2ac94e6fe3. This rejects decoder-incompatible 1.3.0, the earlier 1.2.0 package, and any future 1.4 contract without relying on a direct URL.

The public ingress is admit_mif_reactor_semantic_handoff. It calls only SPO's strict mif_merge_compression_handoff_from_bytes decoder. It does not parse the embedded MIF JSON independently, import a sibling checkout, infer wall time, or load CONTROL action modules. Admission additionally requires:

  • source project SCPN-MIF-CORE and configuration frc_compression_mif;
  • simulation evidence on one exact declared model clock;
  • one semantic record per expected observable with exact carrier identity;
  • exactly the policy-listed numerical phases with declared origin, orientation, wrap, reference signal, and observation operator;
  • usable numerical-phase validity and quality under explicit degradation allowlists;
  • no phase relations, an UNKNOWN zero-confidence regime, and review_only=true / actionable=false.

The current reference receipt has 25 observables and 25 semantics. Two serialized oscillator angles are numerical phase. The other 23 records are bounded or categorical and carry zero phase observability. A CONTROL admission therefore confirms contract custody and review suitability; it does not claim that the two model angles are measured physical plasma phase.

The MIF producer fixture is 2,475 bytes with SHA-256 c780706abd5a0b185a95e85767e623248388664da61126d196fcb3d528b0c0ca. SPO 1.3.1 produces a 101,652-byte handoff with SHA-256 c0f03b7c49346c39342598275556e8ac28c93138ba14f6e21d6739400e0edeb2. Both digests are mandatory policy inputs, not inferred trust.

What this does not establish

Admission does not define a plant, actuator, diagnostic, or controller. Control and disturbance channels, saturation, slew, latency, sampled dynamics, resets, failure semantics, facility safety, performance, and closed-loop guarantees remain unavailable until a named FUSION plant contract supplies and validates them. A successful review decision is evidence for human and software review, not permission to issue a command.

For MIF, the same limitation includes physical compression actuation, pulsed power switching, trigger egress, measured plasma diagnostics, facility clock correlation, machine-protection availability, replay/HIL acceptance, and a versioned device CONTROL adapter. Future SPO ControlIntent is a separate contract and remains non-actuating until CONTROL admission and independent machine-protection veto are proven.