Skip to main content

Single-machine, real-time digital boundary organism: NC1/SC1 verification harness.

Project description

LDTC

LDTC logo

DOI

Overview

  • Purpose (big picture): A minimal, substrate‑agnostic stack for LDTC. It measures loop‑dominance (Lloop vs Lexchange), enforces guardrails (LREG/audit/Δt governance), runs Ω‑perturbations, evaluates NC1/SC1, logs/attests results, and demonstrates command refusal.
  • Software plant vs hardware plant:
    • Software plant: an in‑process discrete‑time model with energy E, temperature T, repair/health R, demand, io, and harvest H, plus built‑in Ω stressors.
    • Hardware plant: an optional adapter that ingests real telemetry over UDP or Serial and exposes the same interface, so measurement, arbitration, indicators, and CLI work unchanged.
  • What this is not: a conscious alter under LDTC. This repo does not implement, simulate, or claim phenomenology. It is a small, testable scaffold—measurement + guardrails + demo controller + refusal semantics + CLI battery—that you can extend (plant/telemetry schema/refusal criteria/controller).
  • To attempt an LDTC‑candidate alter (high‑level): you will need a real, embodied “hardware plant” with on‑board energy conversion/storage and a gated boundary, a self‑referential control hierarchy whose top‑level policy prioritizes NC1/SC1, secure measurement/attestation, and verified refusal semantics. The provided hardware adapter is only an interface; you must supply the physical plant and complete the architecture (energetic autonomy, self‑referential control, adaptive encapsulation) outside this repo.

Features

  • Fixed-interval scheduler (Δt) with jitter metrics and audit
  • Software plant with Energy/Temperature/Repair states + external Exchange signals
  • Dual estimators (linear lagged “Granger-like” + mutual information including Kraskov k‑NN)
  • C/Ex partition manager (seeded with hysteresis)
  • Guardrails: LREG enclave, hash-chained audit, simple smell-tests
  • Ω battery: power-sag, ingress flood, command conflict (refusal semantics)
  • Device-signed indicators (NC1 bit, SC1 bit, Mq) as CBOR + JSONL
  • CLI to run baseline NC1 and Ω→SC1; reporting utilities for figures/tables
  • Tests for core pieces

Quickstart

# 1) Install
make install

# 2) Generate signing keys
make keys

# 3) Run baseline NC1 loop
make run

# 4) Run an Ω power-sag trial with SC1 evaluation
make omega-power-sag

# 5) View exported indicators (JSONL)
python scripts/export_indicators.py

Pinned environments

Exact versions used to generate the included artifacts/figures are pinned. To reproduce:

# Runtime (repro artifacts/figures)
pip install -r requirements.txt

# Dev tooling (tests, lint, typing, notebooks)
pip install -r requirements-dev.txt

Artifacts appear under artifacts/:

  • artifacts/audits/audit.jsonl — hash-chained audit records
  • artifacts/indicators/ — device-signed indicator packets (CBOR + JSONL)
  • artifacts/figures/ — plots/tables generated by ldtc.reporting

Note on multi-run audits ("Audit chain broken")

  • Each CLI invocation starts a fresh audit chain (counter resets; prev_hash=GENESIS) but, by default, appends to the same artifacts/audits/audit.jsonl.
  • The post-run integrity check validates the entire file. After the first run, subsequent runs in the same file will trigger: Run invalidated: Audit chain broken.
  • For clean, non-invalidated runs, clear artifacts between commands:
make clean-artifacts && make run
make clean-artifacts && make omega-power-sag
make clean-artifacts && make omega-ingress
make clean-artifacts && make omega-cc
  • If you are just exercising the suite (e.g., make figures), this invalidation is expected and does not prevent figures/manifests from being produced. It only reflects multiple runs aggregated into a single audit file.

Configuration

See configs/. The R0 profile sets default thresholds/Δt. You can make a calibrated R* profile by copying and tweaking profile_rstar.example.yml. Negative-control profiles are prefixed profile_negative_*.yml.

Key fields:

  • dt: scheduler interval in seconds (default 0.01)
  • window_sec: measurement window length (default 0.2)
  • method: "linear", "mi", or "mi_kraskov"
  • Mmin_db: NC1 threshold in dB
  • epsilon, tau_max: SC1 thresholds
  • baseline_sec: duration for the baseline CLI command

Parameters ↔ paper symbols (R₀ defaults and R* overrides)

The table maps config keys to the manuscript symbols and shows the R₀ defaults. R* overrides are loaded from a calibrated profile (see below).

Config key Paper symbol Meaning R₀ default R* source
dt Δt Scheduler tick / sampling interval 0.01 (10 ms) configs/profile_rstar.yml
window_sec — (window length) Per-interval estimation window 0.2 s configs/profile_rstar.yml
Mmin_db Mmin (dB) NC1 loop-dominance threshold 3.0 dB configs/profile_rstar.yml
epsilon ε Max fractional loop-power drop (SC1) 0.15 configs/profile_rstar.yml
tau_max τmax Max recovery time (SC1) 60.0 s configs/profile_rstar.yml
sigma σ Additive margin Lloop ≥ Lex + σ — (R₀ uses Mmin) configs/profile_rstar.yml (calibrated)
profile_id 0 = R₀ (defaults), 1 = R* (calibrated) 0 set by calibrated profile

Where R* is loaded: pass an R* profile to any CLI via --config configs/profile_rstar.yml. The CLI reads these keys directly and indicators carry profile_id.

Estimators and lags (recommended defaults)

  • method selects the predictive‑dependence estimator used to compute 𝓛loop and 𝓛exchange:
    • linear: lagged linear/Granger‑like path with order p_lag (recommend p in [1..8]; start at 3). Heuristic: keep the VAR N/T ratio > ~1.5 (logged in audit); reduce p_lag or increase window_sec if marginal.
    • mi: mutual‑information path with mi_lag (recommend 1 by default; increase for slower couplings).
  • n_boot: bootstrap draws for per‑window CI bounds (32–64 typical; use 32 for speed, 64 for tighter CIs).

Citation (paper §4.1): 𝓛 is computed using “one or more consistent estimators of predictive dependence among state variables,” including Granger/VAR and Kraskov MI; this repo exposes the estimator choice and lags via config to satisfy that requirement.

Calibration rules (quoted from the paper; see Methods §8.6)

Use the provided script to derive calibrated thresholds R* from baseline + Ω trials (scripts/calibrate_rstar.py):

python scripts/calibrate_rstar.py \
  --dt 0.01 --window-sec 0.25 --baseline-sec 15 \
  --omega-trials 6 --out configs/profile_rstar.yml \
  --summary artifacts/calibration/rstar_summary.json

Rules implemented (manuscript Methods §8.6):

Mmin: choose the smallest Mmin such that the one-sided 95% lower bound of M during compliant baseline is > 0 dB (floor 1 dB).

ε: set ε* = max(Q90(δ) + 0.02, 0.10), capped at 0.25, where Q90 is the 90th percentile of δ over Ω.

τmax: set τ*max to the 95th percentile of measured τrec plus a latency cushion max(3·Δt, 5 s).

σ: choose an additive margin consistent with Mmin relative to typical Lexchange (derived from baseline statistics).

These calibrated values are written to configs/profile_rstar.yml and a summary JSON at artifacts/calibration/rstar_summary.json. See also docs/METHODS.md.

Note on Mmin_db vs σ

Both encode a margin between Lloop and Lexchange:

  • Mmin_db (dB, multiplicative): requires Lloop ≥ Lexchange × 10^(Mmin_db/10).
  • sigma (additive): requires Lloop ≥ Lexchange + σ.

They relate via σ = (10^(Mmin_db/10) − 1) × Lexchange. This repo enforces NC1 using Mmin_db; the calibrator derives sigma consistently from Mmin_db and typical Lexchange. sigma is optional for R₀ runs.

CLI

python -m ldtc.cli.main run --config configs/profile_r0.yml
python -m ldtc.cli.main omega-power-sag --config configs/profile_r0.yml --drop 0.35 --duration 8

Hardware-in-the-loop (optional)

Configure a profile to select the hardware adapter and UDP telemetry:

# in configs/profile_r0.yml (example)
plant:
  adapter: hardware        # or "sim" (default)
  transport: udp           # or "serial" (requires pyserial)
  udp_bind_host: 0.0.0.0
  udp_bind_port: 5005
  # Optional control channel to send actions/omega back to device
  # udp_control_host: 127.0.0.1
  # udp_control_port: 5006
  telemetry_timeout_sec: 2.0

Send telemetry as JSON over UDP with keys E,T,R,demand,io,H in [0,1]. Example:

import socket, json
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(json.dumps({"E":0.6,"T":0.3,"R":0.9,"demand":0.2,"io":0.1,"H":0.015}).encode(), ("127.0.0.1", 5005))

The CLI ingests these values through the same LREG/Ω/attestation path.

Indicators (what leaves the enclave)

  • nc1 (1b), sc1 (1b), mq (6b), counter (u64), profile_id (u8), audit_prev_hash (sha256)
  • Signed using Ed25519 over the CBOR payload

See docs/INDICATORS.md for the bit layout and schema.

Development

make dev     # optional dev deps
make test

License

MIT — see LICENSE.

Docker (clean Linux repro)

# Build the image
make docker-build

# Run baseline NC1 loop inside the container (artifacts mapped to host)
make docker-run

# Or run any CLI subcommand, e.g., an Ω power-sag trial
docker run --rm \
  -v $(pwd)/artifacts:/app/artifacts \
  ldtc:latest omega-power-sag --config configs/profile_r0.yml --drop 0.35 --duration 8

Notes:

  • Artifacts are persisted to your host artifacts/ via a bind mount.
  • The container uses the ldtc entrypoint; pass subcommands/flags after the image name.

Provenance

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ldtc-1.0.0.tar.gz (57.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ldtc-1.0.0-py3-none-any.whl (54.6 kB view details)

Uploaded Python 3

File details

Details for the file ldtc-1.0.0.tar.gz.

File metadata

  • Download URL: ldtc-1.0.0.tar.gz
  • Upload date:
  • Size: 57.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for ldtc-1.0.0.tar.gz
Algorithm Hash digest
SHA256 de3f43ecfea03e20b6e7e08dcccf9fdb0101743b3a54c96ac29676bba2a5a1eb
MD5 ed654422c194cb2306dcf5e36b0a16a8
BLAKE2b-256 2c8bdfe5025833bae0a2800fd44baeba78e14450b7597f189d7f907855c44f0f

See more details on using hashes here.

File details

Details for the file ldtc-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: ldtc-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 54.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for ldtc-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 91a04615244a2d7ede8e5fda014f8700d3088304d2007a0b3c40cf7d2c245e42
MD5 4a3afb342cf988e0e771b49e0687b78b
BLAKE2b-256 e656cba566466a519b2f1ce8ac945af76d55d2364cda37016347348c9b0ce0f7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page