Repository navigation
Releases: Vortitron/HouseFly
Release list
HouseFly 2.22.0 — it smells the house it is in
The planted anomalies on the Swarm (2.21.0) did their job inside four days:
six of the first seven went unheard by every fly that could have smelled them,
and the whole-house fly's familiarity moved from 97.95% to 97.6% when a garage
motor ran for the first time in its life. The quiet weeks before had been
partly deafness. Three faults, found in order:
The antennal lobe latched. Its measured PN→PN synapses, at the recurrent
gain everything runs at, made it bistable: once a smell had lit it, about 40 of
123 projection neurons held themselves above 0.5 with nothing arriving. A live
house is never smell-free, so a running fly's Kenyon code hashed whatever the
lobe had first fallen into — one smell and another 36% alike, the same smell a
minute later 36% alike too, a middling smell 85–95% alike with no smell at all.
The PNs now carry a static circuit gain of 3.0, as the Kenyon cells and the
fan-shaped body already did (swept: the latch ends near 2.4, the code is
repeatable from 2.75). Adaptation, the looming pathway's fix, was tried first
and rang. Check 16 runs the old gain as a control, so it can fail.
One entity in five was invisible. 22 of the 123 odour channels reach no
Kenyon cell — real PNs that go only to the lateral horn — and the hash put
entities on them anyway, the visitor prank's own input_boolean among them.
Entities and suspects now hash onto the 101 that reach the mushroom body.
The alert threw away what it heard. It wanted two unbroken minutes above
0.10, and novelty fades with exposure by design: a never-seen event peaked at
0.27 and was at 0.05 two minutes later. It now judges the two-minute average
(reported as averaged), which still ignores a twitch: one tick at 1.0 among
fifty-nine at 0.03 averages 0.046.
What moved with it. The Kenyon cells' gain (3.0) had been set against a
latched lobe's input; with the lobe letting go it starved the code to about
nine cells and the valence memory to a third (+0.04 for sugar). Swept 1.5–3.0,
it trades the memory against hearing, and 1.75 is the only value that keeps
both: sugar +0.13, punishment −0.09. The clock's channels are PNs, so the 3.0
turned the hour down too — the same house at 03:00 fell to 0.053, under the
line — and its gain goes from 0.55 to three times that, 1.65 (wrong hour 0.245,
strange house 0.521). A restored fly's first tick back is an onset transient
(0.20) that the latched lobe used to hide; it knows the house by the third, so
check 12e reads the third. And a big territory now settles a little sooner than
a small one (about 90 ticks against 125), one point past the 25% the old check
allowed; the check now asks for the safe direction — no slower — rather than
having its line moved.
What a fly hears now, three houses each: four things at once, 3/3 at 6 and 12
watched and 1/3 at 113; one device, 1/3, 1/3 and 0/3. A whole-house fly hears
only big changes, some of the time, and never one switch — a locality-sensitive
hash is meant not to — and one device in a small fly is heard when its
channel's projection neuron answers strongly, which a quarter of them do not. Both stay written down
as known limitations, each with a check. The README's "watch more and it hears
more" was wrong and is gone; a first explanation for the single-device misses
(Kenyon fan-out) was wrong too, and the check measures the PN instead.
Every fly relearns once. The smell code is now part of the nose fingerprint, so
an upgraded fly treats its old familiarity as describing codes that no longer
occur and spends a day re-earning the alert, instead of calling the whole house
strange the moment it starts.
HouseFly 2.21.0 — something to install, not only something to watch
Groundwork for the Home Assistant Marketplace, which replaces HACS in 2026.11.
A blueprint for the unusual alert. The notification that turned "something
unusual" into something a person reads lived only on the Swarm, built by hand.
It is now blueprints/automation/housefly/unusual_notify.yaml, importable with
one button from the README: pick the flies, choose whether alerts where only
the hour is strange are worth hearing about, and add your own actions (title,
message, fly and report are passed to them). Three things went wrong on
the way, all found by running it on the Swarm against a probe sensor rather
than by reading it: device_attr raises for an entity with no device; a dict
of the sensor's attributes cannot be passed on, because Home Assistant's own
keys are enum members and the text does not read back, so report arrived as
a string and every alert was dropped as "not yet learned"; and a folded YAML
block ran the list of changes into one line. Check 15 pins every attribute and
field the blueprint reads to the dicts the coordinator builds, and fails when
either side is renamed (tried both ways).
A fly says what it costs. A new diagnostic sensor, Tick cost, reports
the milliseconds of brain per tick on the machine it runs on, averaged over a
minute, with the event-loop time, the share of one core and the CPU
architecture as attributes. tools/bench.py measures the same with nothing
but numpy, before installing: 61 ms per two-second tick here, 3.0% of one core,
in line with the README's 59 ms. On the Swarm, a hosted virtual machine with
four flies, it read 136–153 ms per fly within minutes of going in: more than
twice the desktop, and now in the README beside it. Nobody has measured a Raspberry Pi or a Home
Assistant Green yet; the README says so, expects a small board to need several
times as much, and explains what the tick interval does and does not buy (up
to three seconds, nothing per second; beyond that, a tick still simulates only
three, so the brain runs slower and costs less).
Smaller things. The device page reported firmware "2.0.0" for twenty
releases; it now reads the manifest. hacs.json asks for Home Assistant
2026.9 or later, the oldest version this has actually been run on, instead of
2024.7, which nobody had tried. (A Marketplace category, categories in the
manifest, waits for 2026.11: the HACS action asks for one and the released
hassfest still rejects the key.)
Scoring the alert, starting now. One alert in about 28 fly-days on the
Swarm reads well, but nothing on a simulated house is ever unusual, so a
detector that hears nothing would read the same. testbed/demo/demo_pranks.yaml
plants one thing a day at no set hour — the garage door motor running, every
light on at once, or somebody walking round a house nobody walks round — holds
it twenty minutes, puts it back and logs it, so the next fortnight's alerts can
be scored for hits and false alarms per fly. Nothing in the README claims the
alert catches anything until that is in.
The README starts with what you get. The Marketplace shows the README, so
its first screen now lists the entities, the event, the blueprint, the cards
and the safety default before the neuroscience, and installation covers the
Marketplace as well as HACS.
HouseFly 2.20.2 — a person just after a restart is still a person
2.20.1 treated every change in a fly's first ten minutes as nobody's,
including a person's or an automation's. Only what nobody caused — the states
Home Assistant restores while starting, with no user and no parent context —
is ignored now; a lamp a person switches off just after a restart stays off,
and an automation's change is respected as usual. Check 10c covers both.
HouseFly 2.20.1 — a restart is nobody's decision
2.20.0 counted only states stamped before a fly started as the house
restoring itself. On the Swarm the template lights rendered two seconds
after, with no user and no parent, so every fly took that for a person and
left every light alone for an hour after each restart. Anything stamped during
the first ten minutes — the same startup grace the unusual alert already uses —
is now nobody's decision. Check 10c covers it.
HouseFly 2.20.0 — someone else's decision stands
2.19.0 let a fly see a lamp as it is, and the first thing that showed on the
demo box was a fly switching a light back on two to fourteen seconds after the
house's own automation had switched it off — four times an hour on one light.
A person turning off a lamp a fly may touch would have met the same.
A fly now leaves alone anything someone else changed recently: for an hour
after a person (a logged-in user, or a device reporting its own change, which
is what a wall switch looks like), and for ten minutes after an automation, a
script or another fly. It knows which is which from the context Home Assistant
stamps on every change; every fly registers its own, so it can tell another
fly from a person, and a restart's restored states count as nobody's.
Counted as total_left_to_others, apart from total_already_as_wanted and
from total_blocked. Five new checks in section 10c of tools/validate.py.
HouseFly 2.19.0 — it sees the lamp it lands on
On the sandboxes, a week after 2.16.0, each fly was "refused" about six
hundred times a day and acted about twice. None of those were the safety layer
protecting anything. Three things, all fixed:
- The deadband compared a wish with the fly's own last command, so it never
noticed anyone else changing a light. It now compares with the light as it
actually is: a fly that lands on a lamp another fly or a person has switched
off sees it off. - A wish that matched the lamp was counted as a safety refusal. It is now
counted apart, astotal_already_as_wanted;total_blockedmeans the
safety layer said no. - The fly's state barely moved what it asked for. At gains of 0.5 on valence
and 0.2 on arousal every wish sat between about 0.45 and 0.6 — inside the
0.15 deadband — so nothing it learned or felt could reach a light. At 2.0
and 0.4, a learned valence shift of 0.1 is a change of 0.2, and its day is
bright when it is lively and dim when it is drowsy.
A switch is now asked for as on or off rather than as a level, so "already as
it wants it" means the same thing for a switch as for a lamp. Six new checks
in section 10b of tools/validate.py.
HouseFly 2.18.0 — rows of numbers, one channel each
A state made of named rows of numbers, m1:21,18,13;s1:0,0,80, is now read as
one channel per value, and each channel adapts to its own range like any
numeric sensor. Home Assistant has no array type, so this is how a device
publishes several readings at once; FrontPath sends both radars' per-gate
energies this way, thirty-six numbers a second.
Read as one string it was a word, a new odour every second. And one shared
scale would not do either: a gate over swaying plants sits near 100 all day
while one over open path sits near 20, so a person at the quiet gate would
vanish into the noisy gate's range. Per channel, the fly learns what the wind
does to each gate and a person at an unusually quiet one is new.
A row name has to start with a letter, so a clock time such as 07:45 is
still a word. Two to sixty-four values per entity, so one sensor cannot crowd
out the house. Suspects name the row and position
(sensor.gate_energies#s2#7). Four new checks in section 8 of
tools/validate.py.
HouseFly 2.17.0 — a row of detectors is a row of detectors
A state made only of 0s and 1s, eight to sixty-four long, is now read as that
many separate detectors, one glomerulus per position. FrontPath publishes its
eighteen radar gates this way, street end to door end, and a fly watching it
was getting nonsense: float("000011000000000000") succeeds, so the pattern
arrived as one reading of eleven trillion, squeezed by range adaptation into a
number that meant nothing.
Reading it as a word would not have been much better — every pattern its own
glomerulus, so gates 4+5 and gates 4+5+6 as unrelated as two rooms. Per
position, patterns that share gates share glomeruli, which is what lets the
mushroom body habituate to the wind's few repeated patterns while a person
walking the path still reads as new. An all-zero mask is a live channel saying
nothing is there. Suspects name the position (sensor.gates#4).
Four new checks in section 8 of tools/validate.py.
HouseFly 2.16.0 — what it learns reaches what it does
The valence memory reaches behaviour (#4). Measured on transplanted synapses alone: a smell paired with sugar gains +0.10 valence, one paired with punishment loses 0.15, an unpaired smell much less, half-life about 50 minutes, and nothing outlives its cause. Before: 0.0003, plus a reward flip-flop that held valence for hours. Fixes: dopamine neurons are modulatory (a build bug made them fast excitatory); MBONs and APL use one joint input budget; valence reads only the 47 MBONs whose Kenyon input is in the hemibrain, with the Aso 2014b sign; sugar lasts the whole meal, or 30 s of Feed. The compass now settles with a brief turn (its ignition from total stillness hung on one cell at threshold). 167 checks.
HouseFly 2.15.0 — it eats, and it sleeps when it is tired
Hunger is discharged by meals (landing on something while foraging), not by a sleep ratio that the house decides; a hungry fly's meal is a reward the mushroom body learns from. Sleep pressure builds with time awake, so a fly in a busy house still sleeps. The house's looming no longer startles a sleeping fly; swatting it still does. Found by a week of four live flies: hunger pinned at 95-100%, a whole-house fly that never slept, and an awake sensor that flickered 720 times a day. 159 checks.