Franklin Python Surface — Substrate-Development Specification
Status: substrate-development surface. Targets the cell platform floor (macOS 26).
Grounded against the live substrate at ~/Library/Application Support/GaiaFTCL/substrate.sqlite and the Swift sources in cells/xcode/Sources/ (2026-06-01).
Purpose
Expose Franklin's surface to local Python clients on the operator's host so
Python-based industry libraries (numpy, scipy, pandas, scikit-learn, biopython,
RDKit, ASE, pymatgen, ROOT) can interface with the substrate. Franklin remains
the cell's only public interface; Python never reaches past Franklin to
substrate internals.
What already exists (do not reimplement)
- Franklin surface:
public actor FranklinConsciousnessActor(.shared) with
awaken(runOnce:), runConsciousnessPreflight(), runPostWakeValidation(),
runPostWakeValidationWithGrace().
- Sealed surface (read path): append-only, witness-bearing tables in
substrate.sqlite, each with canonical_witness, witness_hash_sha256, and
signature_quintet. Witness rule (verified): witness_hash_sha256 = sha256(canonical_witness);
the quintet is a JSON array of exactly five 64-hex federation cosignatures.
- Broadcaster:
NATSBridgeoverSwiftNATSServer— substrate broker127.0.0.1:4222,
Franklin broker 127.0.0.1:4223. Sealed subjects are the nats_subject_sealed
column defaults (e.g. gaiaftcl.qc020.substrate.joint_variation_evidence.sealed).
- Listener pattern:
NWListener/NWConnection(seeSwiftNATSServer,
SovereignQualificationRunner).
What this surface ADDS
FranklinPythonSocket (Sources/FranklinConsciousness/FranklinPythonSocket.swift):
a Unix-domain NWListener at ~/Library/Application Support/GaiaFTCL/franklin.sock,
dispatching into FranklinConsciousnessActor.shared and forwarding substrate
compositions to the miner over the existing NATS broadcaster. No new surface is
created beside Franklin.
Frame protocol
4-byte big-endian length prefix + canonical-JSON payload (sorted keys, compact
separators, slashes unescaped). Identical to the Python client codec in
cells/python/gaiaftcl/_canonical.py.
Operator-signed handshake (required)
1. Server sends {"op":"challenge","challenge":"<base64 32 bytes>"}.
2. Client replies {"op":"handshake","operator_context":"<ctx>","signature":"<base64 Ed25519 sig over challenge>"}.
3. Server verifies via OperatorHandshakeVerifier (default: CryptoKit
Curve25519.Signing against the operator public key provisioned at bind time).
4. On success {"accepted":true}, else {"accepted":false,"reason":...} and close.
Operator key material never transits the socket. Anonymous connections are refused.
Request / response
Request: {"method":"<verb>","args":{...},"request_id":"..."}.
Response: {"request_id":"...","outcome":{...},"canonical_witness":"...","witness_hash":"...","signature_quintet":[...]}.
The Python client federation-verifies every response with the same rule as a
sealed row (sha256(canonical_witness) == witness_hash and a five-element quintet).
Verb routing
| Verb | Path |
|---|---|
franklin_authority_show |
FranklinConsciousnessActor.shared.runConsciousnessPreflight() (authority tunables, self-model version, autonomy envelope) |
compose_qc020_measurement, advance_production_submission_path, evaluate_algorithm, evaluate_all_algorithms, replay_session |
forwarded to the miner over gaiaftcl.substrate.command.<verb>; the daemon composes and seals; the sealed row carries the witness + quintet |
read verbs (heartbeat_history, joint_variation_evidence, research_telemetry, constitutional_evaluations, list/show_substrate_development) |
resolved by the Python client directly against the sealed surface (read-only, verified) — they do not require this socket |
Subscriptions
The Python client subscribes to substrate operations directly against the NATS
brokers (subscribe(nats_subject)), including the sealed subjects above.
Build / run note
The cell platform floor is .macOS(.v26). This file is written to compile on
the v26 toolchain; the QC-020 miner and consciousness service additionally
require ~/.gaiaftcl/qc021_kraken.toml and ~/.gaiaftcl/btc_node.toml and do
not start without them. On hosts below macOS 26 the read path and NATS path are
fully operational; the socket command path activates once the daemon runs on a
v26 host.
Wiring
Bind during sovereign stack launch, after the NATS server and consciousness
actor are up:
let verifier = FederationOperatorVerifier(publicKeysByContext: operatorKeys)
let pySocket = FranklinPythonSocket(verifier: verifier)
try await pySocket.bindPythonClientSocket()
ceb654f4ebbb114e93cba18d7fa196648eb11b1a56bbe673c187ce121afac130.
This page serves with a substrate-honest pending-signature notice until the operator's Franklin signer cosigns it.