Files
last-hearth/docs/botany.md
T
2026-11-03 12:41:09 -05:00

32 KiB
Executable File
Raw Blame History

Botany: 80 temperate taxa and integration contract

Scope and evidence

The catalogue in mods/hearth/botany.lua has 80 distinct real species, partitioned into eight ordered groups of ten. It represents a north-west/central European temperate landscape mosaic: deciduous woods, conifer woods, hedgerows, acid heath, wet meadow, bog and freshwater margins. It does not imply that all species grow together in one patch, or that all are native to every British locality. Norway spruce is native to continental northern/central Europe and widely planted in Britain. Hazel is counted only among trees; heather only among herbs; rushes and reedmace only among grasses/sedges. Lichens are lichen-forming fungi but have their own disjoint gameplay category, not a second count in fungi.

Taxonomic/reference authorities for maintaining these names and broad habitats:

The numeric light/moisture/pH/depth windows below are explicit game approximations, not measured ecological tolerances, identification keys, conservation advice or a scientific simulation. The catalogue selects named species rather than inventing generic “magic herbs”. Rubus plicatus is one real blackberry species, not the Rubus fruticosus aggregate counted as a species. Meadow fescue Schedonorus pratensis is also encountered as Festuca pratensis / Lolium pratense. Wood blewit Collybia nuda is widely recorded as Lepista nuda / Clitocybe nuda. Birch polypore Fomitopsis betulina replaces the familiar Piptoporus betulinus. These synonyms are not extra entries.

No real-world foraging, medicinal or consumption claims are provided. Only three fictional bush outputs use the existing game item hearth:berries. This is a gameplay simplification, not a statement that a wild plant or lookalike is safe. Every fungus, herb, tree and lichen has food=false; toxic/stinging examples are flagged but toxic=false is not a safety certification. browse describes wildlife relationships, not player edibility. No new food items, recipes, poisoning system or damage to player plants are registered.

Exact ID manifest (art, trees and ecology handoff)

id is the canonical catalogue key. Every non-tree node is exactly hearth:<id>. Every tree's initial node is hearth:<id>_seedling; tree stages/resources belong to the diversity/resources owner. Do not create a second generic berry bush or alias a generic patch into this count. Existing generic berry_bush, fern, wildflowers and meadow_grass remain outside the 80.

Owner flags: E = existing node, never registered here; D = tree diversity owner, never registered here; B = new botany-owned node. The 13 existing mappings are retained verbatim: five trees plus clover, nettle, heather, bluebell, sedge, bulrush, moss and lichen. “Sedge”, “moss” and “lichen” receive a specific catalogue interpretation; their old IDs do not change.

Art contract for all 80: hearth_botany_<id>.png. This module uses that exact tile for each of its 62 new understory nodes. Trees use species bark cubes and full-block leaf crowns supplied by diversity/terrain; no seasonal tree mesh is introduced on a cube. Seasonal copying preserves bark/end-grain faces, facedir, callbacks and drops; foliage gets its own species-season texture. Assets and real-engine visual validation remain the art/main integration owners' responsibility.

trees (10; P/T)

id Common name Scientific name Owner Habitat emphasis
oak Pedunculate oak Quercus robur E/D Mesic woodland; ectomycorrhizal roots
birch Silver birch Betula pendula E/D Light acid pioneer woods
pine Scots pine Pinus sylvestris E/D Open acid woods; resin
willow White willow Salix alba E/D Wet alluvial woods; spring flowers
alder Common alder Alnus glutinosa E/D Wet woods; Frankia-associated nitrogen fixation
beech European beech Fagus sylvatica D Well-drained woodland, avoiding saturation
aspen European aspen Populus tremula D Light woodland gaps
rowan Rowan Sorbus aucuparia D Cool acid woodland/edges; flowers
hazel Common hazel Corylus avellana D Woodland understorey; ectomycorrhiza
spruce Norway spruce Picea abies D Moist acid conifer woods; resin

shrubs (10; P/T)

id Common name Scientific name Owner Habitat emphasis
bilberry Bilberry Vaccinium myrtillus B Acid heath/woodland; ericoid, not ectomycorrhizal
blackberry Pleated blackberry Rubus plicatus B Hedgerows/wood edges
raspberry Red raspberry Rubus idaeus B Woodland clearings
elder Black elder Sambucus nigra B Hedgerows; no game food
blackthorn Blackthorn Prunus spinosa B Thorny hedges; spring flowers
hawthorn Common hawthorn Crataegus monogyna B Hedgerows; spring flowers
dog_rose Dog rose Rosa canina B Open scrub; summer pollen
holly European holly Ilex aquifolium B Evergreen woodland cover; no game food
juniper Common juniper Juniperus communis B Open dry heath/scrub; resin
guelder_rose Guelder rose Viburnum opulus B Damp hedges/wet edges; no game food

grasses (10; includes sedges, rushes and reedmace; P)

id Common name Scientific name Owner Habitat emphasis
sedge Greater tussock-sedge Carex paniculata E Wet bank tussocks
bulrush Bulrush (great reedmace) Typha latifolia E Reedbed margin; bank-cell approximation
meadow_fescue Meadow fescue Schedonorus pratensis B Moist neutral grassland
cocksfoot Cock's-foot Dactylis glomerata B Mesic meadow/edge
timothy Timothy Phleum pratense B Moist meadow
sweet_vernal_grass Sweet vernal-grass Anthoxanthum odoratum B Acid grassland
yorkshire_fog Yorkshire-fog Holcus lanatus B Mesic grassland
tufted_hairgrass Tufted hair-grass Deschampsia cespitosa B Wet meadow tussocks
common_reed Common reed Phragmites australis B Wet banks/reedbed edges
soft_rush Soft rush Juncus effusus B Wet pasture/bog margin

herbs (10; P/T/W)

id Common name Scientific name Owner Habitat emphasis
clover White clover Trifolium repens E Open grassland; rhizobial nitrogen fixation
nettle Common nettle Urtica dioica E Nutrient-rich damp edges; larval host, not nectar
heather Heather Calluna vulgaris E Acid heath; late-season flowers
bluebell English bluebell Hyacinthoides non-scripta E Spring woodland floor
yarrow Yarrow Achillea millefolium B Meadow; summer/autumn flowers
foxglove Common foxglove Digitalis purpurea B Acid clearings; no game food
meadowsweet Meadowsweet Filipendula ulmaria B Wet meadow; pollen resource
wild_garlic Wild garlic Allium ursinum B Spring moist woodland; no game food
cowslip Cowslip Primula veris B Base-rich open grassland
wood_anemone Wood anemone Anemone nemorosa B Spring woodland floor; no game food

ferns_mosses (10; five ferns P/T, five mosses M)

id Common name Scientific name Owner Habitat emphasis
bracken Bracken Pteridium aquilinum B Acid slopes/clearings; competition descriptor
lady_fern Lady-fern Athyrium filix-femina B Damp shaded woods
male_fern Male-fern Dryopteris filix-mas B Shaded woods
harts_tongue Hart's-tongue fern Asplenium scolopendrium B Damp base-rich shade
polypody Common polypody Polypodium vulgare B Acid rock/bark/woodland
sphagnum Blunt-leaved bog-moss Sphagnum palustre B Saturated acid bog/wet woodland
haircap_moss Common haircap Polytrichum commune B Damp acid soils
moss Cypress-leaved plait-moss Hypnum cupressiforme E Shady soil, wood, bark and rock
fork_moss Broom fork-moss Dicranum scoparium B Acid woodland/heath
star_moss Swan's-neck thyme-moss Mnium hornum B Damp woodland banks

fungi (10; F)

id Common name Scientific name Owner Habitat emphasis
fly_agaric Fly agaric Amanita muscaria B Ectomycorrhizal: birch/pine/spruce
birch_bolete Brown birch bolete Leccinum scabrum B Ectomycorrhizal: birch only in this model
bay_bolete Bay bolete Imleria badia B Ectomycorrhizal: conifers/beech/oak
chanterelle Chanterelle Cantharellus cibarius B Ectomycorrhizal woodland roots
wood_blewit Wood blewit Collybia nuda B Litter saprotroph; autumn/winter
shaggy_inkcap Shaggy inkcap Coprinus comatus B Grassland-soil saprotroph
turkey_tail Turkey tail Trametes versicolor B Broadleaf deadwood saprotroph
oyster_fungus Oyster mushroom Pleurotus ostreatus B Broadleaf deadwood; late-season fruiting
honey_fungus Honey fungus Armillaria mellea B Deadwood here; parasitism descriptive only
birch_polypore Birch polypore Fomitopsis betulina B Birch deadwood here; parasitism descriptive only

aquatic (10; P/W)

id Common name Scientific name Owner Placement niche
duckweed Common duckweed Lemna minor B Surface; 1–6 depth units
yellow_waterlily Yellow water-lily Nuphar lutea B Surface; 1–3, mud anchor
white_waterlily White water-lily Nymphaea alba B Surface; 1–3, mud anchor
water_crowfoot Common water-crowfoot Ranunculus aquatilis B Surface abstraction; 1–3, mud anchor
water_mint Water mint Mentha aquatica B Wet bank, dry destination
water_forgetmenot Water forget-me-not Myosotis scorpioides B Wet bank, dry destination
brooklime Brooklime Veronica beccabunga B Wet bank, dry destination
water_starwort Common water-starwort Callitriche stagnalis B Submerged abstraction; 1–4, mud anchor
hornwort Rigid hornwort Ceratophyllum demersum B Submerged/rootless; 1–4, water substrate
pondweed Broad-leaved pondweed Potamogeton natans B Surface; 1–3, mud anchor

lichens (10; L)

id Common name Scientific name Owner Habitat emphasis
reindeer_lichen Reindeer lichen Cladonia rangiferina B Open acid heath; wildlife browse
oakmoss Oakmoss Evernia prunastri B Bark in light woodland
old_mans_beard Old man's beard Usnea subfloridana B Humid bark/branches
lichen Map lichen Rhizocarpon geographicum E Acid siliceous rock, not generic soil
dog_lichen Dog lichen Peltigera canina B Mossy soil; cyanobacterial fixation
lungwort_lichen Lungwort lichen Lobaria pulmonaria B Humid woodland bark; cyanobacterial cephalodia
sunburst_lichen Common orange lichen Xanthoria parietina B Well-lit nutrient-enriched bark/base-rich stone
hammered_shield Hammered shield lichen Parmelia sulcata B Woodland bark
cup_lichen Mealy pixie-cup Cladonia chlorophaea B Acid soil/humus, distinct species below
pixie_cup Pebbled pixie-cup Cladonia pyxidata B Soil/humus; not a duplicate of chlorophaea

Exact public interface

Loading the file returns factory(hearth, api) -> B. The factory has no registration side effects and publishes no globals. Main assigns hearth.botany before loading succession. Botany installs no scheduler, globalstep, ABM, LBM, mapgen callback, timer or liquid transformation. mods/hearth/succession.lua consumes this policy in its existing eight-probe loop.

Catalogue/query APIs

  • B.groups, B.group_order: ordered arrays trees, shrubs, grasses, herbs, ferns_mosses, fungi, aquatic, lichens.
  • B.catalogue: ordered 80-record snapshot, group order then manifest row order.
  • B.get(value) -> record|nil; B.list(group_or_nil) -> ordered records; B.group_of(value) -> group|nil; B.kind(value) -> id|nil.
  • value may be a bare ID, full hearth: node name or {name=...}. Trees also resolve canonical _seedling, _young, _mature, _leaves, _log, _planks. Seasonal names resolve through hearth.seasons.kind when available. Generic patches and foreign namespaces do not resolve.
  • Every returned record is a detached copy. Editing a snapshot cannot change internal policy.
  • Record fields: id, common, latin, group, node, texture, existing, food, toxic, seasons (boolean set), tags (boolean set), niche; flowering taxa also have flowering, the three game-fruit taxa have fruiting (both boolean sets).
  • niche fields: substrates set, inclusive light={min,max} on 0–15, moisture={min,max} on 0–1, ph={min,max} in pH units, water={min,max} in game node-depth units, aquatic string. Some also require hosts set or nutrients minimum.

Read-only habitat selection

B.suitable(value, h, season) -> boolean and B.choose(p, h, season) -> bare_node_kind, record | nil use only supplied observations. p must contain finite integer x,y,z within ±30990; h must have loaded=true and finite light, moisture, ph. Missing/invalid facts do not receive optimistic defaults. season is exactly Spring, Summer, Autumn or Winter.

h.ground is a canonical bare/full support node or node table. h.substrate, when supplied, overrides the direct substrate for land/bark/deadwood niches. Bark and deadwood are semantic observations, not assertions that arbitrary planks/logs are safe recruitment sites. The ecological owner must derive those observations from unmodified natural substrate and enforce owner/protection checks. Do not treat crafted timber or planted trees as free fungal substrate.

h.host is a nearby identified tree ID/stage/root association, mandatory for host-specific fungi. Its search radius and finite sampling budget belong to the existing ecological scheduler. Presence of an unrelated tree does not satisfy a birch specialist. h.nutrients must be at least one for nettle. pH is a game support-class observation; callers lacking it should explicitly derive a documented approximation from the substrate, not silently infer that all plants fit.

h.aquatic is land, bank, surface or submerged; land may omit it. h.water is numeric column depth, not a boolean or permission to replace a water node; land/bank may omit it (zero). The selection represents a candidate only:

Mode Required observations Safe external placement rule
land Depth zero; accepted substrate Loaded air destination above accepted natural substrate
bank Explicit bank, depth zero, wet support Loaded air destination beside real freshwater, never inside/over it
surface Explicit surface, freshwater=true, allowed positive column depth; accepted mud bottom Flat pad in a distinct air cell above the actual surface; source node below stays unchanged
submerged Explicit submerged, freshwater=true, positive column depth; rooted starwort needs mud bottom, rootless hornwort needs substrate=water Succession places a qualitative shallow-water stand sprite in the separate air cell above conserved source water. It is not literally rendered inside the liquid. No source replacement, fake liquid, water clearing/refilling or flood-producing liquid flora

Surface depth ranges/anchors are intentionally coarse: even floating duckweed uses a valid freshwater bottom observation rather than an unbounded “water somewhere” fallback. Succession checks up to six consecutive loaded hearth:water_source cells and an accepted bottom, with authority/markers checked on every cell. Flowing water, unknown bottoms, over-depth or unloaded columns fail closed. Surface/submerged mode for a new stand is position-deterministic; established stands retain their species mode. Thus all ten aquatic taxa have establishment/spread/age pathways, but hornwort/starwort use above-water stand markers, not scientifically exact submerged geometry. register_nodes keeps direct source-water item placement disabled. Bank flora occupies dry cells beside actual water.

choose considers all 80 records in a deterministic position-hashed order, skipping trees unless h.include_trees=true. It returns an unprefixed actual node kind, e.g. bluebell, water_mint or beech_seedling, plus a detached descriptor. It never writes the map, chooses an occupied cell, checks claim ownership itself, consumes nutrients or rescans the world. The caller must independently verify loaded, empty, unmodified destination/support and authorization immediately before any write, using its existing bounded scheduler. No plant replaces another, spreads water or creates nutrients here.

Interactions and finite effects

  • B.has_tag(value, tag) -> boolean.
  • B.interactions(value) -> tag-keyed descriptor copies with a description, and where applicable cap or enabled=false.
  • B.active(value, season) -> boolean: establishment/visible-season gate, not an instruction to destroy winter-dormant perennial plants. Four spring woodland herbs gate to Spring; evergreen trees, mosses/lichens and persistent bracket fungi have broader windows.
  • B.pollinator(value, season) -> boolean: actual flowering tag and flowering season. Oak, wind-pollinated grasses, nettle, mosses and fungi do not become nectar sources. Meadowsweet and dog rose represent pollen as well as nectar relations.
  • B.edible(value, season) -> boolean: game berry permission only, independent of wildlife browse; only bilberry/raspberry in Summer and blackberry in Summer/Autumn return true.
  • B.browse(value, season) -> boolean: active wildlife relationship; not a universal diet rule. Wildlife owner must still choose an appropriate animal diet.
  • B.resin(value) -> boolean: only the catalogue's pine/spruce/juniper resin tag. It grants no item or extraction callback.
  • B.nitrogen(value, current) -> suggested_delta: only nitrogen-fixer-tagged taxa; min(1,max(0,2-current)), zero for invalid/negative current. Alder/Frankia, clover/rhizobia and cyanobacterial lichen partners are distinct biological associations. Ecology owner must apply a per-site contribution/cooldown and metadata cap of two; repeatedly calling this pure query is not permission for unlimited fertilizer.
  • B.root_fungi(value, tree, budget) -> transfer_ceiling: only ectomycorrhizal fungi matching the supplied host, at most one and at most the finite positive existing budget. A nearby host can receive a bounded establishment advantage through that owner's already-budgeted resource transfer. Caller debits the same budget; the function creates nothing and never independently raises soil nitrogen. Tree ectomycorrhizal tags alone are not free fungal boosts. Saprotrophs receive no root-fungus boost.

saprotroph describes recycling existing litter/wood: any later benefit must consume existing substrate, not mint nutrients. engineer describes physical substrate/water retention or aquatic cover; it does not grant terraforming. nursery means conditional cover/microhabitat. parasite and allelopathy are disabled descriptive interactions: honey fungus/birch polypore do not infect player trees and bracken never kills neighboring plants. The module mutates no ecological state.

Registration and harvest

B.register_nodes(register_node) accepts the content registrar taking bare names. It is idempotent and skips known existing IDs, all ten trees and any already present api.registered_nodes[full_name]. In an otherwise empty registry it registers 62 nodes (70 non-tree taxa minus eight existing understory IDs). It registers no recipes, aliases, items or tree stages/resources. Existing flora definitions are never overridden. Main should load this factory after seasons and call registration after legacy diversity registration.

New terrestrial plants/fungi/shrubs are conventional crossed plantlike sprites with no meshes/sculptures. Surface aquatics are thin nodeboxes wholly inside ±0.5 of the node. They are not water; submerged sprites are not given liquid behavior or water groups. All are non-walkable and buildable_to=false. Ordinary herbs, mosses, fungi and lichens dig to their own node item. All new shrubs dig to hearth:sticks, so digging/replanting cannot erase a berry cooldown and mint a fresh fruit-bearing bush. Placement marks player_placed=1; normal construction/protection handling is supplied by the existing registrar. There is no new growth timer.

B.harvest(pos, player) -> success_boolean, count_or_reason is the only resource mutation API. Berry callbacks return the original wielded stack. It:

  1. Validates finite integer bounded coordinates and a real player; looks up current hearth.construction.allowed(pos, player, "use") at callback time. Missing policy denies access; no permissive fallback. Existing policy owns reach, claim and protection checks.
  2. Re-reads the loaded node and requires its exact canonical three-bush ID, then current hearth.climate_at().season and game fruiting season.
  3. Checks persisted string metadata botany_ready_at, rejecting malformed/negative/nonfinite values. Missing metadata means initial fruit stock; future timestamps deny until ready.
  4. Requires inventory room for hearth:berries 2; full inventory neither changes stock nor starts cooldown.
  5. Locks the bush by writing a finite timestamp one real day ahead before inserting at most two berries. This blocks callback reentrancy. A completely rejected insertion restores the old timestamp; partial delivery consumes that cycle, never exceeds two or drops overflow into the world. Unexpected insertion results/errors leave the lock in place rather than duplicate stock.

The factory may precede construction publication, but harvest cannot. Time uses optional injected api.now() (numeric Unix seconds, for tests), otherwise os.time(). No offline catch-up or accumulating fruit: one ready bush gives at most two per cooldown even after months away, and cooldown metadata survives module reload. New callbacks are installed only on bilberry, blackberry, raspberry; generic existing berry-bush behavior is untouched.

Reasons: invalid, denied, species, season, clock, metadata, cooldown, inventory; success returns delivered count 1 or 2. No player health changes, medicinal effects, wild-consumption guidance or automatic fertilizer is added.

Ecology80 integration and bounds

The single succession loop owns recruitment, local spread, dormancy, senescence and decomposition for all 80 catalogue entries. It uses the actual node kind returned by B.choose, including species seedling suffixes, and rechecks B.suitable against destination facts before writes. Trees enter older gaps only after 7,200 active seconds; other recruits establish after 180 active seconds (90 with existing nutrients). No second scheduler, unbounded radius, map emergence or offline replay is introduced. Existing eight column probes/second, radius 12, twelve sampled heights, 8,192-entry age cache, 60-second durable attempt cooldown and 1,200-second maximum continuity gap remain.

S.habitat(pos) is read-only. Its 5×5×5 stencil now exposes exact catalogue dimensions: finite light, moisture, ph, nutrients, depth-valued water, separate near_water, ground, semantic substrate, freshwater, aquatic, host, active browse count (edible, retained for wildlife compatibility), seasonal pollination, nursery and host-fungus IDs. pH is an explicit game support-class approximation: peat 4.5; podzol/granite 5; alpine turf/slate/sandstone/scree/stone/forest floor/bark/deadwood/litter 5.5; grass/soil/alluvium/sand/basalt 6.5; limestone 7.5. Missing support observations fail closed. Nursery-tagged natural cover slows accumulated habitat stress by 25%; it creates neither water nor nutrients. Fungal host observations use only nearby identified natural trees or recorded natural wood species, never player timber.

Non-tree active lifetimes (seconds): shrubs/lichens 86,400; grasses/aquatic 21,600; herbs 14,400; ferns/mosses 43,200; fungal fruit bodies 2,400. Dormant perennials occupy their cells and pause, not disappear at first frost. Soil-supported vegetation becomes litter; rock/bark/wood/litter/water stands disappear without replacing their support. Fungal fruit bodies do not independently mint nutrients through litter. Saprotrophs advance only an existing, natural, authorized litter/deadwood clock by at most 60 seconds per attempt. The substrate's eventual consumed decomposition pays once using the existing capped nutrient path.

All nitrogen-fixer tags use a persisted two-unit soil support budget (succ_fixed_nitrogen), shared across death/recolonization/restart; a bark-dwelling fixer without a soil support gets no fertilizer effect. Matching ectomycorrhizal fungi reduce seedling establishment age from 21,600 to 16,200 only with a positive existing soil resource budget; successful growth debits at most one from that same budget. Failed growth creates/debits nothing. parasite and allelopathy remain deliberately disabled descriptors; no tree infection or neighboring-plant damage. engineer/resin stay habitat/resource descriptors, not autonomous terraforming/item generation. Pollination is exposed for wildlife/harvest integration, not a berry-yield multiplier: the unchanged botany harvest policy still returns at most two berries per real-day cooldown. Succession preserves a valid botany_ready_at; other non-succession provenance metadata still opts plants out.

Owned full-block tree lifecycle

D.tree_plan(species, stage) supplies fresh full-block plans for all ten species. Succession validates integer offsets within ±4 horizontally and 0–9 vertically, at most 810 entries, no duplicate/foreign names, and a root. One global tree-plan reservation per wall-clock second, including denied attempts, covers plan construction/preflight/application regardless of player count. Old/new plan union work is bounded (at most two plans); there are no dynamic per-frame world tree registries.

Every destination and its immediate support must be loaded, unclaimed, externally unprotected and unmarked. New components require air; growth never silently replaces even natural groundcover. Existing components must match the root-key succ_component, species/stage expected node (season-canonicalized) and rotation. succ_tree_stage and succ_species persist on the root; components carry its plain coordinate key. Components never independently age or pay nutrients. A tree's own owned leaves do not shade its own root into automatic starvation; neighbouring crowns still shade recruits. Pine and spruce retain winter shade.

Senescence atomically clears only the root's matching components and leaves one ground-supported full-cube fallen log, param2=12; existing content supplies the axe requirement and one-log drop. No floating standing log pile, sculpted tree, or chain of extra resource logs is created. Any protected/marked/foreign component blocks collapse rather than being destroyed. Natural epiphytes losing their owned substrate are removed in the same bounded preflight, while foreign attachments block it.

S.tree_removed(pos, oldnode) -> boolean is the optional after-dig handoff. A standard register_on_dignode hook calls it when available. It validates an empty loaded root, old stage identity and every remaining matching owned component; it cannot clear unrelated mapgen/player wood. External removals that do not invoke this hook must explicitly call the handoff; a denied/unloaded cleanup is not queued/replayed. Unmanaged pre-existing mapgen tree canopies are not retroactively adopted as managed trees. The independently registered generic deadwood adoption remains intact.

Focused validation and integration boundary

tests/botany_spec.lua is a standalone Lua 5.1+ mocked-API suite. It checks all 80 positive niche vectors and each light/moisture/pH/substrate rejection; 8×10 disjoint counts; unique scientific names; exact legacy mappings; seasonal/host/water distinctions; texture and registration ownership; bounded interactions; toxic/food exclusion; denied/full/partial/reentrant harvest; reload/cooldown and invalid clocks/metadata.

Standalone focused suites: tests/botany_spec.lua, tests/succession_spec.lua and tests/seasons_spec.lua. They include all 80 real selector outputs and recruitment/spread/lifecycle pathways with supplied species niche vectors, separately tested actual water/wood/pH habitat sampling, water preservation/authority, atomic real tree plans, owned cleanup/restart, malformed plans, concurrency bounds, finite fungal/nitrogen effects and cube-safe seasonal registration. Verified markers: BOTANY_SPEC_PASS 32, LAST_HEARTH_SUCCESSION_PASS 63, LAST_HEARTH_SEASONS_PASS 12 (107 named cases; the all-80 case additionally loops every taxon). Controlled niche-vector coverage is not evidence that all species spawn in one real-world patch. Require each final marker, all named passes and empty stderr; Fengari exit zero alone can hide assertion failures. On the network workspace, module source was read from disk once and executed in-memory to avoid repeated SMB reads timing out; tests/production modules were not rewritten for staging. No full engine or persistent world is run for this integration. Visual correctness, real-engine harvest/dig callback wiring and empirical gameplay/performance acceptance remain to be verified by main.

Security review followed CodeGuard: centralized runtime authorization, deny-by-default missing policy, finite validated positions/time, persistent bounded harvest, inventory preflight and reentrancy lock. No credentials, certificates, cryptography, network operations or dynamic executable inputs are introduced.