Research-Stack/4-Infrastructure/shim/magnetic_derivative_kernel_probe.py
2026-05-11 22:18:31 -05:00

335 lines
12 KiB
Python

#!/usr/bin/env python3
"""Receipt-backed magnetic derivative kernel probe.
This probe adds a small magnetic-domain route surface for the cross-domain
kernel library. It admits only exact local algebra/vector fixtures and keeps
field-equation, gauge, boundary, and material-model claims in HOLD.
"""
from __future__ import annotations
import hashlib
import json
from datetime import datetime, timezone
from fractions import Fraction
from pathlib import Path
from typing import Any
REPO = Path(__file__).resolve().parents[2]
OUT_DIR = REPO / "shared-data" / "data" / "magnetic_derivative_kernels"
REGISTRY = OUT_DIR / "magnetic_derivative_kernel_registry.json"
RECEIPT = OUT_DIR / "magnetic_derivative_kernel_receipt.json"
SUMMARY = OUT_DIR / "magnetic_derivative_kernel.md"
SOURCE_REFS = [
REPO / "shared-data/data/mass_number_transform_registry/mass_number_transform_registry_receipt.json",
REPO / "shared-data/data/cross_domain_kernel_adapters/cross_domain_kernel_adapter_registry_receipt.json",
]
Vector = tuple[Fraction, Fraction, Fraction]
def stable_json(obj: Any) -> str:
return json.dumps(obj, sort_keys=True, separators=(",", ":"), ensure_ascii=True)
def sha256_bytes(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
def hash_obj(obj: Any) -> str:
return sha256_bytes(stable_json(obj).encode("utf-8"))
def rel(path: Path) -> str:
try:
return str(path.relative_to(REPO))
except ValueError:
return str(path)
def file_hash(path: Path) -> str | None:
return sha256_bytes(path.read_bytes()) if path.exists() else None
def source_ref(path: Path) -> dict[str, Any]:
return {"path": rel(path), "exists": path.exists(), "sha256": file_hash(path)}
def frac_payload(value: Fraction | Vector) -> Any:
if isinstance(value, tuple):
return [frac_payload(item) for item in value]
return {"numerator": value.numerator, "denominator": value.denominator, "decimal": float(value)}
def mn(a: Fraction, b: Fraction) -> Fraction:
return (a - b) / (a + b)
def magnetic_pressure(B: Fraction, mu: Fraction) -> Fraction:
return B * B / (2 * mu)
def d_magnetic_pressure_dB(B: Fraction, mu: Fraction) -> Fraction:
return B / mu
def scalar_dipole_force(moment: Fraction, dBdx: Fraction) -> Fraction:
return moment * dBdx
def cross(a: Vector, b: Vector) -> Vector:
ax, ay, az = a
bx, by, bz = b
return ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx
def lorentz_magnetic_force(charge: Fraction, velocity: Vector, B: Vector) -> Vector:
vxB = cross(velocity, B)
return tuple(charge * item for item in vxB) # type: ignore[return-value]
def check_equal(name: str, compressed: Any, direct: Any) -> dict[str, Any]:
return {
"name": name,
"compressed": frac_payload(compressed),
"direct": frac_payload(direct),
"pass": compressed == direct,
}
def entry(
*,
entry_id: str,
kernel_opcode: str,
magnetic_role: str,
compressed_form: str,
expanded_form: str,
checks: list[dict[str, Any]],
decision: str,
residual_policy: str,
) -> dict[str, Any]:
item = {
"entry_id": entry_id,
"kernel_opcode": kernel_opcode,
"magnetic_role": magnetic_role,
"compressed_form": compressed_form,
"expanded_form": expanded_form,
"checks": checks,
"all_checks_pass": all(check.get("pass", False) for check in checks) if checks else None,
"decision": decision,
"residual_policy": residual_policy,
"claim_boundary": "magnetic route fixture only; not a Maxwell solver or material model",
}
item["entry_hash"] = hash_obj({k: v for k, v in item.items() if k != "entry_hash"})
return item
def build_registry() -> dict[str, Any]:
B = Fraction(3)
mu = Fraction(2)
moment = Fraction(5)
dBdx = Fraction(7, 3)
charge = Fraction(2)
velocity: Vector = (Fraction(1), Fraction(2), Fraction(3))
field: Vector = (Fraction(5), Fraction(-1), Fraction(4))
mu1 = Fraction(3)
mu2 = Fraction(8)
entries = [
entry(
entry_id="magnetic_pressure_derivative",
kernel_opcode="DERIV_QUADRATIC",
magnetic_role="local derivative of magnetic pressure density with respect to field magnitude",
compressed_form="d/dB [B^2/(2*mu)] = B/mu",
expanded_form="P_B = B^2/(2*mu)",
checks=[
check_equal(
"dP_dB_B3_mu2",
d_magnetic_pressure_dB(B, mu),
(magnetic_pressure(B + Fraction(1), mu) - magnetic_pressure(B - Fraction(1), mu)) / 2,
)
],
decision="ACCEPT_DERIVATIVE_FIXTURE",
residual_policy="scalar uniform-mu fixture only; spatial fields require gradient, units, geometry, and boundary receipts",
),
entry(
entry_id="scalar_dipole_gradient_force",
kernel_opcode="DERIV_LINEAR",
magnetic_role="one-dimensional projection of dipole force from potential gradient",
compressed_form="F_x = m * dB/dx",
expanded_form="U = -m*B(x); F_x = -dU/dx",
checks=[check_equal("dipole_force_m5_dBdx7_3", scalar_dipole_force(moment, dBdx), Fraction(35, 3))],
decision="ACCEPT_DERIVATIVE_FIXTURE",
residual_policy="1D aligned-dipole fixture only; vector dipole orientation and material response require adapter receipts",
),
entry(
entry_id="lorentz_magnetic_cross_product",
kernel_opcode="CROSS_PRODUCT",
magnetic_role="magnetic part of Lorentz force as a vector cross-product kernel",
compressed_form="F_B = q * cross(v,B)",
expanded_form="F = q*(v x B)",
checks=[
check_equal(
"lorentz_q2_v123_B5neg14",
lorentz_magnetic_force(charge, velocity, field),
(Fraction(22), Fraction(22), Fraction(-22)),
)
],
decision="ACCEPT_VECTOR_FIXTURE",
residual_policy="magnetic-only vector fixture; electric field term, relativistic conventions, and units remain adapter data",
),
entry(
entry_id="permeability_boundary_contrast",
kernel_opcode="MN_REFLECT",
magnetic_role="two-permeability boundary contrast candidate",
compressed_form="Gamma_mu = MN(mu2,mu1)",
expanded_form="Gamma_mu = (mu2-mu1)/(mu2+mu1)",
checks=[check_equal("mn_mu8_3", mn(mu2, mu1), Fraction(5, 11))],
decision="ACCEPT_KERNEL_ADAPTER",
residual_policy="exact contrast only; electromagnetic boundary conditions, orientation, and sign convention still require domain receipt",
),
entry(
entry_id="alfven_speed_route",
kernel_opcode="ANALYTIC_SQRT_RATIO",
magnetic_role="MHD speed route with square-root denominator",
compressed_form="v_A = B / sqrt(mu*rho)",
expanded_form="Alfven speed candidate",
checks=[],
decision="HOLD_ANALYTIC_ADAPTER",
residual_policy="requires square-root precision, units, density/permeability source, and MHD assumptions",
),
entry(
entry_id="faraday_time_derivative",
kernel_opcode="CURL_TIME_DERIVATIVE",
magnetic_role="field equation route for induction",
compressed_form="curl(E) = -dB/dt",
expanded_form="Faraday induction law candidate",
checks=[],
decision="HOLD_FIELD_EQUATION",
residual_policy="requires orientation, gauge/sign convention, boundary conditions, discretization, and source receipt",
),
entry(
entry_id="ampere_current_derivative",
kernel_opcode="CURL_SOURCE_ADAPTER",
magnetic_role="field equation route for current source",
compressed_form="curl(B) -> mu*J plus displacement-current policy",
expanded_form="Ampere-Maxwell route candidate",
checks=[],
decision="HOLD_FIELD_EQUATION",
residual_policy="requires unit system, displacement-current policy, material model, boundary conditions, and source receipt",
),
entry(
entry_id="magnetic_susceptibility_contrast",
kernel_opcode="MN",
magnetic_role="bounded contrast over two susceptibilities or magnetizations",
compressed_form="MN(chi2,chi1) or MN(M2,M1)",
expanded_form="relative contrast between magnetic response lanes",
checks=[],
decision="HOLD_MATERIAL_ADAPTER",
residual_policy="requires material law, linearity range, hysteresis policy, and measurement receipt",
),
]
return {
"schema": "magnetic_derivative_kernel_registry_v1",
"claim_boundary": (
"Magnetic derivative route registry only. Exact scalar/vector algebra "
"fixtures may be accepted, but Maxwell/MHD/material claims stay HOLD "
"until units, gauge/sign conventions, boundary conditions, source data, "
"and residual policies are receipted."
),
"canonical_statement": (
"Magnetic equations expose reusable derivative, contrast, and cross-product "
"kernels, but field truth lives behind adapter closure."
),
"entries": entries,
"entry_count": len(entries),
"status_counts": {
status: sum(1 for item in entries if item["decision"] == status)
for status in sorted({item["decision"] for item in entries})
},
}
def build_receipt(registry: dict[str, Any]) -> dict[str, Any]:
accepted_statuses = {"ACCEPT_DERIVATIVE_FIXTURE", "ACCEPT_VECTOR_FIXTURE", "ACCEPT_KERNEL_ADAPTER"}
accepted_checks_pass = all(
item["all_checks_pass"] is True
for item in registry["entries"]
if item["decision"] in accepted_statuses
)
receipt = {
"schema": "magnetic_derivative_kernel_receipt_v1",
"generated_at_utc": datetime.now(timezone.utc).isoformat(),
"timestamp_role": "metadata_only",
"generated_at_utc_included_in_receipt_hash": False,
"registry_path": rel(REGISTRY),
"registry_hash": hash_obj(registry),
"source_refs": [source_ref(path) for path in SOURCE_REFS],
"entry_count": registry["entry_count"],
"status_counts": registry["status_counts"],
"accepted_checks_pass": accepted_checks_pass,
"decision": "HOLD_MAGNETIC_DOMAIN_WITH_ACCEPTED_FIXTURES" if accepted_checks_pass else "HOLD_DIAGNOSTIC",
"claim_boundary": registry["claim_boundary"],
}
receipt["receipt_hash"] = sha256_bytes(
stable_json({k: v for k, v in receipt.items() if k not in {"receipt_hash", "generated_at_utc"}}).encode("utf-8")
)
return receipt
def write_summary(registry: dict[str, Any], receipt: dict[str, Any]) -> None:
lines = [
"# Magnetic Derivative Kernel Probe",
"",
f"Decision: `{receipt['decision']}` ",
f"Receipt hash: `{receipt['receipt_hash']}`",
"",
registry["claim_boundary"],
"",
"## Canonical Statement",
"",
registry["canonical_statement"],
"",
"## Entry Table",
"",
"| Entry | Kernel | Decision | Role |",
"|---|---|---|---|",
]
for item in registry["entries"]:
lines.append(
f"| `{item['entry_id']}` | `{item['kernel_opcode']}` | "
f"`{item['decision']}` | {item['magnetic_role']} |"
)
lines.extend(["", "## Guardrail", "", registry["claim_boundary"]])
SUMMARY.write_text("\n".join(lines) + "\n", encoding="utf-8")
def main() -> int:
OUT_DIR.mkdir(parents=True, exist_ok=True)
registry = build_registry()
receipt = build_receipt(registry)
REGISTRY.write_text(json.dumps(registry, indent=2, sort_keys=True) + "\n", encoding="utf-8")
RECEIPT.write_text(json.dumps(receipt, indent=2, sort_keys=True) + "\n", encoding="utf-8")
write_summary(registry, receipt)
print(
json.dumps(
{
"registry": rel(REGISTRY),
"receipt": rel(RECEIPT),
"summary": rel(SUMMARY),
"receipt_hash": receipt["receipt_hash"],
"decision": receipt["decision"],
"status_counts": registry["status_counts"],
},
indent=2,
sort_keys=True,
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())