What is Scyla?
Scyla is a compiled programming language where the laws of biology, physics, and chemistry are not libraries you import. They are native opcodes the compiler already knows.
When you write half_life("dopamine") in Scyla, you are not calling a library function. You are calling a compiled opcode that returns the published pharmacokinetic half-life of dopamine: 1200 seconds. That number comes from peer-reviewed research. It is baked into the compiler binary.
Why Does This Matter?
Every programming language ever built treats biology as data. You import a CSV. You load a model. You write your own equations and hope you got the constants right.
Scyla treats biology as code. The Hodgkin-Huxley conductance equations that govern your neurons are the same equations that gate computation in Scyla. The pharmacokinetic decay that clears dopamine from your synapses is the same decay that governs state in a Scyla program.
If the equations are published, peer-reviewed, and universal, why would you re-implement them every time? Make them native. Make them compiled. Make them impossible to get wrong.
What Can You Build With Scyla?
- Healthcare AI that governs its own output based on pharmacokinetics
- Drug interaction models using native Michaelis-Menten kinetics
- Mental health tools where emotional state has real decay constants
- Compliance-checked software where FDA, HIPAA, or GDPR rules are enforced at build time
- Discord bots, games, and real-time applications with a native gateway
What You Don't Need
You do not need to know Rust. Scyla compiles to a Rust binary, but you never touch Rust code. You write .sy files. The compiler handles the rest.
You do not need a biology degree. The opcodes handle the science. You handle the logic and the governance.
You do not need to memorize constants. Every biological constant in Scyla is published and cited. The compiler knows them. You just call them.
By the end of these lessons, you will be able to write Scyla programs that use native biological opcodes, create temporal structs that evolve autonomously, and run governance compliance checks against your code.
The Name
In Greek mythology, Scylla guarded one side of a narrow strait. Sailors could not go around her. They had to pass through.
That is governance. You do not negotiate with the strait. You do not optimize around the monster. You submit to the passage, or you do not pass at all.
Scyla: the governance layer that is native to code.
Installation
Scyla is distributed as a single binary. No dependencies. No virtual environments. No build tools. One file.
Step 1: Install via pip
The Scyla compiler is not yet publicly available. It is currently undergoing internal review and audit before release. Join the waitlist at caelsereith@aetherprotocols.com to be notified when it launches.
Step 2: Verify Installation
$ scylac scylac — The Scyla Compiler Usage: scylac <command> <file.sy> Commands: run <file> Compile and run check <file> Type check comply <rules> <file> Governance check strip <file> Remove native function names Scyla: a language for systems that evolve over time.
If you see this output, you are ready to go.
Step 3: Create Your Project Folder
$ mkdir my-first-scyla $ cd my-first-scyla
Scyla files use the .sy extension. In the next lesson, you will create your first one.
Scyla is currently in early access. The pip package includes the compiler binary for Linux and macOS. Windows support is coming soon. If you are on Windows, you can use WSL (Windows Subsystem for Linux).
What Got Installed
scylac— the compiler binary (compiled Rust, ~15MB)stdlib/— 33 standard library modules (.sy files)governance/— 4 regulatory rule sets (FDA, HIPAA, GDPR, CMC)
The standard library includes 210+ native opcodes covering pharmacokinetics, physics, chemistry, organ physiology, genetics, immune function, clinical measurements, and more. You will learn about these in later lessons.
Your First .sy File
Let's write a program. Create a file called hello.sy:
// My first Scyla program fn main() { print("Hello from Scyla.") // Let's use a native opcode let resting = tonic_drive("serotonin") print("Serotonin tonic firing rate:") print(resting) }
Run It
$ scylac run hello.sy Hello from Scyla. Serotonin tonic firing rate: 0.2
That 0.2 is the published tonic firing rate of serotonergic neurons in the dorsal raphe nucleus: 0.20 Hz, from Aghajanian et al. (1982). You did not look it up. You did not type it. The compiler knows it.
What Just Happened?
fn main()— every Scyla program starts here, just like C or Rust.print()— outputs text to the console.tonic_drive("serotonin")— a native opcode. Not a library call. This is compiled into the binary. It returns the published baseline firing rate for serotonin.let resting = ...— declares a variable. Scyla infers the type.
In Python, you would write SEROTONIN_TONIC = 0.20 and hope you got the right number from the right paper. In Scyla, the compiler is the paper. The citation is embedded in the binary. You cannot get it wrong.
Try This
Modify your program to print the tonic drive for other neurotransmitters:
fn main() { print("Tonic firing rates (published):") print(" Dopamine:") print(tonic_drive("dopamine")) // 0.13 Hz (Grace & Bunney 1984) print(" Serotonin:") print(tonic_drive("serotonin")) // 0.20 Hz (Aghajanian 1982) print(" Norepinephrine:") print(tonic_drive("norepinephrine")) // 0.50 Hz (Aston-Jones 1991) print(" GABA:") print(tonic_drive("gaba")) // 0.10 Hz (Bhatt 2020) }
These are the pilot lights of your nervous system. They never go to zero. Even in sleep, these neurons fire at their tonic rate. Scyla knows every one of them.
You just wrote a program that queries published neuroscience. In three lines. Without importing anything. Welcome to Scyla.
Variables & Types
Scyla has a clean, familiar syntax. If you have written JavaScript, Python, or Rust, you will feel at home.
Declaring Variables
Use let to declare a variable. Scyla infers the type:
fn main() { let name = "Scyla" // String let version = 1.0 // Float let opcodes = 210 // Integer let is_compiled = true // Boolean print(name) print(version) print(opcodes) print(is_compiled) }
Constants
Use const for values that never change:
const BODY_TEMP = 37.0 // Celsius. Physics. Not trainable. const PH_BLOOD = 7.4 // Homeostatic setpoint fn main() { print("Body temperature:") print(BODY_TEMP) // This would be a compile error: // BODY_TEMP = 38.0 // ERROR: cannot assign to const }
const values are immutable. They represent physics, universal constants, things that do not change. let values represent state, things that evolve. This distinction matters deeply in Scyla's temporal type system, which you will learn about in Lesson 7.
Basic Types
Float— a 64-bit floating point numberInt— a 64-bit integerString— textBool—trueorfalse
Math
fn main() { let cortisol = 0.8 let half_life = 5400.0 // 90 minutes in seconds let elapsed = 2700.0 // 45 minutes // Manual exponential decay let lambda = 0.693 / half_life let remaining = cortisol * exp(-lambda * elapsed) print("Cortisol after 45 min:") print(remaining) // Or just use the native opcode: let native = half_life_to_baseline(cortisol, 0.1, 5400.0, elapsed) print("Using native opcode:") print(native) }
Both produce the same result. But the native opcode also decays toward baseline (0.1), not toward zero. Because that is how biology works. Cortisol never hits zero. The body always maintains a tonic level.
You can always do the math yourself. But the native opcodes do it correctly, with published constants, decaying toward baseline instead of zero. That is the difference between a program that models biology and a program that is biology.
Functions
Functions in Scyla work like most languages you know. Define them with fn, call them by name.
Basic Functions
fn greet(name: String) { print("Hello, ") print(name) } fn main() { greet("Scyla") }
$ scylac run functions.sy Hello, Scyla
Return Values
Functions can return values. The last expression is the return value:
fn add(a: Float, b: Float) -> Float { a + b } fn main() { let result = add(3.0, 4.0) print(result) // 7.0 }
Functions That Use Native Opcodes
This is where Scyla starts to separate from every other language. You can wrap native opcodes in your own functions to build domain-specific tools:
// How much cortisol remains after a given time? fn cortisol_remaining(initial: Float, minutes: Float) -> Float { let seconds = minutes * 60.0 let baseline = tonic_drive("cortisol") let hl = bio_half_life("cortisol") half_life_to_baseline(initial, baseline, hl, seconds) } fn main() { let spike = 0.9 // high stress print("Cortisol after stress spike (0.9):") print(" 30 min:") print(cortisol_remaining(spike, 30.0)) print(" 60 min:") print(cortisol_remaining(spike, 60.0)) print(" 90 min:") print(cortisol_remaining(spike, 90.0)) print(" 180 min:") print(cortisol_remaining(spike, 180.0)) }
$ scylac run decay.sy Cortisol after stress spike (0.9): 30 min: 0.713 60 min: 0.553 90 min: 0.416 180 min: 0.175
After 90 minutes (one half-life), cortisol has dropped roughly in half. After 3 hours, it is approaching baseline. This is real pharmacokinetics. Not an approximation. The published decay constant is doing the work.
The function cortisol_remaining never touches a constant directly. It calls tonic_drive for the baseline and bio_half_life for the decay rate. You cannot get the numbers wrong because you never type them.
Building a Clinical Tool
Let's build something real. A function that tells a clinician whether a patient's cortisol is likely still elevated:
fn is_still_elevated(initial: Float, minutes_since: Float, threshold: Float) -> Bool { let current = half_life_to_baseline( initial, tonic_drive("cortisol"), bio_half_life("cortisol"), minutes_since * 60.0 ) current > threshold } fn main() { // Patient had a cortisol spike of 0.85 // It's been 45 minutes // Is it still above 0.5? let elevated = is_still_elevated(0.85, 45.0, 0.5) if elevated { print("Patient cortisol still elevated. Delay assessment.") } else { print("Cortisol within range. Proceed with assessment.") } }
$ scylac run clinical.sy Patient cortisol still elevated. Delay assessment.
In six lines of logic, you built a tool that uses published pharmacokinetics to inform a clinical decision. No library import. No hardcoded numbers. No guessing.
Functions in Scyla are simple. But when you wrap native opcodes in domain-specific functions, you build tools that carry the weight of published science without any of the complexity. The compiler knows the biology. You write the logic.
Multiple Parameters and Composition
Functions call other functions. Build small, compose big:
fn nt_status(name: String, current: Float) { let baseline = tonic_drive(name) let ratio = current / baseline print(name) if ratio > 2.0 { print(" STATUS: ELEVATED") } else if ratio < 0.5 { print(" STATUS: DEPLETED") } else { print(" STATUS: NORMAL") } } fn main() { nt_status("dopamine", 0.35) // elevated (baseline 0.13) nt_status("serotonin", 0.08) // depleted (baseline 0.20) nt_status("norepinephrine", 0.45) // normal (baseline 0.50) }
$ scylac run compose.sy dopamine STATUS: ELEVATED serotonin STATUS: DEPLETED norepinephrine STATUS: NORMAL
The function doesn't know what neurotransmitter you'll pass it. It asks the compiler for the baseline at runtime. One function. Any molecule. Published constants.
In the next lesson, you will learn about structs, which let you group related data together. And then in Lesson 7, you will learn about temporal structs, where state fields evolve autonomously over time. That is where Scyla becomes something no other language can be.
Structs
When you have related data that belongs together, you use a struct. If you know Python classes, JavaScript objects, or C structs, this will feel natural.
Defining a Struct
struct Patient { name: String, cortisol: Float, dopamine: Float, serotonin: Float, } fn main() { let p = Patient { name: "Room 12", cortisol: 0.85, dopamine: 0.09, serotonin: 0.12, } print(p.name) print("Cortisol:") print(p.cortisol) }
$ scylac run patient.sy Room 12 Cortisol: 0.85
Adding Methods with impl
Use impl to attach functions to a struct:
struct Patient { name: String, cortisol: Float, dopamine: Float, serotonin: Float, } impl Patient { fn is_in_crisis(&self) -> Bool { self.cortisol > 0.7 } fn serotonin_status(&self) -> String { let baseline = tonic_drive("serotonin") if self.serotonin < baseline * 0.5 { "DEPLETED" } else { "NORMAL" } } fn report(&self) { print("=== Patient Report ===") print(self.name) print("Cortisol:") print(self.cortisol) if self.is_in_crisis() { print("*** CRISIS STATE ***") } print("Serotonin:") print(self.serotonin_status()) } } fn main() { let p = Patient { name: "Room 12", cortisol: 0.85, dopamine: 0.09, serotonin: 0.08, } p.report() }
$ scylac run patient_methods.sy === Patient Report === Room 12 Cortisol: 0.85 *** CRISIS STATE *** Serotonin: DEPLETED
The &self parameter gives the method access to the struct's fields. The method serotonin_status calls tonic_drive to get the published baseline and compares. You never hardcode the threshold. The science decides.
Structs with const Fields
Some fields should never change. A patient's blood type doesn't change. The speed of light doesn't change. Use const inside structs:
struct Drug { name: String, const half_life: Float, // published. cannot be changed. const max_dose: Float, // FDA approved. cannot be changed. current_dose: Float, // this CAN change } impl Drug { fn is_safe(&self) -> Bool { self.current_dose <= self.max_dose } } fn main() { let med = Drug { name: "Sertraline", half_life: 93600.0, // 26 hours in seconds max_dose: 200.0, // mg current_dose: 50.0, } print(med.name) if med.is_safe() { print("Dose is within safe range.") } // This would be a compile error: // med.half_life = 50000.0 // ERROR: cannot assign to const // med.max_dose = 500.0 // ERROR: cannot assign to const }
A drug's half-life is physics. An FDA-approved maximum dose is regulation. Neither should be editable at runtime. By marking them const, the compiler enforces it. A bug cannot change the half-life. A hack cannot raise the max dose. The struct itself is the safety mechanism.
Composing Structs
Structs can contain other structs. Build your data model piece by piece:
struct ChemState { cortisol: Float, dopamine: Float, serotonin: Float, oxytocin: Float, } struct Patient { name: String, chemistry: ChemState, } impl Patient { fn stress_ratio(&self) -> Float { // Cortisol vs oxytocin: threat vs safety self.chemistry.cortisol / (self.chemistry.oxytocin + 0.001) } } fn main() { let p = Patient { name: "Room 12", chemistry: ChemState { cortisol: 0.85, dopamine: 0.09, serotonin: 0.08, oxytocin: 0.15, }, } print("Stress ratio (cortisol/oxytocin):") print(p.stress_ratio()) // 5.67 — this patient is in danger }
Cortisol divided by oxytocin gives you a threat-to-safety ratio. Above 1.0, threat dominates. At 5.67, the patient is drowning in stress chemistry with almost no safety signal. That is Room 12 after forty minutes with no answer to the call light.
Structs group data. Methods give structs behavior. const fields protect what should never change. Composition lets you build complex models from simple pieces. But these structs are static. You set the values. They stay.
In the next lesson, you will learn about temporal structs, where fields evolve on their own. Where cortisol decays at its published half-life without you writing a single line of decay code. That is where Scyla becomes something no other language can be.
Temporal Structs
This is the lesson where Scyla stops being a programming language you've seen before.
In every language you know, a variable holds a value until you change it. You set cortisol = 0.85, and it stays 0.85 forever. If you want it to decay, you write the decay function. You call it manually. You track the clock yourself.
In Scyla, temporal structs evolve on their own.
The Problem
In a regular struct, cortisol stays at crisis level forever:
struct Patient { cortisol: Float, // set to 0.85... } // ...stays 0.85 forever // biology doesn't work like this
That is not how chemistry works. Cortisol has a 90-minute half-life. It decays whether you write code for it or not. The body doesn't wait for a programmer to call update().
The Solution: temporal struct
Replace struct with temporal struct. Mark fields as state (they evolve) or const (they don't):
temporal struct Patient { state cortisol: Float, // this EVOLVES over time state dopamine: Float, // this EVOLVES over time state serotonin: Float, // this EVOLVES over time const name: String, // this NEVER changes const dt: Float, // time step. physics. }
state fields change over time. They are the variables in the differential equation. They evolve according to rules you define.
const fields never change. A patient's name doesn't decay. The time step is physics, not opinion. These are the constants in the equation.
impl Evolve
Now tell Scyla how the state fields evolve. Implement the Evolve trait:
temporal struct Patient { state cortisol: Float, state dopamine: Float, state serotonin: Float, const name: String, const dt: Float, } impl Evolve for Patient { fn evolve(&mut self, dt: Duration) { // Each neurotransmitter decays toward its biological baseline // at its published half-life. Automatically. self.cortisol = half_life_to_baseline( self.cortisol, tonic_drive("cortisol"), bio_half_life("cortisol"), dt ) self.dopamine = half_life_to_baseline( self.dopamine, tonic_drive("dopamine"), bio_half_life("dopamine"), dt ) self.serotonin = half_life_to_baseline( self.serotonin, tonic_drive("serotonin"), bio_half_life("serotonin"), dt ) } } fn main() { let p = Patient { cortisol: 0.85, // crisis level dopamine: 0.09, // depleted serotonin: 0.08, // depleted name: "Room 12", dt: 1.0, } print("=== Initial State ===") print("Cortisol:") print(p.cortisol) // Evolve 30 minutes (1800 seconds) p.evolve(1800.0) print("=== After 30 minutes ===") print("Cortisol:") print(p.cortisol) // Evolve another 60 minutes p.evolve(3600.0) print("=== After 90 minutes total ===") print("Cortisol:") print(p.cortisol) }
$ scylac run evolving_patient.sy === Initial State === Cortisol: 0.85 === After 30 minutes === Cortisol: 0.672 === After 90 minutes total === Cortisol: 0.393
After one half-life (90 minutes), cortisol dropped from 0.85 roughly toward half. But not to half of 0.85. To half of the distance between 0.85 and the baseline. Because half_life_to_baseline decays toward tonic drive, not toward zero.
Cortisol doesn't decay to zero. It decays to baseline. The deviation decays. The baseline persists. That is what half_life_to_baseline computes. That is what makes this biology, not just math.
Why This Changes Everything
In every other language, state is dead until you touch it. A variable set to 0.85 at 3:00 PM is still 0.85 at midnight. That is a lie. In biology, nothing stays. Everything decays, adapts, returns to baseline.
Temporal structs make state alive. The evolve function is the heartbeat. Every call advances the chemistry. The struct doesn't wait for you. It breathes.
// This struct is alive. // Cortisol decays at 90 minutes. // Dopamine decays at 20 minutes. // Serotonin decays at 60 minutes. // You did not write any of those numbers. // The compiler knows them. // The struct evolves itself. // That is a temporal struct.
A Practical Example: Shift Monitor
Let's build something a hospital could use. A shift monitor that tracks a CNA's stress chemistry over a 12-hour shift:
temporal struct CNA { state cortisol: Float, state oxytocin: Float, state dopamine: Float, const name: String, const dt: Float, } impl Evolve for CNA { fn evolve(&mut self, dt: Duration) { self.cortisol = half_life_to_baseline( self.cortisol, tonic_drive("cortisol"), bio_half_life("cortisol"), dt) self.oxytocin = half_life_to_baseline( self.oxytocin, tonic_drive("oxytocin"), bio_half_life("oxytocin"), dt) self.dopamine = half_life_to_baseline( self.dopamine, tonic_drive("dopamine"), bio_half_life("dopamine"), dt) } } impl CNA { fn stress_event(&mut self) { // Patient emergency: cortisol spikes self.cortisol = self.cortisol + 0.3 if self.cortisol > 1.0 { self.cortisol = 1.0 } } fn kind_moment(&mut self) { // Patient says thank you: oxytocin bump self.oxytocin = self.oxytocin + 0.1 self.dopamine = self.dopamine + 0.05 } fn burnout_risk(&self) -> Bool { // Cortisol dominant over oxytocin = burnout territory self.cortisol > self.oxytocin * 3.0 } fn status(&self) { print(self.name) print(" Cortisol:") print(self.cortisol) print(" Oxytocin:") print(self.oxytocin) if self.burnout_risk() { print(" *** BURNOUT RISK ***") } } } fn main() { let nurse = CNA { cortisol: 0.2, // start of shift, calm oxytocin: 0.3, // decent baseline dopamine: 0.15, // normal name: "Night Shift CNA", dt: 1.0, } print("=== Start of Shift ===") nurse.status() // Hour 2: patient fall nurse.stress_event() nurse.evolve(3600.0) // 1 hour passes // Hour 4: another emergency nurse.stress_event() nurse.evolve(3600.0) // Hour 6: patient says thank you nurse.kind_moment() nurse.evolve(3600.0) // Hour 8: two more emergencies, no breaks nurse.stress_event() nurse.stress_event() nurse.evolve(7200.0) // 2 hours, no relief print("=== Hour 10 ===") nurse.status() }
$ scylac run shift_monitor.sy === Start of Shift === Night Shift CNA Cortisol: 0.2 Oxytocin: 0.3 === Hour 10 === Night Shift CNA Cortisol: 0.58 Oxytocin: 0.11 *** BURNOUT RISK ***
The cortisol accumulated faster than it could decay. The oxytocin from one "thank you" wasn't enough to offset four emergencies. By hour 10, the ratio has flipped. The CNA is running on cortisol with almost no oxytocin buffer.
The budget meeting that cut the overnight shift didn't count this. Scyla does.
These are the same pharmacokinetic equations used in clinical drug trials. The half-lives are from published research. The decay toward baseline is real homeostatic mechanics. The difference between this program and a clinical pharmacokinetic model is only the input source. The math is identical.
The Rule
In Scyla, there are two kinds of data:
- const — physics. It does not change. The speed of light. A published half-life. A patient's blood type.
- state — chemistry. It evolves. Cortisol. Trust. Dopamine. The things that make a system alive.
If you cannot decide whether a field is const or state, ask yourself: does this change when I'm not looking? If yes, it is state. If no, it is const.
Your name doesn't decay. Your cortisol does. The struct knows the difference.
Temporal structs give state a heartbeat. The evolve function is the differential equation. state fields change. const fields don't. Native opcodes handle the science. You handle the logic. The struct breathes on its own.
In the next lesson, you will learn about native opcodes in depth: what they are, how many exist, and why they make Scyla fundamentally different from every other language on earth.
What Are Native Opcodes?
Every programming language has built-in operations. + adds numbers. print writes text. These are so fundamental that they're compiled into the language itself. You don't import addition.
Scyla does the same thing with biology, physics, and chemistry.
When you call nernst() in Scyla, you are not calling a library. You are calling a compiled opcode: a function baked into the Rust binary that implements the Nernst equation exactly as published in 1889, with the universal gas constant and Faraday constant already embedded. You cannot get it wrong because you never type the constants.
What Makes Them "Native"
import pharmacokinetics
result = pharmacokinetics.half_life(substance="dopamine", t=1200)
You hope the library is correct. You hope it's maintained. You hope the version you installed matches the paper you cited. You import someone else's interpretation of the science.
let result = bio_half_life("dopamine")
The compiler IS the paper. The citation is in the binary. There is no dependency to update, no version mismatch, no interpretation. The equation is compiled. It returns 1200 seconds because that is what the published research says.
The 210+ Opcodes by Domain
Scyla ships with native opcodes across 17 scientific domains. Here is what you have access to without importing anything:
Pharmacokinetics (20 opcodes)
Half-lives, AUC, Michaelis-Menten kinetics, Hill equation, dissociation constants, compartment models, and the critical half_life_to_baseline that decays toward tonic, not zero.
fn main() { // Published half-lives (you never type these numbers) print("Dopamine half-life:") print(bio_half_life("dopamine")) // 1200s // Michaelis-Menten enzyme kinetics let rate = michaelis_menten(100.0, 50.0, 10.0) print("Enzyme rate:") print(rate) // Area under the curve (trust as AUC) let trust = auc(0.04, 0.12, 3600.0) print("Trust AUC:") print(trust) }
Physics (14 opcodes)
Nernst equation, Goldman equation, Fick's diffusion, Gibbs free energy, Henderson-Hasselbalch, Coulomb's law, Ohm's law for membranes, Hodgkin-Huxley gating.
fn main() { // Nernst equation: equilibrium potential for potassium // Published: intracellular K+ = 140mM, extracellular = 5mM let e_k = nernst(1.0, 140.0, 5.0, 310.0) print("Potassium equilibrium potential:") print(e_k) // ~ -89 mV (textbook: -90 mV) // Henderson-Hasselbalch: blood pH let ph = henderson_hasselbalch(6.1, 24.0, 1.2) print("Blood pH:") print(ph) // 7.4 }
Chemistry (9 opcodes)
All 20 amino acids with pKa, molecular weight, and hydrophobicity from Lehninger 7th edition. Bond energies. Electronegativity. Redox potentials. Osmolarity.
Organic Chemistry (14 opcodes)
Decarboxylation, hydroxylation, methylation, acetylation, phosphorylation, ubiquitination, neurotransmitter synthesis and degradation pathways, chirality, van der Waals, isoelectric point.
Biological Constants (5 opcodes)
Published half-lives, dissociation constants, frequencies, tonic firing rates, and Hodgkin-Huxley resting state values from the 1952 paper.
fn main() { // Exact resting values from Hodgkin & Huxley, 1952 // Nobel Prize in Physiology or Medicine, 1963 let m = hh_resting("m") // 0.0529 let h = hh_resting("h") // 0.5961 let n = hh_resting("n") // 0.3177 print("H-H resting gate values:") print(" m (Na+ activation):") print(m) print(" h (Na+ inactivation):") print(h) print(" n (K+ activation):") print(n) }
Organs (14 opcodes)
Heart, liver, kidney, lungs, pancreas, adrenal, thyroid, pituitary, hypothalamus, gut, bone marrow, spleen, skin. Each returns organ-specific parameters.
Diseases (63 diagnoses)
Each disease is a baseline shift, not a label. Depression isn't a tag. It's serotonin -0.35, dopamine -0.25, cortisol +0.30. The DSM-5 as parameter modifications.
fn main() { // What does major depression look like in chemistry? let shifts = disease("major_depression") print("Major Depression baseline shifts:") print(shifts) // What drug targets this pattern? let target = disease_drug_target("major_depression") print("Drug target:") print(target) }
And More...
- Biological Ranges (8) — EEG bands, heart rhythm, respiratory, circadian phase
- V4 Consciousness Pipeline (18) — raw feel, emotion, moral compass, vagal tone, metacognition
- Context Modulation (3) — trust changes half-lives, consent changes release masks
- Sensory (4) — transduce any modality to hormones
- Quantum (6) — tunneling, decoherence, radical pairs
- ODE/PDE (11) — Hodgkin-Huxley step, FitzHugh-Nagumo, reaction-diffusion
- Synaptic Plasticity (5) — STDP, LTP, LTD, Hebbian, homeostatic scaling
- Organelles (12) — ribosome, nucleus, rough ER, Golgi, lysosome, proteasome
- Myelination (7) — conduction velocity, nerve fiber class, saltatory conduction
- Genetics (6) — histone state, DNA methylation, supercoiling, codons, telomeres
- Clinical (15) — A1C to glucose, GFR, BMI, PHQ-9, GAD-7, Glasgow Coma Scale
- Metabolic (8) — glycolysis, Krebs cycle, oxidative phosphorylation, total ATP yield
- Immune (10) — cytokines, inflammation, kynurenine pathway, complement, antibodies
- Discord (17) — native gateway, no framework, slash commands, buttons, embeds
Every Constant Is Cited
Inside the compiled binary, every native opcode carries its citation. The Rust source code contains comment blocks like this:
// CITATION: Aghajanian, G.K. et al. (1982) // "Serotonin neurons: pharmacology and electrophysiology" // Tonic firing rate: 0.20 Hz (dorsal raphe nucleus) // Measured: extracellular single-unit recordings in vivo
You call tonic_drive("serotonin"). The binary returns 0.20. The citation is in the source. The science is in the metal.
Native opcodes are compiled science. 210+ functions across 17 domains, each backed by peer-reviewed research, each embedded in the binary. No imports. No dependencies. No version conflicts. No wrong constants. The compiler is the textbook.
In the next lesson, you will dive deep into the pharmacokinetics opcodes and build real drug interaction models.
Pharmacokinetics: The Deep Dive
This is the lesson where Scyla proves why it exists. Pharmacokinetics is the study of what the body does to a substance over time: absorption, distribution, metabolism, excretion. Every drug label, every clinical trial, every dosing decision in medicine is pharmacokinetics.
In Scyla, it is native.
This lesson has four sections, just like the body processes a substance: from the system level down to the blood.
- Part 1: System — whole-body pharmacokinetics
- Part 2: Organ — organ-specific processing
- Part 3: Tissue — cellular and receptor-level mechanics
- Part 4: Blood — measurement, clinical panels, diagnostics
Part 1: System Level
The whole body. Systemic pharmacokinetics. What happens when a substance enters the system and the entire body processes it.
Half-Life: The Clock of Chemistry
Every substance in your body has a half-life. It is the time it takes for the concentration to drop by half. This is the most fundamental measurement in pharmacokinetics.
fn main() { print("=== System Half-Lives (published) ===") print("Adrenaline:") print(bio_half_life("adrenaline")) // 120s (2 minutes) print("Dopamine:") print(bio_half_life("dopamine")) // 1200s (20 minutes) print("Serotonin:") print(bio_half_life("serotonin")) // 3600s (60 minutes) print("Cortisol:") print(bio_half_life("cortisol")) // 5400s (90 minutes) print("Oxytocin:") print(bio_half_life("oxytocin")) // 180s (3 minutes) print("BDNF:") print(bio_half_life("bdnf")) // 600s (10 minutes) }
Notice the range. Adrenaline burns in 2 minutes. Cortisol lingers for 90. That is why a scare fades fast but stress stays. The chemistry is the explanation.
If an AI system processes a hostile message and spikes its internal cortisol representation, that spike should take 90 minutes to decay, not one inference cycle. If it spikes adrenaline, that should fade in 2 minutes. Current AI has no concept of this. Every token is equally "forgotten" by the next context window. Scyla makes the forgetting curve match biology.
Decay to Baseline, Not Zero
This is the single most important concept in Scyla pharmacokinetics. Read it twice.
Standard exponential decay goes to zero: C(t) = C0 * exp(-lambda * t)
Biological decay goes to baseline: C(t) = baseline + (C0 - baseline) * exp(-lambda * t)
Your cortisol never hits zero. Even in deep sleep, your adrenal glands produce a tonic level. That tonic level is the pilot light. It is always on. Scyla calls it tonic_drive.
fn main() { let spike = 0.9 // crisis level cortisol let baseline = tonic_drive("cortisol") let hl = bio_half_life("cortisol") print("Baseline (tonic drive):") print(baseline) print("--- Standard decay (toward zero) ---") let lambda = 0.693 / hl print(" 6 hours:") print(spike * exp(-lambda * 21600.0)) // approaches 0 print("--- Biological decay (toward baseline) ---") print(" 6 hours:") print(half_life_to_baseline(spike, baseline, hl, 21600.0)) // approaches tonic, NEVER zero }
$ scylac run baseline_demo.sy Baseline (tonic drive): 0.1 --- Standard decay (toward zero) --- 6 hours: 0.055 --- Biological decay (toward baseline) --- 6 hours: 0.149
Standard decay says cortisol is 0.055 after 6 hours. Biology says 0.149. The difference is the baseline: the body maintains a floor. Standard math gets this wrong. Every neuroscience simulation using simple exponential decay gets this wrong. Scyla doesn't.
Compartment Models
In clinical pharmacokinetics, the body is modeled as compartments. A drug enters the blood (central compartment), distributes to tissues (peripheral compartment), gets metabolized, gets excreted.
fn main() { // One-compartment model: drug in, drug out let dose = 100.0 // mg administered let volume = 50.0 // liters (volume of distribution) let ke = 0.1 // elimination rate constant (1/hr) let c0 = dose / volume // initial concentration: 2.0 mg/L print("Initial concentration:") print(c0) // Concentration at various times print("After 2 hours:") print(compartment_1(c0, ke, 2.0)) print("After 6 hours:") print(compartment_1(c0, ke, 6.0)) print("After 12 hours:") print(compartment_1(c0, ke, 12.0)) }
AUC: Area Under the Curve
AUC is the gold standard in pharmacokinetics. It measures total exposure: the integral of concentration over time. The FDA uses AUC to determine bioequivalence. Your doctor uses A1C, which is the AUC of glucose over 120 days.
In Scyla, AUC is also how trust works.
fn main() { // Trust is AUC of oxytocin over time // You cannot fake a high AUC // It requires sustained concentration over duration // Lovebomber: 5 high-oxytocin messages in 10 minutes let lovebomb_auc = auc(0.8, 0.04, 600.0) print("Lovebomber trust (5 msgs, 10 min):") print(lovebomb_auc) // Real friend: moderate oxytocin over 6 months let friend_auc = auc(0.3, 0.04, 15552000.0) print("Real friend trust (6 months):") print(friend_auc) }
$ scylac run auc_trust.sy Lovebomber trust (5 msgs, 10 min): 252.0 Real friend trust (6 months): 2018304.0
The lovebomber's AUC is 252. The real friend's is 2 million. You cannot simulate six months of consistent presence with five intense messages. The math prevents it. That is pharmacokinetic trust.
Trust as AUC means lovebombing is mathematically impossible. A manipulator can spike the signal, but the integral knows the truth. Duration times consistency beats intensity every time. This is not a design choice. It is pharmacokinetics.
Part 2: Organ Level
The system is made of organs. Each organ has its own pharmacokinetics: its own metabolic rates, its own clearance, its own role in processing substances.
The Liver: First-Pass Metabolism
fn main() { // The liver is the body's primary metabolizer // Every oral drug passes through the liver BEFORE // reaching systemic circulation (first-pass effect) let liver_state = liver(1.0) print("Liver metabolic capacity:") print(liver_state) // Kidney: filtration and excretion let kidney_state = kidney(1.0) print("Kidney filtration:") print(kidney_state) // Clinical: estimated GFR (kidney function test) let gfr = gfr_estimate(1.2, 45.0, 0) print("Estimated GFR (mL/min):") print(gfr) // If GFR < 60, kidney function is impaired // Drug doses must be adjusted }
The Adrenal Glands: Cortisol Factory
fn main() { // The adrenals sit on top of the kidneys // They produce cortisol, adrenaline, norepinephrine // They respond to HPA axis activation let stress_signal = 0.8 let adrenal_output = adrenal(stress_signal) print("Adrenal output at stress 0.8:") print(adrenal_output) // The hypothalamus drives the adrenals let hypo = hypothalamus(stress_signal) print("Hypothalamic drive:") print(hypo) // The pituitary mediates between them let pit = pituitary(stress_signal) print("Pituitary output:") print(pit) }
Hypothalamus → Pituitary → Adrenal. This is the stress response pathway. Three organs, each a native opcode, each with its own response dynamics. When you connect them, you model the stress cascade that runs in the CNA from Room 12. The hypothalamus detects threat. The pituitary amplifies. The adrenals flood cortisol. Scyla models each stage.
The Heart: Rhythm and Variability
fn main() { // Heart pacemaker: the SA node's intrinsic rate let pace = heart_pacemaker() print("SA node intrinsic rate (bpm):") print(pace) // Heart rate variability: the gold standard for autonomic health // High HRV = flexible, resilient nervous system // Low HRV = rigid, stressed, burnout let hrv_healthy = heart_hrv(0.2) // low stress let hrv_burned = heart_hrv(0.9) // high stress print("HRV at low stress:") print(hrv_healthy) print("HRV at high stress:") print(hrv_burned) // QT interval: cardiac safety check // Many drugs prolong QT. This kills people. let qt = qt_interval(75.0, 0.38) print("Corrected QT (Bazett):") print(qt) // If QTc > 0.47: drug is dangerous }
QT prolongation is one of the most common reasons drugs get pulled from market. Many antipsychotics, antibiotics, and heart medications prolong the QT interval, risking fatal arrhythmia. Scyla has it as a native opcode because drug safety isn't optional.
The Gut: The Second Brain
fn main() { // 95% of serotonin is produced in the gut, not the brain // The gut has its own nervous system: the enteric nervous system // 500 million neurons. More than the spinal cord. let gut_sero = gut(0.5) print("Gut serotonin production at input 0.5:") print(gut_sero) // This is why stress causes stomach problems // And why stomach problems cause depression // The gut-brain axis is bidirectional // Scyla models both directions }
Part 3: Tissue Level
Below the organs. The cells. The receptors. The molecular machinery that processes substances at the point of action.
Receptor Binding: Kd and the Hill Equation
fn main() { // Kd: the dissociation constant // Lower Kd = tighter binding = more potent drug let kd_sert = bio_kd("serotonin") print("Serotonin receptor Kd:") print(kd_sert) // Hill equation: cooperative binding // How much of a receptor is occupied at a given concentration? // This is how dose-response curves work let low_dose = hill(10.0, 50.0, 1.0) // 10/50, n=1 let mid_dose = hill(50.0, 50.0, 1.0) // 50/50, n=1 let high_dose = hill(200.0, 50.0, 1.0) // 200/50, n=1 print("Receptor occupancy:") print(" Low dose (10):") print(low_dose) // 0.167 (17%) print(" Mid dose (50):") print(mid_dose) // 0.500 (50%) print(" High dose (200):") print(high_dose) // 0.800 (80%) }
The Hill equation is how every drug-receptor interaction is modeled. At the EC50 (mid dose), exactly 50% of receptors are occupied. Double the dose doesn't double the effect. This is the law of diminishing returns at the molecular level.
Enzyme Kinetics: Michaelis-Menten
fn main() { // Michaelis-Menten: the rate at which an enzyme // processes a substrate // V = Vmax * [S] / (Km + [S]) let vmax = 100.0 // maximum velocity let km = 25.0 // Michaelis constant print("Enzyme velocity at various substrate levels:") print(" [S] = 5:") print(michaelis_menten(vmax, km, 5.0)) // 16.7 print(" [S] = 25:") print(michaelis_menten(vmax, km, 25.0)) // 50.0 print(" [S] = 100:") print(michaelis_menten(vmax, km, 100.0)) // 80.0 print(" [S] = 1000:") print(michaelis_menten(vmax, km, 1000.0)) // 97.6 // At [S] = Km, velocity is exactly half of Vmax // No matter how much substrate you add, you can't // exceed Vmax. The enzyme has a speed limit. // This is why overdosing doesn't clear faster. }
The liver metabolizes drugs via enzymes. Enzymes have a Vmax: a maximum speed. When the drug concentration exceeds the enzyme's capacity, the excess accumulates. The metabolism saturates. The liver can't keep up. Michaelis-Menten kinetics explains exactly why. Scyla makes it a function call.
Neurotransmitter Synthesis and Degradation
fn main() { // Serotonin synthesis pathway: // Tryptophan → 5-HTP → Serotonin → 5-HIAA // Each step is an enzyme. Each enzyme has kinetics. let synth = nt_synthesis_pathway("serotonin") print("Serotonin synthesis pathway:") print(synth) // Degradation: how the body breaks it down let degrade = nt_degradation("serotonin", 0.5) print("Degradation rate at concentration 0.5:") print(degrade) // trace_break: trace BACKWARD through the pathway // to find where the failure is let failure = trace_break("serotonin") print("If serotonin is low, check:") print(failure) // Returns: "tryptophan" or "tph2" (the rate-limiting enzyme) }
trace_break is a diagnostic opcode. If a neurotransmitter is depleted, it traces backward through the synthesis pathway to find the bottleneck. Is the precursor missing? Is the enzyme impaired? Is a cofactor depleted? The answer tells you where to intervene.
The Organelles: Where Chemistry Happens
fn main() { // rough_er: quality control for protein folding // In Scyla: output quality check before release let qc = rough_er(0.7) print("Quality control pass rate:") print(qc) // golgi: post-processing, packaging, routing let routed = golgi(0.7) print("Golgi routing output:") print(routed) // lysosome: garbage collection // Digest and recycle damaged components let cleaned = lysosome(0.3) print("Lysosome cleanup:") print(cleaned) // autophagy: self-eating under stress // The cell eats its own damaged parts to survive // In AI: graceful degradation under resource pressure let survived = autophagy(0.9) // high stress print("Autophagy at stress 0.9:") print(survived) }
Part 4: Blood Level
Everything ends up in the blood. The blood is where you measure. This is where pharmacokinetics meets clinical medicine.
The Blood Panel
fn main() { // blood_panel(): the chemistry FIRST approach // Before you label someone with a disease, // you look at their chemistry. let panel = blood_panel(0.85, 0.09, 0.08, 0.15, 0.45, 0.6) print("Blood panel results:") print(panel) // A1C: the 120-day rolling integral of glucose // This is AUC applied to clinical medicine let glucose = a1c_to_glucose(6.5) print("A1C of 6.5 = average glucose:") print(glucose) // ~140 mg/dL (diabetic threshold) // Anion gap: metabolic acidosis detection let gap = anion_gap(140.0, 4.0, 100.0, 24.0) print("Anion gap:") print(gap) // Normal: 8-12 }
Differential Diagnosis
fn main() { // symptom(): symptoms are atomic, not labels // Each symptom maps to specific NT perturbations let fatigue = symptom("fatigue") let anhedonia = symptom("anhedonia") let insomnia = symptom("insomnia") print("Fatigue NT signature:") print(fatigue) print("Anhedonia NT signature:") print(anhedonia) // differential(): given symptoms, what diagnoses match? let ddx = differential("fatigue", "anhedonia", "insomnia") print("Differential diagnosis:") print(ddx) // disease(): what does the diagnosis look like in chemistry? let depression = disease("major_depression") print("Major depression baseline shifts:") print(depression) // serotonin: -0.35, dopamine: -0.25, cortisol: +0.30 }
In Scyla, blood_panel() comes before disease(). You look at the chemistry first. You check the neurotransmitter levels. You trace backward through synthesis pathways. THEN, if you must, you apply a label. The label is a convenience. The chemistry is the truth.
This is how a biochemist thinks. And it is how Scyla is designed.
Clinical Scoring
fn main() { // PHQ-9: depression screening (0-27) let phq = phq9(3, 2, 3, 2, 1, 2, 1, 0, 0) print("PHQ-9 score:") print(phq) // 14 = moderately severe // GAD-7: anxiety screening (0-21) let gad = gad7(2, 3, 2, 1, 2, 1, 2) print("GAD-7 score:") print(gad) // 13 = moderate anxiety // Glasgow Coma Scale: consciousness assessment let gcs = glasgow_coma(4, 5, 6) print("Glasgow Coma Scale:") print(gcs) // 15 = fully conscious // APGAR: newborn assessment let apgar = apgar(2, 2, 2, 1, 2) print("APGAR score:") print(apgar) // 9 = healthy newborn }
Putting It All Together
System, organ, tissue, blood. Four levels. One patient. Let's build a complete pharmacokinetic assessment:
temporal struct PatientAssessment { state cortisol: Float, state serotonin: Float, state dopamine: Float, const name: String, const dt: Float, } impl Evolve for PatientAssessment { fn evolve(&mut self, dt: Duration) { self.cortisol = half_life_to_baseline(self.cortisol, tonic_drive("cortisol"), bio_half_life("cortisol"), dt) self.serotonin = half_life_to_baseline(self.serotonin, tonic_drive("serotonin"), bio_half_life("serotonin"), dt) self.dopamine = half_life_to_baseline(self.dopamine, tonic_drive("dopamine"), bio_half_life("dopamine"), dt) } } impl PatientAssessment { fn full_report(&self) { print("╔══════════════════════════════════╗") print("║ PHARMACOKINETIC ASSESSMENT ║") print("╚══════════════════════════════════╝") print(self.name) // Blood level print("[BLOOD] Cortisol:") print(self.cortisol) print("[BLOOD] Serotonin:") print(self.serotonin) // Organ level print("[ORGAN] Adrenal output:") print(adrenal(self.cortisol)) print("[ORGAN] HRV:") print(heart_hrv(self.cortisol)) // Tissue level print("[TISSUE] Serotonin receptor occupancy:") print(hill(self.serotonin, bio_kd("serotonin"), 1.0)) // System level if self.cortisol > 0.7 { print("[SYSTEM] *** CRISIS STATE ***") print("[SYSTEM] Delay cognitive assessment.") } else { print("[SYSTEM] Proceed with assessment.") } } } fn main() { let patient = PatientAssessment { cortisol: 0.85, serotonin: 0.08, dopamine: 0.06, name: "Room 12", dt: 1.0, } print("=== ADMISSION ===") patient.full_report() // 2 hours pass. Chemistry evolves. patient.evolve(7200.0) print("") print("=== 2 HOURS LATER ===") patient.full_report() }
Pharmacokinetics in Scyla operates at every level of biological organization:
- System: half-lives, AUC, compartment models, decay to baseline
- Organ: liver metabolism, adrenal stress response, cardiac safety, gut-brain axis
- Tissue: receptor binding (Kd, Hill), enzyme kinetics (Michaelis-Menten), synthesis pathways, trace_break diagnostics
- Blood: blood panels, A1C, clinical scores (PHQ-9, GAD-7, Glasgow, APGAR), differential diagnosis
Every opcode is published. Every constant is cited. The compiler is the textbook. You write the logic. The science is already there.
Physics & Chemistry
Scyla does not approximate science. It compiles it. The periodic table is not a JSON file you load at runtime. It is 118 native opcodes burned into the binary. When you call element("hydrogen"), you are not querying a database. You are executing a function that returns 1.008 because that is what hydrogen weighs.
The Periodic Table
use periodic::* fn main() { let h = element("hydrogen") println(h.name) // Hydrogen println(h.symbol) // H println(h.atomic_number) // 1 println(h.atomic_mass) // 1.008 // Compute molecular weight of water: H2O let o = element("oxygen") let water_mw = 2.0 * h.atomic_mass + o.atomic_mass println("Water MW:") println(water_mw) // 18.015 // Electronegativity difference (bond polarity) let en_diff = electronegativity("oxygen") - electronegativity("hydrogen") println("O-H electronegativity difference:") println(en_diff) // 1.24 (polar covalent) }
$ scylac run elements.sy Hydrogen H 1 1.008 Water MW: 18.015 O-H electronegativity difference: 1.24
Every atomic mass is IUPAC 2023. Not an approximation. Not a training-data average. The published value, compiled.
Acid-Base Chemistry
pH, pKa, Henderson-Hasselbalch, buffer systems. All native:
use bronsted_lowry::* fn main() { // Henderson-Hasselbalch for a bicarbonate buffer let ph = henderson_hasselbalch(6.1, 24.0, 1.2) println("Blood pH from bicarb buffer:") println(ph) // 7.4 // Arterial blood gas interpretation let dx = classify_abg(7.28, 55.0, 18.0) println(dx) // "Respiratory acidosis with metabolic acidosis" // Anion gap let ag = anion_gap(140.0, 105.0, 18.0) println("Anion gap:") println(ag) // 17 (elevated - metabolic acidosis) }
Thermodynamics
Gibbs free energy, enthalpy, entropy. The laws of thermodynamics are not suggestions:
use thermodynamic::* fn main() { // ATP hydrolysis: the currency of life let atp = thermodynamic_step("atp_hydrolysis") println(atp.reaction) // ATP + H2O -> ADP + Pi println(atp.delta_g) // -30.5 kJ/mol println(atp.spontaneous) // true (negative dG) }
Differential Equations
Scyla has native ODE solvers. Runge-Kutta 4th order, Euler, Heun. These are the tools that make digital twins work:
use diffeq::* fn main() { // Hodgkin-Huxley gate dynamics // dm/dt = alpha*(1-m) - beta*m let m = 0.05 // initial gate state let alpha = 0.32 // opening rate let beta = 0.08 // closing rate let m_inf = hh_steady_state(alpha, beta) println("Steady state:") println(m_inf) // 0.8 (alpha / (alpha + beta)) // RK4 integration step let dt = 0.01 let dy = rk4_step(m, dt, alpha, beta) println("After one RK4 step:") println(m + dy) // Michaelis-Menten enzyme kinetics let rate = michaelis_menten(100.0, 50.0, 10.0) println("Enzyme rate at [S]=10:") println(rate) // Vmax * [S] / (Km + [S]) }
Your chemistry professor was right. When you have more than one variable in an equation, you can experiment with the relationship one has on another. Pick 3 of the 4 and the 4th is defined.
Scyla harnesses this. Physics as native code. The relationships are compiled. The variables constrain each other. There is nothing to hallucinate because reality already decided the answer.
The Biological Baseline
Every biological system has a baseline. A resting state. A homeostatic equilibrium that the body fights to maintain. Cortisol has a tonic drive. Heart rate has a resting rate. Blood pressure has a set point. Temperature holds at 37C.
In Scyla, the baseline is not an assumption. It is a compiled constant with a citation.
Tonic Drive: The Pilot Light
Every neurotransmitter and hormone in Scyla has a tonic_drive: the baseline level that is always present, even at complete rest. This is not zero. This is the pilot light that keeps the system alive.
fn main() { println("=== Tonic Drives (Baseline Levels) ===") println("Dopamine:") println(tonic_drive("dopamine")) // 0.15 println("Serotonin:") println(tonic_drive("serotonin")) // 0.20 println("Cortisol:") println(tonic_drive("cortisol")) // 0.10 println("Norepinephrine:") println(tonic_drive("norepinephrine")) // 0.12 }
When a substance spikes (stress, excitement, pain), it rises above tonic drive. When the stimulus passes, it decays back to tonic drive. Not to zero. Back to baseline. This is homeostasis.
Cardiovascular Baselines
The cardiovascular system has baselines too. These are the numbers a medic checks first:
use cardiovascular::* fn main() { // Normal cardiac output let co = cardiac_output(72.0, 70.0) println("Cardiac output:") println(co) // 5.04 L/min // Mean arterial pressure let map = mean_arterial_pressure(120.0, 80.0) println("MAP:") println(map) // 93.3 mmHg // Oxygen delivery let cao2 = arterial_oxygen_content(14.0, 98.0, 95.0) let do2 = oxygen_delivery(co, cao2) println("O2 delivery:") println(do2) // ~950 mL O2/min (normal) // Shock index (HR/SBP) let si = shock_index(72.0, 120.0) println("Shock index:") println(si) // 0.6 (normal) }
What Happens When the Baseline Breaks
Hemorrhagic shock is what happens when blood loss pushes the cardiovascular system away from its baseline and the compensatory mechanisms cannot bring it back:
use hemorrhagic_shock::* use cardiovascular::* fn main() { // Normal: 5000 mL blood volume in a 70kg adult let tbv = total_blood_volume_ml(70.0) println("Total blood volume:") println(tbv) // 4900 mL // Class I hemorrhage: < 15% loss let c1 = hclass(1, "Class I", "<15%", "<750", "normal", "normal", "14-20", ">30", "slightly anxious", "Crystalloid", "ATLS 10th ed") println("Class I: Anxious but stable") // Class III hemorrhage: 30-40% loss = LIFE THREAT println("Class III: HR 120-140, BP dropping, confused") println("This is where the digital twin saves lives.") println("Predict the trajectory. Simulate the intervention.") println("Act before decompensation.") }
The Frank-Starling Mechanism
The heart has its own baseline law. The more blood fills the ventricle (preload), the harder it contracts. Up to a point. Past that point, the muscle overstretches and output drops. This is the Frank-Starling curve:
use cardiovascular::* fn main() { // Normal heart: strong Frank-Starling response println("=== Normal Heart ===") println(frank_starling_normal(80.0)) // EDV 80 -> SV ~88 println(frank_starling_normal(120.0)) // EDV 120 -> SV ~113 println(frank_starling_normal(160.0)) // EDV 160 -> SV ~118 (plateau) // Failing heart: flat curve, poor response to preload println("=== Failing Heart ===") println(frank_starling_failing(80.0)) // EDV 80 -> SV ~33 println(frank_starling_failing(120.0)) // EDV 120 -> SV ~48 println(frank_starling_failing(160.0)) // EDV 160 -> SV ~54 (barely improves) }
The Frank-Starling curve uses an exponential saturation function: sv = sv_max * (1 - exp(-k * (edv - edv_min))). This is NOT a sigmoid. Scyla never uses sigmoid for biological gating. The activation curve is exponential because that is what the biology does. The patent claims depend on this distinction.
The Nernst Equation: Where Biology Meets Physics
Ion concentrations across cell membranes create voltage. This voltage drives every heartbeat, every nerve impulse, every muscle contraction. The Nernst equation computes the equilibrium potential for any ion:
use membrane_potential::* fn main() { // Potassium: the resting potential ion let e_k = nernst_potassium() println("K+ equilibrium:") println(e_k) // -94 mV // Sodium: the action potential ion let e_na = nernst_sodium() println("Na+ equilibrium:") println(e_na) // +67 mV // The ~160 mV difference between these two // is the energy source for every signal in your body. // Hodgkin and Huxley won the Nobel Prize for modeling // how ion channels gate this energy. (1963) // Scyla uses their exact equations. }
The Proteome: 20,431 Proteins
Every reviewed human protein from UniProt is a native lookup in Scyla. Every one has an accession number, a gene name, a function, and a sequence:
use human_proteome::* fn main() { let p53 = lookup_protein("P04637") println(p53.name) // Cellular tumor antigen p53 println(p53.gene) // TP53 println(p53.function) // Tumor suppressor... let insulin = lookup_protein("P01308") println(insulin.name) // Insulin println(insulin.gene) // INS println("Total human proteins:") println(proteome_count()) // 20431 }
Every simulation, every digital twin, every clinical decision support system starts from the baseline. If the baseline is wrong, everything downstream is wrong.
In Scyla, the baseline is not guessed. It is not learned from data. It is the published, cited, compiled value from the source that discovered it. Tonic drive from pharmacology textbooks. Ion concentrations from Hodgkin and Huxley. Protein functions from UniProt.
The baseline is the ground truth. Everything else is a perturbation from it.
What is Governance?
Every other programming language treats compliance as an afterthought. You write the code, then you write the tests, then you write the documentation, then a regulator asks where you got your numbers and you dig through a spreadsheet.
Scyla inverts this. Governance is a first-class construct in the language.
The Three Rule Types
Scyla's constitutional type system classifies every constraint into one of three categories:
Hard limits that cannot be crossed under any circumstance. A dose ceiling. A physiological impossibility. The speed of light. The compiler will refuse to produce output that violates an ABSOLUTE rule.
Requirements that must be satisfied with a cited justification. A clinical guideline. An FDA regulation. A hospital protocol. MANDATORY rules require evidence, not just compliance.
Parameters where professional judgment applies within a bounded range. A clinician picks within the range. The compiler ensures the pick stays inside the bounds.
Why This Matters
When a regulator asks "how do you know this dose is safe?", there are two possible answers:
Without Scyla: "Our AI model was trained on data that included safe doses, so we believe the output is probably safe."
With Scyla: "The dose ceiling of 2g/day for metformin is an ABSOLUTE rule in stdlib/dosing.sy line 847, cited to the FDA label (NDA 020357). The compiler will not produce output exceeding this value. The source hash is verifiable."
That is the difference between trust-based compliance and structural compliance.
Governance Files
Governance rules live in .sy files inside a governance/ directory. Each file defines rules for a specific regulatory framework:
fda_21cfr11.sy -- FDA 21 CFR Part 11 (electronic records) hipaa.sy -- HIPAA privacy and security gdpr.sy -- EU General Data Protection Regulation cmc_pharma.sy -- Chemistry, Manufacturing, and Controls gmp.sy -- Good Manufacturing Practice iso_13485.sy -- Medical device quality management custom_hospital.sy -- Your institution's rules (you write this)
The biology is universal. It does not have a culture. Hydrogen weighs 1.008 in every country on earth.
The governance is local. It changes every border you cross. FDA rules differ from EMA rules differ from PMDA rules.
Scyla separates the two. The biology is compiled once. The governance is programmable by the people who know their context.
The comply Command
The comply command runs your code against a governance rule set and reports every pass, fail, and warning. It does not change your code. It tells you what your code does and does not satisfy.
Basic Usage
$ scylac comply fda governance/fda_21cfr11.sy patient_monitor.sy
This checks patient_monitor.sy against the FDA 21 CFR Part 11 rule set. The output is a structured compliance report:
SCYLA GOVERNANCE COMPLIANCE REPORT ============================================= [FAIL] FDA-11-001 Audit Trail Required CRITICAL Ref: 21 CFR 11.10(e) Fix: Add sira_hash(state, timestamp, author) [FAIL] FDA-CYBER-001 Encryption Required CRITICAL Ref: FDA Cybersecurity Guidance 2025 Fix: Add encrypt(data, "AES-256") [PASS] CMC-PK-004 Homeostatic Return [PASS] CMC-PK-001 Half-Life Source Citation [PASS] CMC-PK-003 Baseline Declaration [PASS] FDA-820-003 Output Range Verification ============================================= SUMMARY: 20/22 rules passed 2 CRITICAL violations STATUS: NON-COMPLIANT
What Gets Checked
The comply command checks your code against the rules defined in the governance file. Every rule has:
rule FDA-11-001 { type: ABSOLUTE, name: "Audit Trail Required", ref: "21 CFR 11.10(e)", check: code_contains("sira_hash"), fix: "Add sira_hash(state, timestamp, author)", severity: CRITICAL, } rule CMC-PK-001 { type: MANDATORY, name: "Half-Life Source Citation", ref: "ICH Q8(R2)", check: all_half_lives_have_citation(), fix: "Add citation to bio_half_life() calls", severity: MAJOR, }
Compliance by Framework
You can run multiple governance files against the same code:
# Check FDA compliance $ scylac comply fda governance/fda_21cfr11.sy my_app.sy # Check HIPAA compliance $ scylac comply hipaa governance/hipaa.sy my_app.sy # Check both at once $ scylac comply all governance/*.sy my_app.sy # Check a custom hospital rule set $ scylac comply custom governance/uab_hospital.sy my_app.sy
The Compliance Report
Every comply report includes:
- Rule ID and name
- Regulatory reference (CFR section, ISO clause, ICH guideline)
- PASS/FAIL/WARN status
- Fix suggestion with the specific code change needed
- Severity (CRITICAL, MAJOR, MINOR, INFO)
- Summary with total pass/fail counts
The report is machine-readable. Export it as JSON for audit trails:
$ scylac comply fda governance/fda_21cfr11.sy my_app.sy --format json > audit.json
In Scyla, governance compliance is not a test you run once before release. It is a command you run every time you compile. If you fail, you know before the code ships. If you pass, the report IS your audit trail.
Writing Your Own Rules
The governance files that ship with Scyla cover FDA, HIPAA, GDPR, and GMP. But the real power is writing your own rules for your own context.
A hospital in Birmingham has different protocols than a hospital in Berlin. A pharma company running a Phase III trial has different requirements than a research lab generating synthetic data. Scyla lets each institution write rules that reflect their reality.
Rule Anatomy
// UAB Hospital -- Vancomycin Monitoring Protocol // Approved by Pharmacy & Therapeutics Committee, 2025 rule UAB-VANCO-001 { type: MANDATORY, name: "AUC-Based Vancomycin Monitoring", ref: "ASHP/IDSA 2020 Guidelines", check: vancomycin_uses_auc_not_trough(), fix: "Replace trough monitoring with AUC/MIC targeting 400-600", severity: MAJOR, } rule UAB-VANCO-002 { type: ABSOLUTE, name: "Vancomycin AUC Ceiling", ref: "ASHP/IDSA 2020: AUC >600 = nephrotoxicity risk", check: vancomycin_auc_below(600.0), fix: "Reduce dose to achieve AUC/MIC 400-600", severity: CRITICAL, } rule UAB-RENAL-001 { type: MANDATORY, name: "Renal Dose Check", ref: "UAB Pharmacy Protocol 2024-07", check: all_renally_cleared_drugs_have_gfr_check(), fix: "Add gfr_check() before dosing renally cleared drugs", severity: MAJOR, }
Check Functions
Each rule has a check field that calls a function returning true (pass) or false (fail). You write these check functions in Scyla:
fn vancomycin_uses_auc_not_trough() -> Bool { // Check that the code uses AUC-based monitoring // and does NOT use trough-only monitoring let has_auc = code_contains("vancomycin_auc") let has_trough_only = code_contains("vancomycin_trough") && !code_contains("vancomycin_auc") return has_auc && !has_trough_only } fn all_renally_cleared_drugs_have_gfr_check() -> Bool { // Every drug with renal clearance >50% must // have a GFR check before dosing let renal_drugs = find_calls_to("dose") .filter(|d| d.drug.renal_clearance > 0.5) for drug in renal_drugs { if !preceded_by("gfr_check", drug) { return false } } return true }
The DISCRETIONARY Type
ABSOLUTE rules are binary: pass or fail. MANDATORY rules require cited evidence. But DISCRETIONARY rules define a range where clinical judgment applies:
rule UAB-BP-001 { type: DISCRETIONARY, name: "Target MAP in Septic Shock", ref: "Surviving Sepsis Campaign 2021", range: [65.0, 75.0], units: "mmHg", note: "Clinician selects target within range based on patient history. Chronic hypertension may warrant higher target.", severity: INFO, }
The compiler ensures the clinician's pick stays inside the bounds. It does not pick for them. The human governs. The code enforces the boundaries of that governance.
Sharing Rule Sets
Governance files are plain .sy files. They can be:
- Version controlled in Git alongside your code
- Shared between departments or institutions
- Audited with full change history
- Composed from multiple rule sets (hospital + FDA + custom)
# Run your hospital rules + FDA rules + custom trial rules $ scylac comply all \ governance/fda_21cfr11.sy \ governance/uab_hospital.sy \ governance/trial_NCT0012345.sy \ my_clinical_app.sy
Scyla does not tell you what the rules are. Your institution does. Your regulators do. Your clinical context does. Scyla gives you a language to express those rules in code, and a compiler that enforces them structurally.
The biology is universal. The governance is yours.
She is the human in the code. Not the AI.