Skip to content

LLM Resources

The plant on its own terms โ€‹

Everything above compares the plant against a reference: a species profile, a wall clock, a table of healthy ranges. That is where most plant monitoring quietly goes wrong, because the reference is a population average and your plant is one individual, in one pot, in one room.

These four layers drop the reference and compare the plant against itself.

๐Ÿงฌ Electrome fingerprint โ€” what is normal for this plant โ€‹

A signature of the plant's baseline electrical state across several axes: complexity, entropy, variability, and the distribution of power across physiological bands. The library learns it over the first windows, then reports departures from it.

js
const s = await plant.listen( { seconds : 600 } )

s.shift.verdict
// "Learning this plant's normal: 6/12 windows."
// then, later:
// "Signature has moved: complexity down 38%, band power shifted low.
//  This plant is not behaving like itself."

s.shift.delta[ 0 ]   // { axis: 'complexity', direction: 'down', weighted: 0.41 }

plant:electrome-shift fires when the signature genuinely moves.

Two design decisions carry most of the weight. The fingerprint is DC-offset invariant โ€” an electrode drifting by 40 mV is a wiring fact, not a new plant, and must not read as one. And the baseline refuses to judge before it has settled: a "normal" derived from a single window is not a normal, so early calls say so rather than inventing a verdict.

๐Ÿ• Internal clock โ€” what time it is for the plant โ€‹

circadianHealth asks whether a rhythm exists. This asks the question that actually changes behaviour: where is the plant in its own day, and how far is that from the clock on the wall?

js
s.clock
// { periodHours: 26.4, acrophaseHour: 15.2, subjectiveHour: 4.1,
//   offsetHours: 2.2, freeRunning: true, aligned: false,
//   verdict: 'Free-running at 26.4h rather than 24h. The plant is following its
//             internal clock because the light cycle is not strong or regular
//             enough to entrain it.' }

timingAdvice( s.clock, 'probe' )
// { good: false, betterInHours: 5.9,
//   reason: 'A stomatal probe at subjective night measures a plant that has
//            closed down. The response would read as "weak" for reasons that
//            have nothing to do with health.' }

A plant whose subjective dawn falls at 3pm is not "arrhythmic" โ€” it is entrained to something you did not intend: a corridor light, a west-facing window, a lamp on a timer. Every decision made on wall time is landing at the wrong point in its day.

๐Ÿ“ก Two-site coherence โ€” is this the plant, or the electrode? โ€‹

The electrode is the weakest link in the whole evidence chain. A dry contact or a callus forming produces a confident, well-shaped waveform that means nothing, and every layer downstream then reasons beautifully about an artefact.

Two electrodes fix what one never can, because plant signals propagate at speeds physiology constrains:

EventSpeedA 50 mm gap implies
Action potential1โ€“40 mm/s1.2 โ€“ 50 s
Variation potential0.5โ€“5 mm/s10 โ€“ 100 s
System potential0.1โ€“2 mm/s25 โ€“ 500 s
js
await plant.attachSensor( {
  driver : 'electrode', transport : 'synthetic',
  sites  : [ { id : 'stem', distanceMm : 50 } ],
} )

s.coherence.stem.verdict
// "Both electrodes saw the same event, 5.00s apart across 50mm. Implied speed
//  10.00mm/s is consistent with an action potential (1-40mm/s).
//  This is the plant, corroborated at two sites."

The failure modes are the point:

  • Zero delay is diagnostic. Nothing biological reaches two separated points at the same instant โ€” but mains pickup and ground loops do exactly that. A simultaneous event is rejected as interference, not accepted as a strong signal.
  • Overlapping speed ranges are reported honestly. 2 mm/s fits all three event classes, so the library returns every candidate and names none. Claiming "variation potential" there would be false precision.
  • An ambiguous lag corroborates nothing. A periodic signal correlates just as well at lag as at lag + period, so when rival peaks come close the result is flagged ambiguous and coherence is withheld โ€” match discrete events instead.

That is corroboration grounded in physics rather than statistics, and it is very hard to fake.

๐Ÿ”ต VPD-aware blue โ€” the same response, opposite meanings โ€‹

Blue light opens stomata. So a strong blue response was read as a healthy, responsive plant. That reading is wrong roughly half the time, because it ignores the air.

Vapour pressure deficit โ€” how hard the atmosphere is pulling water out of the leaf โ€” is now computed from temperature and humidity and folded into every blue reading:

Blue responseVPDSoilReading
stronghighdry๐Ÿ”ด demand_with_deficit โ€” transpiring hard against a supply it does not have. This precedes sudden wilting.
stronghighwethigh_demand โ€” demand, not comfort
weaklowโ€”no_demand โ€” still humid air, not water stress
weakhighโ€”closed_under_demand โ€” refusing to open under strong pull is a clear ABA signal: stress
js
plant.context().vpd       // 2.14
plant.context().vpdBand   // 'severe'

The same closed stoma means "nothing to do" in still humid air and "the plant is defending itself" in dry air. Reading it without the atmosphere is how a monitoring system talks itself into watering a plant that is fine, or reassuring you about one that is not.