Complete summaries on your biggest PRs, and sharper blocking reviews.
CLASSIFICATION — PUBLIC RELEASE RECORD 001 OA·RSRCH·2026·0016·PUB
RECORD INDEX
001 FILED 2026·09·16 18 MIN READ

We put a fly's sense of smell in a security scanner

The circuit has an extraordinary nose for resemblance. Danger is the one thing it cannot smell.

We put a fly’s sense of smell in a security scanner. Optimal AI research.

It spots a warning it has seen before, or a function quietly copied into another project, thousands of times better than chance. Asked whether a piece of code is dangerous, it does no better than a coin.

The same circuit on four tasks
What we asked it to do How it did Pure guessing gets
Quiet repeated alerts without silencing a new one Quieted 96 in every 100, and missed no new ones nothing to compare
Find a snippet’s near-identical twin among 5,000 others Right first time, 79 times in 100 2 times in 10,000
Match a function to its copy in a different project Right first time, 93 times in 100 4 times in 10,000
Tell a real security flaw from the fix that removed it Right 51 times in 100 50 times in 100
Read the last two columns together. On the first three it beats guessing by a mile. On the fourth it does not beat guessing at all. The first three ask have I seen this before? The fourth asks is this dangerous? One circuit, and the line falls exactly between those two questions.

In plain language

No background needed

The problem

Software gets scanned automatically for security problems. The scanners are noisy. A big company might get thousands of warnings a week, and nearly all of them are the same few harmless things, reported over and over.

So engineers stop reading them. Then the one warning that mattered arrives, and nobody looks.

The usual fix is a mute button. Someone gets sick of a warning and switches that kind off. It works, and it is dangerous, because it switches that kind off everywhere, including the one place it mattered.

What a fly does instead

A fruit fly has the same problem with smells. It cannot react to the same harmless smell forever. It also cannot afford to miss a new one.

Its answer is not a mute button. It gets less and less responsive to that one smell, while staying fully alert to everything else. And if something important happens, its sensitivity comes straight back.

In 2017 researchers worked out how the fly does this, precisely enough to write it down as a recipe. Each smell gets turned into a pattern of a few dozen lit-up cells out of about two thousand. Similar smells light up overlapping patterns. Different smells light up separate ones.

We used that recipe on security warnings instead of smells.

The 2,000 channels, after 600 pull requests
Untouched Worn down by repetition Lit by the finding arriving now
After 600 pull requests · 216 channels worn
Every square is one of the 2,000 channels, from a real run. Violet means worn down by findings the team kept dismissing. After 600 pull requests only 216 are worn at all, so most of the field is still fully sensitive. The 32 orange squares are one finding: 26 of them landed on unworn ground, so it was shown. A later finding landed on ground worn six times deeper and was held back. Press replay to watch the wear level off instead of climbing.
Why that beats a mute button

A hardcoded password in a test file is not worth anyone’s time. The same warning about a password in the live payment settings absolutely is. Mute the category and you silence both.

Our version goes quiet on the first and stays loud on the second, because the two warnings light up mostly different patterns.

Did it work?

Yes. It removed about 96 warnings in every 100 while still catching every important one we had hidden in the pile, and it never silenced anything marked serious.

We also ran it over the real history of Django, a big well-known open-source project. Nearly 2,000 real changes, with the “did this matter?” answer taken from what the developers actually did afterwards rather than from anything we invented. It removed 97 in every 100.

Then we got greedy

Going quiet on repeats is one job. The tempting next one is judgement. If it can tell seen it from never seen it, can it tell dangerous from safe?

To find out we needed examples where someone trustworthy had already decided. Django’s own security fixes gave us 186. For each one we had the code while it was still broken, and the same code after the developers fixed it. Two versions of the same thing, one genuinely dangerous, and a human’s word for which was which.

Our system got 51 out of 100 right. A coin gets 50.

It cannot tell the difference at all. And looking back, it was never going to. Code does not look strange just because it is dangerous. Most security holes look perfectly ordinary. That is exactly why they get written.

What it is genuinely brilliant at

So we asked the opposite question, using the very same material. Here is a piece of code before the fix. Can you find the fixed version of it, hidden among five thousand other snippets?

It found the right one first try about 8 times in 10. Guessing would get it right twice in ten thousand.

Then a harder version. Developers often copy a whole library into their own project instead of linking to it, and the two copies slowly drift apart as each gets edited. We took a real case of this and asked our system to match up the functions between the two projects. It got it right first try more than 9 times in 10.

The whole finding, in one line

Same system, same code, same afternoon. Thousands of times better than guessing at find the one that matches. No better than a coin at tell me which one is dangerous.

It is a machine for spotting resemblance. It does not form opinions. That explains why the first job worked: have I seen this warning before? is a resemblance question. Is this code dangerous? is an opinion, and resemblance does not contain one.

Where it loses, and we should say so

If the same warning turns up in exactly the same words every time, a much simpler trick, just remembering what you have already seen, beats ours slightly. Ours only pulls ahead when warnings drift: when the code around them gets edited or renamed, so each one looks brand new to the simple method but still looks familiar to ours.

How much real warnings drift is something we have not measured yet. If the answer is “hardly at all,” the simple method wins and this was a scenic detour.

One thing we are careful about

Nothing here is a simulated fly. We borrowed one specific, well-documented trick from an insect’s sense of smell, because it happens to solve a problem that also shows up in software. Everything built on top of that trick is ordinary engineering, and we have tried to be strict about which is which.

It also matters for the obvious next question: would a bigger brain work better? Scientists finished mapping an entire fruit fly brain in 2024, all 139,255 cells of it. The biggest piece of human brain mapped in that kind of detail is about a grain of sand, roughly a millionth of the whole thing.

How much of the fly we actually used
~2,000 KENYON CELLS139,255 NEURONS IN THE WHOLE FLY BRAIN · ONE DOT = 1,000 NEURONS
One dot for every thousand neurons. Two of them are the Kenyon cells whose behaviour the 2017 paper explained, and those two dots are the entire part of the fly this work draws on. The fifty projection neurons that feed them would be a twentieth of a single dot. Everything else, the other 137 dots, we never touched and would not have known what to do with.

But the map was never the hard part. We never used the fly’s map. We used one circuit that somebody had already worked out the purpose of, and that explanation is what we could build from. A complete wiring diagram with no explanation attached would not have helped. Our own results show it: the trick we borrowed worked beautifully for the job it was explained for, and was worthless one step outside it.


Three examples

Real code, taken straight from the runs

Percentages are easier to trust when you can see one case. Here is what each of the three results looks like on an actual piece of code.

1. Why it cannot spot a flaw

This is a real Django security fix. The bug let an attacker send a deeply nested shape to a map field and tie up the server. Here is the code before the fix, and after it.

Vulnerable
def converter(value, expression, connection):
      if value is not None:
          geom = GEOSGeometryBase(read(memoryview(value)), geom_class)
          if srid:
              geom.srid = srid
          return geom
Fixed
def converter(value, expression, connection):
      if value is not None:
          geom = GEOSGeometryBase(
              read(memoryview(value), max_geom_collections=None), geom_class
          )
          if srid:
              geom.srid = srid
          return geom

CVE-2026-15830, django/contrib/gis/db/backends/mysql/operations.py

The whole fix is one argument: max_geom_collections=None. To our system the two versions light up 66% of the same channels, which is to say they look almost the same. That is the correct answer to the question it was asked, and the wrong answer to the question we wanted. Nothing about the shape of the broken version looks unusual, because it is not unusual. It is ordinary code that happens to be exploitable.

2. Why it is so good at spotting a copy

pip keeps its own copy of a library called packaging. Over time the two copies drifted apart. This function was rewritten on one side and not the other: the return type changed, and the body went from handing back results one at a time to collecting them in a list.

In pypa/packaging
def _cpython_abis(py_version, warn=False) -> Iterator[str]:
      version = _version_nodot(py_version[:2])
      ...
      yield f"cp{version}{threading}{debug}{pymalloc}{ucs4}"
In pip’s copy
def _cpython_abis(py_version, warn=False) -> list[str]:
      abis = []
      version = _version_nodot(py_version[:2])
      ...
      abis.append(f"cp{version}{threading}{debug}{pymalloc}{ucs4}")

Asked to find the second one given the first, out of 2,285 candidate functions, it put the right answer first. Its score for the correct match was 0.59. The next-best guess scored 0.25, less than half. Different projects, different file paths, rewritten body, and it still knew.

3. Why it beats a mute button

This is the case that makes the whole thing worth building. The same scanner rule fires twice, on code that is almost word for word the same:

In a test file. Genuinely harmless.
password = "hunter2"
  client = PoolClient(user="test", password=password)
In production config. Genuinely serious.
password = "hunter2"
  client = PoolClient(user="svc", password=password)

Mute the rule and you have silenced both. Our system gives these two only 8% shared channels, because where a file sits is part of what it encodes. So it goes quiet on the first after a few dismissals and stays loud on the second. In the full test it got every one of these pairs right; rule muting got none of them.


The technical note

For people who build detection and triage systems

Why run this at all

Alert fatigue looks like a duplicate-removal problem, and removing duplicates does not fix it. Exact matching collapses identical findings and nothing else; rule-level muting collapses far too much. The gap between them is where a similarity measure should live, and the fly olfactory circuit is one of the few anyone has worked out in full.

That last point is why this is not an analogy. Dasgupta, Stevens and Navlakha showed in Science (2017) that the circuit is doing locality-sensitive hashing: turning each input into a short code, so that similar inputs get similar codes. Fifty odorant receptor types feed fifty projection neurons, which fan out to about 2,000 Kenyon cells through a sparse binary random matrix, a 40-fold expansion. One inhibitory neuron, APL, then silences all but the highest-firing 5%, and that surviving 5% is the odour’s tag. Similar inputs get similar tags. It beats conventional LSH on nearest-neighbour search, partly because sparse binary projections cost around 20× less than the dense Gaussian ones LSH normally uses.

The same six stages, in a fly and in our encoder
TAGrule_idfilepathcodeTAG50 RECEPTORTYPES50 PROJECTIONNEURONS2,000 KENYONCELLSTOP 5%100 CELLSLABELCODEFINDING~60 ACTIVEOF 4,096 SLOTS2,000CHANNELSTOP 1.6%32 CHANNELSLABELFRUIT FLY · OLFACTORY CIRCUITOUR SYSTEM · CODE FINDINGSINPUTENCODESPARSEPROJECTIONHIGH-DIMREPRESENTATIONWINNERTAKE ALLOUTPUTLOCALITY-SENSITIVE HASHING VIA SPARSE RANDOM PROJECTION
The borrowed part is the middle: a sparse random projection into a wide space, then a winner-take-all that keeps only the strongest few. Both ends differ, and the differences matter. The fly’s input is 50-dimensional and every dimension is always live, so its projection is a 40-fold expansion. Ours is a 4,096-slot hash space of which a typical finding activates about 60, so the same step is a contraction. We also run more than three times sparser than the fly, keeping 32 channels of 2,000 rather than 5%, which was a tuning result rather than anything inherited.

So there is a real algorithm to borrow, and two questions worth asking of it:

  1. Can it suppress repeated findings without suppressing new ones?
  2. Does that same representation also help it detect? Can “unlike anything here” stand in for “dangerous”?

What we expected

Written down before each experiment ran, which is the only thing that makes a prediction worth anything:

ExperimentPredictionOutcome
Suppression vs dedup and rule-muting Beats both on the combination of volume and recall held
Telling a vulnerability from its fix At chance, since a hunk is as unusual before a fix as after held
Cross-project clone matching Worse than same-project, because path features disagree wrong on the net

The third is covered below: the mechanism was right and the net effect was not, because the granularity changed at the same time.

How it is put together

Each finding is projected through a fixed random sparse binary matrix to 2,000 channels; the top 32 survive. Similar findings share most of their channels, unrelated ones share almost none, and no taxonomy is maintained anywhere:

Pair of findingsShared channels
Identical1.00
Same finding, file renamed0.78
Same finding, one token changed0.52
Same rule, code rewritten0.10
Same rule, test fixture vs production config0.08
Unrelated0.00

Everything past the encoder is ours, not biology. Each channel carries an inhibition level; a finding’s response is its severity prior scaled by how inhibited its channels are, and below a threshold it is withheld. Inhibition decays with distance measured in pull requests, never wall clock. One design decision matters more than the rest:

Outcome-gated, not presentation-gated

Showing a finding habituates nothing. A finding has to be dismissed or ignored for inhibition to build, and one that gets acted on actively relieves it. That is what separates this from time decay, which forgets on a schedule regardless of whether anyone cared.

A property we did not design, and noticed only because a test failed: outcome gating is self-limiting. Once a class stops surfacing, nobody is dismissing it, so reinforcement drops to the much smaller suppressed-item increment and inhibition levels off near 0.61 instead of maxing out. That headroom is load-bearing: at forced saturation (~0.91) a near-miss finding still surfaces at 0.60 against a 0.35 threshold.

Result 1: suppression works

Twelve seeds, 600 pull requests each, against the two things teams actually do:

Approach Volume removed New findings caught Near-miss split
Exact-match dedup93.9%100%100%
Rule-level muting97.9%49%0%
Habituation95.8%100%100%

Zero high-severity findings withheld on any seed. Rule muting, the industry default, buys the most volume by losing half the new findings and every near-miss.

The near-miss case is the one to dwell on: the same rule firing on a hardcoded credential in a test fixture and on one in a production config. Muting the rule silences both. The fly separates them, because file class and path push the two onto largely different channels.

We also ran it over the real history of 1,950 Django commits. The “did this matter?” signal came from what actually happened to each finding, not from labels we invented. There, habituation removed 97.0% of the volume with zero high-severity suppressions, against 91.4% for exact dedup. Only two of the five metrics are measurable there, since an ordinary repository carries no labels for the other three.

Alert volume removed, as recurring findings mutate
Habituation (the fly) Exact-match dedup
60% 70% 80% 90% 100% No drift, exact dedup 96.6% 2 of 6 classes drifting, exact dedup 93.9% 4 of 6 classes drifting, exact dedup 91.4% 6 of 6 classes drifting, exact dedup 89.0% Mutating every 30 PRs, exact dedup 80.1% Mutating every 15 PRs, exact dedup 62.2% 62.2% No drift, habituation 95.9% 2 of 6 classes drifting, habituation 95.7% 4 of 6 classes drifting, habituation 95.9% 6 of 6 classes drifting, habituation 96.0% Mutating every 30 PRs, habituation 95.3% Mutating every 15 PRs, habituation 94.0% 94.0% none 2 of 6 every 60 4 of 6 every 60 6 of 6 every 60 6 of 6 every 30 6 of 6 every 15 noise classes drifting · mutation interval in PRs →
With nothing mutating, plain exact-match dedup beats the fly, 96.6% against 95.9%. It is the better tool for that job. The gap only opens as findings change shape: dedup falls off a cliff, the fly barely notices. How much real findings mutate is therefore the question that decides whether any of this is worth building.

Result 2: judgement does not

The second question needed ground truth we did not have. The trick was to stop hunting the commit that created a flaw. Finding those means reaching for SZZ, a family of algorithms that tops out near 40% accuracy. Use the commit that fixed the flaw instead. A security fix says, with a maintainer’s authority, that this code was vulnerable and this code is not. Pre-fix and post-fix versions of the same hunk are a labelled positive and a negative matched on file, project, author, era and style. Nothing but the flaw separates them.

Django tags its fixes Fixed CVE-YYYY-NNNNN, which makes them exactly identifiable: 186 matched pairs across 77 CVEs in 67 source files. The analysis is paired, which needs no base rate. For each pair, did the detector rank the vulnerable side above the fixed one? Chance is 50%.

Detector Ranked the vulnerable side higher Could not separate
Habituation encoder (the fly) 51.1% [43.9–58.3], n=182 4 pairs
Claude Haiku 4.5 100% [77.2–100], n=13 173 pairs

The model flagged the vulnerable side 10.2% of the time against 3.2% for the fixed side: real signal, weak, silent on most pairs. A six-line fragment is hard for anyone to judge with no way to check whether untrusted input can actually reach it.

The fly is at chance, with an interval straddling 50%. As predicted, and for the predicted reason: a hunk is about as unusual before a fix as after it.

Results 3 and 4: the tasks it is actually for

So we asked the complementary question on identical data. Given a pre-fix hunk, find its post-fix counterpart among 5,000 spans from the same repository. The pair is a near-duplicate by construction, which makes this similarity search, the exact problem the circuit was shown to solve.

MetricResultChance
Correct match at rank 179.0% [72.6–84.3]0.02%
Correct match in top 1092.5%0.2%
Median rank of the true match12,500

That is a generous test: same function, same file, same repository. The harder version uses vendoring. pip carries a copy of the packaging library inside src/pip/_vendor/. The two copies have since drifted apart by 4 to 69 lines per module: copied once, then edited separately by each project. That is a near-clone, not an identical one, which is the harder case. The vendoring is the ground truth.

Encoderrecall@1recall@10MRR
Default92.9% [90.3–94.8]99.2%0.953
Path- and repo-blind96.0% [93.9–97.3]99.6%0.975

519 queries against 2,285 blocks, chance 0.044%. Run locally.

This is where the prediction failed. We expected cross-project matching to score worse, because the encoder weights directory and repository features and those disagree by construction across two projects. Turning those features off does gain 3.1 points, so the reasoning was right. But the size of the chunks changed too. This test matches whole functions; the earlier one matched arbitrary 13-line windows, and a whole function is far more distinctive. The two headline numbers are therefore not comparable, and the ablation is the only controlled claim here.

The practical consequence is immediate: an encoder aimed at cross-project matching should drop path and repository features. They exist to separate findings within a repository and can only mislead between two.

What it adds up to

Similarity engine, not detector

Three similarity tasks far above chance. One judgement task exactly at chance. Same encoder throughout, and on the CVE pairs literally the same spans an hour apart.

Stated plainly, this is not a disappointment. It is the organising fact. Suppression works because “is this the same finding again?” is a similarity question. Detection fails because “is this dangerous?” is a judgement, and no amount of channel overlap contains one.

One casualty: different jobs, you want both does not survive. On real code the two detectors flag genuinely disjoint sets, Jaccard overlap 0.000, so the two signals are unrelated. But unrelated is not the same as complementary. Complementarity would need the fly to catch real issues the model misses, and against human labels it catches them at chance. We had written that claim into an earlier draft on the strength of a synthetic benchmark, and it was wrong.

What we are not claiming

  • No biological fidelity. The connectome is measured wiring from a dead brain. The encoder is a published algorithm; the inhibition dynamics, the finding-to-channel mapping and the salience signals are ours. Nothing here simulates a fly.
  • The advantage over dedup is the drift rate, and nothing else. On byte-identical repeats, dedup wins. We have not measured how much real findings mutate, so we cannot say which regime production is in.
  • A severity ceiling needs context-aware severity. On real data a rule-level analyzer marks 87% of findings high or critical, while 265 of 317 sit in test files. The safety ceiling then becomes a switch between doing nothing and hiding thousands of high-severity findings.
  • An earlier version of the detection comparison was retracted. It ran on a synthetic stream whose negatives were vulnerability-shaped code labelled benign because of which directory it sat in. Any detector reasoning about code rather than location scored backwards against it. The CVE pairs exist because of that failure.
  • We deviate from the biology on sparsity, and measured why. The fly keeps the top 5%, 100 of 2,000 cells. We keep 32, about 1.6%. Sweeping k from 16 to 128 made things steadily worse above about 32. This is the clearest case where copying the circuit more faithfully would have made the tool worse.

Which circuit next

Forward-looking: none of this is measured yet

The obvious reading of “borrow a circuit from a brain” is that the constraint is brain data, and that the frontier runs from insects toward mammals toward us. The wiring diagrams do line up that way. A complete adult fruit fly brain was published in 2024 by the FlyWire consortium: 139,255 neurons and roughly 50 million chemical synapses, sorted in a companion paper into 8,453 cell types. The largest human reconstruction is one cubic millimetre of temporal cortex: about 57,000 cells, 150 million synapses, 1.4 petabytes of imagery, and roughly one-millionth of a human brain.

Why a circuit and not the brain

We did not use the fly connectome, and the reason is not that it was hard to obtain. It is public, and the counts above came from it. The reason is that a wiring diagram is not an algorithm.

A connectome tells you which neuron connects to which, and how strongly. It does not tell you what the network computes, what its inputs mean, or which of the many things it does is the one worth copying. There is no run button on a graph of 139,255 nodes. To build anything from it you would first have to work out the function, and that is both the hard part and the part the data does not contain.

What we used instead was a circuit somebody had already explained. Dasgupta, Stevens and Navlakha reduced the fly’s olfactory pathway to a stated algorithm, sparse random projection followed by winner-take-all, and showed what it computes. That reduction is a few lines of linear algebra. It runs on a laptop, inside a scanner, on every finding, in under a millisecond. A simulation of 139,255 neurons does none of those things, and would need timing, neurotransmitter dynamics and plasticity rules that the wiring diagram does not carry anyway.

Our own results are the strongest form of this argument. The circuit did not fail for want of capacity. It was hundreds of times better than chance at every similarity task we gave it and exactly at chance at judgement, on identical inputs. That gap is a category boundary, not a size limit, and a hundred times more neurons would not turn a resemblance engine into a detector. A different explained circuit might. So the axis that matters is not how much wiring has been mapped. It is how much of it anyone has worked out the purpose of, and that number is far smaller and growing far more slowly.

But the fly brain is playing Doom

It is. In September 2026 Google and the Howard Hughes Medical Institute released MaleCNS, a map of an adult male fly’s brain and nerve cord: about 166,000 neurons and 125 million synapses. Within days an engineer called Alex Wormuth wired it into a simulator and pointed it at Doom.

That is a great hack, and it makes our point for us. Look at what he had to supply that the map does not contain. Which neurons count as input. How a frame of Doom becomes activity on them. Which activity becomes a movement command. A learning signal, which he built by pulsing two dopamine cells whenever the player takes damage. The connectome gave him the graph. He supplied everything that made it mean anything. Six thousand attempts in, it still has not beaten the game.

We went the other way round. Our paper is from 2017, seven years before the first whole fly brain, so it cannot have come from a connectome. The fact it rests on, that the wiring from antennal lobe to mushroom body is random rather than organised, came from Caron, Ruta, Abbott and Axel in 2013, who traced Kenyon cells one at a time. Decades of lab work had already worked out what that pathway does. The 2017 paper spotted that it adds up to locality-sensitive hashing and wrote it down as an algorithm. So what we borrowed was never in a wiring diagram. It was in the literature, because people spent thirty years asking what the circuit is for and not just what it connects to.

Two different products

A brain yields two separable things, and they come from different work. A map says who connects to whom. A characterisation says what the connected thing computes. Mapping has become fast, industrial and largely automated. Characterising is slow, manual, and done one circuit at a time.

Doom is built on the map. This piece is built on the characterisation, and never needed the map at all. Which is why the interesting number is not how many neurons have been reconstructed. It is how many circuits anyone can currently write down as an algorithm, and that number is still short enough to list.

Provenance: the connectome figures above are read from FlyWire, which publishes the dataset at codex.flywire.ai and its annotations at flyconnectome/flywire_annotations. We used the counts and nothing else. No connectome data enters the encoder, and no result in this piece depends on it.

So the near-term candidates are not bigger brains but other circuits somebody has already worked out, and insects are where most of those are:

  • The central complex keeps track of which way the insect is facing, and adds up each step it takes so it can fly straight home. It is a way of holding onto a position over time. The software version is an agent keeping a stable sense of where it is in a long task.
  • The mushroom body is the same sparse code we used, with a chemical signal writing “this was good” or “this was bad” onto it. That is learning from a handful of examples. The software version is a tool that improves from a few corrections instead of a retraining run.
  • The locust looming detector (LGMD) computes time-to-collision from raw visual flow with two neurons, and has already been built into collision-avoidance hardware. It is the clearest existing proof that this kind of borrowing produces working engineering.

Human cortex is a poor next step for a second reason beyond scale. The fly was solvable partly because every fly is wired almost the same way, so one diagram describes the whole species. Cortex is not like that, so even a complete human connectome would be a map of one person, and working out what the wiring does, already the hard part, gets harder still.

The honest version of the ambition is narrower, and more useful, than “copy a brain.” Find a circuit somebody has already explained. Check whether what it computes is something your problem actually needs. Then expect it to be useless one step outside that job. We got one of those three right on the first try and had to measure our way to the other two.


OPTIMAL AI — RESEARCH DIVISION RECORD 001 ALL RECORDS