From 11fbc839e48dbc637148745b861e07bb299beb34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ahmet=20Bar=C4=B1=C5=9F=20G=C3=BCnayd=C4=B1n?=
webgpu-fly runs a whole-animal Drosophila nervous system inside a web browser with no installation and no server. The FlyWire FAFB whole-brain connectome (139,255 neurons, ~15 million synaptic connections) and the Janelia MANC ventral-nerve-cord connectome (23,188 neurons, 5.2 million connections) are each simulated as leaky integrate-and-fire (LIF) networks in fused WebGPU compute kernels — gather, integrate, threshold and reset in a single kernel, with presynaptic-neurotransmitter signs pre-baked into the connection weights so the inner loop never branches on excitatory/inhibitory type. The brain's descending command neurons drive the spinal cord by cell-type name match (the same named cell on both sides of the brain–VNC boundary), and the spine's motor neurons actuate a physically simulated 67-body, 111-actuator TuragaLab flybody model running in MuJoCo compiled to WebAssembly. A 64×16 retina rendered each frame from the fly's own head pose is fed back into the brain's optic neurons, closing a sensorimotor loop. An optional trained reinforcement-learning walking policy (Vaxenburg et al. 2025) runs as a pure-TypeScript forward pass verified element-wise against the published SavedModel checkpoint. The deployment is a game: the player fires real descending neurons with keypresses to steer the fly to a target, and a winning run produces a deterministic, shareable replay URL that re-executes the identical neuron cascade against the same connectome — a brain trace, not a video. Performance is reported honestly: the brain LIF kernel is memory-bandwidth-bound and runs at ~0.25 kHz of biological time on an Apple M2 Pro, benchmarked on the same machine against NEST 3.10 (0.67 kHz) and a hand-written multicore Rust port (0.45 kHz). The original 1 kHz target was unreachable for any of the three on that hardware; the contribution is reachability — a real connectome simulation behind a single URL — not raw throughput. Known limitations (RL-walker speed gap, closed-loop visual-reflex approximation, kinematic-assist options) are enumerated in LIMITATIONS.md.",
+ "description": " webgpu-fly runs a whole-animal Drosophila nervous system inside a web browser with no installation and no server. The FlyWire FAFB whole-brain connectome (139,255 neurons, ~15 million synaptic connections) and the Janelia MANC ventral-nerve-cord connectome (23,188 neurons, 5.2 million connections) are each simulated as leaky integrate-and-fire (LIF) networks in fused WebGPU compute kernels — gather, integrate, threshold and reset in a single kernel, with presynaptic-neurotransmitter signs pre-baked into the connection weights so the inner loop never branches on excitatory/inhibitory type. The brain's descending command neurons drive the spinal cord by cell-type name match (the same named cell on both sides of the brain–VNC boundary), and the spine's 369 leg motor neurons are averaged into a walking magnitude and a turn bias that scale a hand-written tripod gait, which in turn actuates a physically simulated 67-body, 111-actuator TuragaLab flybody model running in MuJoCo compiled to WebAssembly. The connectome scales that gait; it does not generate the stepping rhythm, which is an analytic sinusoid of simulation time. A 64×16 retina rendered each frame from the fly's own head pose is fed back into the brain's optic neurons, closing a sensorimotor loop. An optional trained reinforcement-learning walking policy (Vaxenburg et al. 2025) runs as a pure-TypeScript forward pass checked element-wise against an independent NumPy re-run of the same extracted weights; that check validates the port's arithmetic, not the assumed layer architecture against the original SavedModel. The deployment is a game: the player fires real descending neurons with keypresses to steer the fly to a target, and a winning run produces a deterministic, shareable replay URL that re-executes the identical neuron cascade against the same connectome — a brain trace, not a video. Performance is reported honestly: the brain LIF kernel is memory-bandwidth-bound and runs at ~0.25 kHz of biological time on an Apple M2 Pro, benchmarked on the same machine against NEST 3.10 (0.67 kHz) and a hand-written multicore Rust port (0.45 kHz). The original 1 kHz target was unreachable for any of the three on that hardware; the contribution is reachability — a real connectome simulation behind a single URL — not raw throughput. Known limitations (RL-walker speed gap, closed-loop visual-reflex approximation, kinematic-assist options) are enumerated in LIMITATIONS.md.",
"keywords": [
"WebGPU",
"WebAssembly",
diff --git a/CITATION.cff b/CITATION.cff
index 2ccd971..3e65785 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -33,13 +33,18 @@ abstract: >-
leaky integrate-and-fire networks in fused WebGPU compute kernels, with
presynaptic-neurotransmitter signs baked into the weights so the inner
loop never branches on excitatory/inhibitory type. Brain command
- neurons drive the spine by cell-type name match; the spine's motor
- neurons drive a physically simulated 67-body, 111-actuator TuragaLab
- flybody model running in MuJoCo compiled to WebAssembly. A 64x16 retina
+ neurons drive the spine by cell-type name match; the spine's 369 leg
+ motor neurons are averaged into a walking magnitude and a turn bias that
+ scale a hand-written tripod gait, which actuates a physically simulated
+ 67-body, 111-actuator TuragaLab flybody model running in MuJoCo
+ compiled to WebAssembly — the connectome scales that gait but does not
+ generate its stepping rhythm. A 64x16 retina
rendered from the fly's head pose feeds back into the brain's optic
neurons. An optional trained reinforcement-learning walking policy
- (Vaxenburg et al. 2025) runs as a pure-TypeScript forward pass verified
- element-wise against the published checkpoint. The project is a game
+ (Vaxenburg et al. 2025) runs as a pure-TypeScript forward pass checked
+ element-wise against an independent NumPy re-run of the same extracted
+ weights, which validates the port's arithmetic but not the assumed
+ layer architecture against the original SavedModel. The project is a game
with shareable, deterministic replay URLs: a shared link re-executes
the identical neuron cascade against the same connectome. The brain LIF
kernel is memory-bandwidth-bound and runs at ~0.25 kHz biological time
diff --git a/LIMITATIONS.md b/LIMITATIONS.md
index a0f9321..207614e 100644
--- a/LIMITATIONS.md
+++ b/LIMITATIONS.md
@@ -10,6 +10,12 @@ for "a real connectome on a phone in 30 seconds." Treat it as a teaching,
demonstration, and intuition-building tool — not as a validated platform for
publishing fly-brain dynamics.
+A second summary, for the body specifically: **the connectome does not walk
+the fly.** Roughly 20.3M connectome edges reach the body as about one scalar
+magnitude plus a turn bias per tick, and those two numbers scale a hand-written
+`sin(t × 10 Hz)` tripod. §8 is the complete shortcut inventory, with measured
+numbers for what the body does once the assist is off.
+
---
## 1. Performance — what "0.25 kHz" means and doesn't
@@ -58,30 +64,55 @@ publishing fly-brain dynamics.
## 4. The brain → spine → body path has documented approximations
-These are the "honest gaps" from the README, restated as limitations:
-
-1. **Trained RL walker walks slower than native.** The published policy
- checkpoint shipped **without** its `ObservationActionNorm` running
- mean/std, so the policy expects raw observations. We feed raw obs (which
- matches native best) or, optionally, a rollout-derived norm; either keeps
- actions non-saturating, but per-simulated-second walking speed is roughly
- **half** of native flybody. Part of the remaining gap is sim-time vs
- wall-time budget — we run ~25% of real time at 60 fps.
-2. **Closed-loop visual reflex is approximated.** When the target is visible,
- the default path can fall back to `turn ∝ retinal angle` because the
- brain's genuine optic→DN contralateral cascade takes longer than our 50 ms
- tick to develop. An opt-in "honest mode" replaces this with a
- brain-cascade-derived turn (dnLeft/dnRight asymmetry), which is slower and
- weaker but real. The shortcut is a usability default, not a biological
- claim.
-3. **Optional kinematic assist on the body.** In CPG mode (RL policy off),
- a soft assist on the freejoint translation, scaled by motor command, makes
- the demo watchable. It is **off** in RL-policy mode and can be turned off
- everywhere via the "Honest mode" button (`Physics.kinematicAssistEnabled`).
- With it off, the body moves only via actuator → ground reaction.
+These are the "honest gaps" from the README, restated as limitations. §8 is
+the complete list; these four are the ones with the longest history.
+
+1. **Trained RL walker does not walk.** The published policy checkpoint
+ shipped **without** its `ObservationActionNorm` running mean/std, so the
+ policy expects raw observations. We feed raw obs (which matches native
+ best) or, optionally, a rollout-derived norm; either keeps actions
+ non-saturating (|action| max ≈ 7). But every browser speed number ever
+ recorded for this path — including the "roughly half of native" figure
+ this item used to carry — was measured with the kinematic assist active
+ (item 3), which writes body velocity directly. With the assist off, the
+ fly capsizes within ~1.5 s of the policy being enabled and stays on its
+ back: uprightness −0.851 → −0.978, net travel 0.057–0.317 cm over ~2
+ simulated seconds. The network is self-consistent and the actions are
+ in-distribution; the defect is downstream of it — observation
+ construction, plant, or initial pose. See §8.
+2. **Closed-loop visual reflex is a hand-written angle law.** When the target
+ is visible, the default path is `turn ∝ retinal angle`
+ (`src/vnc.ts:369-378`), and forward speed is set from retinal area and
+ alignment regardless of branch (`src/vnc.ts:380-384`). The brain's genuine
+ optic→DN contralateral cascade takes longer than our 50 ms tick to
+ develop. An opt-in "honest mode" switches to a brain-cascade-derived turn
+ (dnLeft/dnRight asymmetry) — but that path falls back to the identical
+ hand-written law whenever cascade asymmetry is below 0.05, and the code
+ records the cascade's sign as empirically wrong for tracking under our
+ window (`src/vnc.ts:322-326`). It is an opt-in to a path that does not
+ currently work, not a working honest alternative.
+3. **Kinematic assist on the body — on by default, and it is the
+ locomotion.** A direct write to the freejoint sets translation and yaw
+ velocity from the motor command (`qvel[0]`, `qvel[1]`, `qvel[5]`,
+ re-asserted every substep, `src/physics.ts:596-604`). It is **not** off in
+ RL-policy mode: `fwdCmd`/`turnCmd` are written only by `driveLegs`
+ (`src/physics.ts:717-718`), the policy path skips `driveLegs`
+ (`src/room.ts:633-647`), and nothing clears them — not `reset()`
+ (`src/physics.ts:991-1010`) either — so the last CPG command keeps driving
+ the body throughout "trained walking". The "Honest mode" button turns the
+ assist off everywhere (`Physics.kinematicAssistEnabled`). With it off the
+ body's translation comes only from actuator → ground reaction, but the
+ pitch/roll damper (§8) still runs.
4. **Reference walking trajectory.** The trained policy expects a reference
trajectory; the default is a procedural straight line. Real fly mocap from
- the Vaxenburg deposit is wired in as opt-in (`__walkingRefFromMocap`).
+ the Vaxenburg deposit is wired in as opt-in (`__walkingRefFromMocap`), but
+ it is baked at 50 Hz (`tools/bake_walking_ref.py:46`) and replayed one
+ frame per 2 ms control tick (`src/physics.ts:896`), a 10× rate error, and
+ the 65-frame lookahead exceeds the 57-frame trajectory so the window wraps
+ mid-observation. Measured: enabling it takes |action| max from ~7 to
+ 3097–3250 and the fly spins 944–1051° in ~1.8 simulated seconds. The
+ opt-in currently makes the policy's input further out of distribution,
+ not closer.
## 5. Brain ↔ spine wiring is name-match, not synaptic
@@ -112,6 +143,128 @@ These are the "honest gaps" from the README, restated as limitations:
- Not a synaptically continuous brain-to-body reconstruction.
- Not benchmarked beyond a single M2 Pro / Chromium configuration.
+## 8. Full shortcut inventory — what actually moves the body
+
+The "Honest mode" button flips exactly three flags (`src/main.ts:669-683`).
+The table below has thirteen rows, and nine of them are behind no toggle at
+all. This section is all of them — the ones the button covers and the ones it
+does not — so the button is not the only place they are disclosed.
+
+Nothing here is a claim about the neural simulation. The FlyWire and MANC
+connectomes are real, both LIF networks genuinely run on the GPU, and the
+stimulus→cascade dynamics are connectome-derived. What follows is about how
+the *body* is driven, which is a different and much weaker story.
+
+### The information bottleneck
+
+Start here, because it frames every row of the table:
+
+```
+FlyWire 139,255 neurons / 15,091,983 edges
+ ↓ name join: 7 DN types → 16 of 23,188 VNC neurons (0.069%) main.ts:383-391
+ ↓ L and R copies collapsed to one scalar each main.ts:387-390
+MANC 23,188 neurons / 5,243,574 edges
+ ↓ 369 leg motor neurons → 6 leg-group means main.ts:396-400
+ ↓ → mancTotal, mancAsym main.ts:452-453
+ ↓ and the direction sign is discarded — it comes from the
+ hand-wired 200-neuron synthetic spine main.ts:470
+ ↓ driveLegs(walk, turn) room.ts:640
+ = sin(t · 10 Hz), 18 of 48 leg actuators physics.ts:663-719
+```
+
+**Roughly 20.3 million connectome edges reach the body as about one scalar
+magnitude plus a turn bias per tick, and those two numbers scale a
+`sin(t × 10 Hz)` tripod.** In the "Track target" closed loop the connectome
+contribution to locomotion is zero: MANC is skipped entirely
+(`src/main.ts:457-465`) and both forward and turn are overwritten by retinal
+geometry (`src/vnc.ts:369-384`).
+
+### The inventory
+
+| Shortcut | Substitutes for | Honest mode? | Where |
+|---|---|---|---|
+| **Kinematic assist** — writes freejoint `qvel[0]`, `qvel[1]`, `qvel[5]` from `fwdCmd`/`turnCmd`, re-asserted every substep before `mj_step` | ground reaction from leg contact | **yes** (`Physics.kinematicAssistEnabled`) | `src/physics.ts:576-604`, default on at `:554` |
+| **Assist is live in RL-policy mode** — `fwdCmd`/`turnCmd` are written only by `driveLegs`, the policy path skips `driveLegs`, and nothing zeroes them (including `reset()`), so a stale CPG command keeps driving the body under the policy | — | only insofar as it turns the assist off globally; nothing else clears the commands | `src/physics.ts:717-718`, `src/room.ts:633-647`, `src/physics.ts:991-1010` |
+| **Pitch/roll attitude damper** — `qvel[3] *= 0.85; qvel[4] *= 0.85` per substep, ×0.039 per 2 ms control tick | balance, and the body's ability to tip at all | **no** — it sits before and outside the assist guard | `src/physics.ts:592-595` |
+| **Boot stimulus drives itself** — science mode auto-runs `STIMULI[0]` at load, saturating the spine to `fwdCmd = 0.99999` for the length of its window; the drive is put back to rest when that window ends, so the residual no longer survives to the first user click. `decayDrive()` is defined and never called (one grep hit, the definition) | a brain whose drive responds to what you click | **no** | `src/main.ts:1287-1291`, `src/main.ts:499` |
+| **Tripod CPG is the source of leg timing** — `phase = data.time · 10 Hz`, hard-coded gait constants, 3 of 8 DOFs driven per leg | motor-neuron output setting stance/swing | **no** | `src/physics.ts:654-661`, `:663-719`, actuator cache `:213-220` |
+| **Wing motion is hand-written** — 218 Hz analytic stroke, amplitude hard-capped at ×0.2 of flybody's canonical pattern because anything above ~0.25 launches the freejoint body | wing motor neurons (MANC's 66 are read for the readout only) | **no** | `src/physics.ts:494-518`, cap at `:504` |
+| **`jumpImpulse` writes `qvel[2]` directly** | leg extension producing a takeoff | **no** | `src/physics.ts:979-981`, called from `src/main.ts:495` |
+| **Adhesion clamped to 1.0** at init and whenever walk drive < 0.01 — a standing fly is glued to the floor | claw contact and friction holding a stationary fly | **no** | `src/physics.ts:221-227`, `:709-712` |
+| **Visual-reflex angle bypass** — `turn ∝ retinal angle`, forward speed from retinal area | the brain's optic→DN contralateral cascade | **yes**, but the brain path falls back to the identical law when cascade asymmetry < 0.05, and the code records the cascade's sign as empirically **wrong** for tracking | `src/vnc.ts:369-378`; brain path `:352-368`; sign note `:322-326` |
+| **Sweep-mode spine bypass** — target lost for 4+ ticks writes a scripted alternating scan turn straight to the body | search behaviour emerging from the brain | **no** | `src/main.ts:998-1005` |
+| **Walking reference** — synthetic open-loop ramp by default; the mocap opt-in is baked at 50 Hz and replayed at 500 Hz, and the 65-frame lookahead exceeds the 57-frame clip | the policy's training reference clip | switches to mocap, which measures **worse** (§4.4) | `src/physics.ts:905-919`, `:896`; `tools/bake_walking_ref.py:46` |
+| **"Evolve gait (WebGPU ARS)" does not evolve against MuJoCo** — the fitness is a 1-D point-mass rollout with analytic thrust and quadratic drag: no gravity, no ground contact, no body — and the winner is written into the live physics body | optimizing the gait against the actual simulated fly | **no** | `src/shaders/evolve.wgsl:4-6`, `:101-104`; applied at `src/main.ts:1054-1056` |
+| **The speed readout displays the assist** — `bodySpeed` reads `qvel[0..1]`, the exact slots the assist writes immediately before `mj_step` | measured locomotion | **no** | `src/physics.ts:985-989`, rendered at `src/main.ts:739,746` |
+
+One more, about evidence rather than physics: **the walking policy's forward
+pass is not verified against the published SavedModel.**
+`tools/verify_walking_policy.py` imports only `json`, `struct`, `pathlib` and
+`numpy` — no TensorFlow. It reads `public/walking-policy.bin`, the file
+`extract_walking_policy.py` wrote, and re-implements the same *assumed*
+architecture. The passing fixture therefore shows TS ≡ a numpy
+re-implementation of the same guess, not TS ≡ flybody's deployed policy. The
+extractor's own comments record the guess as unresolved
+(`tools/extract_walking_policy.py:43`, "layernorm bias (?) — actually
+unsure").
+
+### What the body does with the assist off (measured)
+
+16 controlled browser runs, headed Chromium, one M-series Mac, ~2 simulated
+seconds of sampling per window. "cm/sim s" is net displacement per *simulated*
+second (the portable number; wall-clock distance is machine-dependent).
+"Upright" is the body z-axis' world-z component: +1 upright, −1 upside down.
+These runs were sampled while the boot stimulus still left its saturated drive
+in place, so the two "boot residual" rows and the DNa01 delta below describe a
+build whose idle forward command was 1.000; `src/main.ts:1287-1291` now returns
+it to zero. The assist-on/assist-off contrast, which is what the table is for,
+is unaffected — it is measured within each row.
+
+| Controller | Assist | cm/sim s | Straightness | Total yaw | Upright |
+|---|---|---|---|---|---|
+| none (boot residual only) | ON | 0.820 / 0.815 | 0.87 / 0.86 | +99° / +100° | 0.98 → 1.00 |
+| none (boot residual only) | OFF | 0.052 / 0.053 | 0.036 | −258° / −259° | 0.98 → 0.98 |
+| hand-coded CPG (DNa01) | ON | 0.798 / 0.798 | 0.84 | +113° | 0.98 → 0.98 |
+| hand-coded CPG (DNa01) | OFF | 0.071 / 0.074 | 0.048 / 0.049 | −244° / −245° | 0.99 → 0.98 |
+| trained RL policy | ON | 0.878 / 0.670 | 0.93 / 0.69 | −68° / +152° | **+0.057 → −0.944** / 0.97 → 0.80 |
+| trained RL policy | OFF | 0.029 / 0.163 | 0.53 / 0.48 | −108° / +138° | **−0.851 → −0.978** |
+
+Reading it:
+
+- **The assist is the locomotion, and it does not care what the controller is
+ doing.** 0.798–0.878 cm/sim s with the assist on across three completely
+ different controller states — no controller at all, the hand-coded CPG, and
+ the trained RL policy. With it off, the same three give 0.029–0.163
+ cm/sim s. A 4×–30× collapse, and the assist-on number is just the 1.0 cm/s
+ command minus what yaw and MuJoCo take back.
+- **Displacement is decoupled from body state.** In one assist-on run the
+ fly's uprightness went from +0.057 to −0.944 — it turned over — and it still
+ translated at 0.878 cm/sim s with straightness 0.93. A fly gliding smoothly
+ forward on its back at the commanded speed.
+- **Assist off is not a slow walk; the direction is wrong.** The CPG
+ accumulates 3.43 cm of path length for 0.163–0.170 cm of net displacement,
+ straightness 0.048, total yaw −245°. The fly pirouettes in place. The legs
+ do move and do couple to the ground; the net effect is rotation and jitter.
+- **The DNa01 button contributes ~nothing to forward motion.** A page nobody
+ clicked travels 1.831 / 1.858 cm; after clicking DNa01, 1.838 / 1.838 cm — a
+ 0.4% difference. `fwdCmd` was already pinned at 1.000 by the boot residual
+ these runs still carried; DNa01 moved only `turnCmd` (0.012 → 0.119). What
+ the measurement shows about the button is that its forward axis is a no-op
+ whenever anything has already saturated the drive.
+- **Nothing is numerically unstable.** Zero non-finite `qpos` entries across
+ all 16 runs; vertical drift within 0.16 cm of spawn everywhere. The
+ simulation is healthy and simply produces no net thrust.
+- On the CPG path, "Honest mode" is *exactly* equivalent to "assist off" — the
+ honest-mode CPG runs reproduce the plain assist-off CPG runs to 3–4
+ significant figures, because the other two flags are only read in code paths
+ CPG mode never enters.
+
+The pitch/roll damper is not in that table, because **the project has never
+been run with it off.** It has been ×0.005 per CPG render frame for the entire
+life of the codebase, in every mode including Honest mode, so no measurement
+here — or in any commit message — describes a fly that could tip over. That
+baseline is unmeasured.
+
---
*Found something here that's worse than described, or a claim in the README
diff --git a/README.md b/README.md
index abcc845..5ef0c3d 100644
--- a/README.md
+++ b/README.md
@@ -23,9 +23,13 @@
You control a fly by firing real **descending neurons** in the
[FlyWire](https://flywire.ai) connectome. The spike cascade propagates through
-the real wiring; the fly walks because the connectome says so. There is no
-scripted animation — every step you see is an LIF cascade through a real fly's
-brain map, into a real fly's spinal cord, driving a physically simulated body.
+the real wiring, into a real fly's spinal cord, and what comes out of the spine
+is a walking magnitude and a turn bias. Those two numbers modulate a hand-written
+tripod gait and — with the kinematic assist that ships on by default — are also
+written straight into the body's velocity. The connectome simulation is real and
+runs on the GPU every frame; the locomotion layered on top of it is an
+approximation, and every approximation and shortcut is inventoried in
+[`LIMITATIONS.md`](./LIMITATIONS.md).
---
@@ -37,7 +41,7 @@ brain map, into a real fly's spinal cord, driving a physically simulated body.
- A whole-animal *Drosophila* nervous system — brain, spinal cord, and body — running end-to-end in a browser tab on WebGPU, no install and no server.
- Two real connectomes (FlyWire brain + Janelia MANC spine) simulated as leaky integrate-and-fire networks, with gather, integrate, threshold and reset fused into a single LIF kernel per timestep.
-- A physically simulated fly body (TuragaLab flybody in MuJoCo/WASM) driven by the spine's motor neurons, with a retina feeding vision back into the brain.
+- A physically simulated fly body (TuragaLab flybody in MuJoCo/WASM) driven by a hand-written tripod gait that the spine's motor output scales, with a retina feeding vision back into the brain.
- A game with **replay-as-URL**: a shared link re-fires your keystrokes at the same simulation steps, so the identical neuron cascade re-runs against the same connectome and the same seeded target.
@@ -57,7 +61,7 @@ brain map, into a real fly's spinal cord, driving a physically simulated body.
- **The curious public.** A real animal brain you can poke, with a 30-second time-to-first-spike and no setup.
- **Educators.** Every key fires a named command neuron and you watch the consequence ripple to the legs — the connectome made tangible.
-- **Connectome / WebGPU folks.** A real ~140k-neuron LIF kernel benchmarked honestly in the browser, with the brain→spine→body path wired from real biology.
+- **Connectome / WebGPU folks.** A real ~140k-neuron LIF kernel benchmarked honestly in the browser, with the brain→spine path wired from real biology.
- **Anyone who wants reproducibility.** Runs are URLs; a replay link is a verifiable brain trace, not a video.
@@ -103,13 +107,20 @@ mode, ARS evolver, raw spike-rate log.
| **Spine** | [Janelia MANC](https://www.janelia.org/project-team/flyem/manc-connectome) connectome (Takemura et al. 2024) | 23,188 VNC neurons, 5.2M edges, second WebGPU LIF instance |
| **Body** | [TuragaLab/flybody](https://github.com/TuragaLab/flybody) MJCF (Vaxenburg et al. 2025, *Nature*) | 67 bodies, 111 actuators, real physics in MuJoCo/WASM |
| **Eyes** | offscreen render-to-texture from fly head pose | 64×16 retinal sample fed to brain optic neurons |
-| **Walker** | trained RL policy ([Vaxenburg et al. 2025 Figshare](https://janelia.figshare.com/articles/dataset/25309105)) | LayerNormMLP, 741-dim obs → 59 actions, pure-TS forward pass, verified element-wise vs the published checkpoint |
+| **Walker** | trained RL policy ([Vaxenburg et al. 2025 Figshare](https://janelia.figshare.com/articles/dataset/25309105)) | LayerNormMLP, 741-dim obs → 59 actions, pure-TS forward pass, checked element-wise against a numpy re-run of the same extracted weights (`tools/verify_walking_policy.py`) — that validates the port's arithmetic, not the assumed architecture against the original SavedModel |
Brain → spine wiring is by **cell-type name match** (`DNa01` in the brain is the
same neuron as `DNa01` in the VNC — brain side has the soma, VNC side the axon).
-VNC motor neurons drive the leg actuators. Wire-by-wire from real biology, no
-learned shortcuts in the brain→spine path. (Caveat: it's a name join across two
-*different* animals' connectomes, not a reconstructed synaptic bridge — see
+That path — sensory drive → brain LIF → named DNs → VNC LIF — is a real spike
+cascade across two real connectomes, with nothing learned or scripted in it.
+Below the spine it is an approximation: the VNC's 369 leg motor neurons are
+averaged into six leg-group means, and those become a walking magnitude and a
+turn bias (the forward/backward sign is not MANC's — it comes from the
+hand-wired synthetic spine in `src/vnc.ts`). Those two scalars scale a
+hand-written tripod CPG (`driveLegs`, `src/physics.ts`) that writes the leg
+actuators. The connectome scales that gait; it does not generate its rhythm, and
+the leg phase itself is `sin(sim_time · freq)`. (Caveat: it's a name join across two *different* animals'
+connectomes, not a reconstructed synaptic bridge — see
[`LIMITATIONS.md`](./LIMITATIONS.md) §5.)
---
diff --git a/index.html b/index.html
index bfcd749..15152d3 100644
--- a/index.html
+++ b/index.html
@@ -6,7 +6,7 @@
The brain talks to the fly's spinal cord - (a second real connectome), which drives the legs of a + (a second real connectome), and what the spinal cord decides steers a physically simulated body. Press a key and you inject current into specific command neurons, then watch the - consequences ripple all the way down to the feet. If the wiring says - "this makes the fly walk forward," it walks forward. If it doesn't, it - doesn't. + consequences ripple all the way down to the legs. What comes out of + the connectome is a walking speed and a turn — the stepping rhythm + itself is a hand-written tripod gait, not neuron-by-neuron muscle + control.
@@ -457,7 +459,7 @@
The brain and spine are joined the way real biology does it: a command
neuron named DNa01 in the brain is the same cell as
- DNa01 in the spinal cord. No learned shortcuts — wire for
- wire from the real animal.
+ DNa01 in the spinal cord. Nothing in that path is learned
+ or scripted — it is wire for wire from the real animal. Past the
+ spinal cord it changes: the motor neurons set a walking speed and a
+ turn, and a hand-written leg rhythm does the actual stepping.