Skip to content

Tend: a plant you cannot draw, only tend — and the prune button that never pruned - #49

Open
aj-dev-smith wants to merge 7 commits into
mainfrom
tend
Open

aj-dev-smith wants to merge 7 commits into
mainfrom
tend

Conversation

@aj-dev-smith

Copy link
Copy Markdown
Owner

What this is

tend.html is a third page and the first one you do something on. You can't draw the plant. You can only do what a plant physiologist does, with the three instruments auxin was discovered through:

year experiment instrument what the engine does
1880 the Darwins Lamp growing tips steer to normalize(up + k·toward_lamp), the exact equilibrium of additive sine laws, k = photoGain·I^0.4
1928 Went the glow every living tip's auxin drawn as motes running rootward at polar-transport speed
1933 Thimann & Skoog Shears the stream below a cut drains; the buds it held come free, race, and the first to commit puts the rest back to sleep
1933 their control Auxin put back on the cut, the buds stay asleep until you take it away

Every sentence the page says afterward is measured off the plant. Example: "The drain freed 17 of the 17 buds the tip was holding. One grew out, the first 1 cm below the cut, about 2 days after it, and put 16 back to sleep." Share copies a link that regrows your exact plant from its seed, cut for cut.

The bug it started from

The main page's "cut the apex" button has always frozen the plant it cut. prune() set the tallest axis to not-alive, and a not-alive axis returned from step() before its buds were ever looked at again. Measured before anything was written:

before after
Cathedral Fern, pruned at step 500 1 axis, 13 organs, forever 5 axes, 96 organs
Sun Coral, pruned at step 500 (same freeze) 7 axes, 96 organs

test/tend.mjs §2 is the regression test.

The science, and what the literature changed

docs/research_9_22_26_tend.md is a literature sweep, briefed before building and flagged [D]/[I]/[OURS]/⚠. It corrected the design in five places:

  • Agar, not lanolin. Thimann & Skoog used agar blocks renewed every 6 h, and their buds grew "as soon as the application ... was stopped". The page copy is fixed.
  • The depletion front decides commitment, not release. The first flush after a cut is sugar and cytokinin (Mason 2014). Auxin decides which freed bud commits (Morris 2005; Balla 2016). So a bud here is held, then free, then committed, and the page says the first flush isn't modelled.
  • Instant commitment forced exactly one winner. A freed bud now exports on a ramp for tauCommit, and the one nearest the cut puts the ones below it back to sleep. Nothing states the winner.
  • Transport speed is a lookup: 6.6× growth rate, Kramer 2011's median of 227 measured speeds.
  • Light's gain goes as I^0.4 (Bastien 2015 fitting Galland 2002). It is not the saturating curve the draft used.

It also found Snow 1931 measuring inhibition rising with distance, so dominance is booked as a dial with the only data point against it. SCIENCE.md has the accounting table:

  • lookups: patRatio, commitReach, photoExp;
  • a genuine parameter: photoGain;
  • dials: dominance and branching;
  • numerical: BUD_BAND.

Nothing is added to the numbered imposed list. Cuts, auxin and the lamp are environment.

Numbers

Shipped path unchanged. Uncut specimens are bit-identical to main: 4 species × 2 seeds grown through senescence, with every stem point hashed every 400 steps, compared against a pristine copy of main's src/. smoke 73/73. views 23/23 (Cathedral Fern) and 35/35 (garden of eight).

node test/tend.mjs, all eight bench species × two seeds:

  • every cut had held buds below it, and every one ended in a commitment (16/16);
  • where several came free, fewer committed than came free;
  • with auxin back on the cut, not one held bud came free (16/16);
  • taking it away let one commit (16/16);
  • the drain reaches the nearest held bud within one step of t_cut + d/v (predicted 700.23, freed at 701) and it commits exactly tauCommit later;
  • the lamp's equilibrium lands within 0.05° of atan(k) at three irradiances.

node tools/tend_replay.mjs: a live browser session is shared as a ~500-character link and regrown in a second page to the same fingerprint of every stem point at the same step. The session has a dragged lamp, a cut, a cut dressed with auxin, and the auxin taken off. Checked on Ember Creeper and Cathedral Fern.

Cost: a bushy tended Ember Creeper (25 axes, 380 organs) runs at 1.5 ms a step and 7.6 ms to build geometry.

The plant's clock, calibrated

The drain front runs at patV world units a step. A real one runs at ~1 cm/h (Morris 2005). So one step of a Cathedral Fern is about an hour of a plant's life, and one second on screen is about five days. The page reports every interval in those plant hours.

What's in the change

  • src/40_plant.js:
    • Axis.streamAt, releaseBuds (held, then free, then committed), budsPending and phototropicPull;
    • Plant.cut, paste and wipe, and prune() as a real cut;
    • a spent() that waits for a stump's buds.
    • All of it is off unless something asks (budField: 'apex', plant.light = null).
  • src/70_app.js: a stemGlow hook in drawSpecimen and a program hook in makeSpecimen, both undefined elsewhere. src/80_main.js: the prune tooltip now says what happens.
  • tend/: build script, program, the TendApp bench, the page, template and README. tend.html is the built artifact.
  • test/tend.mjs: the harness, derivation first.
  • tools/tend_shot.mjs (photographs the experiments), tools/tend_replay.mjs (checks a share link bit for bit), tools/tend_film.mjs (renders each experiment frame by frame to mp4).
  • Docs: SCIENCE, JOURNAL, PITFALLS (six traps), ROADMAP (two follow-ons: run the canalisation switch for bud activation; the AC model for every tropism), CLAUDE.md, README.

What still needs a human eye

  • The drain at 1× is about a second across a whole plant, so the page slows the clock and leans the camera in for ~3 s after a cut, and says so. Is the slow-motion window the right length?
  • The motes' density (0.42 units apart) is the one purely visual number in the stream drawing.
  • The bench's reach of dominance (18 units) is a dial chosen so a cut is legible. The untouched plant branches only near its base as a result.
  • Hosting. tend.html is one self-contained file like canalisation.html. The Pages workflow only publishes the three.js demo, so putting it on the site is your call.

Clips for a post are rendered but not committed (shots/ is gitignored); node tools/tend_film.mjs shots/tend rebuilds them.

🤖 Generated with Claude Code

aj-dev-smith and others added 7 commits September 22, 2026 16:04
… and the buds it frees

The main page's "cut the apex" set the tallest axis to not-alive, and a
not-alive axis returned from step() before its buds were looked at again —
and the shipped dominance rule measures suppression from the axis's own tip,
which a decapitated axis does not have. Measured before touching anything:
three species cut at two ages, not one bud woke; a young Cathedral Fern cut at
step 500 stood at 1 axis and 13 organs forever. Thimann & Skoog's result, the
oldest experiment in auxin biology, killed the plant.

What replaces it, all in 40_plant.js and all off unless something asks:

- Axis.streamAt(s, t): the auxin flowing past arc s — the axis's apex, every
  apex attached above s, freed buds, paste on a stump — attenuated over the
  existing `dominance`, each with a drain/arrival front at polar-transport
  speed. patV = patRatio (6.6, Kramer 2011's median of 227 measured speeds
  over organ growth rate) x the species' own growth rate.
- Held, free, committed. A freed bud exports on a ramp and commits only if it
  stays free for tauCommit (commitReach 6 units ~ 24-72 h of a ~1 cm/h front,
  Morris 2005 / Balla 2016); the one nearest the cut is freed first and puts
  the ones below it back to sleep. No budTake coin on this path.
- Plant.cut / paste / wipe, and prune() as a real cut one internode down.
- phototropicPull: normalize(want + k * toward_lamp), k = photoGain * I^0.4
  (Bastien 2015 on Galland 2002). Null unless plant.light is set.
- drawSpecimen gains a stemGlow hook and makeSpecimen a program hook; both
  undefined everywhere but tend.html.

Uncut specimens are bit-identical to main: 4 species x 2 seeds grown through
senescence, every stem point hashed every 400 steps, identical. smoke 73/73,
views 23/23 (Cathedral Fern) and 35/35 (garden of eight).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tend.html is a bench with the three instruments auxin was discovered through —
a lamp (the Darwins, 1880), shears (Thimann & Skoog, 1933), and the tip's
auxin put back on the cut (their control). Nothing a person does touches the
plant's shape; the engine decides what grows back and which way.

- The auxin stream is drawn as what it is: motes leaving every source at patV,
  fading over `dominance`, present only if their source was on when they left.
  After a cut you watch the tail of the stream run down past the buds.
- Buds at every axil show their state: held, freed and racing, dormant.
- Every sentence the page says after an experiment is measured off the plant,
  against the buds the stream was holding at the cut, in plant hours
  calibrated by the drain (~1 cm/h): "The drain freed 17 of the 17 buds the tip
  was holding. One grew out, the first 1 cm below the cut, about 2 days after
  it, and put 16 back to sleep."
- Share copies a link that regrows the plant from its seed, cut for cut; the
  plant reads a committed, logged copy of the lamp so a replay is exact.

test/tend.mjs (all eight bench species x two seeds): every cut ends in a
commitment; with auxin back on the cut not one held bud comes free (16/16);
taking it away lets one commit (16/16); the drain reaches the nearest bud
within one step of t_cut + d/v and it commits tauCommit later; the lamp's
equilibrium lands within 0.05 deg of atan(k). tools/tend_replay.mjs: a live
browser session shared as a 499-character link regrows to the same
fingerprint of every stem point at the same step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… it corrected the design

docs/research_9_22_26_tend.md is the sweep, flagged [D]/[I]/[OURS]/⚠ like the
two before it. It changed: agar not lanolin (page copy); the depletion front
decides commitment, not release (sugar does that, and is not modelled);
instant commitment forced exactly one winner; transport speed is a lookup
(6.6x growth); light enters as I^0.4. It also found Snow 1931 measuring
inhibition rising with distance, so `dominance` is booked as a dial with the
only data point against it.

SCIENCE.md gets the accounting table (lookups, one genuine parameter, dials, one
numerical band) and nothing on the numbered imposed list. JOURNAL has the
story and the three bugs the harness caught; PITFALLS the six traps; ROADMAP
the two follow-ons the literature named (run the canalisation switch for bud
activation; the AC model for every tropism). CLAUDE.md and README point at it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…it a phone

- The lamp's sentence said a tip had "turned 13 degrees away from the lamp"
  while the leader visibly arched over toward it: a tip that grows up past the
  lamp's height changes the direction TO the lamp faster than it turns. It
  reports the lean now — degrees from upright, signed by whether it faces the
  lamp — which is what Darwin measured and what a person sees.
- The shears' preview traces everything that would leave the plant as a halo
  wider than the stem, instead of a hairline nobody could find.
- A phone gets a two-row bar (species, then the clock and buttons), the dock
  and the status line move up with it, and the status line steps aside for the
  instruction line and the experiments sheet instead of overprinting both.
- The species rail fades at its ends instead of clipping a name in half.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
tools/tend_film.mjs renders each experiment as a clip: with `?film` the page
does not run its own loop, the tool advances it one frame at a time through
window.__tendFrame(ms) and photographs each frame, and ffmpeg encodes a 1080
master and a 720p cut. The actions are the page's own methods at fixed frames
— what a pointer would have called — so a clip is as smooth as its frame rate
and identical every run. Scenarios: cut (an Ember Creeper), lamp (a Cathedral
Fern), auxin (a Sun Coral dressed, held, then released).

- `?clean&caption` keeps only the title, the line saying what is happening and
  the measured sentence for the instrument in hand, for clips that are about
  the plant rather than the page.
- The status line's lifetime is measured on the page's clock rather than a
  timer, so a film holds it as long as a person would see it held.
- The lean-in stops at 0.6 of the fitted distance, not 0.42: on a large-leaved
  species the closer lean filled the frame with out-of-focus blades.
- Encoding note written where it bites: the grade grains every frame and every
  leaf moves every frame in the wind, so an unconstrained encode is 100+ MB for
  eleven seconds; a temporal denoise halves it and the 720p cut is 4-11 MB.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Plant.cut removed the organs above the cut but left any that had already come
free on the stump's freeBuds list, so a bud that fell with the cutting went on
feeding the stream below the cut as a phantom source. What it had already sent
down is in the cut's measured `level`, so dropping the entry loses nothing.
Also removes the lamp's old angle-to-lamp bookkeeping, dead since the lean
metric replaced it.

Re-checked after: test/tend.mjs quick all passed; smoke 73/73; views 23/23;
uncut specimens bit-identical to main; tools/tend_replay.mjs identical on a
Cathedral Fern (seed 21) as well as the Ember Creeper it was first run on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#caption had no display rule of its own, so on the ordinary page the measured
sentence for the instrument in hand printed over the dock and the species rail.
Caught on a 1200x630 still; hidden by default now and shown only when both
clean and caption are asked for.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant