Studio API
Studio helper functions are pure payload builders used by the Streamlit
operator surface and by tests that validate browser-facing contracts without
opening transports or writing hardware.
The public scpn_phase_orchestrator.studio facade exports the passive physics
review panels below alongside the lower-level helper module. Operator code can
therefore depend on the Studio package surface without importing private helper
paths or bypassing the review-only safety gates.
The workflow dataclasses (ImportedSourceSummary, BindingProposal,
RuntimeSnapshot, ExportManifest, and StudioProjectState) fail closed on
malformed audit payloads: identifiers must be non-empty strings, hashes must be
valid SHA-256 hex digests, telemetry and confidence values must be finite
non-boolean numbers, metadata/provenance must be JSON-safe with string keys,
exports must be explicit ExportManifest sequences, and export safety posture
must be either review_artifact or deployable.
The deployment helpers keep package materialisation operator-invoked. Validation
warnings block Docker, WASM, and hardware targets with explicit
blocked_reasons; malformed readiness rows or command tables raise
ValueError instead of emitting partial deployment artefacts. Command tables
include only reviewable non-blocked targets, and materialisation plans mark
which commands write artefacts without opening a network or permitting hardware
writes.
build_studio_product_manifest() returns the metadata-only standalone Studio
product manifest used by the packaged tools/spo_studio.py shell. The manifest
lists every passive physics review panel, the public builder name, the
claim/proof boundary, required evidence, disabled execution gates, and a
deterministic manifest_sha256 over the canonical manifest payload while keeping
network_opened, hardware_write_permitted, qpu_execution_permitted, and
actuation_permitted false. It does not execute panel builders, import optional
runtimes, open transports, or touch hardware. Custom panel registries fail
closed when panel IDs are missing or duplicated, or when a panel enables
actuation, live merge, hot patching, execution, or bypasses operator review.
build_studio_control_feed(snapshot, studio_version=...) emits the live
studio.control-feed.v1 envelope used by the runtime server at
/api/studio-feed. The envelope mirrors the sibling scpn-control feed shape
(feed_schema, studio, studio_version, content_digest, verbs, claims)
and adds a SPO-specific runtime payload with
runtime.schema=spo.studio-runtime-snapshot.v1. It is read-only Studio
ingestion data, not a command channel.
build_studio_evidence_emissions(snapshot, studio_version=...,
activity_timestamp=...) turns that same validated snapshot into concrete
studio.runtime-state.v1, studio.phase-coherence.v1, and
studio.regime-state.v1 schema-B evidence. Each result binds immutable
canonical artifact bytes to a Platform EvidenceBundle, passes the era-v2
federation gate, and remains a bounded-model boundary claim on the
numerical-model substrate. Runtime and coherence observations are measured;
the unverified regime label is explicitly producer-asserted. Seal-bound
numbers are decimal strings, and a recursive guard rejects any JSON float
before canonicalization. This is evidence emission only: it does not sign,
publish, actuate, or upgrade a claim to reference validation.
build_integrated_information_panel(records) renders passive
integrated_information monitor audit records into an operator payload with
latest Phi proxy values, normalised-Phi and total-integration ranges,
minimum-partition review cards, and explicit actuation_permitted: false plus
consciousness_claim_permitted: false gates. The helper requires the
engineering_proxy_not_theoretical_iit claim boundary, finite real-valued
non-negative information metrics, Phi/log-bin normalisation consistency,
integer-only minimum partitions, and symmetric bounded pairwise-MI matrices
when matrix evidence is supplied.
build_strange_loop_studio_panel(records) renders offline
StrangeLoopSupervisor drift-scenario result records into a Studio payload with
scenario pass counts, triggered-mode summaries, maximum drift/oscillation/
over-control scores, minimum control coherence, and failed-scenario IDs. It
requires the strange_loop_drift_review_not_live_actuation claim boundary,
non_actuating: true, execution_disabled: true, supported expected triggers,
finite non-negative metrics, unit-interval coherence, and SHA-256 scenario/
result hashes before Studio may display the evidence. The payload remains
review-only and sets actuation_permitted: false.
build_twin_confidence_studio_panel(score_records, summary_record) renders
digital-twin confidence audit evidence into a Studio payload. It consumes real
TwinConfidenceScore.to_audit_record() rows plus the matching
TwinConfidenceSummary.to_audit_record() aggregate, validates every score and
summary SHA-256 hash, cross-checks status counts and confidence aggregates
against the supplied score sequence, exposes latest/worst status cards and
backend summaries, and keeps actuation_permitted, live_merge_permitted,
hot_patch_permitted, and execution_disabled locked to review-only values.
build_morphogenetic_field_studio_panel(svg_artifact) renders a passive
render_morphogenetic_field_svg() artefact into a Studio payload with SVG
metadata, fixed-width ASCII heatmap rows, field-energy statistics, strongest
off-diagonal topology edges, and explicit actuation_permitted: false. The
helper requires a complete SVG document, square snapshot shape, bounded
unit-interval field statistics, shape-compatible heatmap rows, sorted
off-diagonal top-edge records, and finite non-negative L2 energy before Studio
may expose the field rendering to an operator.
build_multiverse_counterfactual_studio_panel(manifest, risk_report) joins a
passive multiverse rollout manifest with the matching branch-risk report and
renders branch comparison rows, approval counts, rejected-branch IDs,
coherence ranges, safest-branch metadata, and immutable manifest/report hashes.
The helper requires non-actuating execution-disabled rollout and risk claim
boundaries, supported NumPy or JAX vectorised backends, unit-interval R
metrics with ordered intervals, matching branch hashes across rollout and risk
records, finite topology pressure metrics, approval/rejection counts that match
the per-branch risk decisions, and explicit actuation_permitted: false output.
build_hybrid_order_studio_panel(records, scenarios=...) renders passive
hybrid classical-quantum order-parameter audit records and deterministic
scenario fixtures into a Studio payload. It exposes classical R/Psi,
bipartition Von Neumann entropy, normalised entropy, participation-ratio
ranges, strongest-entanglement review cards, simulator backend summaries, and
scenario candidate rows. The helper requires the
quantum_cosimulation_monitor_not_qpu_execution claim boundary, true
non_actuating and execution_disabled flags, finite unit-interval
coherence and normalised-entropy metrics, positive qubit counts, valid
two-group bipartitions, supported local NumPy simulator backends, and matching
record SHA-256 hashes before Studio may display the evidence. The payload sets
both actuation_permitted: false and qpu_execution_permitted: false.
build_information_geometry_studio_panel(records, scenarios=...) renders
passive information-geometry control proposal audit records and deterministic
domain scenarios into a Studio payload. It exposes Fisher-Rao and Wasserstein
distance ranges, metric-tensor and positive metric-diagonal ranges,
natural-gradient norm ranges, curvature/geodesic metrics, backend summaries,
latest review proposal cards, and scenario candidate rows. The helper requires the
information_geometry_control_not_live_actuation claim boundary, true
non_actuating and execution_disabled flags, supported NumPy/JAX information
geometry backends, SHA-256 proposal/scenario hashes, unit-mass simplex
coordinates, matching target/tangent dimensions, positive finite metric
diagonals, symmetric metric tensors, matching geodesic/Fisher-Rao metrics, and
strictly positive review TTL/max-step values before Studio may display the
evidence. The payload sets actuation_permitted: false and never exposes
executable control actions.
build_sheaf_cohomology_studio_panel(records, summaries, control_proposals)
renders passive sheaf-Laplacian obstruction evidence into an operator payload.
It joins sheaf_coherence() audit records, obstruction-summary residual rows,
and review-only propose_sheaf_obstruction_control() records under the
sheaf_cohomology_review_not_live_actuation claim boundary. The helper
requires finite non-negative obstruction/energy metrics, shape-compatible
Laplacian and residual dimensions, valid cohomology-dimension evidence,
explicit residual-edge triage rows, true non_actuating,
execution_disabled, and operator_review_required flags, bounded update
norms, and monotone accepted projections before Studio may display the
evidence. The payload sets actuation_permitted: false,
hot_patch_permitted: false, and live_merge_permitted: false; it is an
operator review surface, not a live sheaf-control channel.
build_topos_semantic_binding_studio_panel(symbolic_reports, policy_reports,
examples=...) renders passive Topos-theoretic semantic-binding evidence into
an operator payload. It joins symbolic-binding functor validation reports,
policy-composition category reports, and deterministic domain obligation
examples while preserving the prototype proof boundary. The helper requires
the categorical_validation_prototype_not_formal_topos_proof proof boundary,
true non_actuating flags, supported validation schemas, SHA-256 report and
example hashes, matching object/morphism counts, deterministic morphisms,
well-formed obligation records, and passed domain examples before Studio may
display the evidence. The payload sets actuation_permitted: false and
formal_proof_claim_permitted: false; it is a review surface, not a
machine-checked proof or executable policy channel.
build_evolutionary_supervisor_policy_search_studio_panel(reports,
examples=..., dsl_reports=...) renders passive evolutionary supervisor policy
search evidence into an operator payload. It joins offline replay-search
reports, enriched deterministic domain examples, and optional policy-DSL
mutation reports while preserving review-only gates. The helper requires the
offline_evolutionary_supervisor_review_not_live_actuation claim boundary for
core search reports, evolutionary_supervisor_search_not_live_actuation for
domain examples, true non_actuating and execution_disabled flags where the
source schema carries them, disabled live merge, disabled hot patching,
operator review requirements, SHA-256 report/candidate/scenario hashes,
matching candidate and accepted/rejected counts, finite replay/STL metrics,
JSON-safe STL scalar or sequence diagnostics, non-empty blocked reasons for
rejected candidates, no blocked reasons for accepted candidates, and
candidate-level actuation denial before Studio may display the evidence. The
payload sets actuation_permitted: false, hot_patch_permitted: false, and
live_merge_permitted: false.
build_autopoietic_lineage_studio_panel(manifests) renders passive
autopoietic lineage sandbox evidence into an operator payload. It preserves
offline lineage manifests, domain-labelled replay corpus rows, child-policy
SHA-256 hashes, accepted child rows, rejected child rows, and blocked-reason
evidence under the autopoietic_lineage_sandbox_review_not_live_merge claim
boundary. The helper requires the lineage sandbox schema, true review and
execution-disabled flags, disabled live merge, disabled hot patching, disabled
actuation, canonical SHA-256 hashes, matching child/replay/domain counts,
finite replay metrics, and candidate-level policy diffs before Studio may
display the evidence. The payload sets actuation_permitted: false,
hot_patch_permitted: false, live_merge_permitted: false, and
operator_review_required: true; it is a review surface for comparing
resource-bounded child-policy proposals, not a self-modifying runtime.
build_intergenerational_inheritance_studio_panel(histories) renders passive
intergenerational policy-inheritance history evidence into an operator payload.
It preserves signed inheritance-history packages, inheritance SHA-256 hashes,
child-policy hashes, HMAC signature metadata, replay-domain coverage, and
multi-objective replay-fitness rows under the
intergenerational_inheritance_review_not_direct_hot_patch claim boundary. The
helper requires deterministic history hashes, matching history/signed-count
rows, contiguous generation indices, finite fitness metrics, reviewed-hot-patch
merge semantics, disabled direct hot patching, and disabled actuation before
Studio may display the evidence. The payload sets
direct_hot_patch_permitted: false, hot_patch_permitted: false,
live_merge_permitted: false, actuation_permitted: false, and
operator_review_required: true; it is a signed review surface, not an
executable patch channel.
Operational role
The Studio API is the fixed review boundary between interactive analysis and
runtime actuation logic. This module collects deterministic payloads from validated
evidence sources and intentionally keeps execution-disabled behavior visible in each
panel.
Use these helpers when you need to:
- prepare human-readable summaries for a control meeting,
- export reviewer-facing context from replay outputs,
- compare model outputs under the same binding assumptions across runs,
- keep policy review evidence separated from any command that can mutate system state.
All panel builders preserve claim markers and hash references so each display can be
reconciled against its source artifacts.
workflow
Pure-Python workflow state objects for SPO Studio audit artefacts.
Classes
ImportedSourceSummary
dataclass
ImportedSourceSummary(
source_kind: str,
sha256: str,
byte_count: int,
channel_count: int,
sample_count: int,
)
Audit-ready summary of a source imported into SPO Studio.
Methods:
from_payload
classmethod
from_payload(
*,
source_kind: str,
payload: bytes,
channel_count: int,
sample_count: int,
) -> ImportedSourceSummary
Create a stable source summary from raw imported bytes.
Parameters
source_kind : str
Kind of imported source data.
payload : bytes
The payload mapping or bytes.
channel_count : int
Number of channels in the source.
sample_count : int
Number of samples in the source.
Returns
ImportedSourceSummary
A stable source summary from raw imported bytes.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| @classmethod
def from_payload(
cls,
*,
source_kind: str,
payload: bytes,
channel_count: int,
sample_count: int,
) -> ImportedSourceSummary:
"""Create a stable source summary from raw imported bytes.
Parameters
----------
source_kind : str
Kind of imported source data.
payload : bytes
The payload mapping or bytes.
channel_count : int
Number of channels in the source.
sample_count : int
Number of samples in the source.
Returns
-------
ImportedSourceSummary
A stable source summary from raw imported bytes.
"""
return cls(
source_kind=source_kind,
sha256=_stable_sha256(payload),
byte_count=len(payload),
channel_count=channel_count,
sample_count=sample_count,
)
|
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-ready audit record.
Returns
dict[str, object]
A JSON-ready audit record.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-ready audit record.
Returns
-------
dict[str, object]
A JSON-ready audit record.
"""
return {
"source_kind": self.source_kind,
"sha256": self.sha256,
"byte_count": self.byte_count,
"channel_count": self.channel_count,
"sample_count": self.sample_count,
}
|
BindingProposal
dataclass
BindingProposal(
yaml_text: str,
validation_errors: tuple[str, ...] = (),
inferred_channels: tuple[str, ...] = (),
confidence_factors: dict[str, float] = dict(),
provenance: Mapping[str, JsonValue] = dict(),
)
Candidate binding specification and its validation context.
Attributes
yaml_sha256
property
Stable digest for the proposed binding YAML.
Returns
str
Stable digest for the proposed binding YAML.
Methods:
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-ready audit record.
Returns
dict[str, object]
A JSON-ready audit record.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-ready audit record.
Returns
-------
dict[str, object]
A JSON-ready audit record.
"""
return {
"yaml_sha256": self.yaml_sha256,
"validation_errors": list(self.validation_errors),
"inferred_channels": list(self.inferred_channels),
"confidence_factors": _finite_float_mapping(
self.confidence_factors,
field_name="confidence_factors",
),
"provenance": _json_safe_mapping(
self.provenance,
field_name="provenance",
),
}
|
RuntimeSnapshot
dataclass
RuntimeSnapshot(
R: float,
Psi: float,
K: float,
alpha: float,
zeta: float,
regime: str,
layer_metrics: tuple[tuple[str, float], ...] = (),
hierarchy_watermarks: dict[str, int] = dict(),
replay_status: str = "not_started",
)
Current runtime telemetry exposed to Studio review workflows.
Methods:
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-ready audit record.
Returns
dict[str, object]
A JSON-ready audit record.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-ready audit record.
Returns
-------
dict[str, object]
A JSON-ready audit record.
"""
return {
"R": _finite_float(self.R, field_name="R"),
"Psi": _finite_float(self.Psi, field_name="Psi"),
"K": _finite_float(self.K, field_name="K"),
"alpha": _finite_float(self.alpha, field_name="alpha"),
"zeta": _finite_float(self.zeta, field_name="zeta"),
"regime": self.regime,
"layer_metrics": [
{
"layer": _layer_metric_name(layer),
"value": _finite_float(value, field_name="layer_metrics"),
}
for layer, value in self.layer_metrics
],
"hierarchy_watermarks": _hierarchy_watermarks(self.hierarchy_watermarks),
"replay_status": self.replay_status,
}
|
ExportManifest
dataclass
ExportManifest(
target_kind: str,
file_name: str,
payload: str,
command: str,
safety_posture: SafetyPosture,
warnings: tuple[str, ...] = (),
)
Manifest for an exportable Studio artefact.
Attributes
payload_sha256
property
Stable digest for the exported payload.
Returns
str
Stable digest for the exported payload.
Methods:
review_artifact
classmethod
review_artifact(
*,
target_kind: str,
file_name: str,
payload: str,
command: str,
warnings: tuple[str, ...] = (),
) -> ExportManifest
Build a manifest for review-only artefacts.
Parameters
target_kind : str
Target export kind.
file_name : str
Destination file name.
payload : str
The payload mapping or bytes.
command : str
The command string.
warnings : tuple[str, ...]
Warning messages.
Returns
ExportManifest
A manifest for review-only artefacts.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| @classmethod
def review_artifact(
cls,
*,
target_kind: str,
file_name: str,
payload: str,
command: str,
warnings: tuple[str, ...] = (),
) -> ExportManifest:
"""Build a manifest for review-only artefacts.
Parameters
----------
target_kind : str
Target export kind.
file_name : str
Destination file name.
payload : str
The payload mapping or bytes.
command : str
The command string.
warnings : tuple[str, ...]
Warning messages.
Returns
-------
ExportManifest
A manifest for review-only artefacts.
"""
return cls(
target_kind=target_kind,
file_name=file_name,
payload=payload,
command=command,
safety_posture="review_artifact",
warnings=warnings,
)
|
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-ready audit record.
Returns
dict[str, object]
A JSON-ready audit record.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-ready audit record.
Returns
-------
dict[str, object]
A JSON-ready audit record.
"""
return {
"target_kind": self.target_kind,
"file_name": self.file_name,
"payload_sha256": self.payload_sha256,
"command": self.command,
"safety_posture": self.safety_posture,
"warnings": list(self.warnings),
}
|
StudioProjectState
dataclass
StudioProjectState(
project_name: str,
source: ImportedSourceSummary,
binding: BindingProposal,
runtime: RuntimeSnapshot,
exports: tuple[ExportManifest, ...] = (),
metadata: Mapping[str, JsonValue] = dict(),
)
Complete SPO Studio state for serialisation into audit logs.
Methods:
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-ready project-state audit record.
Returns
dict[str, object]
A JSON-ready project-state audit record.
Source code in src/scpn_phase_orchestrator/studio/workflow.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-ready project-state audit record.
Returns
-------
dict[str, object]
A JSON-ready project-state audit record.
"""
return {
"project_name": self.project_name,
"source": self.source.to_audit_record(),
"binding": self.binding.to_audit_record(),
"runtime": self.runtime.to_audit_record(),
"exports": [manifest.to_audit_record() for manifest in self.exports],
"metadata": _json_safe_mapping(self.metadata, field_name="metadata"),
}
|
product
Standalone Studio product manifest for passive physics review panels.
Functions:
build_studio_product_manifest
build_studio_product_manifest(
*,
panel_registry: Sequence[
PanelRecord
] = STUDIO_REVIEW_PANEL_REGISTRY,
) -> dict[str, object]
Return the standalone Studio product manifest.
The manifest is intentionally metadata-only. It lets a packaged Studio shell
discover passive panel contracts and required evidence without importing
optional runtimes, executing panel builders, opening transports, or touching
hardware.
Parameters
panel_registry : Sequence[PanelRecord]
The Studio panel records.
Returns
dict[str, object]
The standalone Studio product manifest.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/product.py
| def build_studio_product_manifest(
*,
panel_registry: Sequence[PanelRecord] = STUDIO_REVIEW_PANEL_REGISTRY,
) -> dict[str, object]:
"""Return the standalone Studio product manifest.
The manifest is intentionally metadata-only. It lets a packaged Studio shell
discover passive panel contracts and required evidence without importing
optional runtimes, executing panel builders, opening transports, or touching
hardware.
Parameters
----------
panel_registry : Sequence[PanelRecord]
The Studio panel records.
Returns
-------
dict[str, object]
The standalone Studio product manifest.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
panels = tuple(dict(panel) for panel in panel_registry)
panel_ids = [panel.get("panel_id") for panel in panels]
if any(not isinstance(panel_id, str) or not panel_id for panel_id in panel_ids):
raise ValueError("panel_registry entries require non-empty panel_id values")
if len(set(panel_ids)) != len(panel_ids):
raise ValueError("panel_registry panel_id values must be unique")
for panel in panels:
_require_disabled_panel_gates(panel)
manifest = {
"manifest_kind": "studio_product_manifest",
"product": "spo_studio",
"standalone_shell": "tools/spo_studio.py",
"launch_command": "streamlit run tools/spo_studio.py",
"review_panel_count": len(panels),
"review_panels": panels,
"operator_review_required": True,
"actuation_permitted": False,
"live_merge_permitted": False,
"hot_patch_permitted": False,
"network_opened": False,
"hardware_write_permitted": False,
"qpu_execution_permitted": False,
}
manifest["manifest_sha256"] = _manifest_sha256(manifest)
return manifest
|
live_feed
Build the SPO live Studio feed using the shared control-feed envelope.
Classes
StudioFeedVerb
dataclass
StudioFeedVerb(
name: str,
safety_tier: str,
side_effect: str,
timing_class: str,
domain_distinctive: bool,
)
A verb summary in the studio.control-feed.v1 wire envelope.
Attributes
name : str
Verb name rendered by Studio.
safety_tier : str
Studio safety tier: research, certified, or production.
side_effect : str
Studio side-effect class: read-only, simulated, or
live-hardware.
timing_class : str
Studio timing class: batch, interactive, or realtime.
domain_distinctive : bool
Whether the verb is domain-specific rather than core-spine.
Methods:
to_record
to_record() -> dict[str, object]
Return the verb as a JSON-safe feed record.
Returns
dict[str, object]
The verb record emitted in the feed's verbs list.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def to_record(self) -> dict[str, object]:
"""Return the verb as a JSON-safe feed record.
Returns
-------
dict[str, object]
The verb record emitted in the feed's ``verbs`` list.
"""
return {
"name": self.name,
"safety_tier": self.safety_tier,
"side_effect": self.side_effect,
"timing_class": self.timing_class,
"domain_distinctive": self.domain_distinctive,
}
|
StudioFeedClaim
dataclass
StudioFeedClaim(
schema: str, status: str, admission: str, kind: str
)
A claim summary in the studio.control-feed.v1 wire envelope.
Attributes
schema : str
Evidence schema identifier.
status : str
Claim-boundary status from the shared Studio lattice.
admission : str
Runtime admission decision, admitted or rejected.
kind : str
Evidence modality, such as measured or curated.
Methods:
to_record
to_record() -> dict[str, str]
Return the claim as a JSON-safe feed record.
Returns
dict[str, str]
The claim record emitted in the feed's claims list.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def to_record(self) -> dict[str, str]:
"""Return the claim as a JSON-safe feed record.
Returns
-------
dict[str, str]
The claim record emitted in the feed's ``claims`` list.
"""
return {
"schema": self.schema,
"status": self.status,
"admission": self.admission,
"kind": self.kind,
}
|
Functions:
build_studio_control_feed
build_studio_control_feed(
snapshot: Mapping[str, object], *, studio_version: str
) -> dict[str, object]
Build a live Studio feed from a runtime server snapshot.
The envelope mirrors the sibling CONTROL studio.control-feed.v1 shape
(feed_schema, studio, studio_version, content_digest,
verbs, claims) and adds a SPO-specific runtime payload for live
state ingestion. The extra field is additive: existing Studio loaders that
only consume verbs and claims can ignore it.
Parameters
snapshot : Mapping[str, object]
JSON-safe snapshot from runtime.server.SimulationState.snapshot.
studio_version : str
SPO package version stamped into the feed.
Returns
dict[str, object]
JSON-safe Studio feed document.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def build_studio_control_feed(
snapshot: Mapping[str, object],
*,
studio_version: str,
) -> dict[str, object]:
"""Build a live Studio feed from a runtime server snapshot.
The envelope mirrors the sibling CONTROL ``studio.control-feed.v1`` shape
(``feed_schema``, ``studio``, ``studio_version``, ``content_digest``,
``verbs``, ``claims``) and adds a SPO-specific ``runtime`` payload for live
state ingestion. The extra field is additive: existing Studio loaders that
only consume verbs and claims can ignore it.
Parameters
----------
snapshot : Mapping[str, object]
JSON-safe snapshot from ``runtime.server.SimulationState.snapshot``.
studio_version : str
SPO package version stamped into the feed.
Returns
-------
dict[str, object]
JSON-safe Studio feed document.
"""
runtime = runtime_summary(snapshot)
claims = claim_summaries(runtime)
verbs = [verb.to_record() for verb in _VERBS]
claim_records = [claim.to_record() for claim in claims]
return {
"feed_schema": FEED_SCHEMA,
"studio": STUDIO_ID,
"studio_version": studio_version,
"content_digest": _content_digest(verbs, claim_records),
"verbs": verbs,
"claims": claim_records,
"runtime": runtime,
}
|
runtime_summary
runtime_summary(
snapshot: Mapping[str, object],
) -> dict[str, object]
Return the SPO runtime payload embedded in the live Studio feed.
Parameters
snapshot : Mapping[str, object]
Server snapshot to validate and reduce.
Returns
dict[str, object]
JSON-safe runtime summary with finite numeric fields.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def runtime_summary(snapshot: Mapping[str, object]) -> dict[str, object]:
"""Return the SPO runtime payload embedded in the live Studio feed.
Parameters
----------
snapshot : Mapping[str, object]
Server snapshot to validate and reduce.
Returns
-------
dict[str, object]
JSON-safe runtime summary with finite numeric fields.
"""
result: dict[str, object] = {
"schema": RUNTIME_SCHEMA,
"step": _required_int(snapshot, "step"),
"r_global": _required_unit_float(snapshot, "R_global"),
"regime": _required_text(snapshot, "regime"),
"n_oscillators": _required_int(snapshot, "n_oscillators"),
"amplitude_mode": _required_bool(snapshot, "amplitude_mode"),
"layers": _layer_records(snapshot.get("layers")),
}
if snapshot.get("mean_amplitude") is not None:
result["mean_amplitude"] = _required_float(snapshot, "mean_amplitude")
return result
|
claim_summaries
claim_summaries(
runtime: Mapping[str, object],
) -> tuple[StudioFeedClaim, ...]
Return claim summaries derived from a validated runtime payload.
Parameters
runtime : Mapping[str, object]
Validated spo.studio-runtime-snapshot.v1 payload.
Returns
tuple[StudioFeedClaim, ...]
Claim-boundary summaries for Studio honesty rendering.
Raises
ValueError
If the runtime payload has malformed coherence or layer fields.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def claim_summaries(runtime: Mapping[str, object]) -> tuple[StudioFeedClaim, ...]:
"""Return claim summaries derived from a validated runtime payload.
Parameters
----------
runtime : Mapping[str, object]
Validated ``spo.studio-runtime-snapshot.v1`` payload.
Returns
-------
tuple[StudioFeedClaim, ...]
Claim-boundary summaries for Studio honesty rendering.
Raises
------
ValueError
If the runtime payload has malformed coherence or layer fields.
"""
r_global = _required_unit_float(runtime, "r_global")
layers = runtime.get("layers")
if not isinstance(layers, Sequence) or isinstance(layers, (str, bytes)):
raise ValueError("runtime layers must be a sequence")
admission = "admitted" if layers else "rejected"
coherence_status = "bounded-model" if 0.0 <= r_global <= 1.0 else "validation-gap"
return (
StudioFeedClaim(RUNTIME_STATE_SCHEMA, "bounded-model", admission, "measured"),
StudioFeedClaim(
PHASE_COHERENCE_SCHEMA,
coherence_status,
admission,
"measured",
),
StudioFeedClaim(
REGIME_STATE_SCHEMA,
"bounded-model",
admission,
"producer-asserted",
),
)
|
render_studio_control_feed_json
render_studio_control_feed_json(
snapshot: Mapping[str, object], *, studio_version: str
) -> str
Render a live Studio feed as deterministic JSON.
Parameters
snapshot : Mapping[str, object]
Runtime server snapshot.
studio_version : str
SPO package version stamped into the feed.
Returns
str
Sorted, indented JSON feed with a trailing newline.
Source code in src/scpn_phase_orchestrator/studio/live_feed.py
| def render_studio_control_feed_json(
snapshot: Mapping[str, object],
*,
studio_version: str,
) -> str:
"""Render a live Studio feed as deterministic JSON.
Parameters
----------
snapshot : Mapping[str, object]
Runtime server snapshot.
studio_version : str
SPO package version stamped into the feed.
Returns
-------
str
Sorted, indented JSON feed with a trailing newline.
"""
return (
json.dumps(
build_studio_control_feed(snapshot, studio_version=studio_version),
indent=2,
sort_keys=True,
)
+ "\n"
)
|
evidence_bundles
Emit float-free Studio schema-B evidence from a SPO runtime snapshot.
The live Studio feed advertises three evidence families: runtime state, phase
coherence, and regime state. This module makes those declarations load-bearing
by reducing a validated runtime snapshot to an immutable canonical artifact,
binding its digest into :class:scpn_studio_platform.evidence.EvidenceBundle,
and passing the wire bundle through the Platform federation gate.
The producer never promotes a simulator observation to reference validation.
Every bundle is admitted only as a boundary claim on the numerical-model
substrate. Seal-bound artifacts and bundle wires contain no JSON floats:
bounded numeric observations cross the wire as shortest-round-trip strings, so
Python and JavaScript cannot disagree over integer-looking float encodings.
Classes
StudioEvidenceEmission
dataclass
StudioEvidenceEmission(
bundle: EvidenceBundle,
verdict: FederationVerdict,
_artifact_bytes: bytes,
)
One immutable artifact, its schema-B bundle, and federation verdict.
Parameters
bundle : EvidenceBundle
Platform schema-B bundle whose entity digest pins the artifact bytes.
verdict : FederationVerdict
Era-v2 Platform admission result for the bundle wire.
Notes
Canonical artifact bytes are held privately so callers cannot mutate a
dictionary after its digest has been bound into bundle.entity.digest.
The :attr:artifact property returns a fresh decoded mapping.
Attributes
artifact
property
artifact: dict[str, JsonValue]
Return a fresh copy of the canonical float-free evidence artifact.
Returns
dict[str, JsonValue]
Decoded artifact data. Mutating it cannot invalidate the stored
content digest because the canonical source bytes remain private.
Methods:
__post_init__
Reject inconsistent or non-canonical emission components.
Source code in src/scpn_phase_orchestrator/studio/evidence_bundles.py
| def __post_init__(self) -> None:
"""Reject inconsistent or non-canonical emission components."""
artifact = self.artifact
_assert_float_free(artifact)
if canonicalize(artifact) != self._artifact_bytes:
raise ValueError("artifact bytes must use Platform canonical serialization")
if artifact.get("schema") != self.bundle.schema:
raise ValueError("artifact and evidence bundle schemas must match")
if content_digest(artifact) != self.bundle.entity.digest:
raise ValueError("artifact digest does not match bundle entity digest")
if not self.verdict.admitted or self.verdict.rejections:
raise ValueError("evidence bundle must pass the Platform federation gate")
if self.verdict.mode != "boundary":
raise ValueError("SPO runtime evidence must remain a boundary claim")
_assert_float_free(self.bundle.to_dict())
|
to_dict
to_dict() -> dict[str, object]
Return the artifact and schema-B bundle as a seal-safe wire record.
Returns
dict[str, object]
Mapping with artifact and evidence_bundle fields and no
JSON floating-point values.
Source code in src/scpn_phase_orchestrator/studio/evidence_bundles.py
| def to_dict(self) -> dict[str, object]:
"""Return the artifact and schema-B bundle as a seal-safe wire record.
Returns
-------
dict[str, object]
Mapping with ``artifact`` and ``evidence_bundle`` fields and no
JSON floating-point values.
"""
record: dict[str, object] = {
"artifact": self.artifact,
"evidence_bundle": self.bundle.to_dict(),
}
_assert_float_free(record)
return record
|
Functions:
build_studio_evidence_emissions
build_studio_evidence_emissions(
snapshot: Mapping[str, object],
*,
studio_version: str,
activity_timestamp: str,
operator: str = "local-operator",
) -> tuple[StudioEvidenceEmission, ...]
Build and federation-gate the three live SPO evidence emissions.
Parameters
snapshot : Mapping[str, object]
Raw mapping from runtime.server.SimulationState.snapshot.
studio_version : str
Exact SPO package version responsible for the emission.
activity_timestamp : str
ISO-8601 timestamp recorded as both start and end of the snapshot
reduction. It is explicit so deterministic replays remain deterministic.
operator : str, optional
Opaque local operator or tenant identity for the PROV agent.
Returns
tuple[StudioEvidenceEmission, ...]
Runtime-state, phase-coherence, and regime-state emissions, in the same
stable order as the schema-A manifest's evidence types.
Raises
ValueError
If snapshot validation fails, metadata is empty, a seal-bound float is
found, or the Platform gate does not admit a boundary-only bundle.
Source code in src/scpn_phase_orchestrator/studio/evidence_bundles.py
| def build_studio_evidence_emissions(
snapshot: Mapping[str, object],
*,
studio_version: str,
activity_timestamp: str,
operator: str = "local-operator",
) -> tuple[StudioEvidenceEmission, ...]:
"""Build and federation-gate the three live SPO evidence emissions.
Parameters
----------
snapshot : Mapping[str, object]
Raw mapping from ``runtime.server.SimulationState.snapshot``.
studio_version : str
Exact SPO package version responsible for the emission.
activity_timestamp : str
ISO-8601 timestamp recorded as both start and end of the snapshot
reduction. It is explicit so deterministic replays remain deterministic.
operator : str, optional
Opaque local operator or tenant identity for the PROV agent.
Returns
-------
tuple[StudioEvidenceEmission, ...]
Runtime-state, phase-coherence, and regime-state emissions, in the same
stable order as the schema-A manifest's evidence types.
Raises
------
ValueError
If snapshot validation fails, metadata is empty, a seal-bound float is
found, or the Platform gate does not admit a boundary-only bundle.
"""
_require_text(studio_version, "studio_version")
_require_text(activity_timestamp, "activity_timestamp")
_require_text(operator, "operator")
runtime = runtime_summary(snapshot)
artifacts = _artifacts(runtime)
specifications = (
(
"simulate",
EvidenceKind.MEASURED,
artifacts[0],
"One validated SPO numerical-model runtime snapshot only; no "
"temporal stability, safety, hardware, or actuation claim.",
),
(
"analyse",
EvidenceKind.MEASURED,
artifacts[1],
"Finite order parameters from one validated SPO numerical-model "
"snapshot; no reference-validation, stability, safety, hardware, "
"or actuation claim.",
),
(
"supervise",
EvidenceKind.PRODUCER_ASSERTED,
artifacts[2],
"Producer-reported regime label from one SPO numerical-model "
"snapshot; no independent validation, forecast, safety, hardware, "
"or actuation claim.",
),
)
return tuple(
_build_emission(
artifact=artifact,
verb=verb,
evidence_kind=kind,
validity_note=note,
studio_version=studio_version,
activity_timestamp=activity_timestamp,
operator=operator,
)
for verb, kind, artifact, note in specifications
)
|
render_studio_evidence_emissions_json
render_studio_evidence_emissions_json(
snapshot: Mapping[str, object],
*,
studio_version: str,
activity_timestamp: str,
operator: str = "local-operator",
) -> str
Render canonical float-free JSON for all live evidence emissions.
Parameters
snapshot : Mapping[str, object]
Raw mapping from runtime.server.SimulationState.snapshot.
studio_version : str
Exact SPO package version responsible for the emission.
activity_timestamp : str
ISO-8601 timestamp recorded in every PROV activity.
operator : str, optional
Opaque local operator or tenant identity for the PROV agent.
Returns
str
Platform-canonical compact JSON array followed by one newline.
Source code in src/scpn_phase_orchestrator/studio/evidence_bundles.py
| def render_studio_evidence_emissions_json(
snapshot: Mapping[str, object],
*,
studio_version: str,
activity_timestamp: str,
operator: str = "local-operator",
) -> str:
"""Render canonical float-free JSON for all live evidence emissions.
Parameters
----------
snapshot : Mapping[str, object]
Raw mapping from ``runtime.server.SimulationState.snapshot``.
studio_version : str
Exact SPO package version responsible for the emission.
activity_timestamp : str
ISO-8601 timestamp recorded in every PROV activity.
operator : str, optional
Opaque local operator or tenant identity for the PROV agent.
Returns
-------
str
Platform-canonical compact JSON array followed by one newline.
"""
emissions = build_studio_evidence_emissions(
snapshot,
studio_version=studio_version,
activity_timestamp=activity_timestamp,
operator=operator,
)
records = [emission.to_dict() for emission in emissions]
_assert_float_free(records)
canonical = cast("bytes", canonicalize(records))
return canonical.decode("utf-8") + "\n"
|
ui_helpers
Pure helper layer for the SPO Studio Streamlit surface.
Classes
StudioKnobState
dataclass
StudioKnobState(
K: float = 1.0,
alpha: float = 0.0,
zeta: float = 0.0,
Psi: float = 0.0,
)
Review-only knob state used by Studio replay controls.
Methods:
to_audit_record
to_audit_record() -> dict[str, float]
Return a JSON-safe knob record.
Returns
dict[str, float]
A JSON-safe knob record.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/_state.py
| def to_audit_record(self) -> dict[str, float]:
"""Return a JSON-safe knob record.
Returns
-------
dict[str, float]
A JSON-safe knob record.
"""
return {
"K": float(self.K),
"alpha": float(self.alpha),
"zeta": float(self.zeta),
"Psi": float(self.Psi),
}
|
StudioReplayResult
dataclass
StudioReplayResult(
project_state: StudioProjectState,
r_history: tuple[float, ...],
regime_history: tuple[str, ...],
layer_table: tuple[dict[str, object], ...],
oscillator_table: tuple[dict[str, object], ...],
canvas_graph: Mapping[str, object],
connector_plan: Mapping[str, object],
export_manifests: tuple[ExportManifest, ...],
)
Replay output rendered by SPO Studio.
Methods:
to_audit_record
to_audit_record() -> dict[str, object]
Return a JSON-safe replay audit record.
Returns
dict[str, object]
A JSON-safe replay audit record.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/_state.py
| def to_audit_record(self) -> dict[str, object]:
"""Return a JSON-safe replay audit record.
Returns
-------
dict[str, object]
A JSON-safe replay audit record.
"""
return {
"project": self.project_state.to_audit_record(),
"r_history": list(self.r_history),
"regime_history": list(self.regime_history),
"layer_table": list(self.layer_table),
"oscillator_table": list(self.oscillator_table),
"canvas_graph": dict(self.canvas_graph),
"connector_plan": dict(self.connector_plan),
"exports": [
manifest.to_audit_record() for manifest in self.export_manifests
],
}
|
Functions:
apply_knob_update
apply_knob_update(
knobs: StudioKnobState,
*,
K: float | None = None,
alpha: float | None = None,
zeta: float | None = None,
Psi: float | None = None,
) -> StudioKnobState
Return validated knobs after a UI edit.
Parameters
knobs : StudioKnobState
The Studio knob state.
K : float | None
Coupling-strength knob value, or None.
alpha : float | None
Phase-lag knob value, or None.
zeta : float | None
Drive-strength knob value, or None.
Psi : float | None
Drive reference-phase knob value, or None.
Returns
StudioKnobState
Validated knobs after a UI edit.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/_state.py
| def apply_knob_update(
knobs: StudioKnobState,
*,
K: float | None = None,
alpha: float | None = None,
zeta: float | None = None,
Psi: float | None = None,
) -> StudioKnobState:
"""Return validated knobs after a UI edit.
Parameters
----------
knobs : StudioKnobState
The Studio knob state.
K : float | None
Coupling-strength knob value, or ``None``.
alpha : float | None
Phase-lag knob value, or ``None``.
zeta : float | None
Drive-strength knob value, or ``None``.
Psi : float | None
Drive reference-phase knob value, or ``None``.
Returns
-------
StudioKnobState
Validated knobs after a UI edit.
"""
return StudioKnobState(
K=knobs.K if K is None else K,
alpha=knobs.alpha if alpha is None else alpha,
zeta=knobs.zeta if zeta is None else zeta,
Psi=knobs.Psi if Psi is None else Psi,
)
|
discover_domainpacks
discover_domainpacks(
domainpack_dir: Path,
) -> tuple[str, ...]
Return domainpack names containing a binding spec.
Parameters
domainpack_dir : Path
Directory containing domainpacks.
Returns
tuple[str, ...]
Domainpack names containing a binding spec.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/_state.py
| def discover_domainpacks(domainpack_dir: Path) -> tuple[str, ...]:
"""Return domainpack names containing a binding spec.
Parameters
----------
domainpack_dir : Path
Directory containing domainpacks.
Returns
-------
tuple[str, ...]
Domainpack names containing a binding spec.
"""
if not domainpack_dir.exists():
return ()
return tuple(
sorted(
path.name
for path in domainpack_dir.iterdir()
if path.is_dir() and (path / "binding_spec.yaml").exists()
)
)
|
apply_canvas_binding_rewrite_candidate
apply_canvas_binding_rewrite_candidate(
candidate: Mapping[str, object],
*,
binding_spec_path: str | Path,
operator_signoff: bool,
create_backup: bool = True,
) -> dict[str, object]
Apply a reviewed canvas binding candidate with hash and validation gates.
Parameters
candidate : Mapping[str, object]
The binding rewrite candidate mapping.
binding_spec_path : str | Path
Path to the binding-spec file.
operator_signoff : bool
Whether the operator has signed off.
create_backup : bool
Whether to write a backup before applying.
Returns
dict[str, object]
A reviewed canvas binding candidate with hash and validation gates.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def apply_canvas_binding_rewrite_candidate(
candidate: Mapping[str, object],
*,
binding_spec_path: str | Path,
operator_signoff: bool,
create_backup: bool = True,
) -> dict[str, object]:
"""Apply a reviewed canvas binding candidate with hash and validation gates.
Parameters
----------
candidate : Mapping[str, object]
The binding rewrite candidate mapping.
binding_spec_path : str | Path
Path to the binding-spec file.
operator_signoff : bool
Whether the operator has signed off.
create_backup : bool
Whether to write a backup before applying.
Returns
-------
dict[str, object]
A reviewed canvas binding candidate with hash and validation gates.
"""
path = Path(binding_spec_path)
candidate_yaml = _require_non_empty_payload(
candidate.get("candidate_yaml"),
"candidate_yaml",
)
before_digest = _require_sha256_digest(
candidate.get("before_yaml_sha256"),
"before_yaml_sha256",
)
candidate_digest = _require_sha256_digest(
candidate.get("candidate_yaml_sha256"),
"candidate_yaml_sha256",
)
blocked_reasons = _binding_apply_blocked_reasons(
candidate,
path,
candidate_yaml,
before_digest,
candidate_digest,
operator_signoff=operator_signoff,
)
if blocked_reasons:
return _binding_apply_record(
candidate,
path,
status="blocked",
before_digest=before_digest,
after_digest="",
backup_path="",
blocked_reasons=blocked_reasons,
)
current_yaml = path.read_text(encoding="utf-8")
backup_path = ""
if create_backup:
backup = _next_binding_backup_path(path, before_digest)
backup.write_text(current_yaml, encoding="utf-8")
backup_path = str(backup)
_atomic_write_text(path, candidate_yaml)
after_digest = sha256(path.read_text(encoding="utf-8").encode("utf-8")).hexdigest()
return _binding_apply_record(
candidate,
path,
status="applied",
before_digest=before_digest,
after_digest=after_digest,
backup_path=backup_path,
blocked_reasons=[],
)
|
build_canvas_binding_rewrite_candidate
build_canvas_binding_rewrite_candidate(
result: StudioReplayResult,
*,
after_graph: Mapping[str, object],
) -> dict[str, object]
Build validated binding YAML candidate from reviewed canvas edits.
Parameters
result : StudioReplayResult
The Studio replay result.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
dict[str, object]
Validated binding YAML candidate from reviewed canvas edits.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_binding_rewrite_candidate(
result: StudioReplayResult,
*,
after_graph: Mapping[str, object],
) -> dict[str, object]:
"""Build validated binding YAML candidate from reviewed canvas edits.
Parameters
----------
result : StudioReplayResult
The Studio replay result.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
-------
dict[str, object]
Validated binding YAML candidate from reviewed canvas edits.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if not isinstance(result, StudioReplayResult):
raise ValueError("replay result must be a StudioReplayResult")
_, after_edges = _normalise_canvas_graph(after_graph, "after_graph")
before_yaml = result.project_state.binding.yaml_text
before_digest = sha256(before_yaml.encode("utf-8")).hexdigest()
unsupported = [
_require_non_empty_text(edge.get("id"), "canvas edge id")
for edge in after_edges
if edge.get("kind") != "cross_channel_coupling"
]
if unsupported:
return _blocked_binding_rewrite_candidate(
result,
before_digest,
["only cross_channel_coupling edges can rewrite binding YAML"],
)
try:
candidate_yaml = _rewrite_binding_cross_channel_couplings(
before_yaml,
after_edges,
)
except ValueError as exc:
return _blocked_binding_rewrite_candidate(result, before_digest, [str(exc)])
validation_errors = _validate_candidate_binding_yaml(candidate_yaml)
return {
"candidate_kind": "canvas_binding_rewrite_candidate",
"project_name": result.project_state.project_name,
"status": "blocked" if validation_errors else "review_ready",
"binding_spec_rewritten": False,
"actuation_permitted": False,
"network_opened": False,
"before_yaml_sha256": before_digest,
"candidate_yaml_sha256": sha256(candidate_yaml.encode("utf-8")).hexdigest(),
"coupling_count_before": _canvas_graph_count(result, "edge_count"),
"coupling_count_after": len(after_edges),
"validation_errors": validation_errors,
"candidate_yaml": candidate_yaml,
}
|
build_canvas_edit_artifact
build_canvas_edit_artifact(
before_graph: Mapping[str, object],
after_graph: Mapping[str, object],
) -> ExportManifest
Build a review artefact from edited Studio canvas graph rows.
Parameters
before_graph : Mapping[str, object]
The canvas graph before the change.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
ExportManifest
A review artefact from edited Studio canvas graph rows.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_edit_artifact(
before_graph: Mapping[str, object],
after_graph: Mapping[str, object],
) -> ExportManifest:
"""Build a review artefact from edited Studio canvas graph rows.
Parameters
----------
before_graph : Mapping[str, object]
The canvas graph before the change.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
-------
ExportManifest
A review artefact from edited Studio canvas graph rows.
"""
before_nodes, before_edges = _normalise_canvas_graph(before_graph, "before_graph")
after_nodes, after_edges = _normalise_canvas_graph(after_graph, "after_graph")
payload = json.dumps(
{
"artifact": "canvas_edit_review",
"changed": (before_nodes, before_edges) != (after_nodes, after_edges),
"node_count_before": len(before_nodes),
"node_count_after": len(after_nodes),
"edge_count_before": len(before_edges),
"edge_count_after": len(after_edges),
"nodes_before": before_nodes,
"nodes_after": after_nodes,
"edges_before": before_edges,
"edges_after": after_edges,
},
sort_keys=True,
indent=2,
)
return ExportManifest.review_artifact(
target_kind="canvas_edit_review",
file_name="canvas_edit_review.json",
payload=payload,
command="review canvas_edit_review.json before updating binding_spec.yaml",
)
|
build_canvas_graph
build_canvas_graph(spec: BindingSpec) -> dict[str, object]
Return a deterministic layer/coupling graph for Studio canvas review.
Parameters
spec : BindingSpec
The binding specification.
Returns
dict[str, object]
A deterministic layer/coupling graph for Studio canvas review.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_graph(spec: BindingSpec) -> dict[str, object]:
"""Return a deterministic layer/coupling graph for Studio canvas review.
Parameters
----------
spec : BindingSpec
The binding specification.
Returns
-------
dict[str, object]
A deterministic layer/coupling graph for Studio canvas review.
"""
family_channels = {
family_name: family.channel
for family_name, family in spec.oscillator_families.items()
}
channel_order = {
channel: index for index, channel in enumerate(sorted(spec.used_channels()))
}
channels = tuple(sorted(channel_order))
nodes: list[dict[str, object]] = []
for layer in sorted(spec.layers, key=lambda item: item.index):
family = layer.family or ""
channel = family_channels.get(family, "")
nodes.append(
{
"id": f"layer_{layer.index}",
"label": layer.name,
"kind": "layer",
"layer_index": int(layer.index),
"family": family,
"channel": channel,
"oscillator_count": len(layer.oscillator_ids),
"x": float(layer.index) * 220.0,
"y": float(channel_order.get(channel, 0)) * 140.0,
}
)
for index, channel in enumerate(channels):
nodes.append(
{
"id": _canvas_channel_id(channel),
"label": channel,
"kind": "channel",
"channel": channel,
"layer_index": -1,
"family": "",
"oscillator_count": 0,
"x": float(index) * 220.0,
"y": 420.0,
}
)
edges = [
{
"id": f"cross_channel_{index}",
"source": _canvas_channel_id(coupling.source),
"target": _canvas_channel_id(coupling.target),
"kind": "cross_channel_coupling",
"source_channel": coupling.source,
"target_channel": coupling.target,
"strength": float(coupling.strength),
"mode": coupling.mode,
"template": coupling.template or "",
}
for index, coupling in enumerate(spec.cross_channel_couplings, 1)
if coupling.source in channel_order and coupling.target in channel_order
]
return {
"canvas_kind": "layer_coupling_graph",
"node_count": len(nodes),
"layer_count": len(spec.layers),
"channel_count": len(channels),
"edge_count": len(edges),
"nodes": nodes,
"edges": edges,
}
|
build_canvas_interaction_state
build_canvas_interaction_state(
*,
canvas_artifact: ExportManifest,
canvas_layout: ExportManifest,
canvas_patch: ExportManifest,
canvas_rewrite: Mapping[str, object],
operator_signoff: bool,
) -> dict[str, object]
Summarise Canvas browser controls for deterministic operator feedback.
Parameters
canvas_artifact : ExportManifest
The canvas edit artefact manifest.
canvas_layout : ExportManifest
The canvas layout manifest.
canvas_patch : ExportManifest
The canvas topology patch manifest.
canvas_rewrite : Mapping[str, object]
The canvas binding-rewrite candidate.
operator_signoff : bool
Whether the operator has signed off.
Returns
dict[str, object]
Canvas browser controls for deterministic operator feedback.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_interaction_state(
*,
canvas_artifact: ExportManifest,
canvas_layout: ExportManifest,
canvas_patch: ExportManifest,
canvas_rewrite: Mapping[str, object],
operator_signoff: bool,
) -> dict[str, object]:
"""Summarise Canvas browser controls for deterministic operator feedback.
Parameters
----------
canvas_artifact : ExportManifest
The canvas edit artefact manifest.
canvas_layout : ExportManifest
The canvas layout manifest.
canvas_patch : ExportManifest
The canvas topology patch manifest.
canvas_rewrite : Mapping[str, object]
The canvas binding-rewrite candidate.
operator_signoff : bool
Whether the operator has signed off.
Returns
-------
dict[str, object]
Canvas browser controls for deterministic operator feedback.
"""
record = json.loads(canvas_artifact.payload)
changed = bool(record.get("changed"))
rewrite_status = _require_non_empty_text(
canvas_rewrite.get("status"),
"rewrite_status",
)
validation_errors = _string_list(
canvas_rewrite.get("validation_errors", ()),
"validation_errors",
)
disabled_reasons: list[str] = []
if rewrite_status != "review_ready":
disabled_reasons.append("binding rewrite candidate is blocked")
disabled_reasons.extend(validation_errors)
if not operator_signoff:
disabled_reasons.append("operator sign-off required")
apply_enabled = not disabled_reasons
return {
"state_kind": "studio_canvas_interaction_state",
"changed": changed,
"rewrite_status": rewrite_status,
"apply_enabled": apply_enabled,
"disabled_reasons": disabled_reasons,
"next_action": _canvas_next_action(
changed=changed,
rewrite_status=rewrite_status,
operator_signoff=operator_signoff,
apply_enabled=apply_enabled,
),
"status_message": (
"Canvas edits need review before apply."
if changed
else "Canvas graph matches the current binding."
),
"download_manifest": [
canvas_artifact.file_name,
canvas_layout.file_name,
canvas_patch.file_name,
"binding_rewrite_candidate.yaml",
],
"candidate_yaml_sha256": canvas_rewrite.get("candidate_yaml_sha256", ""),
}
|
build_canvas_layout_manifest
build_canvas_layout_manifest(
*, project_name: str, graph: Mapping[str, object]
) -> ExportManifest
Build a deterministic canvas layout manifest from node positions.
Parameters
project_name : str
Name of the project.
graph : Mapping[str, object]
The canvas graph mapping.
Returns
ExportManifest
A deterministic canvas layout manifest from node positions.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_layout_manifest(
*,
project_name: str,
graph: Mapping[str, object],
) -> ExportManifest:
"""Build a deterministic canvas layout manifest from node positions.
Parameters
----------
project_name : str
Name of the project.
graph : Mapping[str, object]
The canvas graph mapping.
Returns
-------
ExportManifest
A deterministic canvas layout manifest from node positions.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
nodes, edges = _normalise_canvas_graph(graph, "canvas_layout")
positions = []
for node in sorted(nodes, key=lambda item: str(item.get("id", ""))):
try:
node_id = _require_non_empty_text(node.get("id"), "canvas layout id")
kind = _require_non_empty_text(node.get("kind"), "canvas layout kind")
label = _require_non_empty_text(node.get("label"), "canvas layout label")
x = _finite_number(node.get("x"), "canvas layout x")
y = _finite_number(node.get("y"), "canvas layout y")
except ValueError as exc:
raise ValueError(f"canvas layout node is invalid: {exc}") from exc
positions.append({"id": node_id, "kind": kind, "label": label, "x": x, "y": y})
payload = json.dumps(
{
"manifest_kind": "canvas_layout_manifest",
"project_name": _require_non_empty_text(project_name, "project_name"),
"node_count": len(nodes),
"edge_count": len(edges),
"positions": positions,
},
sort_keys=True,
indent=2,
)
return ExportManifest.review_artifact(
target_kind="canvas_layout_manifest",
file_name="canvas_layout_manifest.json",
payload=payload,
command="review canvas_layout_manifest.json before restoring Studio layout",
)
|
build_canvas_topology_patch
build_canvas_topology_patch(
*,
project_name: str,
before_graph: Mapping[str, object],
after_graph: Mapping[str, object],
) -> ExportManifest
Build a review patch for persistent Studio topology edits.
Parameters
project_name : str
Name of the project.
before_graph : Mapping[str, object]
The canvas graph before the change.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
ExportManifest
A review patch for persistent Studio topology edits.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_canvas_topology_patch(
*,
project_name: str,
before_graph: Mapping[str, object],
after_graph: Mapping[str, object],
) -> ExportManifest:
"""Build a review patch for persistent Studio topology edits.
Parameters
----------
project_name : str
Name of the project.
before_graph : Mapping[str, object]
The canvas graph before the change.
after_graph : Mapping[str, object]
The edited canvas graph after the change.
Returns
-------
ExportManifest
A review patch for persistent Studio topology edits.
"""
before_nodes, before_edges = _normalise_canvas_graph(before_graph, "before_graph")
after_nodes, after_edges = _normalise_canvas_graph(after_graph, "after_graph")
_validate_canvas_edge_endpoints(after_nodes, after_edges)
node_changes = _canvas_item_changes(
before_nodes,
after_nodes,
fields=("id", "kind", "label", "x", "y"),
)
edge_changes = _canvas_item_changes(
before_edges,
after_edges,
fields=("id", "kind", "source", "target"),
)
changed = any(node_changes[key] or edge_changes[key] for key in node_changes)
payload = json.dumps(
{
"patch_kind": "canvas_topology_patch",
"project_name": _require_non_empty_text(project_name, "project_name"),
"status": "review_required",
"changed": changed,
"node_count_before": len(before_nodes),
"node_count_after": len(after_nodes),
"edge_count_before": len(before_edges),
"edge_count_after": len(after_edges),
"node_changes": node_changes,
"edge_changes": edge_changes,
"safety": {
"binding_spec_rewritten": False,
"actuation_permitted": False,
},
},
sort_keys=True,
indent=2,
)
return ExportManifest.review_artifact(
target_kind="canvas_topology_patch",
file_name="canvas_topology_patch.json",
payload=payload,
command="review canvas_topology_patch.json before rewriting binding_spec.yaml",
)
|
build_oscillator_edit_artifact
build_oscillator_edit_artifact(
before_rows: Sequence[Mapping[str, object]],
after_rows: Sequence[Mapping[str, object]],
) -> ExportManifest
Build a review artefact from edited oscillator table rows.
Parameters
before_rows : Sequence[Mapping[str, object]]
The table rows before the change.
after_rows : Sequence[Mapping[str, object]]
The edited table rows after the change.
Returns
ExportManifest
A review artefact from edited oscillator table rows.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/canvas.py
| def build_oscillator_edit_artifact(
before_rows: Sequence[Mapping[str, object]],
after_rows: Sequence[Mapping[str, object]],
) -> ExportManifest:
"""Build a review artefact from edited oscillator table rows.
Parameters
----------
before_rows : Sequence[Mapping[str, object]]
The table rows before the change.
after_rows : Sequence[Mapping[str, object]]
The edited table rows after the change.
Returns
-------
ExportManifest
A review artefact from edited oscillator table rows.
"""
before = _normalise_table_rows(before_rows, "before_rows")
after = _normalise_table_rows(after_rows, "after_rows")
payload = json.dumps(
{
"artifact": "oscillator_edit_review",
"changed": before != after,
"row_count_before": len(before),
"row_count_after": len(after),
"rows_before": before,
"rows_after": after,
},
sort_keys=True,
indent=2,
)
return ExportManifest.review_artifact(
target_kind="oscillator_edit_review",
file_name="oscillator_edit_review.json",
payload=payload,
command="review oscillator_edit_review.json before updating binding_spec.yaml",
)
|
build_integrated_information_panel(
records: Sequence[Mapping[str, object]],
) -> dict[str, object]
Return a Studio panel payload for integrated-information audit records.
The panel is deliberately pure and non-actuating: it converts validated
monitor audit records into a deterministic operator payload suitable for
rendering charts, latest-value tiles, and partition review cards. The input
must preserve the monitor's explicit claim boundary so Studio cannot display
the Phi proxy as a theoretical IIT or consciousness claim.
records : Sequence[Mapping[str, object]]
The records to summarise.
dict[str, object]
A Studio panel payload for integrated-information audit records.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/charts.py
| def build_integrated_information_panel(
records: Sequence[Mapping[str, object]],
) -> dict[str, object]:
"""Return a Studio panel payload for integrated-information audit records.
The panel is deliberately pure and non-actuating: it converts validated
monitor audit records into a deterministic operator payload suitable for
rendering charts, latest-value tiles, and partition review cards. The input
must preserve the monitor's explicit claim boundary so Studio cannot display
the Phi proxy as a theoretical IIT or consciousness claim.
Parameters
----------
records : Sequence[Mapping[str, object]]
The records to summarise.
Returns
-------
dict[str, object]
A Studio panel payload for integrated-information audit records.
"""
normalised_records = _normalise_integrated_information_records(records)
latest = normalised_records[-1]
strongest = max(
normalised_records,
key=lambda item: cast("float", item["phi"]),
)
phi_values = [cast("float", item["phi"]) for item in normalised_records]
normalised_phi_values = [
cast("float", item["normalised_phi"]) for item in normalised_records
]
total_integration_values = [
cast("float", item["total_integration"]) for item in normalised_records
]
return {
"panel_kind": "studio_integrated_information_panel",
"monitor": "integrated_information",
"record_count": len(normalised_records),
"claim_boundary": "engineering_proxy_not_theoretical_iit",
"latest": latest,
"strongest_partition": strongest,
"series": normalised_records,
"phi_range": {
"min": min(phi_values),
"max": max(phi_values),
},
"normalised_phi_range": {
"min": min(normalised_phi_values),
"max": max(normalised_phi_values),
},
"total_integration_range": {
"min": min(total_integration_values),
"max": max(total_integration_values),
},
"operator_summary": (
"latest Phi proxy "
f"{cast('float', latest['phi']):.6g}; latest normalised Phi "
f"{cast('float', latest['normalised_phi']):.6g}; records "
f"{len(normalised_records)}"
),
"operator_action": (
"render as an engineering integration proxy; preserve the claim "
"boundary and review the minimum partition before operational use"
),
"actuation_permitted": False,
"consciousness_claim_permitted": False,
}
|
build_regime_chart_payload
build_regime_chart_payload(
regimes: Sequence[str],
) -> list[dict[str, object]]
Return deterministic chart rows for regime timelines.
Parameters
regimes : Sequence[str]
Per-step regime labels.
Returns
list[dict[str, object]]
Deterministic chart rows for regime timelines.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/charts.py
| def build_regime_chart_payload(regimes: Sequence[str]) -> list[dict[str, object]]:
"""Return deterministic chart rows for regime timelines.
Parameters
----------
regimes : Sequence[str]
Per-step regime labels.
Returns
-------
list[dict[str, object]]
Deterministic chart rows for regime timelines.
"""
regime_levels = {
"critical": 0.0,
"degraded": 1.0,
"recovery": 1.5,
"nominal": 2.0,
}
rows: list[dict[str, object]] = []
for index, regime in enumerate(regimes, 1):
regime_text = _require_non_empty_text(regime, "regime")
rows.append(
{
"step": index,
"regime": regime_text,
"regime_level": regime_levels.get(regime_text, 0.0),
}
)
return rows
|
build_series_chart_payload
build_series_chart_payload(
label: str, values: Sequence[float]
) -> list[dict[str, float | int]]
Return dense chart rows for a scalar time-series.
Parameters
label : str
Series or chart label.
values : Sequence[float]
Scalar time-series values.
Returns
list[dict[str, float | int]]
Dense chart rows for a scalar time-series.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/charts.py
| def build_series_chart_payload(
label: str,
values: Sequence[float],
) -> list[dict[str, float | int]]:
"""Return dense chart rows for a scalar time-series.
Parameters
----------
label : str
Series or chart label.
values : Sequence[float]
Scalar time-series values.
Returns
-------
list[dict[str, float | int]]
Dense chart rows for a scalar time-series.
"""
_require_non_empty_text(label, "label")
return [
{"step": index, label: _finite_number(value, label)}
for index, value in enumerate(values, 1)
]
|
build_live_connector_plan
build_live_connector_plan(
spec: BindingSpec,
) -> dict[str, object]
Return non-opening connector ownership guidance for Studio.
Parameters
spec : BindingSpec
The binding specification.
Returns
dict[str, object]
Non-opening connector ownership guidance for Studio.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/connectors.py
| def build_live_connector_plan(spec: BindingSpec) -> dict[str, object]:
"""Return non-opening connector ownership guidance for Studio.
Parameters
----------
spec : BindingSpec
The binding specification.
Returns
-------
dict[str, object]
Non-opening connector ownership guidance for Studio.
"""
contract = build_digital_twin_binding_contract(spec)
connector_specs = (
("memory", True, False, "review offline memory connector"),
("jsonl", True, False, "review JSONL replay connector"),
("rest", False, True, "assign connector owner and auth policy"),
("grpc", False, True, "assign connector owner and auth policy"),
("kafka", False, True, "assign connector owner and auth policy"),
("hardware", False, True, "assign connector owner and auth policy"),
)
connectors: list[dict[str, object]] = []
for transport, supports_replay, requires_auth, action in connector_specs:
compatibility = build_digital_twin_adapter_manifest(
contract,
name=f"studio-{transport}",
transport=transport,
sync_capabilities=[
capability.name for capability in contract.sync_capabilities
],
supports_replay=supports_replay,
requires_auth=requires_auth,
notes="SPO Studio connector review",
)
manifest = compatibility.manifest
owner_required = transport in {"rest", "grpc", "kafka", "hardware"}
connectors.append(
{
"name": manifest.name,
"transport": manifest.transport,
"status": "owner_required" if owner_required else "review_ready",
"compatible": compatibility.compatible,
"reasons": list(compatibility.reasons),
"sync_capabilities": list(manifest.sync_capabilities),
"supports_replay": manifest.supports_replay,
"requires_auth": manifest.requires_auth,
"operator_action": action,
"network_opened": False,
"hardware_write_permitted": False,
}
)
return {
"plan_kind": "studio_live_connector_plan",
"project_name": spec.name,
"contract_hash": contract.contract_hash,
"network_opened": False,
"actuation_permitted": False,
"connectors": connectors,
}
|
build_live_connector_run_record
build_live_connector_run_record(
connector_plan: Mapping[str, object],
*,
transport: str,
payload: Mapping[str, object],
dry_run: bool = True,
) -> dict[str, object]
Return a gated live-connector execution record without opening transport.
Parameters
connector_plan : Mapping[str, object]
The live-connector plan mapping.
transport : str
Transport identifier.
payload : Mapping[str, object]
The payload mapping or bytes.
dry_run : bool
Whether to run without opening transport.
Returns
dict[str, object]
A gated live-connector execution record without opening transport.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/connectors.py
| def build_live_connector_run_record(
connector_plan: Mapping[str, object],
*,
transport: str,
payload: Mapping[str, object],
dry_run: bool = True,
) -> dict[str, object]:
"""Return a gated live-connector execution record without opening transport.
Parameters
----------
connector_plan : Mapping[str, object]
The live-connector plan mapping.
transport : str
Transport identifier.
payload : Mapping[str, object]
The payload mapping or bytes.
dry_run : bool
Whether to run without opening transport.
Returns
-------
dict[str, object]
A gated live-connector execution record without opening transport.
"""
connector = _connector_by_transport(
connector_plan,
_require_non_empty_text(transport, "transport"),
)
payload_json = _stable_json_payload(payload, "payload")
connector_status = _require_non_empty_text(connector.get("status"), "status")
blocked_reasons: list[str] = []
if connector_status != "review_ready":
blocked_reasons.append("connector owner and auth policy required")
if not dry_run:
blocked_reasons.append("Studio live execution uses dry-run records only")
status = "blocked" if blocked_reasons else "accepted"
return {
"record_kind": "studio_live_connector_run",
"project_name": _require_non_empty_text(
connector_plan.get("project_name"),
"project_name",
),
"transport": connector["transport"],
"connector_name": connector["name"],
"status": status,
"dry_run": bool(dry_run),
"payload_sha256": sha256(payload_json.encode("utf-8")).hexdigest(),
"blocked_reasons": blocked_reasons,
"operator_action": (
"review dry-run connector payload"
if status == "accepted"
else _require_non_empty_text(
connector.get("operator_action"),
"operator_action",
)
),
"network_opened": False,
"actuation_permitted": False,
"hardware_write_permitted": False,
}
|
build_owned_live_connector_runtime_record
build_owned_live_connector_runtime_record(
result: StudioReplayResult,
*,
transport: str,
owner: str,
auth_policy: Mapping[str, object],
payload: Mapping[str, object],
sequence: int = 1,
capability: str = "audit_replay",
direction: str = "twin_to_spo",
) -> dict[str, object]
Validate an owned live connector boundary without opening transport.
Parameters
result : StudioReplayResult
The Studio replay result.
transport : str
Transport identifier.
owner : str
Owner of the connector boundary.
auth_policy : Mapping[str, object]
The connector authentication policy.
payload : Mapping[str, object]
The payload mapping or bytes.
sequence : int
Monotonic sequence number.
capability : str
The sync capability identifier.
direction : str
Sync direction (e.g. inbound/outbound).
Returns
dict[str, object]
An owned live connector boundary without opening transport.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/connectors.py
| def build_owned_live_connector_runtime_record(
result: StudioReplayResult,
*,
transport: str,
owner: str,
auth_policy: Mapping[str, object],
payload: Mapping[str, object],
sequence: int = 1,
capability: str = "audit_replay",
direction: str = "twin_to_spo",
) -> dict[str, object]:
"""Validate an owned live connector boundary without opening transport.
Parameters
----------
result : StudioReplayResult
The Studio replay result.
transport : str
Transport identifier.
owner : str
Owner of the connector boundary.
auth_policy : Mapping[str, object]
The connector authentication policy.
payload : Mapping[str, object]
The payload mapping or bytes.
sequence : int
Monotonic sequence number.
capability : str
The sync capability identifier.
direction : str
Sync direction (e.g. ``inbound``/``outbound``).
Returns
-------
dict[str, object]
An owned live connector boundary without opening transport.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if not isinstance(result, StudioReplayResult):
raise ValueError("replay result must be a StudioReplayResult")
checked_transport = _require_non_empty_text(transport, "transport")
checked_payload = _normalise_json_mapping(
cast("Mapping[object, object]", payload),
"payload",
)
payload_json = _stable_json_payload(checked_payload, "payload")
blocked_reasons = _owned_runtime_blocked_reasons(
result.connector_plan,
checked_transport,
owner,
auth_policy,
)
base = _owned_runtime_base_record(
result,
transport=checked_transport,
owner=owner,
payload_sha256=sha256(payload_json.encode("utf-8")).hexdigest(),
sequence=sequence,
capability=capability,
direction=direction,
)
if blocked_reasons:
return {
**base,
"status": "blocked",
"blocked_reasons": blocked_reasons,
"response": {},
"adapter": {},
"queued_count": 0,
}
spec_path = _result_binding_spec_path(result)
spec = load_binding_spec(spec_path)
contract = build_digital_twin_binding_contract(spec)
envelope = build_digital_twin_sync_envelope(
contract,
capability=_require_non_empty_text(capability, "capability"),
direction=_require_non_empty_text(direction, "direction"),
sequence=_non_negative_int(sequence, "sequence"),
payload=checked_payload,
)
response, adapter_record = _run_owned_live_adapter(
contract,
transport=checked_transport,
envelope_record=envelope.to_audit_record(),
)
return {
**base,
"status": "accepted" if response.get("accepted") is True else "blocked",
"blocked_reasons": (
[] if response.get("accepted") is True else [str(response["reason"])]
),
"response": response,
"adapter": adapter_record,
"queued_count": _mapping_count(adapter_record, "queued_count"),
}
|
build_command_table
build_command_table(
project_state: StudioProjectState,
) -> tuple[dict[str, object], ...]
Return copyable deployment-review commands for ready targets.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
tuple[dict[str, object], ...]
Copyable deployment-review commands for ready targets.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_command_table(
project_state: StudioProjectState,
) -> tuple[dict[str, object], ...]:
"""Return copyable deployment-review commands for ready targets.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
tuple[dict[str, object], ...]
Copyable deployment-review commands for ready targets.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
readiness = build_deployment_readiness(project_state)
rows: list[dict[str, object]] = []
for target in _require_sequence(readiness.get("targets"), "targets"):
if not isinstance(target, Mapping):
raise ValueError("readiness targets must be mappings")
status = _require_non_empty_text(target.get("status"), "status")
if status == "blocked":
continue
target_name = _require_non_empty_text(target.get("target"), "target")
commands = target.get("commands", ())
if isinstance(commands, str | bytes) or not isinstance(commands, Sequence):
raise ValueError("target commands must be a sequence of strings")
for index, command in enumerate(commands, 1):
rows.append(
{
"target": target_name,
"command_index": index,
"command": _require_non_empty_text(command, "command"),
"status": status,
}
)
return tuple(rows)
|
build_deployment_package
build_deployment_package(
project_state: StudioProjectState,
) -> dict[str, object]
Return a deterministic deployment package manifest for Studio.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
dict[str, object]
A deterministic deployment package manifest for Studio.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_deployment_package(
project_state: StudioProjectState,
) -> dict[str, object]:
"""Return a deterministic deployment package manifest for Studio.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
dict[str, object]
A deterministic deployment package manifest for Studio.
"""
readiness = build_deployment_readiness(project_state)
targets = _readiness_targets(readiness)
blocked_reasons = _deployment_blocked_reasons(project_state.exports)
return {
"package_kind": "studio_deployment_package",
"project_name": project_state.project_name,
"overall_status": readiness["overall_status"],
"ready_targets": [
target["target"] for target in targets if target["status"] == "ready"
],
"postponed_targets": [
target["target"] for target in targets if target["status"] == "postponed"
],
"blocked_targets": [
target["target"] for target in targets if target["status"] == "blocked"
],
"blocked_reasons": list(blocked_reasons),
"required_artifacts": _unique_artifacts(targets),
"export_artifacts": [
{
"target_kind": manifest.target_kind,
"file_name": manifest.file_name,
"payload_sha256": manifest.payload_sha256,
"safety_posture": manifest.safety_posture,
"warnings": list(manifest.warnings),
}
for manifest in project_state.exports
],
"commands": list(build_command_table(project_state)),
"safety_gates": [
"local replay completed",
(
"binding validation blocked"
if blocked_reasons
else "binding validation passed"
),
"live actuation disabled",
"hardware output requires verified evidence",
],
"readiness": readiness,
}
|
build_deployment_readiness
build_deployment_readiness(
project_state: StudioProjectState,
) -> dict[str, object]
Return target-specific deployment readiness guidance for Studio.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
dict[str, object]
Target-specific deployment readiness guidance for Studio.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_deployment_readiness(
project_state: StudioProjectState,
) -> dict[str, object]:
"""Return target-specific deployment readiness guidance for Studio.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
dict[str, object]
Target-specific deployment readiness guidance for Studio.
"""
blocked_reasons = _deployment_blocked_reasons(project_state.exports)
if blocked_reasons:
return {
"project_name": project_state.project_name,
"overall_status": "blocked",
"operator_next_step": "fix binding validation errors",
"targets": [
_blocked_target("docker", blocked_reasons),
_blocked_target("wasm", blocked_reasons),
_blocked_target("hardware", blocked_reasons),
],
}
return {
"project_name": project_state.project_name,
"overall_status": "review_ready",
"operator_next_step": "review target-specific packaging",
"targets": [
{
"target": "docker",
"status": "ready",
"required_artifacts": [
"binding_spec.yaml",
"spo_studio_audit.json",
"docker_manifest.json",
],
"commands": [
"docker compose config",
"docker build -t scpn-phase-orchestrator:local .",
"docker run --rm -v $PWD:/workspace "
"scpn-phase-orchestrator:local "
"spo run binding_spec.yaml --audit audit.jsonl",
],
"operator_action": "run docker manifest review before packaging",
},
{
"target": "wasm",
"status": "ready",
"required_artifacts": [
"binding_spec.yaml",
"spo_studio_audit.json",
"wasm_manifest.json",
],
"commands": [
"cd spo-kernel && wasm-pack build crates/spo-wasm "
"--target web --out-dir ../../../docs/wasm-pkg",
],
"operator_action": "review browser-safe replay constraints",
},
{
"target": "hardware",
"status": "postponed",
"required_artifacts": [
"binding_spec.yaml",
"spo_studio_audit.json",
"verified_hardware_target_evidence",
],
"commands": [],
"operator_action": "attach verified hardware-target evidence",
},
],
}
|
build_export_manifests
build_export_manifests(
*,
project_name: str,
binding_yaml: str,
audit_payload: Mapping[str, object],
validation_errors: Sequence[str],
) -> tuple[ExportManifest, ...]
Build review-only export manifests for Studio.
Parameters
project_name : str
Name of the project.
binding_yaml : str
The binding spec serialised as YAML.
audit_payload : Mapping[str, object]
The audit payload mapping.
validation_errors : Sequence[str]
Binding validation error messages.
Returns
tuple[ExportManifest, ...]
Review-only export manifests for Studio.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_export_manifests(
*,
project_name: str,
binding_yaml: str,
audit_payload: Mapping[str, object],
validation_errors: Sequence[str],
) -> tuple[ExportManifest, ...]:
"""Build review-only export manifests for Studio.
Parameters
----------
project_name : str
Name of the project.
binding_yaml : str
The binding spec serialised as YAML.
audit_payload : Mapping[str, object]
The audit payload mapping.
validation_errors : Sequence[str]
Binding validation error messages.
Returns
-------
tuple[ExportManifest, ...]
Review-only export manifests for Studio.
"""
deploy_warnings = disabled_export_reasons(validation_errors)
audit_export_payload = {
**dict(audit_payload),
"enabled": not deploy_warnings,
"disabled_reasons": list(deploy_warnings),
}
audit_json = json.dumps(audit_export_payload, sort_keys=True, indent=2)
docker_payload = json.dumps(
{
"project_name": project_name,
"image": "scpn-phase-orchestrator:local",
"command": "spo run binding_spec.yaml --audit audit.jsonl",
"enabled": not deploy_warnings,
"disabled_reasons": list(deploy_warnings),
},
sort_keys=True,
indent=2,
)
wasm_payload = json.dumps(
{
"project_name": project_name,
"target": "wasm_review_manifest",
"enabled": not deploy_warnings,
"disabled_reasons": list(deploy_warnings),
},
sort_keys=True,
indent=2,
)
return (
ExportManifest.review_artifact(
target_kind="binding_spec",
file_name="binding_spec.yaml",
payload=binding_yaml,
command="spo run binding_spec.yaml --audit audit.jsonl",
warnings=deploy_warnings,
),
ExportManifest.review_artifact(
target_kind="audit_summary",
file_name="spo_studio_audit.json",
payload=audit_json,
command="spo audit summary spo_studio_audit.json",
warnings=deploy_warnings,
),
ExportManifest.review_artifact(
target_kind="docker_manifest",
file_name="docker_manifest.json",
payload=docker_payload,
command="docker compose config",
warnings=deploy_warnings,
),
ExportManifest.review_artifact(
target_kind="wasm_manifest",
file_name="wasm_manifest.json",
payload=wasm_payload,
command="spo export wasm --manifest wasm_manifest.json",
warnings=deploy_warnings,
),
)
|
build_operator_checklist
build_operator_checklist(
project_state: StudioProjectState,
) -> tuple[dict[str, object], ...]
Return beginner-friendly ordered deployment steps for Studio.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
tuple[dict[str, object], ...]
Beginner-friendly ordered deployment steps for Studio.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_operator_checklist(
project_state: StudioProjectState,
) -> tuple[dict[str, object], ...]:
"""Return beginner-friendly ordered deployment steps for Studio.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
tuple[dict[str, object], ...]
Beginner-friendly ordered deployment steps for Studio.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
readiness = build_deployment_readiness(project_state)
validation_blocked = readiness["overall_status"] == "blocked"
steps: list[dict[str, object]] = [
{
"step": 1,
"title": "Run local replay",
"status": (
"complete"
if project_state.runtime.replay_status == "completed"
else "blocked"
),
"detail": project_state.runtime.replay_status,
},
{
"step": 2,
"title": "Validate binding",
"status": "blocked" if validation_blocked else "complete",
"detail": (
"; ".join(_deployment_blocked_reasons(project_state.exports))
if validation_blocked
else "binding validation passed"
),
},
]
for target in _require_sequence(readiness.get("targets"), "targets"):
if not isinstance(target, Mapping):
raise ValueError("readiness targets must be mappings")
target_name = _require_non_empty_text(target.get("target"), "target")
status = _require_non_empty_text(target.get("status"), "status")
operator_action = _require_non_empty_text(
target.get("operator_action"),
"operator_action",
)
blocked_detail = "; ".join(
str(reason)
for reason in _require_sequence(
target.get("blocked_reasons", ()),
"blocked_reasons",
)
)
steps.append(
{
"step": len(steps) + 1,
"title": f"Review {target_name} packaging",
"target": target_name,
"status": status,
"detail": blocked_detail or operator_action,
}
)
return tuple(steps)
|
build_package_materialisation_plan
build_package_materialisation_plan(
project_state: StudioProjectState,
) -> dict[str, object]
Return ordered, operator-invoked package materialisation commands.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
dict[str, object]
Ordered, operator-invoked package materialisation commands.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_package_materialisation_plan(
project_state: StudioProjectState,
) -> dict[str, object]:
"""Return ordered, operator-invoked package materialisation commands.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
dict[str, object]
Ordered, operator-invoked package materialisation commands.
"""
package = build_deployment_package(project_state)
command_rows = build_command_table(project_state)
commands = [
{
"step": index,
"target": _require_non_empty_text(row.get("target"), "target"),
"command": _require_non_empty_text(row.get("command"), "command"),
"status": _require_non_empty_text(row.get("status"), "status"),
"requires_operator": True,
"writes_artifact": _materialisation_command_writes_artifact(
row.get("command")
),
}
for index, row in enumerate(command_rows, 1)
]
readiness = build_deployment_readiness(project_state)
targets = _readiness_targets(readiness)
return {
"plan_kind": "studio_package_materialisation_plan",
"project_name": project_state.project_name,
"overall_status": package["overall_status"],
"execution_mode": "operator_invoked",
"network_opened": False,
"hardware_write_permitted": False,
"commands": commands,
"blocked_targets": list(
_require_sequence(package.get("blocked_targets"), "blocked_targets")
),
"blocked_reasons": list(
_require_sequence(package.get("blocked_reasons"), "blocked_reasons")
),
"postponed_targets": [
{
"target": target["target"],
"reason": _require_non_empty_text(
target.get("operator_action"),
"operator_action",
),
}
for target in targets
if target["status"] == "postponed"
],
"required_artifacts": list(
_require_sequence(package.get("required_artifacts"), "required_artifacts")
),
"safety_gates": list(
_require_sequence(package.get("safety_gates"), "safety_gates")
),
}
|
build_service_process_manifest
build_service_process_manifest(
project_state: StudioProjectState,
) -> dict[str, object]
Return localhost-only service process packaging for Studio deployment.
Parameters
project_state : StudioProjectState
The Studio project state.
Returns
dict[str, object]
Localhost-only service process packaging for Studio deployment.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def build_service_process_manifest(
project_state: StudioProjectState,
) -> dict[str, object]:
"""Return localhost-only service process packaging for Studio deployment.
Parameters
----------
project_state : StudioProjectState
The Studio project state.
Returns
-------
dict[str, object]
Localhost-only service process packaging for Studio deployment.
"""
blocked_reasons = _deployment_blocked_reasons(project_state.exports)
if blocked_reasons:
return {
"manifest_kind": "studio_service_process_manifest",
"project_name": project_state.project_name,
"overall_status": "blocked",
"execution_mode": "operator_invoked",
"network_opened": False,
"actuation_permitted": False,
"hardware_write_permitted": False,
"host_bind": "127.0.0.1",
"compose_file": "spo_studio_services.compose.yaml",
"services": [],
"blocked_reasons": list(blocked_reasons),
"required_artifacts": [],
"compose_yaml": "",
"compose_yaml_sha256": "",
}
services = _studio_service_processes()
compose_yaml = _render_service_compose_yaml(services)
return {
"manifest_kind": "studio_service_process_manifest",
"project_name": project_state.project_name,
"overall_status": "operator_ready",
"execution_mode": "operator_invoked",
"network_opened": False,
"actuation_permitted": False,
"hardware_write_permitted": False,
"host_bind": "127.0.0.1",
"compose_file": "spo_studio_services.compose.yaml",
"services": services,
"blocked_reasons": [],
"required_artifacts": [
"binding_spec.yaml",
"spo_studio_audit.json",
"docker_manifest.json",
"owned_connector_runtime.json",
],
"operator_commands": [
"docker compose -f spo_studio_services.compose.yaml config",
"docker compose -f spo_studio_services.compose.yaml up spo-studio-ui",
],
"compose_yaml": compose_yaml,
"compose_yaml_sha256": sha256(compose_yaml.encode("utf-8")).hexdigest(),
}
|
disabled_export_reasons
disabled_export_reasons(
validation_errors: Sequence[str],
) -> tuple[str, ...]
Return reasons deploy-like exports must stay review-only.
Parameters
validation_errors : Sequence[str]
Binding validation error messages.
Returns
tuple[str, ...]
Reasons deploy-like exports must stay review-only.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/deployment.py
| def disabled_export_reasons(validation_errors: Sequence[str]) -> tuple[str, ...]:
"""Return reasons deploy-like exports must stay review-only.
Parameters
----------
validation_errors : Sequence[str]
Binding validation error messages.
Returns
-------
tuple[str, ...]
Reasons deploy-like exports must stay review-only.
"""
errors = tuple(str(error) for error in validation_errors)
if not errors:
return ()
return (
"binding validation must pass before deploy manifests are enabled",
*errors,
)
|
binding_spec_project_state
binding_spec_project_state(
*,
project_name: str,
spec_path: Path,
knobs: StudioKnobState,
runtime: RuntimeSnapshot,
) -> StudioProjectState
Create a Studio project state from an existing binding spec file.
Parameters
project_name : str
Name of the project.
spec_path : Path
Filesystem path to the binding-spec file.
knobs : StudioKnobState
The Studio knob state.
runtime : RuntimeSnapshot
The workflow runtime snapshot.
Returns
StudioProjectState
A Studio project state from an existing binding spec file.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/guidance.py
| def binding_spec_project_state(
*,
project_name: str,
spec_path: Path,
knobs: StudioKnobState,
runtime: RuntimeSnapshot,
) -> StudioProjectState:
"""Create a Studio project state from an existing binding spec file.
Parameters
----------
project_name : str
Name of the project.
spec_path : Path
Filesystem path to the binding-spec file.
knobs : StudioKnobState
The Studio knob state.
runtime : RuntimeSnapshot
The workflow runtime snapshot.
Returns
-------
StudioProjectState
A Studio project state from an existing binding spec file.
"""
yaml_text = spec_path.read_text(encoding="utf-8")
spec = load_binding_spec(spec_path)
validation_errors = tuple(validate_binding_spec(spec))
source = ImportedSourceSummary.from_payload(
source_kind="binding_spec_yaml",
payload=yaml_text.encode("utf-8"),
channel_count=max(1, len(spec.used_channels())),
sample_count=sum(len(layer.oscillator_ids) for layer in spec.layers),
)
provenance: dict[str, JsonValue] = {
"source_path": str(spec_path),
"knobs": dict(knobs.to_audit_record()),
"validator": "validate_binding_spec",
}
binding = BindingProposal(
yaml_text=yaml_text,
validation_errors=validation_errors,
inferred_channels=tuple(sorted(spec.used_channels())),
confidence_factors={
"validator_acceptance": 1.0 if not validation_errors else 0.0,
"layer_coverage": 1.0 if spec.layers else 0.0,
},
provenance=provenance,
)
exports = build_export_manifests(
project_name=project_name,
binding_yaml=yaml_text,
audit_payload={
"project_name": project_name,
"runtime": runtime.to_audit_record(),
},
validation_errors=validation_errors,
)
return StudioProjectState(
project_name=project_name,
source=source,
binding=binding,
runtime=runtime,
exports=exports,
metadata={
"domainpack": project_name,
"safety": "local_replay_only",
},
)
|
build_beginner_guidance
build_beginner_guidance(
result: StudioReplayResult,
) -> dict[str, object]
Return domain-term guidance for first-time Studio operators.
Parameters
result : StudioReplayResult
The Studio replay result.
Returns
dict[str, object]
Domain-term guidance for first-time Studio operators.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/guidance.py
| def build_beginner_guidance(result: StudioReplayResult) -> dict[str, object]:
"""Return domain-term guidance for first-time Studio operators.
Parameters
----------
result : StudioReplayResult
The Studio replay result.
Returns
-------
dict[str, object]
Domain-term guidance for first-time Studio operators.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if not isinstance(result, StudioReplayResult):
raise ValueError("replay result must be a StudioReplayResult")
project = result.project_state
runtime = project.runtime
layers = [
_require_non_empty_text(row.get("name"), "layer")
for row in result.layer_table
if isinstance(row, Mapping)
]
channels = [
_require_non_empty_text(node.get("channel"), "channel")
for node in _require_sequence(result.canvas_graph.get("nodes", ()), "nodes")
if isinstance(node, Mapping) and node.get("kind") == "channel"
]
validation_errors = list(project.binding.validation_errors)
canvas_evidence = {
"layers": _canvas_graph_count(result, "layer_count"),
"channels": _canvas_graph_count(result, "channel_count"),
"couplings": _canvas_graph_count(result, "edge_count"),
}
return {
"guide_kind": "beginner_mode",
"project_name": project.project_name,
"actuation_permitted": False,
"runtime_summary": {
"replay_status": runtime.replay_status,
"regime": runtime.regime,
"R": float(runtime.R),
"domain_signal": (
"R summarises how closely the reviewed domain signals move together."
),
},
"concept_cards": [
{
"title": "Signals",
"plain_language": (
"Each layer groups domain measurements that Studio reviews as "
"oscillators."
),
"evidence": {
"layers": layers,
"channels": sorted(channels),
"source_kind": project.source.source_kind,
},
},
{
"title": "Coupling",
"plain_language": (
"K raises or lowers how much the reviewed signals influence "
"one another during replay."
),
"evidence": {
"K": float(runtime.K),
"alpha": float(runtime.alpha),
"zeta": float(runtime.zeta),
"Psi": float(runtime.Psi),
"cross_channel_edges": _canvas_graph_count(result, "edge_count"),
},
},
{
"title": "Objectives",
"plain_language": (
"The objective is to keep reviewed good layers coherent while "
"validation errors block packaging."
),
"evidence": {
"validation_errors": validation_errors,
"binding_ready": not validation_errors,
},
},
{
"title": "Supervisor",
"plain_language": (
"The supervisor reads the replay regime and emits review "
"evidence only; live actuation stays disabled."
),
"evidence": {
"regime": runtime.regime,
"hierarchy_watermarks": dict(runtime.hierarchy_watermarks),
},
},
],
"next_actions": (
["review binding validation"]
+ (["fix validation errors"] if validation_errors else ["review exports"])
+ ["download project_state.json"]
),
"walkthrough_steps": [
{
"step": 1,
"title": "Load project",
"status": "complete",
"operator_action": "review source summary",
"evidence": {"source_kind": project.source.source_kind},
},
{
"step": 2,
"title": "Run replay",
"status": (
"complete" if runtime.replay_status == "completed" else "blocked"
),
"operator_action": "run local replay",
"evidence": {"replay_status": runtime.replay_status},
},
{
"step": 3,
"title": "Review binding",
"status": "blocked" if validation_errors else "complete",
"operator_action": (
"fix validation errors"
if validation_errors
else "review binding and continue"
),
"evidence": {"validation_errors": validation_errors},
},
{
"step": 4,
"title": "Inspect canvas",
"status": "complete",
"operator_action": "inspect layer, channel, and coupling graph",
"evidence": canvas_evidence,
},
{
"step": 5,
"title": "Prepare exports",
"status": "blocked" if validation_errors else "ready",
"operator_action": (
"fix validation errors"
if validation_errors
else "download review artefacts"
),
"evidence": {
"export_count": len(result.export_manifests),
"connector_count": len(
_require_sequence(
result.connector_plan.get("connectors", ()),
"connectors",
)
),
},
},
],
}
|
build_error_report
build_error_report(
*,
operation: str,
error: Exception,
project_name: str = "unknown",
) -> dict[str, object]
Return a path-safe operator report for failed Studio actions.
Parameters
operation : str
The operation label.
error : Exception
The exception that was raised.
project_name : str
Name of the project.
Returns
dict[str, object]
A path-safe operator report for failed Studio actions.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/guidance.py
| def build_error_report(
*,
operation: str,
error: Exception,
project_name: str = "unknown",
) -> dict[str, object]:
"""Return a path-safe operator report for failed Studio actions.
Parameters
----------
operation : str
The operation label.
error : Exception
The exception that was raised.
project_name : str
Name of the project.
Returns
-------
dict[str, object]
A path-safe operator report for failed Studio actions.
"""
return {
"project_name": _require_non_empty_text(project_name, "project_name"),
"operation": _require_non_empty_text(operation, "operation"),
"status": "blocked",
"error_type": type(error).__name__,
"operator_action": "review input artefacts and rerun",
}
|
build_runtime_snapshot
build_runtime_snapshot(
*,
final_state: Mapping[str, object],
knobs: StudioKnobState,
hierarchy_watermarks: Mapping[str, int] | None = None,
replay_status: str = "not_started",
) -> RuntimeSnapshot
Build a workflow runtime snapshot from a simulation state dict.
Parameters
final_state : Mapping[str, object]
The final simulation state mapping.
knobs : StudioKnobState
The Studio knob state.
hierarchy_watermarks : Mapping[str, int] | None
Per-source hierarchy watermarks, or None.
replay_status : str
Replay status label.
Returns
RuntimeSnapshot
A workflow runtime snapshot from a simulation state dict.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/guidance.py
| def build_runtime_snapshot(
*,
final_state: Mapping[str, object],
knobs: StudioKnobState,
hierarchy_watermarks: Mapping[str, int] | None = None,
replay_status: str = "not_started",
) -> RuntimeSnapshot:
"""Build a workflow runtime snapshot from a simulation state dict.
Parameters
----------
final_state : Mapping[str, object]
The final simulation state mapping.
knobs : StudioKnobState
The Studio knob state.
hierarchy_watermarks : Mapping[str, int] | None
Per-source hierarchy watermarks, or ``None``.
replay_status : str
Replay status label.
Returns
-------
RuntimeSnapshot
A workflow runtime snapshot from a simulation state dict.
"""
layers = _layer_metrics(final_state.get("layers", ()))
return RuntimeSnapshot(
R=_finite_number(final_state.get("R_global", 0.0), "R_global"),
Psi=knobs.Psi,
K=knobs.K,
alpha=knobs.alpha,
zeta=knobs.zeta,
regime=_require_non_empty_text(final_state.get("regime", "unknown"), "regime"),
layer_metrics=layers,
hierarchy_watermarks=dict(hierarchy_watermarks or {}),
replay_status=replay_status,
)
|
build_hardware_target_package
build_hardware_target_package(
result: StudioReplayResult,
) -> dict[str, object]
Return a review-only hardware target package for Studio.
Parameters
result : StudioReplayResult
The Studio replay result.
Returns
dict[str, object]
A review-only hardware target package for Studio.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/hardware.py
| def build_hardware_target_package(result: StudioReplayResult) -> dict[str, object]:
"""Return a review-only hardware target package for Studio.
Parameters
----------
result : StudioReplayResult
The Studio replay result.
Returns
-------
dict[str, object]
A review-only hardware target package for Studio.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if not isinstance(result, StudioReplayResult):
raise ValueError("replay result must be a StudioReplayResult")
connector_plan = result.connector_plan
hardware_connector = _connector_by_transport(connector_plan, "hardware")
return {
"package_kind": "studio_hardware_target_package",
"project_name": result.project_state.project_name,
"overall_status": "evidence_required",
"contract_hash": _require_non_empty_text(
connector_plan.get("contract_hash"),
"contract_hash",
),
"hardware_write_permitted": False,
"network_opened": False,
"targets": ["fpga_verilog", "neuromorphic_schedule"],
"required_evidence": [
"generated hardware artefact path",
"simulator parity report",
"target toolchain version",
"operator sign-off",
],
"commands": [
"review connector_plan.json",
"generate FPGA Verilog with KuramotoVerilogCompiler",
"run simulator parity before hardware handoff",
],
"connector": hardware_connector,
"export_artifacts": [
manifest.to_audit_record() for manifest in result.export_manifests
],
}
|
build_verified_hardware_target_package
build_verified_hardware_target_package(
result: StudioReplayResult,
*,
evidence: Mapping[str, object],
) -> dict[str, object]
Return a verified hardware package only when evidence is complete.
Parameters
result : StudioReplayResult
The Studio replay result.
evidence : Mapping[str, object]
Verification evidence mapping.
Returns
dict[str, object]
A verified hardware package only when evidence is complete.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/hardware.py
| def build_verified_hardware_target_package(
result: StudioReplayResult,
*,
evidence: Mapping[str, object],
) -> dict[str, object]:
"""Return a verified hardware package only when evidence is complete.
Parameters
----------
result : StudioReplayResult
The Studio replay result.
evidence : Mapping[str, object]
Verification evidence mapping.
Returns
-------
dict[str, object]
A verified hardware package only when evidence is complete.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if not isinstance(result, StudioReplayResult):
raise ValueError("replay result must be a StudioReplayResult")
if not isinstance(evidence, Mapping):
raise ValueError("hardware evidence must be a mapping")
base_package = build_hardware_target_package(result)
normalised, invalid_evidence = _normalise_hardware_evidence(evidence)
verified = not invalid_evidence
return {
"package_kind": "studio_verified_hardware_target_package",
"project_name": result.project_state.project_name,
"overall_status": "review_ready" if verified else "evidence_required",
"evidence_status": "verified" if verified else "blocked",
"contract_hash": base_package["contract_hash"],
"hardware_write_permitted": False,
"network_opened": False,
"targets": list(_require_sequence(base_package.get("targets"), "targets")),
"required_evidence": list(
_require_sequence(
base_package.get("required_evidence"),
"required_evidence",
)
),
"invalid_evidence": invalid_evidence,
"evidence": normalised,
"connector": base_package["connector"],
"commands": (
[
"review verified_hardware_target_package.json",
"compare generated artefact hash before handoff",
"archive simulator parity report with package",
]
if verified
else []
),
"safety_gates": [
"local replay completed",
"binding validation passed",
"hardware evidence verified" if verified else "hardware evidence blocked",
"hardware output remains operator-controlled",
],
"export_artifacts": list(
_require_sequence(
base_package.get("export_artifacts"),
"export_artifacts",
)
),
}
|
build_evolutionary_supervisor_policy_search_studio_panel
build_evolutionary_supervisor_policy_search_studio_panel(
reports: Sequence[Mapping[str, object]],
*,
examples: Sequence[Mapping[str, object]] = (),
dsl_reports: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]
Return a Studio panel for offline evolutionary policy-search evidence.
The panel renders deterministic replay search reports, optional enriched
domain examples, and optional policy-DSL mutation reports for operator
review. It validates hashes, candidate counts, replay/STL summaries, DSL
mutation records, and all disabled execution gates before exposing data to
Studio. No returned field permits live merge, hot patching, or actuation.
Parameters
reports : Sequence[Mapping[str, object]]
The report records.
examples : Sequence[Mapping[str, object]]
Example records.
dsl_reports : Sequence[Mapping[str, object]]
Policy-DSL search reports.
Returns
dict[str, object]
A Studio panel for offline evolutionary policy-search evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_evolutionary.py
| def build_evolutionary_supervisor_policy_search_studio_panel(
reports: Sequence[Mapping[str, object]],
*,
examples: Sequence[Mapping[str, object]] = (),
dsl_reports: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]:
"""Return a Studio panel for offline evolutionary policy-search evidence.
The panel renders deterministic replay search reports, optional enriched
domain examples, and optional policy-DSL mutation reports for operator
review. It validates hashes, candidate counts, replay/STL summaries, DSL
mutation records, and all disabled execution gates before exposing data to
Studio. No returned field permits live merge, hot patching, or actuation.
Parameters
----------
reports : Sequence[Mapping[str, object]]
The report records.
examples : Sequence[Mapping[str, object]]
Example records.
dsl_reports : Sequence[Mapping[str, object]]
Policy-DSL search reports.
Returns
-------
dict[str, object]
A Studio panel for offline evolutionary policy-search evidence.
"""
normalised_reports = _normalise_evolutionary_search_reports(reports)
normalised_examples, example_rows = _normalise_evolutionary_examples(examples)
normalised_dsl_reports = _normalise_evolutionary_dsl_reports(dsl_reports)
candidate_counts = [
cast("int", report["candidate_count"]) for report in normalised_reports
] + [cast("int", report["candidate_count"]) for report in normalised_dsl_reports]
accepted_total = sum(
cast("int", report["accepted_count"]) for report in normalised_reports
) + sum(cast("int", report["accepted_count"]) for report in normalised_dsl_reports)
rejected_total = sum(
cast("int", report["rejected_count"]) for report in normalised_reports
) + sum(cast("int", report["rejected_count"]) for report in normalised_dsl_reports)
best_rows = [
report["best_candidate"]
for report in normalised_reports
if report["best_candidate"] is not None
]
replay_reward_values = [
cast(
"float",
cast("Mapping[str, object]", report["replay_summary"])["mean_reward"],
)
for report in normalised_reports
]
return {
"panel_kind": "studio_evolutionary_supervisor_policy_search_panel",
"supervisor": "evolutionary_policy_search",
"search_report_count": len(normalised_reports),
"dsl_report_count": len(normalised_dsl_reports),
"example_count": len(normalised_examples),
"claim_boundary": _EVOLUTIONARY_SEARCH_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"operator_review_required": True,
"hot_patch_permitted": False,
"live_merge_permitted": False,
"actuation_permitted": False,
"search_reports": normalised_reports,
"dsl_reports": normalised_dsl_reports,
"example_rows": example_rows,
"example_domains": tuple(
sorted({cast("str", example["domain"]) for example in normalised_examples})
),
"best_candidate_rows": tuple(best_rows),
"candidate_count_range": {
"minimum": min(candidate_counts),
"maximum": max(candidate_counts),
},
"accepted_candidate_total": accepted_total,
"rejected_candidate_total": rejected_total,
"replay_reward_range": {
"minimum": min(replay_reward_values),
"maximum": max(replay_reward_values),
},
"operator_summary": (
"evolutionary policy-search review: "
f"{len(normalised_reports)} replay report(s), "
f"{len(normalised_dsl_reports)} DSL report(s), "
f"{len(normalised_examples)} domain example(s), "
f"{accepted_total} accepted candidate(s)"
),
"operator_action": (
"render as offline evolutionary review evidence only; compare replay "
"reward, STL robustness, candidate rejection reasons, and DSL mutation "
"rows before any separately reviewed policy merge workflow"
),
}
|
build_hybrid_order_studio_panel
build_hybrid_order_studio_panel(
records: Sequence[Mapping[str, object]],
*,
scenarios: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]
Return a Studio panel for hybrid classical-quantum order evidence.
The helper renders local simulator evidence only. It preserves the
explicit quantum co-simulation claim boundary, validates deterministic
record hashes, summarises statevector/density-matrix simulator backends,
and folds deterministic scenario fixtures into candidate review rows.
Nothing in the payload permits live QPU execution or actuation.
Parameters
records : Sequence[Mapping[str, object]]
The records to summarise.
scenarios : Sequence[Mapping[str, object]]
Scenario records.
Returns
dict[str, object]
A Studio panel for hybrid classical-quantum order evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_hybrid_order.py
| def build_hybrid_order_studio_panel(
records: Sequence[Mapping[str, object]],
*,
scenarios: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]:
"""Return a Studio panel for hybrid classical-quantum order evidence.
The helper renders local simulator evidence only. It preserves the
explicit quantum co-simulation claim boundary, validates deterministic
record hashes, summarises statevector/density-matrix simulator backends,
and folds deterministic scenario fixtures into candidate review rows.
Nothing in the payload permits live QPU execution or actuation.
Parameters
----------
records : Sequence[Mapping[str, object]]
The records to summarise.
scenarios : Sequence[Mapping[str, object]]
Scenario records.
Returns
-------
dict[str, object]
A Studio panel for hybrid classical-quantum order evidence.
"""
normalised_records = _normalise_hybrid_order_records(records)
normalised_scenarios, candidate_rows = _normalise_hybrid_order_scenarios(scenarios)
entropies = [
cast("float", record["entanglement_entropy"]) for record in normalised_records
]
normalised_entropies = [
cast("float", record["normalised_entanglement_entropy"])
for record in normalised_records
]
participation_ratios = [
cast("float", record["participation_ratio"]) for record in normalised_records
]
strongest = max(
normalised_records,
key=lambda record: cast("float", record["entanglement_entropy"]),
)
backends = tuple(
sorted({cast("str", record["backend"]) for record in normalised_records})
)
scenario_domains = tuple(
sorted({cast("str", scenario["domain"]) for scenario in normalised_scenarios})
)
return {
"panel_kind": "studio_hybrid_order_panel",
"monitor": "hybrid_entanglement_order_parameter",
"record_count": len(normalised_records),
"scenario_count": len(normalised_scenarios),
"claim_boundary": _HYBRID_ORDER_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"actuation_permitted": False,
"qpu_execution_permitted": False,
"simulator_backends": backends,
"scenario_domains": scenario_domains,
"latest": normalised_records[-1],
"strongest_entanglement": strongest,
"series": normalised_records,
"candidate_rows": candidate_rows,
"entropy_range": {
"minimum": min(entropies),
"maximum": max(entropies),
},
"normalised_entanglement_range": {
"minimum": min(normalised_entropies),
"maximum": max(normalised_entropies),
},
"participation_ratio_range": {
"minimum": min(participation_ratios),
"maximum": max(participation_ratios),
},
"operator_summary": (
"hybrid order review: "
f"{len(normalised_records)} monitor records across "
f"{len(backends)} local simulator backend(s); "
f"max entropy {max(entropies):.6g}"
),
"operator_action": (
"render as local quantum co-simulation evidence only; compare "
"classical R/Psi with entanglement entropy and keep QPU execution, "
"actuation, and backend promotion behind separate evidence gates"
),
}
|
build_information_geometry_studio_panel(
records: Sequence[Mapping[str, object]],
*,
scenarios: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]
Return a Studio panel for information-geometry control evidence.
The panel renders already-computed Fisher-Rao/Wasserstein review proposals
and deterministic scenario fixtures. It validates metric tensors, simplex
coordinates, natural-gradient tangents, geodesic/curvature metrics, hash
fields, and disabled-execution boundaries before exposing anything to the
operator surface. No returned field is an executable control channel.
records : Sequence[Mapping[str, object]]
The records to summarise.
scenarios : Sequence[Mapping[str, object]]
Scenario records.
dict[str, object]
A Studio panel for information-geometry control evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_information_geometry.py
| def build_information_geometry_studio_panel(
records: Sequence[Mapping[str, object]],
*,
scenarios: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]:
"""Return a Studio panel for information-geometry control evidence.
The panel renders already-computed Fisher-Rao/Wasserstein review proposals
and deterministic scenario fixtures. It validates metric tensors, simplex
coordinates, natural-gradient tangents, geodesic/curvature metrics, hash
fields, and disabled-execution boundaries before exposing anything to the
operator surface. No returned field is an executable control channel.
Parameters
----------
records : Sequence[Mapping[str, object]]
The records to summarise.
scenarios : Sequence[Mapping[str, object]]
Scenario records.
Returns
-------
dict[str, object]
A Studio panel for information-geometry control evidence.
"""
normalised_records = _normalise_information_geometry_records(records)
normalised_scenarios, candidate_rows = _normalise_information_geometry_scenarios(
scenarios
)
fisher_values = [
cast("float", record["fisher_rao_distance"]) for record in normalised_records
]
wasserstein_values = [
cast("float", record["wasserstein_distance"]) for record in normalised_records
]
gradient_values = [
cast("float", record["natural_gradient_norm"]) for record in normalised_records
]
curvature_values = [
cast("float", record["curvature_proxy"]) for record in normalised_records
]
metric_values = [
value
for record in normalised_records
for row in cast("tuple[tuple[float, ...], ...]", record["metric_tensor"])
for value in row
]
metric_diagonal_values = [
row[index]
for record in normalised_records
for index, row in enumerate(
cast("tuple[tuple[float, ...], ...]", record["metric_tensor"])
)
]
backends = tuple(
sorted({cast("str", record["backend"]) for record in normalised_records})
)
scenario_domains = tuple(
sorted({cast("str", scenario["domain"]) for scenario in normalised_scenarios})
)
return {
"panel_kind": "studio_information_geometry_panel",
"supervisor": "information_geometry_control",
"proposal_count": len(normalised_records),
"scenario_count": len(normalised_scenarios),
"claim_boundary": _INFORMATION_GEOMETRY_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"actuation_permitted": False,
"backends": backends,
"scenario_domains": scenario_domains,
"latest": normalised_records[-1],
"series": normalised_records,
"candidate_rows": candidate_rows,
"fisher_rao_range": {
"minimum": min(fisher_values),
"maximum": max(fisher_values),
},
"wasserstein_range": {
"minimum": min(wasserstein_values),
"maximum": max(wasserstein_values),
},
"natural_gradient_range": {
"minimum": min(gradient_values),
"maximum": max(gradient_values),
},
"curvature_range": {
"minimum": min(curvature_values),
"maximum": max(curvature_values),
},
"metric_tensor_range": {
"minimum": min(metric_values),
"maximum": max(metric_values),
},
"metric_diagonal_range": {
"minimum": min(metric_diagonal_values),
"maximum": max(metric_diagonal_values),
},
"operator_summary": (
"information-geometry review: "
f"{len(normalised_records)} proposal record(s) across "
f"{len(backends)} backend(s); max Fisher-Rao distance "
f"{max(fisher_values):.6g}"
),
"operator_action": (
"render as non-actuating geometry-aware control evidence; compare "
"Fisher-Rao/Wasserstein distances, metric conditioning, and "
"natural-gradient magnitude before any separately gated policy use"
),
}
|
build_autopoietic_lineage_studio_panel
build_autopoietic_lineage_studio_panel(
manifests: Sequence[Mapping[str, object]],
) -> dict[str, object]
Build a passive Studio panel for autopoietic lineage sandbox review.
Parameters
manifests : Sequence[Mapping[str, object]]
The manifest records.
Returns
dict[str, object]
A passive Studio panel for autopoietic lineage sandbox review.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_lineage.py
| def build_autopoietic_lineage_studio_panel(
manifests: Sequence[Mapping[str, object]],
) -> dict[str, object]:
"""Build a passive Studio panel for autopoietic lineage sandbox review.
Parameters
----------
manifests : Sequence[Mapping[str, object]]
The manifest records.
Returns
-------
dict[str, object]
A passive Studio panel for autopoietic lineage sandbox review.
"""
normalised_manifests = _normalise_autopoietic_lineage_manifests(manifests)
replay_corpus_rows = tuple(
row
for manifest in normalised_manifests
for row in cast(tuple[dict[str, object], ...], manifest["replay_corpus"])
)
replay_domains = tuple(sorted({str(row["domain"]) for row in replay_corpus_rows}))
child_rows = tuple(
child
for manifest in normalised_manifests
for child in cast(tuple[dict[str, object], ...], manifest["child_candidates"])
)
accepted_child_rows = tuple(
child for child in child_rows if child["status"] == "accepted_for_review"
)
rejected_child_rows = tuple(
child for child in child_rows if child["status"] == "rejected"
)
return {
"panel_kind": "studio_autopoietic_lineage_panel",
"supervisor": "autopoietic_lineage_sandbox",
"manifest_count": len(normalised_manifests),
"claim_boundary": _AUTOPOIETIC_LINEAGE_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"operator_review_required": True,
"hot_patch_permitted": False,
"live_merge_permitted": False,
"actuation_permitted": False,
"lineage_manifests": normalised_manifests,
"replay_corpus_rows": replay_corpus_rows,
"replay_domains": replay_domains,
"replay_domain_count": len(replay_domains),
"child_candidate_total": len(child_rows),
"accepted_child_total": len(accepted_child_rows),
"rejected_child_total": len(rejected_child_rows),
"accepted_child_rows": accepted_child_rows,
"rejected_child_rows": rejected_child_rows,
"operator_summary": (
"autopoietic lineage review: "
f"{len(normalised_manifests)} manifest(s), "
f"{len(replay_domains)} replay domain(s), "
f"{len(accepted_child_rows)} accepted child candidate(s)"
),
"operator_action": (
"render as offline lineage sandbox evidence only; compare replay "
"domains, policy diffs, and blocked reasons before a separately "
"reviewed inheritance workflow"
),
}
|
build_intergenerational_inheritance_studio_panel
build_intergenerational_inheritance_studio_panel(
histories: Sequence[Mapping[str, object]],
) -> dict[str, object]
Build a passive Studio panel for inheritance-history review.
Parameters
histories : Sequence[Mapping[str, object]]
Inheritance-history records.
Returns
dict[str, object]
A passive Studio panel for inheritance-history review.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_lineage.py
| def build_intergenerational_inheritance_studio_panel(
histories: Sequence[Mapping[str, object]],
) -> dict[str, object]:
"""Build a passive Studio panel for inheritance-history review.
Parameters
----------
histories : Sequence[Mapping[str, object]]
Inheritance-history records.
Returns
-------
dict[str, object]
A passive Studio panel for inheritance-history review.
"""
normalised_histories = _normalise_intergenerational_inheritance_histories(histories)
child_rows = tuple(
child
for history in normalised_histories
for child in cast(tuple[dict[str, object], ...], history["child_rows"])
)
replay_domains = tuple(
sorted(
{
str(domain)
for history in normalised_histories
for domain in cast(tuple[str, ...], history["replay_domains"])
}
)
)
fitness_scores = tuple(
float(cast(float, row["fitness_score"])) for row in child_rows
)
return {
"panel_kind": "studio_intergenerational_inheritance_panel",
"supervisor": "intergenerational_policy_inheritance",
"history_count": len(normalised_histories),
"claim_boundary": _INTERGENERATIONAL_HISTORY_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"operator_review_required": True,
"direct_hot_patch_permitted": False,
"hot_patch_permitted": False,
"live_merge_permitted": False,
"actuation_permitted": False,
"histories": normalised_histories,
"inheritance_child_rows": child_rows,
"history_record_total": len(child_rows),
"signed_metadata_total": sum(
int(cast(int, history["signed_metadata_count"]))
for history in normalised_histories
),
"replay_domains": replay_domains,
"replay_domain_count": len(replay_domains),
"fitness_range": {
"minimum": min(fitness_scores),
"maximum": max(fitness_scores),
},
"operator_summary": (
"intergenerational inheritance review: "
f"{len(normalised_histories)} history package(s), "
f"{len(child_rows)} signed child record(s), "
f"{len(replay_domains)} replay domain(s)"
),
"operator_action": (
"render as signed inheritance-history evidence only; require "
"separate operator approval before any reviewed hot-patch workflow"
),
}
|
build_morphogenetic_field_studio_panel
build_morphogenetic_field_studio_panel(
svg_artifact: Mapping[str, object],
) -> dict[str, object]
Return a Studio panel payload for morphogenetic field SVG artefacts.
The helper renders already-computed topology-field evidence only. It
validates the dependency-free SVG artefact, preserves the snapshot
statistics and strongest off-diagonal field edges, and keeps actuation
disabled for operator review.
Parameters
svg_artifact : Mapping[str, object]
The morphogenetic field SVG artefact.
Returns
dict[str, object]
A Studio panel payload for morphogenetic field SVG artefacts.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_morphogenetic.py
| def build_morphogenetic_field_studio_panel(
svg_artifact: Mapping[str, object],
) -> dict[str, object]:
"""Return a Studio panel payload for morphogenetic field SVG artefacts.
The helper renders already-computed topology-field evidence only. It
validates the dependency-free SVG artefact, preserves the snapshot
statistics and strongest off-diagonal field edges, and keeps actuation
disabled for operator review.
Parameters
----------
svg_artifact : Mapping[str, object]
The morphogenetic field SVG artefact.
Returns
-------
dict[str, object]
A Studio panel payload for morphogenetic field SVG artefacts.
"""
record = _normalise_morphogenetic_field_svg_artifact(svg_artifact)
snapshot = cast("dict[str, object]", record["snapshot"])
top_edges = cast("tuple[dict[str, object], ...]", snapshot["top_edges"])
strongest_edge = top_edges[0] if top_edges else {}
return {
"panel_kind": "studio_morphogenetic_field_panel",
"renderer": "morphogenetic_field_svg",
"format": "svg",
"width": record["width"],
"height": record["height"],
"shape": snapshot["shape"],
"snapshot": snapshot,
"top_edge_count": len(top_edges),
"strongest_edge": strongest_edge,
"field_energy": {
"mean": snapshot["mean"],
"minimum": snapshot["minimum"],
"maximum": snapshot["maximum"],
"l2_norm": snapshot["l2_norm"],
},
"svg": record["svg"],
"actuation_permitted": False,
"operator_action": (
"render as passive topology-field evidence; review strongest "
"off-diagonal edges before any downstream policy action"
),
}
|
build_multiverse_counterfactual_studio_panel
build_multiverse_counterfactual_studio_panel(
manifest: Mapping[str, object],
risk_report: Mapping[str, object],
) -> dict[str, object]
Return a Studio panel payload for multiverse branch review evidence.
The panel joins a non-actuating rollout manifest with a non-actuating risk
gate report. It validates both audit artefacts before rendering branch
comparison rows, safest-branch metadata, and coherence ranges for operator
review. The helper never emits executable actions.
Parameters
manifest : Mapping[str, object]
The manifest object.
risk_report : Mapping[str, object]
The multiverse risk report mapping.
Returns
dict[str, object]
A Studio panel payload for multiverse branch review evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_multiverse.py
| def build_multiverse_counterfactual_studio_panel(
manifest: Mapping[str, object],
risk_report: Mapping[str, object],
) -> dict[str, object]:
"""Return a Studio panel payload for multiverse branch review evidence.
The panel joins a non-actuating rollout manifest with a non-actuating risk
gate report. It validates both audit artefacts before rendering branch
comparison rows, safest-branch metadata, and coherence ranges for operator
review. The helper never emits executable actions.
Parameters
----------
manifest : Mapping[str, object]
The manifest object.
risk_report : Mapping[str, object]
The multiverse risk report mapping.
Returns
-------
dict[str, object]
A Studio panel payload for multiverse branch review evidence.
"""
rollout = _normalise_multiverse_manifest(manifest)
risk = _normalise_multiverse_risk_report(risk_report)
branch_rows = _join_multiverse_branch_rows(rollout, risk)
final_values = [cast("float", row["final_R"]) for row in branch_rows]
mean_values = [cast("float", row["mean_R"]) for row in branch_rows]
min_values = [cast("float", row["min_R"]) for row in branch_rows]
max_values = [cast("float", row["max_R"]) for row in branch_rows]
rejected_ids = [
cast("str", row["branch_id"])
for row in branch_rows
if row["risk_approved"] is not True
]
return {
"panel_kind": "studio_multiverse_counterfactual_panel",
"simulator": "multiverse_counterfactual",
"risk_gate": "multiverse_branch_risk_gate",
"schema_version": rollout["schema_version"],
"risk_schema_version": risk["schema_version"],
"backend": rollout["backend"],
"horizon": rollout["horizon"],
"branch_count": rollout["branch_count"],
"approved_count": risk["approved_count"],
"rejected_count": risk["rejected_count"],
"safest_branch_id": risk["safest_branch_id"],
"safest_branch_hash": risk["safest_branch_hash"],
"rejected_branch_ids": rejected_ids,
"rejection_reasons": risk["rejection_reasons"],
"manifest_hash": rollout["manifest_hash"],
"risk_report_hash": risk["report_hash"],
"claim_boundary": _MULTIVERSE_ROLLOUT_CLAIM_BOUNDARY,
"risk_claim_boundary": _MULTIVERSE_RISK_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"actuation_permitted": False,
"branch_rows": branch_rows,
"coherence_range": {
"minimum": min(min_values),
"maximum": max(max_values),
"final_minimum": min(final_values),
"final_maximum": max(final_values),
"mean_minimum": min(mean_values),
"mean_maximum": max(mean_values),
},
"operator_summary": (
"multiverse branch review: "
f"{risk['approved_count']}/{rollout['branch_count']} branches approved"
),
"operator_action": (
"render as counterfactual review evidence only; no branch action "
"may be applied without a separate safety-gated control workflow"
),
}
|
build_sheaf_cohomology_studio_panel
build_sheaf_cohomology_studio_panel(
records: Sequence[Mapping[str, object]],
*,
summaries: Sequence[Mapping[str, object]],
control_proposals: Sequence[Mapping[str, object]],
) -> dict[str, object]
Return a Studio panel for sheaf-cohomology review evidence.
The panel renders already-computed sheaf-Laplacian obstruction records,
residual triage summaries, and review-only control proposals. It validates
cohomology dimensions, finite obstruction/energy metrics, residual rows,
disabled execution gates, and monotone accepted projections before exposing
evidence to Studio. No returned field is an executable control channel.
Parameters
records : Sequence[Mapping[str, object]]
The records to summarise.
summaries : Sequence[Mapping[str, object]]
Summary records.
control_proposals : Sequence[Mapping[str, object]]
Sheaf control-proposal records.
Returns
dict[str, object]
A Studio panel for sheaf-cohomology review evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_sheaf.py
| def build_sheaf_cohomology_studio_panel(
records: Sequence[Mapping[str, object]],
*,
summaries: Sequence[Mapping[str, object]],
control_proposals: Sequence[Mapping[str, object]],
) -> dict[str, object]:
"""Return a Studio panel for sheaf-cohomology review evidence.
The panel renders already-computed sheaf-Laplacian obstruction records,
residual triage summaries, and review-only control proposals. It validates
cohomology dimensions, finite obstruction/energy metrics, residual rows,
disabled execution gates, and monotone accepted projections before exposing
evidence to Studio. No returned field is an executable control channel.
Parameters
----------
records : Sequence[Mapping[str, object]]
The records to summarise.
summaries : Sequence[Mapping[str, object]]
Summary records.
control_proposals : Sequence[Mapping[str, object]]
Sheaf control-proposal records.
Returns
-------
dict[str, object]
A Studio panel for sheaf-cohomology review evidence.
"""
normalised_records = _normalise_sheaf_cohomology_records(records)
normalised_summaries, residual_rows = _normalise_sheaf_obstruction_summaries(
summaries
)
normalised_proposals = _normalise_sheaf_control_proposals(control_proposals)
obstruction_scores = [
cast("float", record["obstruction_score"]) for record in normalised_records
]
consistency_energies = [
cast("float", record["consistency_energy"]) for record in normalised_records
]
kernel_dimensions = [
cast("int", record["kernel_dimension"]) for record in normalised_records
]
obstruction_dimensions = [
cast("int", record["obstruction_dimension"]) for record in normalised_records
]
accepted_count = sum(
1
for proposal in normalised_proposals
if proposal["accepted_for_review"] is True
)
critical_count = sum(
1 for summary in normalised_summaries if summary["severity"] == "critical"
)
return {
"panel_kind": "studio_sheaf_cohomology_panel",
"supervisor": "sheaf_cohomology_control",
"claim_boundary": _SHEAF_COHOMOLOGY_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"operator_review_required": True,
"actuation_permitted": False,
"live_merge_permitted": False,
"hot_patch_permitted": False,
"record_count": len(normalised_records),
"summary_count": len(normalised_summaries),
"control_proposal_count": len(normalised_proposals),
"accepted_control_proposal_count": accepted_count,
"critical_summary_count": critical_count,
"records": normalised_records,
"summaries": normalised_summaries,
"control_proposals": normalised_proposals,
"top_residual_rows": residual_rows,
"obstruction_range": {
"minimum": min(obstruction_scores),
"maximum": max(obstruction_scores),
},
"consistency_energy_range": {
"minimum": min(consistency_energies),
"maximum": max(consistency_energies),
},
"cohomology_dimension_range": {
"kernel_minimum": min(kernel_dimensions),
"kernel_maximum": max(kernel_dimensions),
"obstruction_minimum": min(obstruction_dimensions),
"obstruction_maximum": max(obstruction_dimensions),
},
"operator_summary": (
"sheaf-cohomology review: "
f"{len(normalised_records)} obstruction record(s), "
f"{len(residual_rows)} residual edge row(s), "
f"{accepted_count}/{len(normalised_proposals)} accepted proposal(s)"
),
"operator_action": (
"render as non-actuating sheaf-Laplacian obstruction evidence; "
"review residual edges and cohomology-dimension changes before any "
"separately approved operator workflow"
),
}
|
build_strange_loop_studio_panel
build_strange_loop_studio_panel(
records: Sequence[Mapping[str, object]],
) -> dict[str, object]
Return a Studio panel payload for strange-loop drift scenario records.
The panel renders precomputed StrangeLoopSupervisor review evidence.
It does not observe live actions, execute recommendations, or apply control
changes. All scenario records must keep the supervisor's non-actuating
claim boundary and disabled-execution flags intact.
Parameters
records : Sequence[Mapping[str, object]]
The records to summarise.
Returns
dict[str, object]
A Studio panel payload for strange-loop drift scenario records.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_strange_loop.py
| def build_strange_loop_studio_panel(
records: Sequence[Mapping[str, object]],
) -> dict[str, object]:
"""Return a Studio panel payload for strange-loop drift scenario records.
The panel renders precomputed ``StrangeLoopSupervisor`` review evidence.
It does not observe live actions, execute recommendations, or apply control
changes. All scenario records must keep the supervisor's non-actuating
claim boundary and disabled-execution flags intact.
Parameters
----------
records : Sequence[Mapping[str, object]]
The records to summarise.
Returns
-------
dict[str, object]
A Studio panel payload for strange-loop drift scenario records.
"""
normalised_records = _normalise_strange_loop_records(records)
drift_scores = [
cast("float", record["max_drift_score"]) for record in normalised_records
]
oscillation_scores = [
cast("float", record["max_oscillation_score"]) for record in normalised_records
]
overcontrol_scores = [
cast("float", record["max_overcontrol_score"]) for record in normalised_records
]
coherence_scores = [
cast("float", record["min_control_coherence"]) for record in normalised_records
]
failed_ids = [
cast("str", record["scenario_id"])
for record in normalised_records
if record["passed_expected_trigger"] is not True
]
triggered_modes = tuple(
sorted(
{cast("str", record["expected_trigger"]) for record in normalised_records}
)
)
return {
"panel_kind": "studio_strange_loop_panel",
"supervisor": "strange_loop",
"scenario_count": len(normalised_records),
"passed_count": len(normalised_records) - len(failed_ids),
"failed_scenario_ids": failed_ids,
"triggered_modes": triggered_modes,
"claim_boundary": _STRANGE_LOOP_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"actuation_permitted": False,
"series": normalised_records,
"maxima": {
"drift_score": max(drift_scores),
"oscillation_score": max(oscillation_scores),
"overcontrol_score": max(overcontrol_scores),
},
"minima": {
"control_coherence": min(coherence_scores),
},
"operator_summary": (
"strange-loop scenario review: "
f"{len(normalised_records) - len(failed_ids)}/"
f"{len(normalised_records)} expected triggers passed"
),
"operator_action": (
"render as offline supervisor self-control evidence; keep all "
"recommendations behind the normal review and safety gate"
),
}
|
build_topos_semantic_binding_studio_panel
build_topos_semantic_binding_studio_panel(
symbolic_reports: Sequence[Mapping[str, object]],
policy_reports: Sequence[Mapping[str, object]],
*,
examples: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]
Return a Studio panel for Topos semantic-binding evidence.
The helper renders categorical validation reports and deterministic domain
obligations as review evidence only. It validates schema names, proof
boundaries, report hashes, obligation/object/morphism counts, non-actuation
flags, and example hashes before exposing a compact payload to Studio. The
payload intentionally makes no formal Topos proof claim and emits no
executable policy actions.
Parameters
symbolic_reports : Sequence[Mapping[str, object]]
Symbolic-binding reports.
policy_reports : Sequence[Mapping[str, object]]
Policy-composition reports.
examples : Sequence[Mapping[str, object]]
Example records.
Returns
dict[str, object]
A Studio panel for Topos semantic-binding evidence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_topos.py
| def build_topos_semantic_binding_studio_panel(
symbolic_reports: Sequence[Mapping[str, object]],
policy_reports: Sequence[Mapping[str, object]],
*,
examples: Sequence[Mapping[str, object]] = (),
) -> dict[str, object]:
"""Return a Studio panel for Topos semantic-binding evidence.
The helper renders categorical validation reports and deterministic domain
obligations as review evidence only. It validates schema names, proof
boundaries, report hashes, obligation/object/morphism counts, non-actuation
flags, and example hashes before exposing a compact payload to Studio. The
payload intentionally makes no formal Topos proof claim and emits no
executable policy actions.
Parameters
----------
symbolic_reports : Sequence[Mapping[str, object]]
Symbolic-binding reports.
policy_reports : Sequence[Mapping[str, object]]
Policy-composition reports.
examples : Sequence[Mapping[str, object]]
Example records.
Returns
-------
dict[str, object]
A Studio panel for Topos semantic-binding evidence.
"""
normalised_symbolic = _normalise_topos_validation_reports(
symbolic_reports,
schema_name="symbolic_binding_functor",
label="symbolic binding report",
)
normalised_policy = _normalise_topos_validation_reports(
policy_reports,
schema_name="policy_composition_category",
label="policy composition report",
)
normalised_examples, example_rows = _normalise_topos_domain_examples(examples)
all_reports = (*normalised_symbolic, *normalised_policy)
object_counts = [cast("int", report["object_count"]) for report in all_reports]
morphism_counts = [cast("int", report["morphism_count"]) for report in all_reports]
failed_symbolic = [
cast("str", report["report_hash"])
for report in normalised_symbolic
if report["passed"] is not True
]
failed_policy = [
cast("str", report["report_hash"])
for report in normalised_policy
if report["passed"] is not True
]
return {
"panel_kind": "studio_topos_semantic_binding_panel",
"proof_surface": "topos_semantic_binding",
"symbolic_report_count": len(normalised_symbolic),
"policy_report_count": len(normalised_policy),
"example_count": len(normalised_examples),
"passed_symbolic_report_count": len(normalised_symbolic) - len(failed_symbolic),
"passed_policy_report_count": len(normalised_policy) - len(failed_policy),
"failed_symbolic_report_hashes": failed_symbolic,
"failed_policy_report_hashes": failed_policy,
"proof_boundary": _TOPOS_PROOF_BOUNDARY,
"non_actuating": True,
"actuation_permitted": False,
"formal_proof_claim_permitted": False,
"symbolic_reports": normalised_symbolic,
"policy_reports": normalised_policy,
"example_rows": example_rows,
"example_domains": tuple(
sorted({cast("str", example["domain"]) for example in normalised_examples})
),
"object_count_range": {
"minimum": min(object_counts),
"maximum": max(object_counts),
},
"morphism_count_range": {
"minimum": min(morphism_counts),
"maximum": max(morphism_counts),
},
"operator_summary": (
"Topos semantic-binding review: "
f"{len(normalised_symbolic)} symbolic report(s), "
f"{len(normalised_policy)} policy report(s), "
f"{len(normalised_examples)} domain example(s)"
),
"operator_action": (
"render as categorical validation prototype evidence only; preserve "
"the proof boundary and require a separate formal-methods gate "
"before claiming machine-checked Topos proofs or applying policy"
),
}
|
build_twin_confidence_studio_panel
build_twin_confidence_studio_panel(
score_records: Sequence[Mapping[str, object]],
summary_record: Mapping[str, object],
) -> dict[str, object]
Return a Studio panel for digital-twin confidence audit evidence.
The panel consumes the real audit records emitted by
monitor.twin_confidence. It validates score and summary hashes,
cross-checks summary aggregates against the supplied tick records, preserves
calibrated confidence/status evidence, and keeps the operator surface
observability-only: no actuation, hot patch, live merge, or execution gate is
enabled by this payload.
Parameters
score_records : Sequence[Mapping[str, object]]
Chronological TwinConfidenceScore.to_audit_record() mappings.
summary_record : Mapping[str, object]
TwinConfidenceSummary.to_audit_record() mapping for the same score
sequence.
Returns
dict[str, object]
A review-only Studio panel payload for twin-confidence evidence.
Raises
ValueError
If a record is malformed, a hash does not match, or the summary does not
describe the supplied score sequence.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/panel_twin_confidence.py
| def build_twin_confidence_studio_panel(
score_records: Sequence[Mapping[str, object]],
summary_record: Mapping[str, object],
) -> dict[str, object]:
"""Return a Studio panel for digital-twin confidence audit evidence.
The panel consumes the real audit records emitted by
``monitor.twin_confidence``. It validates score and summary hashes,
cross-checks summary aggregates against the supplied tick records, preserves
calibrated confidence/status evidence, and keeps the operator surface
observability-only: no actuation, hot patch, live merge, or execution gate is
enabled by this payload.
Parameters
----------
score_records : Sequence[Mapping[str, object]]
Chronological ``TwinConfidenceScore.to_audit_record()`` mappings.
summary_record : Mapping[str, object]
``TwinConfidenceSummary.to_audit_record()`` mapping for the same score
sequence.
Returns
-------
dict[str, object]
A review-only Studio panel payload for twin-confidence evidence.
Raises
------
ValueError
If a record is malformed, a hash does not match, or the summary does not
describe the supplied score sequence.
"""
scores = _normalise_twin_confidence_scores(score_records)
summary = _normalise_twin_confidence_summary(summary_record)
_require_matching_summary(scores, summary)
latest = scores[-1]
worst = max(
scores,
key=lambda score: (
_STATUS_LEVELS[cast("str", score["status"])],
cast("float", score["composite_z"]),
),
)
backends = tuple(sorted({cast("str", score["backend"]) for score in scores}))
status_counts = {
"healthy": summary["healthy_count"],
"warning": summary["warning_count"],
"critical": summary["critical_count"],
}
return {
"panel_kind": "studio_twin_confidence_panel",
"monitor": "digital_twin_confidence",
"claim_boundary": _TWIN_CONFIDENCE_CLAIM_BOUNDARY,
"non_actuating": True,
"execution_disabled": True,
"actuation_permitted": False,
"live_merge_permitted": False,
"hot_patch_permitted": False,
"score_count": len(scores),
"status_counts": status_counts,
"worst_status_level": _STATUS_LEVELS[cast("str", summary["worst_status"])],
"latest": latest,
"worst": worst,
"summary": summary,
"series": scores,
"backends": backends,
"operator_summary": (
"twin-confidence review: "
f"{summary['tick_count']} scored ticks, worst status "
f"{summary['worst_status']}, latest confidence "
f"{cast('float', summary['latest_confidence']):.6g}"
),
"operator_action": (
"render as digital-twin observability evidence only; investigate "
"warning or critical confidence drift before considering any "
"separate reviewed control action"
),
}
|
run_binding_spec_replay
run_binding_spec_replay(
spec_path: Path, *, steps: int, knobs: StudioKnobState
) -> StudioReplayResult
Run a local binding-spec replay and return Studio-ready payloads.
Parameters
spec_path : Path
Filesystem path to the binding-spec file.
steps : int
Number of replay steps.
knobs : StudioKnobState
The Studio knob state.
Returns
StudioReplayResult
A local binding-spec replay and return Studio-ready payloads.
Raises
ValueError
If the inputs are invalid or inconsistent.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/replay.py
| def run_binding_spec_replay(
spec_path: Path,
*,
steps: int,
knobs: StudioKnobState,
) -> StudioReplayResult:
"""Run a local binding-spec replay and return Studio-ready payloads.
Parameters
----------
spec_path : Path
Filesystem path to the binding-spec file.
steps : int
Number of replay steps.
knobs : StudioKnobState
The Studio knob state.
Returns
-------
StudioReplayResult
A local binding-spec replay and return Studio-ready payloads.
Raises
------
ValueError
If the inputs are invalid or inconsistent.
"""
if isinstance(steps, bool) or not isinstance(steps, int) or steps < 1:
raise ValueError("steps must be a positive integer")
from scpn_phase_orchestrator.runtime.server import SimulationState
spec = load_binding_spec(spec_path)
sim: _ReplaySimulationState = SimulationState(spec)
_apply_replay_knobs(sim, knobs)
r_history: list[float] = []
regime_history: list[str] = []
final_state: Mapping[str, object] = sim.snapshot()
for _ in range(steps):
final_state = sim.step()
r_history.append(_finite_number(final_state["R_global"], "R_global"))
regime_history.append(_require_non_empty_text(final_state["regime"], "regime"))
runtime = build_runtime_snapshot(
final_state=final_state,
knobs=knobs,
replay_status="completed",
)
project_state = binding_spec_project_state(
project_name=spec.name,
spec_path=spec_path,
knobs=knobs,
runtime=runtime,
)
return StudioReplayResult(
project_state=project_state,
r_history=tuple(r_history),
regime_history=tuple(regime_history),
layer_table=build_layer_table(spec),
oscillator_table=build_oscillator_table(spec),
canvas_graph=build_canvas_graph(spec),
connector_plan=build_live_connector_plan(spec),
export_manifests=project_state.exports,
)
|
build_layer_table
build_layer_table(
spec: BindingSpec,
) -> tuple[dict[str, object], ...]
Return editable layer rows for the Studio oscillator canvas.
Parameters
spec : BindingSpec
The binding specification.
Returns
tuple[dict[str, object], ...]
Editable layer rows for the Studio oscillator canvas.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/tables.py
| def build_layer_table(spec: BindingSpec) -> tuple[dict[str, object], ...]:
"""Return editable layer rows for the Studio oscillator canvas.
Parameters
----------
spec : BindingSpec
The binding specification.
Returns
-------
tuple[dict[str, object], ...]
Editable layer rows for the Studio oscillator canvas.
"""
return tuple(
{
"index": int(layer.index),
"name": layer.name,
"oscillator_count": len(layer.oscillator_ids),
"family": layer.family or "",
"omega_count": len(layer.omegas or ()),
}
for layer in sorted(spec.layers, key=lambda item: item.index)
)
|
build_oscillator_table
build_oscillator_table(
spec: BindingSpec,
) -> tuple[dict[str, object], ...]
Return oscillator rows suitable for Streamlit data editing.
Parameters
spec : BindingSpec
The binding specification.
Returns
tuple[dict[str, object], ...]
Oscillator rows suitable for Streamlit data editing.
Source code in src/scpn_phase_orchestrator/studio/ui_helpers/tables.py
| def build_oscillator_table(spec: BindingSpec) -> tuple[dict[str, object], ...]:
"""Return oscillator rows suitable for Streamlit data editing.
Parameters
----------
spec : BindingSpec
The binding specification.
Returns
-------
tuple[dict[str, object], ...]
Oscillator rows suitable for Streamlit data editing.
"""
family_channels = {
family_name: family.channel
for family_name, family in spec.oscillator_families.items()
}
rows: list[dict[str, object]] = []
for layer in sorted(spec.layers, key=lambda item: item.index):
channel = family_channels.get(layer.family or "", "")
for oscillator_id in layer.oscillator_ids:
rows.append(
{
"layer": layer.name,
"layer_index": int(layer.index),
"oscillator_id": oscillator_id,
"family": layer.family or "",
"channel": channel,
}
)
return tuple(rows)
|
STUDIO federation manifest
federation_manifest builds the schema-A CapabilityManifest the SCPN STUDIO
Hub ingests (scpn-studio-platform): the verbs SPO exposes and their honesty
attributes (safety tier, side effect, timing, fidelity, proof, produces,
backends). It is distinct from tools/capability_manifest.py, which generates
the repository's static public inventory. Honesty is built in by construction —
no verb is live-hardware, none claims a discharged formal proof, and the
safety tier is research. Requires the studio optional extra. The manifest's
ui_module names the federated remote built in studio-web/
(STUDIO_FEDERATION_NAME, STUDIO_EXPOSED_MODULE, STUDIO_REMOTE_ENTRY).
federation_manifest
Build the SCPN STUDIO federation CapabilityManifest for SPO.
This emits the schema-A capability manifest the SCPN STUDIO Hub ingests
(scpn-studio-platform), describing the verbs SPO exposes and their honesty
attributes (safety tier, side effect, timing, fidelity, proof, produces,
backends). It is distinct from tools/capability_manifest.py, which generates
the repository's static public inventory.
Honesty is built in by construction: SPO is review-only, so no verb is
live-hardware; SPO exports PRISM/TLA+ models but does not discharge them to a
proven depth, so no verb claims a formal proof; and the safety tier is
research rather than certified/production because SPO is a
research-grade toolkit, not a certified product. The platform SDK is an optional
dependency (the studio extra); importing this module without it raises a
clear error.
The manifest declares the federated UI remote through ui_module: the panel
built in studio-web/ and pull-deployed to the studio's own space. Its
federation name, exposed module, and remote-entry URL
(:data:STUDIO_FEDERATION_NAME, :data:STUDIO_EXPOSED_MODULE,
:data:STUDIO_REMOTE_ENTRY) are the contract with
studio-web/module-federation.config.ts and must match it exactly.
Functions:
build_capability_manifest
build_capability_manifest(
*, studio_version: str
) -> _CapabilityManifest
Construct SPO's STUDIO federation CapabilityManifest.
Parameters
studio_version : str
The SPO package version stamped into the manifest.
Returns
CapabilityManifest
The schema-A manifest describing SPO's verbs and honesty attributes.
Raises
RuntimeError
If the scpn-studio-platform SDK is not installed.
Source code in src/scpn_phase_orchestrator/studio/federation_manifest.py
| def build_capability_manifest(*, studio_version: str) -> _CapabilityManifest:
"""Construct SPO's STUDIO federation `CapabilityManifest`.
Parameters
----------
studio_version : str
The SPO package version stamped into the manifest.
Returns
-------
CapabilityManifest
The schema-A manifest describing SPO's verbs and honesty attributes.
Raises
------
RuntimeError
If the ``scpn-studio-platform`` SDK is not installed.
"""
_require_sdk()
verbs = _verbs()
evidence_types = LIVE_FEED_EVIDENCE_SCHEMAS
digest = _manifest_content_digest(verbs, evidence_types)
return CapabilityManifest(
studio="scpn-phase-orchestrator",
studio_version=studio_version,
platform_sdk=_PLATFORM_SDK,
content_digest=digest,
protocol_version=_PROTOCOL_VERSION,
transport_profile=TransportProfile.LOCAL_FIRST,
verbs=verbs,
evidence_types=evidence_types,
external_reference_datasets=(),
ui_module=UiModule(
remote_entry=STUDIO_REMOTE_ENTRY,
exposes=(STUDIO_EXPOSED_MODULE,),
federation=STUDIO_FEDERATION_NAME,
),
contract_era="v1",
enumeration="language-agnostic",
)
|
manifest_dict
manifest_dict(*, studio_version: str) -> dict[str, object]
Return the federation manifest as a JSON-serialisable dict.
Parameters
studio_version : str
The SPO package version stamped into the manifest.
Returns
dict[str, object]
CapabilityManifest.to_dict() output.
Source code in src/scpn_phase_orchestrator/studio/federation_manifest.py
| def manifest_dict(*, studio_version: str) -> dict[str, object]:
"""Return the federation manifest as a JSON-serialisable dict.
Parameters
----------
studio_version : str
The SPO package version stamped into the manifest.
Returns
-------
dict[str, object]
``CapabilityManifest.to_dict()`` output.
"""
result: dict[str, object] = build_capability_manifest(
studio_version=studio_version
).to_dict()
return result
|
STUDIO panel data
panel_data assembles the honest data the federated studio panel
(studio-web/) renders: the evidence-coverage map. For each of SPO's six
assurance evidence categories it lists the EU AI Act, ISO/IEC 42001 and
ANSI/UL 4600 clauses the category contributes to, with the addressed /
partially_addressed status taken verbatim from the assurance-case clause map
(assurance.case.DEFAULT_EVIDENCE_CLAUSE_MAP), so the panel restates the
repository's own self-description rather than a hand-authored copy. The rendered
JSON snapshot is committed at studio-web/src/panel/evidence_coverage.json and
regenerated by tools/build_studio_panel_data.py; a drift-guard test keeps the
two in lock-step. Unlike federation_manifest, this module needs no optional
extra — it reads only the in-tree assurance surface.
panel_data
Assemble the honest data the SPO STUDIO federation panel renders.
The federated studio panel (studio-web/) is a pure renderer: it never
computes and never upgrades a claim. Its one committed data surface is the
evidence-coverage map — for each of SPO's six assurance evidence categories
(:data:~scpn_phase_orchestrator.assurance.evidence.EVIDENCE_CATEGORIES), the
regulatory clauses that category contributes to and whether the contribution is
addressed or partially_addressed. The map is the same one the
assurance-case bundle uses
(:data:~scpn_phase_orchestrator.assurance.case.DEFAULT_EVIDENCE_CLAUSE_MAP),
so the panel restates the repository's own honest self-description rather than a
hand-authored copy that could drift.
The panel bundle is inlined into the JavaScript remote at build time as
studio-web/src/panel/evidence_coverage.json; :func:render_panel_data_json
produces that file and a drift-guard test asserts the committed snapshot equals
the live producer output, keeping the two in lock-step.
Attributes
STUDIO_ID
module-attribute
STUDIO_ID = 'scpn-phase-orchestrator'
The stable federation id, matching the STUDIO capability manifest.
PANEL_DATA_SCHEMA
module-attribute
PANEL_DATA_SCHEMA = 'spo.studio.evidence-coverage.v1'
Schema identifier for the panel evidence-coverage payload.
Functions:
build_evidence_coverage_panel
build_evidence_coverage_panel() -> dict[str, object]
Return the JSON-serialisable evidence-coverage panel payload.
For every assurance evidence category, the payload lists the regulatory
clauses the category contributes to — resolved to their catalogued standard,
identifier and official title — with the addressed /
partially_addressed status and rationale taken verbatim from
:data:~scpn_phase_orchestrator.assurance.case.DEFAULT_EVIDENCE_CLAUSE_MAP.
A summary block totals the categories, clause mappings, and coverage status
counts, and names the standards spanned.
Returns
dict[str, object]
The panel payload: schema, studio, disclaimer, ordered
categories (each with its clauses and per-category counts), and a
summary.
Raises
ValueError
If :data:_CATEGORY_ORDER has drifted from the clause-map key set, so a
renamed or added category can never silently drop from the panel.
Source code in src/scpn_phase_orchestrator/studio/panel_data.py
| def build_evidence_coverage_panel() -> dict[str, object]:
"""Return the JSON-serialisable evidence-coverage panel payload.
For every assurance evidence category, the payload lists the regulatory
clauses the category contributes to — resolved to their catalogued standard,
identifier and official title — with the ``addressed`` /
``partially_addressed`` status and rationale taken verbatim from
:data:`~scpn_phase_orchestrator.assurance.case.DEFAULT_EVIDENCE_CLAUSE_MAP`.
A summary block totals the categories, clause mappings, and coverage status
counts, and names the standards spanned.
Returns
-------
dict[str, object]
The panel payload: ``schema``, ``studio``, ``disclaimer``, ordered
``categories`` (each with its ``clauses`` and per-category counts), and a
``summary``.
Raises
------
ValueError
If :data:`_CATEGORY_ORDER` has drifted from the clause-map key set, so a
renamed or added category can never silently drop from the panel.
"""
if set(_CATEGORY_ORDER) != set(DEFAULT_EVIDENCE_CLAUSE_MAP):
raise ValueError(
"the studio panel category order has drifted from the assurance "
"clause map; align _CATEGORY_ORDER with DEFAULT_EVIDENCE_CLAUSE_MAP"
)
categories: list[dict[str, object]] = []
standards_covered: set[str] = set()
total_addressed = 0
total_partial = 0
total_mappings = 0
for category in _CATEGORY_ORDER:
clause_records: list[dict[str, str]] = []
addressed = 0
partial = 0
for key, status, rationale in DEFAULT_EVIDENCE_CLAUSE_MAP[category]:
clause = clause_for_key(key)
clause_records.append(
{
"standard": clause.standard,
"clause_id": clause.clause_id,
"title": clause.title,
"status": status,
"rationale": rationale,
}
)
standards_covered.add(clause.standard)
if status == ADDRESSED:
addressed += 1
elif status == PARTIALLY_ADDRESSED:
partial += 1
total_addressed += addressed
total_partial += partial
total_mappings += len(clause_records)
categories.append(
{
"category": category,
"clause_count": len(clause_records),
"addressed_count": addressed,
"partially_addressed_count": partial,
"clauses": clause_records,
}
)
summary: dict[str, object] = {
"category_count": len(categories),
"clause_mapping_count": total_mappings,
"addressed_count": total_addressed,
"partially_addressed_count": total_partial,
"standards_covered": sorted(standards_covered),
}
return {
"schema": PANEL_DATA_SCHEMA,
"studio": STUDIO_ID,
"disclaimer": REGULATORY_DISCLAIMER,
"categories": categories,
"summary": summary,
}
|
render_panel_data_json
render_panel_data_json() -> str
Return the panel payload as a canonical, human-diffable JSON document.
The document is indented two spaces, keeps non-ASCII characters verbatim, and
ends with a trailing newline, matching the committed
studio-web/src/panel/evidence_coverage.json snapshot.
Returns
str
The rendered JSON document with a trailing newline.
Source code in src/scpn_phase_orchestrator/studio/panel_data.py
| def render_panel_data_json() -> str:
"""Return the panel payload as a canonical, human-diffable JSON document.
The document is indented two spaces, keeps non-ASCII characters verbatim, and
ends with a trailing newline, matching the committed
``studio-web/src/panel/evidence_coverage.json`` snapshot.
Returns
-------
str
The rendered JSON document with a trailing newline.
"""
return (
json.dumps(build_evidence_coverage_panel(), indent=2, ensure_ascii=False) + "\n"
)
|