# Tripartite Synapse — Pseudocode v10

> Companion document: `tripartite_synapse_v10_biology.md` explains the biological
> meaning of every variable and behavior. This document is the logic only.

---

## Conventions

```
SCOPE   = { DAY, NIGHT }
CONTEXT = { AP, NOT_AP, bAP, NOT_bAP, CONTINUOUS }
COMPONENTS = { PRE, POST, DEND, SOMA, AXON, ASTRO }

DAY variables
  budget          fast resource (energy + consumables), consumed by behavior
  fast_trace      local record, decays in ms–s, biases next behavior
  possible_tag    accumulates from fast_trace, decays in s–min
  endurance_need  accumulates on interrupted local success, decays in s–min

DAY→NIGHT bridge
  tag             decays in hours; POST: CANDIDATE → STABLE

NIGHT variables
  energy          assembly ATP, NOT recoverable
  material        structural proteins, RECOVERABLE after decay
  structure       strength ceiling   — READ in DAY, WRITTEN in NIGHT
  budget_ceiling  endurance ceiling  — READ in DAY, WRITTEN in NIGHT

LOCALITY RULE
  every evaluation uses only local state + signals that have arrived.
  no component reads another compartment's internal state.

CLEFT MESSAGE CHANNELS (the only PRE/POST/ASTRO interaction — each writes, others read)
  glutamate     PRE → POST, ASTRO     (forward transmitter; cleared by ASTRO)
  astro_Dserine ASTRO → POST          (NMDA co-agonist gate)
  retro_NO      POST → PRE  (+)       (NO/BDNF: "release reached a responsive target")
  retro_eCB     POST → PRE  (−)       (endocannabinoid: "over-driven, suppress release" = DSE)
  Each channel decays/clears; a component reads a channel into a local copy and computes locally.
```

---

## Saturating form (used wherever a graded signal drives output)

```
sat(x, K) = x / (K + x)
```

---

## Fixed parameters

```
K_release  K_AMPA  K_Dserine
Mg_eject   Ca_STP   Ca_TAG   eCB_thr
elig       dop_thr  tag_thr  tag_expiry
traj_thr   endur_thr
spillover  inactivation  overload
homeostatic_ceiling  decay_rate  capacity_decay_rate  recycle

dopamine  NE  ACh                      // organism broadcast (external)
glucose                                // vascular ceiling (external)
geometry                               // dendritic topology (external)
```

---
---
# DAY

Execution contexts (AP, bAP, CONTINUOUS): run behavior, spend budget, deposit traces.
Replenishment contexts (NOT_AP, NOT_bAP): competitive refill, ship downstream, decay traces, set tags.

---

## Pool-filling primitives

Two shapes share the core "rise toward a ceiling, bounded by the gap, paying budget":

```
// PRIVATE: fill own pool from own reserve toward own ceiling, at a rate cap
fill(pool, ceiling, rate_cap, cost, budget):
    amount   = min(rate_cap, ceiling - pool)·Δt          // bounded by rate AND gap
    pool    += amount
    budget  -= amount·cost

// CONTESTED: fill toward ceiling by a rationed share of a shared supply S
refill(component c from supply S):
    demand   = c.budget_ceiling - c.budget               // claim = gap to ceiling
    total    = Σ demand over components on S
    factor   = min(1, S / (total + ε))
    c.budget += demand × factor                          // never exceeds ceiling
    S        -= demand × factor
```

Choose by source: a pool drawn from a **private reserve** uses `fill`; a pool drawn from a
**contested shared supply** uses `refill`. The distinction is biologically real — RRP comes
from the bouton's private reserve pool, while operational budget comes from astrocytic lactate
that neighbours compete for.

---

## PRE

```
// ─── PRESYNAPSE EXTERNAL INTERFACE ────────────────────────────────────────
// PRE computes locally. Everything below crosses its boundary as a signal it
// emits or a resource/signal it receives. It never reads another component's state.
//
// OUTPUT (PRE writes; others read)
//   glutamate          → POST, ASTRO    forward transmitter; ASTRO clears it
//
// RESOURCES IN (others write; PRE reads in NOT_AP)
//   astro_lactate[syn] ← ASTRO          primary fast fuel  → pre_budget
//   axon_ship_pre      ← AXON           secondary fuel     → pre_budget
//                                        ship(axon_budget → pre_budget, gap_to(pre))
//   pre_material       ← AXON  (NIGHT)  AZ proteins (RIM, Munc13, VGCC subunits)
//   pre_energy         ← SOMA  (NIGHT)  assembly ATP for active-zone construction
//
// BACKWARD MESSAGES IN (POST writes from its own state; PRE reads)
//   retro_NO  (+)      ← POST           "release reached a responsive target" → endurance
//   retro_eCB (−)      ← POST           DSE: "over-driven, release less"      → brake
//
// CLEFT SELF-FEEDBACK (PRE reads the channel it writes)
//   glutamate          ← cleft          spillover autoreceptor brake (mGluR2/3 on PRE)
//
// ORGANISM BROADCAST IN (external; arrives as a local level)
//   dopamine           ← VTA            gates pre_tag (the non-local coincidence)
//   NE, ACh            ← LC, basal      excitability/threshold context
//
// OWN STRUCTURE (written NIGHT, read DAY)
//   pre_structure      slot_ceiling, VGCC_coupling, refill_ceiling
//   pre_budget_ceiling endurance ceiling (bounds replenishment)
//
// EMERGENCY
//   shockwave_lockdown ← ASTRO          global Ca²⁺ wave overrides PRE
// ──────────────────────────────────────────────────────────────────────────

DAY | AP:
    // SENSE — deposit fast trace (residual Ca²⁺ from this spike; also drives release)
    pre_fast_trace += spike_Ca(input_freq)

    // BEHAVE — release, or fail if depleted
    if pre_budget < release_cost:
        suppress(NT_flux)
        // EVALUATE (endurance) — interrupted LOCAL success, confirmed by retro_NO
        if pre_fast_trace > traj_thr:
            pre_endurance_need += pre_fast_trace × (1 + retro_NO_local)
        exit
    drive = sat(pre_fast_trace, K_release) × (1 - retro_eCB_local)   // received DSE brake
    if RRP > 0:
        NT_flux = RRP × drive
        // EMIT — glutamate into cleft (read by POST, ASTRO)
        glutamate += NT_flux·Δt
        RRP -= NT_flux·Δt;  pre_budget -= NT_flux·fusion_cost
    if glutamate > spillover: drive *= brake             // own-cleft autoreceptor brake
    // no RECOVER here — RRP refills in NOT_AP; high-frequency firing depletes
    // faster than it recovers → short-term depression deepens

DAY | NOT_AP:
    // RECEIVE — latch arrived backward messages; replenish budget (contested supply)
    retro_NO_local  = retro_NO
    retro_eCB_local = retro_eCB
    refill(pre from astro_lactate[syn] + axon_ship_pre)

    // RECOVER — refill RRP from private reserve toward its ceiling
    fill(RRP, pre_structure.slot_ceiling, pre_structure.refill_ceiling, vatpase_cost, pre_budget)

    // EVALUATE (strength) — eligibility → possible_tag → tag (needs dopamine)
    if pre_fast_trace > elig: pre_possible_tag += pre_fast_trace
    if dopamine > dop_thr and pre_possible_tag > tag_thr:
        pre_tag += dopamine × pre_possible_tag

    // DECAY — all traces and channels recede, closing their windows
    pre_fast_trace     *= decay(100ms)
    pre_possible_tag   *= decay(s)
    pre_endurance_need *= decay(min)
    pre_tag            *= decay(hr)
    dopamine           *= decay(ms)                      // broadcast transient fades
    retro_NO *= decay(s);  retro_eCB *= decay(s)         // backward channels clear
```

---

## POST

```
DAY | NOT_bAP:
    refill(post from astro_lactate[syn] + dend_ship_post)

    // SOURCE 1 — AMPA: current + small Ca + begins Mg ejection
    a = sat(glutamate, K_AMPA)
    AMPA_current = a × AMPA_surface;  Vm += AMPA_current
    post_fast_trace += AMPA_Ca·AMPA_current;  post_budget -= AMPA_cost

    // SOURCE 2 — NMDA: large Ca if local coincidence
    if Vm > Mg_eject and astro_Dserine > thr and glutamate > 0:
        post_fast_trace += NMDA_Ca(glutamate)·rise_speed();  post_budget -= NMDA_cost
        retro_NO += NO_emit(post_fast_trace);  post_budget -= NO_synth_cost
        // POST → PRE (+): nNOS coupled to NMDA emits NO/BDNF — "your release was effective"

    // backward brake to PRE (−): strong depolarization → endocannabinoid (DSE)
    if Vm > eCB_thr:
        retro_eCB += eCB_emit(Vm);  post_budget -= eCB_synth_cost
        // POST → PRE (−): "I am over-driven — reduce release"

    post_fast_trace *= decay(ms)

    // CASE 1 — short-term potentiation: fill slots from private reserve (no dopamine)
    // NOT generic fill(): rate is Ca-driven, and the else-branch is the STD consequence
    if post_fast_trace > Ca_STP:
        AMPA_surface = min(AMPA_surface + Ca_insert(post_fast_trace),
                           post_structure.slot_ceiling)    // private: spine endosomal reserve
        post_budget -= traffic_cost
    else:
        AMPA_surface = max(AMPA_surface - drift·Δt, baseline)     // STD = consequence

    // interrupted success (LOCAL: my Ca was climbing toward a tag)
    if post_budget < req_cost and post_fast_trace > traj_thr and post_fast_trace_rising:
        post_endurance_need += post_fast_trace

    // CASE 2 — tagging CANDIDATE
    if post_fast_trace > Ca_TAG: post_possible_tag += post_fast_trace
    post_possible_tag *= decay(min);  post_endurance_need *= decay(min)
    post_budget -= pka_cost
    dopamine *= decay(ms)
    if dopamine > dop_thr and post_possible_tag > tag_thr:
        post_tag += dopamine × post_possible_tag                  // STABLE
    post_tag *= decay(hr)

DAY | bAP:
    // SOURCE 3 — bAP: depolarization + Ca, amplifies existing signal
    Vm += bAP_depol × dend_structure.bAP_fidelity;  post_budget -= bAP_cost
    if post_possible_tag > Ca_TAG: post_fast_trace += bAP_Ca_boost()
```

---

## DEND

```
DAY | bAP:
    bAP_local, reached = propagate(SOMA.fired, dend_structure.bAP_fidelity,
                                   dend_budget, geometry)
    dend_budget -= prop_cost × reached
    // interrupted success (LOCAL: my branch was strongly active)
    if reached < full and dend_fast_trace > traj_thr:
        dend_endurance_need += dend_fast_trace
    dend_fast_trace += bAP_Ca(bAP_local) + spine_spillover();  dend_fast_trace *= decay(300ms)
    dend_budget -= branch_Ca_cost
    branch_Vm = integrate(POST.Vm, spines);  dend_budget -= integrate_cost

DAY | NOT_bAP:
    dend_fast_trace *= decay(300ms);  dend_endurance_need *= decay(min)
    refill(dend from astro_lactate[branch] + soma_ship_dend)
    ship(dend_budget → post_budget, gap_to(post))
    if dend_fast_trace > elig: dend_possible_tag += dend_fast_trace
    dend_possible_tag *= decay(s);  dopamine *= decay(ms)
    if dopamine > dop_thr and dend_possible_tag > tag_thr:
        dend_tag += dopamine × dend_possible_tag
    dend_tag *= decay(hr)
    if dend_tag > tag_expiry and dend_budget > translate_cost:
        dend_budget -= translate_cost
    commit_threshold *= 1/(1 + ACh·gain)
```

---

## SOMA

```
DAY | AP:
    threshold = soma_structure.baseline / (1)            // baseline strength
              × (1 + soma_adaptation)
              × neuromod(NE, ACh)
    can_fire  = soma_Na_inactivation < inactivation
    if branch_Vm > threshold and can_fire:
        if soma_budget < ap_cost:
            // interrupted success (LOCAL: nuclear Ca climbing toward CREB)
            if soma_fast_trace > traj_thr and soma_fast_trace_rising:
                soma_endurance_need += soma_fast_trace
            exit
        fired = True;  soma_budget -= ap_cost
        soma_Na_inactivation += ap_amp                   // → refractory (emergent)
        soma_adaptation      += ap_contrib               // → threshold rise
        soma_fast_trace      += nuclear_Ca()             // → plasticity
        soma_budget -= nuclear_cost
        if soma_fast_trace > elig: soma_possible_tag += soma_fast_trace
        soma_possible_tag *= decay(s);  dopamine *= decay(ms)
        if dopamine > dop_thr and soma_possible_tag > tag_thr:
            soma_tag += dopamine × soma_possible_tag
        soma_tag *= decay(hr);  soma_budget -= creb_cost

DAY | NOT_AP:
    // bottom-up alignment: suprathreshold input during refractory (LOCAL)
    if branch_Vm > threshold and soma_Na_inactivation > inactivation:
        soma_refractory_alignment += (branch_Vm - threshold) × soma_Na_inactivation
    recovery = base_recovery × (1 + soma_refractory_alignment)
    soma_Na_inactivation      *= decay(τ_Na / recovery)
    soma_adaptation           *= decay(τ_adapt)
    soma_fast_trace           *= decay(τ_nuclear)
    soma_refractory_alignment *= decay(τ_align)          // self-limiting
    soma_endurance_need       *= decay(min)
    fill(soma_budget, soma_budget_ceiling, mito_output, 0, soma_budget)  // private: own mitochondria, no external cost
    branch_Vm = integrate(DEND.branch_Vm, branches)
    ship(soma_budget → dend_budget, gap_to(dend))
    ship(soma_budget → axon_budget, gap_to(axon))
```

---

## AXON

```
DAY | AP:
    reliability = axon_structure.propagation × (1 - fail(axon_fast_trace))
    if axon_budget < prop_cost:
        reliability *= budget_factor
        // interrupted success (LOCAL: I was propagating a strong train)
        if axon_fast_trace > traj_thr:
            axon_endurance_need += axon_fast_trace
    delivered = fired × reliability;  axon_budget -= prop_cost × delivered
    axon_fast_trace += delivered;  axon_fast_trace *= decay(s)

DAY | NOT_AP:
    axon_fast_trace *= decay(s);  axon_endurance_need *= decay(min)
    refill(axon from soma_ship_axon + astro_lactate[shaft])
    ship(axon_budget → pre_budget, gap_to(pre))
    if axon_fast_trace > elig: axon_possible_tag += axon_fast_trace
    axon_possible_tag *= decay(s);  dopamine *= decay(ms)
    if dopamine > dop_thr and axon_possible_tag > tag_thr:
        axon_tag += dopamine × axon_possible_tag
    axon_tag *= decay(hr)
```

---

## ASTRO

```
DAY | CONTINUOUS:
    astro_central_budget += glycolysis(glucose)·Δt       // root, capped by glucose

    // demand-weighted lactate allocation across territory
    for each astrosynapse i:
        demand[i] = clearance_load[i] × astro_structure[i].delivery_eff
    factor = min(1, astro_central_budget / (Σ demand · lactate_cost + ε))
    for each i:
        astro_lactate[i] = demand[i] × factor
        astro_central_budget -= astro_lactate[i] × lactate_cost

    // per-astrosynapse fast operation (synapse i)
    glutamate[i] -= astro_structure[i].EAAT × glutamate[i]·Δt
    astro_central_budget -= clearance × EAAT_cost
    astro_Dserine[i] += astro_structure[i].Dserine_tonic·Δt

    if glutamate[i] > spillover:
        astro_fast_trace[i] += mGluR_Ca();  astro_fast_trace[i] *= decay(s)
        want = sat(astro_fast_trace[i], K_Dserine) × Ds_max
        got  = min(want, astro_central_budget × Ds_frac)
        // interrupted success (LOCAL: I was under high demand)
        if got < want and astro_fast_trace[i] > traj_thr:
            astro_endurance_need[i] += (want - got)
        astro_Dserine[i] += got;  astro_central_budget -= got × Ds_cost
        drive_pre[i] *= brake                            // same signal, PRE brake
        if astro_fast_trace[i] > elig: astro_possible_tag[i] += astro_fast_trace[i]
        astro_possible_tag[i] *= decay(s);  dopamine *= decay(ms)
        if dopamine > dop_thr and astro_possible_tag[i] > tag_thr:
            astro_tag[i] += dopamine × astro_possible_tag[i]
        astro_tag[i] *= decay(hr)
    astro_endurance_need[i] *= decay(min)
    if astro_fast_trace[i] > overload: trigger(lockdown)
```

---

## Special — Shockwave Lockdown

```
DAY or NIGHT | OVERLOAD:
    Vm = HYPERPOLARIZED;  AMPA_surface = mass_internalize() → post reserve
    axon_fast_trace += overdrive();  astro_central_budget -= emergency_cost
```

---
---
# NIGHT

Build ceilings (structure = strength, budget_ceiling = endurance) from DAY evidence.
Two economies (energy: astrocyte→astrosynapse ; material: soma→spine/bouton) compete.
Unmaintained ceilings decay; recovered material funds the rest.

---

## Step 1 — Replenish and distribute

```
NIGHT | 1:
    // energy economy (astrocyte central → astrosynapses, tag-weighted)
    astro_central_budget   += overnight_glycolysis(glucose)·Δt
    astro_central_energy   += overnight_astro_energy()·Δt
    astro_central_material += astro_cellbody_synth()·Δt
    W = Σ astro_tag[i] over astro_tag[i] > tag_expiry
    for each i with astro_tag[i] > tag_expiry:
        w = astro_tag[i]/W
        astro_energy[i]   += astro_central_energy   × w
        astro_material[i] += astro_central_material × w

    // material economy (soma → branch/axon → spine/bouton)
    soma_budget   += overnight_mito()·Δt
    soma_energy   += overnight_soma_energy()·Δt
    soma_material += CREB_synth(soma_tag)·Δt                  // bottleneck

    dend_material += soma_material × f_dend;  axon_material += soma_material × f_axon
    soma_material -= (f_dend + f_axon)·soma_material
    post_material += dend_material × f_spine;  dend_material -= f_spine·dend_material
    pre_material  += axon_material × f_bouton; axon_material -= f_bouton·axon_material

    {pre,post,dend,axon}_energy += soma_energy × f_energy[·]
    {pre,post,dend,axon}_budget += astro_lactate_reserve × f[·]·Δt
```

## Step 2 — Strength commits (raise structure)

```
NIGHT | 2:
    coherence = (pre_tag, post_tag, astro_tag all > tag_expiry) ? bonus : 1

    for each component c with c_tag > tag_expiry:
        Δ = min(slot_cost, c_material, c_energy × f)
        c_structure += Δ × (coherence if c in {pre,post,astro} else 1)
        c_material  -= Δ;  c_energy -= Δ × assembly_cost
        if Δ < slot_cost: queue(c_strength_deficit → next NIGHT)
    // astro_structure self-reinforcing: higher → future LTP easier
```

## Step 2b — Endurance commits (raise budget_ceiling)

```
NIGHT | 2b:
    // driven by endurance_need (interrupted local success), NO dopamine
    // competes with step 2 for the SAME material + energy
    for each component c with c_endurance_need > endur_thr:
        Δ = min(cap_cost, c_material × f_cap, c_energy × f_cap)
        c_budget_ceiling += Δ
        c_material -= Δ;  c_energy -= Δ × biogenesis_cost
        if Δ < cap_cost: queue(c_endurance_deficit → next NIGHT)
```

## Step 3 — Passive decay (both ceilings, by neglect)

```
NIGHT | 3:
    remaining = total_material - consumed_by_commits
    maint     = remaining × maint_frac / synapse_count

    for each synapse:
        {pre,post,dend,astro}_structure -= decay_rate·Δt
        {pre,post,dend,astro}_budget_ceiling -= capacity_decay_rate·Δt
        if maint ≥ maint_cost:
            structure += full_maint;  budget_ceiling += full_cap_maint
        else:
            structure += maint × frac;  budget_ceiling += maint × cap_frac
            // both drift down — depotentiation / endurance-loss by neglect

    for each synapse with net_change < 0:
        rec = |net_change| × recycle
        {pre,post,astro}_material += rec × frac           // material recovered, energy not
```

## Step 4 — Homeostatic scaling

```
NIGHT | 4:
    if soma_tag > homeostatic_ceiling:
        s = homeostatic_ceiling / soma_tag
        for each synapse:
            post_structure.slot_ceiling *= s;  pre_structure.slot_ceiling *= s
        soma_material += Σ reduction × recycle
```

## Step 5 — Clear traces

```
NIGHT | 5:
    all fast_trace = 0;  all possible_tag = 0;  all endurance_need = 0
    soma_Na_inactivation = soma_adaptation = soma_refractory_alignment = 0
    for each tag: if tag < tag_expiry: tag = 0           // else carry forward
    // structure and budget_ceiling PERSIST
```

---

## One-view summary

```
DAY    behavior runs within structure (strength) and budget_ceiling (endurance),
       both filled by competition; consumes budget; deposits fast_trace.
       fast_trace + non-local coincidence            → tag            (strength evidence)
       depletion + interrupted LOCAL success         → endurance_need (endurance evidence)
       traces decay in NOT/CONTINUOUS contexts.

NIGHT  tag            → raise structure
       endurance_need → raise budget_ceiling
       both draw the SAME material + energy → strength and endurance compete
       unmaintained ceilings decay → freed material funds the rest.

LOCALITY  every evaluation uses only local state + arrived signals.
          cross-compartment influence travels only as signals that become local.
```
