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

375 lines
28 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Landscape and ecosystem integration
This integrates the independent [terrain factory](../mods/hearth/biomes.lua),
[diversity policy](../mods/hearth/diversity.lua), and named botanical art into
[content.lua](../mods/hearth/content.lua). No save-schema/version change, engine
fork, new simulation scheduler, global API wrapper or runtime mapgen editing is
introduced. The precise upstream contracts remain [world generation](world-generation.md),
[ecosystems](ecosystems.md), and [original art](art-direction.md).
## Registration order and API
1. Construct/install `hearth.seasons`, then `hearth.botany` and `hearth.diversity`
**before** creating succession. Both extend seasonal policy; succession reads
`hearth.biomes` lazily when it needs habitat information.
2. Register all original nodes, ecological flora, seasonal food patches, resource
inputs, tools and recipes through the existing private registration facade.
3. Call the lazy biome factory with `(hearth, api, register_node, construction)`;
assign `hearth.biomes = biomes.register()`. This is the sole registration of
new terrain, full-block species trees, geology, aliases and decorations.
4. Call `diversity.register_nodes(register_node)`, then
`botany.register_nodes(register_node)`, then `seasons.register()`.
Species leaves and full-block tree stages now exist for seasonal copies.
5. Instantiate wildlife after these registrations.
The entire old mapgen section is removed, including its aliases, two biome
definitions, simple floor iron decoration, old weir/tree schematics and seep
registration. The biome module retains the canonical temperate/riverbank names,
canonical meadow timber and gathering routes, while supplying ten communities,
ten tree species and ordered real-host ore registrations. Its aliases are
**non-forcing** and honor existing registrations; nothing clears engine tables.
Its instance registration and diversity node registration are idempotent.
The private node helper honors explicit `def.tiles`. Species logs therefore keep
their top/top/side faces; soils keep their authored top and canonical earth sides;
full-block trees retain their species faces. Seasonal copies retain base placement,
protection, ownership and room-invalidation callbacks. Plantlike silhouettes use
their supplied texture rather than a guessed node-name image. All resource
craftitems use the existing `hearth_item_<name>.png` naming convention. The new
pick uses **hearth_item_copper_pick.png**, not a legacy `hearth_icon_` tool name.
No duplicate ore, wood, leaf or seasonal nodes are intentionally registered.
## Resource utilities and process handoff
| Resource | Content integration | Process-owner boundary |
| --- | --- | --- |
| Quartz | Three `hearth:quartz` shapelessly craft one existing `hearth:window` | No new furnace/glass process or scientific manufacturing claim |
| Copper | One `hearth:copper_ore` plus one `hearth:charcoal` shapelessly craft one `hearth:copper_charge` | A lit hearth processes one charge for **45 real seconds**, reserving **30 fuel seconds**, yielding **one** `hearth:copper_ingot` |
| Copper ingot | Three ingots across the top row and two central sticks craft one `hearth:copper_pick` | Ingot/charge registration alone does not implement smelting |
| Coal | Biome-owned coal seams drop two `hearth:coal` items | Each coal adds **240 real fuel seconds**, subject to the same **600-second** reserve cap and household authorization |
| Rock and timber | One granite/basalt/limestone/slate/sandstone crafts **four matching bricks**; **two matching rocks → two canonical stones**. One oak/birch/pine/willow/alder/beech/aspen/rowan/hazel/spruce log crafts **four matching planks**; **two matching species logs → two canonical logs**. One species plank crafts **one canonical plank** | All these conversions are shapeless; each pair uses two separate crafting slots, preserving mass (2:2). No single-log or single-rock canonical conversion; mixed types do not convert together |
The original reed/plank window recipe remains available; quartz is an alternate
mineral supply route to the same protected building node, not free reeds or a
new unsupported window. Clay keeps its existing pottery and charcoal roles.
### Exact process and thermal contract
The copper pick recipe is shaped: three `hearth:copper_ingot` across the top row,
one `hearth:sticks` in the center of each remaining row, empty side cells; output
is one pick. Quartz windows are shapeless: three quartz, one existing window.
The original window uses two identical rows of plank / reed / plank (four
canonical planks and two reeds). Each quartz/copper/coal seam drops two matching
items, but each copper charge consumes exactly one ore and one charcoal.
The direct exact-name fuel table accepts sticks **45s**, canonical logs **180s**,
oak/birch/pine/willow/alder/beech/aspen/rowan/hazel/spruce logs **180s each**,
charcoal **90s**, coal **240s**.
Fuel does not ignite itself. A whole fuel item is refused without consumption if
it would exceed 600 seconds. Planks, building nodes, raw ore, quartz and arbitrary
tree groups are not fuels. Coal is a geological, nonrenewable supply; its higher
heat value is not a renewable conversion loop.
Copper requires **75 seconds available at queue time** (45 duration + 30 cost).
The existing JOBS/RESULTS allowlists validate its distinct `smelt_copper` kind,
30 cost and copper-ingot output. Queueing reserves 30 seconds immediately and
consumes one charge; the absolute UTC fuel deadline also burns 45 seconds during
processing. Coal cannot replace the charcoal ingredient in the charge. Iron's
separate charge still takes 60 seconds with 30 reserved.
One canonical log + one clay shapelessly make one charcoal charge; species logs
must first convert in matching pairs: two same-species logs in separate crafting
slots yield two canonical logs, not a single-log conversion. The charcoal job takes 60 seconds and
reserves 30, producing one charcoal worth 90 seconds. There is no planks-to-log
recipe and no fuel gain from converting timber to charcoal. No recipe is added
by the process/UI integration; it exposes the content owner's actual recipes.
One hearth holds one job or one finished output. Queueing, fuel, ignition and
collection retain the same claim/external-protection, household-use and six-block
reach checks. Repeated timer/load reconciliation after restart or long absence
finishes the paid job only once, even after fuel expires; it never creates an
inventory item until authorized empty-handed collection. A full inventory or
rejected insertion leaves the one output waiting and blocks replacement jobs.
### Field notes and observational survey
The Mocha journal retains its original seven page indices and adds an eighth
regional geology/timber page. It describes all ten registered communities:
temperate meadow, oak woodland, birch forest, pine taiga, wet forest, floodplain,
dry scrub, alpine meadow, rocky peaks and riverbank. Recipe search includes both
window routes, copper charge/pick, all ten species planks, canonical log/plank/
stone conversions and all five regional rock bricks. Copper-ingot search also
finds its real-time process instructions; ingots are not direct crafting outputs.
The survey reads the actual `succession.habitat()` result once: support `ground`,
canopy/light/moisture, `pollination` (supporting plants, **not an insect census**)
and `nutrients` (bounded reserve out of eight). Missing optional observations are
shown as unavailable, not invented zeros. Ground labels are escaped for formspecs.
Pine and spruce retain evergreen winter shade; the other eight tree species
thin in winter. The API
does not expose separate evergreen/deciduous canopy counts, so the survey does
not invent them. Global active wildlife totals remain labeled as nonlocal.
Seasonal guidance explains pioneer birch, pine on podzol/alpine turf, wet-soil
willow/alluvium and alder, clover/flower pollinator support, spring bluebells,
autumn heather, wet sedge/bulrush, shade moss/ferns, rock lichen and nettle's
nutrient requirement. Clover adds at most two nutrient units per support across
replacement/restart while reserves are low; alder has a nitrogen-fixer habitat
profile by itself, **not an independent fertilizer process**; with botany installed,
the shared nitrogen-fixer policy also covers alder and other tagged species,
subject to the same finite support budget. Decomposers
recycle finite material. Habitat moisture is a bounded substrate/water/canopy
estimate, not fully simulated hydrology, watersheds, erosion or flooding. The
shared synthetic climate HUD and altitude-based environment remain unchanged.
Survey observation never advances succession, spawns wildlife or loads terrain.
### Eighty-species botanical field guide
The current catalogue is **80 named species, eight categories of ten each**.
It is a game catalogue of temperate north-west European organisms, **not a
real-world identification, toxicity or foraging guide**. Category membership is
an exclusive gameplay classification (for example, hazel is counted with trees,
and sedges/rushes with grasses), not a claim about taxonomic rank.
Names below follow the actual `hearth.botany.list()` records, including their
chosen scientific-name synonyms:
| Category (10 each) | Common name — scientific name |
| --- | --- |
| Trees | Pedunculate oak — *Quercus robur*; Silver birch — *Betula pendula*; Scots pine — *Pinus sylvestris*; White willow — *Salix alba*; Common alder — *Alnus glutinosa*; European beech — *Fagus sylvatica*; European aspen — *Populus tremula*; Rowan — *Sorbus aucuparia*; Common hazel — *Corylus avellana*; Norway spruce — *Picea abies* |
| Shrubs | Bilberry — *Vaccinium myrtillus*; Pleated blackberry — *Rubus plicatus*; Red raspberry — *Rubus idaeus*; Black elder — *Sambucus nigra*; Blackthorn — *Prunus spinosa*; Common hawthorn — *Crataegus monogyna*; Dog rose — *Rosa canina*; European holly — *Ilex aquifolium*; Common juniper — *Juniperus communis*; Guelder rose — *Viburnum opulus* |
| Grasses, sedges and rushes | Greater tussock-sedge — *Carex paniculata*; Bulrush (great reedmace) — *Typha latifolia*; Meadow fescue — *Schedonorus pratensis*; Cock's-foot — *Dactylis glomerata*; Timothy — *Phleum pratense*; Sweet vernal-grass — *Anthoxanthum odoratum*; Yorkshire-fog — *Holcus lanatus*; Tufted hair-grass — *Deschampsia cespitosa*; Common reed — *Phragmites australis*; Soft rush — *Juncus effusus* |
| Herbs | White clover — *Trifolium repens*; Common nettle — *Urtica dioica*; Heather — *Calluna vulgaris*; English bluebell — *Hyacinthoides non-scripta*; Yarrow — *Achillea millefolium*; Common foxglove — *Digitalis purpurea*; Meadowsweet — *Filipendula ulmaria*; Wild garlic — *Allium ursinum*; Cowslip — *Primula veris*; Wood anemone — *Anemone nemorosa* |
| Ferns and mosses | Bracken — *Pteridium aquilinum*; Lady-fern — *Athyrium filix-femina*; Male-fern — *Dryopteris filix-mas*; Hart's-tongue fern — *Asplenium scolopendrium*; Common polypody — *Polypodium vulgare*; Blunt-leaved bog-moss — *Sphagnum palustre*; Common haircap — *Polytrichum commune*; Cypress-leaved plait-moss — *Hypnum cupressiforme*; Broom fork-moss — *Dicranum scoparium*; Swan's-neck thyme-moss — *Mnium hornum* |
| Fungi | Fly agaric — *Amanita muscaria*; Brown birch bolete — *Leccinum scabrum*; Bay bolete — *Imleria badia*; Chanterelle — *Cantharellus cibarius*; Wood blewit — *Collybia nuda*; Shaggy inkcap — *Coprinus comatus*; Turkey tail — *Trametes versicolor*; Oyster mushroom — *Pleurotus ostreatus*; Honey fungus — *Armillaria mellea*; Birch polypore — *Fomitopsis betulina* |
| Aquatic plants | Common duckweed — *Lemna minor*; Yellow water-lily — *Nuphar lutea*; White water-lily — *Nymphaea alba*; Common water-crowfoot — *Ranunculus aquatilis*; Water mint — *Mentha aquatica*; Water forget-me-not — *Myosotis scorpioides*; Brooklime — *Veronica beccabunga*; Common water-starwort — *Callitriche stagnalis*; Rigid hornwort — *Ceratophyllum demersum*; Broad-leaved pondweed — *Potamogeton natans* |
| Lichens | Reindeer lichen — *Cladonia rangiferina*; Oakmoss — *Evernia prunastri*; Old man's beard — *Usnea subfloridana*; Map lichen — *Rhizocarpon geographicum*; Dog lichen — *Peltigera canina*; Lungwort lichen — *Lobaria pulmonaria*; Common orange lichen — *Xanthoria parietina*; Hammered shield lichen — *Parmelia sulcata*; Mealy pixie-cup — *Cladonia chlorophaea*; Pebbled pixie-cup — *Cladonia pyxidata* |
**How do I browse it?** Use `/botany [search]`, or the Botanical guide button in
the existing journal or ecosystem survey. The journal remains eight pages; no
ninth sidebar pane is added. The browser has ten species rows per page in
catalogue order, scrollable readable notes, Previous/Next, search, survey and
field-note controls. The ecosystem journal page also lists all eight categories
and their real common/scientific names. Missing or empty optional botany APIs
produce an unavailable message, not fictional substitute species.
**What does search mean?** Up to 48 characters of literal text, never Lua patterns.
It matches common/scientific names, IDs, category, habitat, seasons and roles.
Control characters become spaces; queries and all displayed catalogue text are
formspec-escaped. Page inputs are floored/clamped, including NaN and infinities;
no match and empty catalogue each retain one navigable page. New search resets
to page one; paging preserves the sanitized query.
**Which interactions are active?** The browser's substrate/light/moisture/pH,
host and aquatic-depth ranges are **game niche windows**, not measured field
data. Seasonal flowering supports the pollinator index, not spawned insects;
browse supports wildlife, not human food permission. Nursery cover reduces
recruit stress conditionally. Nitrogen-fixer policy consumes a finite two-unit
support budget while reserves are low. Host-compatible root fungi can accelerate
tree establishment while spending existing nutrient reserve. Saprotrophs can
advance an existing natural litter/deadwood clock; they do not create a second
nutrient payout. These require the appropriate season, habitat, natural origin,
protection checks and loaded simulation; a tag is not an unconditional aura.
Habitat engineering and resin-bearing labels are descriptive here, not a new
hydrology simulator or extraction recipe. Parasitism and allelopathy are explicitly
descriptor-only: no damage to player plants and no chemical killing effect.
**Does a missing toxic flag mean edible?** No. Toxic flags are catalogue labels,
not an implemented general poisoning system or real-world safety assessment.
Only bilberry, pleated blackberry and red raspberry have the catalogue's
seasonal game berry-harvest permission; this does not add food interactions for
other named fungi/herbs. Existing generic seasonal forage is a separate system.
Never use these notes to identify or eat real organisms.
**What does the survey count?** It reads the actual habitat API, not an 80-species
local census: grass/flower-support cover and combined shrub/fern/aquatic/tree
cover, canopy, light and moisture. Optional pH, nursery support, aquatic niche,
water depth, pollinator support and nutrients are displayed only when supplied;
missing optional fields say unavailable. In the botanical API, nearby water
cells (`near_water`) and aquatic depth (`water`) are different observations;
the legacy API's `water` cell count is not presented as depth. The pH is a coarse
substrate-class estimate, not a soil measurement. No species abundance is invented.
**How do fallen logs work now?** They remain ordinary full cubes laid sideways,
with an axe required and exactly one canonical log as the drop. There is no
hand-to-two-sticks harvest. The existing metadata-preserving orientation fix,
tree stages and ten-tree botany implementation are retained unchanged by this
process/journal pass. Claims and player-placed material remain protected from
autonomous succession. Voice work is explicitly deferred.
The copper pick mines `cracky=3` in **1.4 seconds**, with **70 uses**, versus
flint's 2.4 seconds and 35 uses. It retains mining `maxlevel=1`, drop level 1,
damage 3 and punch interval 1.2; it adds no tougher-rock capability and no wood
capability. It is not a replacement for the separate iron axe progression.
The exact new icons are `hearth_item_copper_ingot.png`,
`hearth_item_copper_charge.png`, and `hearth_item_copper_pick.png`; ore, quartz
and coal icons/nodes are registered by the biome owner only.
## Broad-relief v7 preset: new worlds only
[terrain.mjs](../scripts/terrain.mjs) exports pure `terrainSettings(newWorld)`
and `isTerrainSetting(line)` helpers. [run.mjs](../scripts/run.mjs) exports
`writeWorld()` for direct disposable tests; importing it does not invoke its CLI.
The launcher checks for existing world metadata **before** creating the world
identity. Either existing world.mt or map_meta.txt suppresses the new preset.
This also protects a legacy world without map metadata and an orphan map metadata
file. Every play still gets a fresh, exclusive session configuration, but existing
worlds get **no mapgen, seed, water-level or mapgen-limit overrides**, including
from an inherited fixture. Saved map metadata is neither parsed nor rewritten.
[Game defaults](../minetest.conf) and the launcher agree on v7, water level 1,
**mapgen limit ±4096**, caves, light, decorations, biomes and ores. Dungeons and
floatlands are disabled; mountains, ridges and caverns are enabled. The launcher
retains seed 731104 for fresh worlds, with explicit fresh-world fixture/seed-test
overrides taking precedence. Existing seed and mapgen remain engine-owned.
This applies the [source-reviewed recommendation](world-generation.md#recommended-v7-preset--new-worlds-only)
with three deliberate adjustments: terrain-base scale **45** instead of 65,
mount-height offset **250** instead of 230, and world bound **4096** instead of
512. Base offset 12 and alternate scale 28 keep gentler accessible terrain among
the relief. Hills have 384-node spread, mountains/ridge-water fields 700-node
spread and climate fields 256-node spread. Mountain density keeps the −0.6 bias
and 180×280×180 spread. Mount-height noise is a density-gradient input, **not an
absolute peak-height cap**. Neither the fixed seed nor these inputs guarantees
a low, dry or resource-complete starting location.
The goal is broad hills, grounded massifs, river channels/canyon walls, woodland
and alpine transitions—not floating islands or voxel confetti. This is native
v7 noise and registered geology, **not scientific erosion or watershed simulation**.
Small native overhangs/disconnected remnants remain possible despite nofloatlands.
There is no global per-frame voxel rewriting or custom terrain postprocessor.
### Existing worlds and transitions
Use a separate empty runtime root/new world to try the coherent preset. Do not
delete the current save or metadata to obtain it. Managed play retains its normal
prelaunch full backup and embedded-game identity checks. Existing generated chunks
remain untouched; the world bound and mapgen parameters are not expanded in place.
New biome/ore/decoration registrations can affect **future ungenerated chunks** of
an old world and create visible seams against old terrain. Existing mapgen noise
does not imply old biome registration tables are restored. There is no migration,
automatic regeneration, chunk deletion or retrofit of old geology/vegetation.
The operator must explicitly decide between a separate fresh world for coherent
terrain and accepting new-biome boundaries in unexplored parts of an old world;
this integration makes no automatic migration decision for existing saves.
## Focused validation and remaining native gates
### Botanical process/journal follow-up — 2026-11-03
**72 focused standalone checks passed:** hearth processes **34**, recipe/journal/
survey **38**. Both used in-memory snapshots of the actual on-disk modules and
required the exact named-check total, final suite marker and empty stderr.
The journal fixture loads the actual botanical factory and `list()` method,
checking all 80 common/scientific names across eight ten-row pages and category
counts. Coverage includes missing/empty botany APIs, all ten timber recipe/fuel
routes, building-fuel rejection, bounded literal/escaped queries, pagination,
chat/buttons/exit/session routing, footer/sidebar bounds, honest role/toxic
labels, optional survey fields and axe-only fallen-log guidance.
Only the seven requested process/UI/test/documentation files changed in this
follow-up. No voice work, full engine run, persistent-world launch or native
visual certification was performed. Historical results below remain historical;
they do not certify the newer 80-species pass.
### Final integrated verification — 2026-11-02
- Full pinned Luanti 5.18.0 check/smoke passed with **25 isolated Lua suites**;
the expanded suites cover 466 checks. The final invocation exited zero.
- Native registration/crafting checks resolved **63 recipes / 47 outputs**.
Species logs and rocks use distinct matching-pair conversion recipes; no
single-input canonical-conversion ambiguity remains.
- Native media closure checked **807 references**, with **zero missing files**.
- All **eight fixed seeds** passed in one complete run without seed retries.
Each had exposed water, food, flint, sticks, rushes, side-accessible timber,
and dry natural landing patches (412–658 sampled patches per seed).
Timber access checks inspect horizontal air beside trunks: a leaf canopy
above a trunk does not make it unreachable, while buried logs do not count.
- Four separated bounded worldgen probes observed four surface biomes and
granite/slate/limestone/sandstone strata plus quartz, copper, coal and iron.
This is sampled evidence, not proof every biome occurs in every seed.
- All **59 Node tests** passed, including original artwork, geometry,
deterministic packaging, terrain presets and saved-world preservation.
Final native, seed and Node commands each exited zero with empty stderr.
- Earlier integration checks exposed ambiguous conversion recipes and an
upland-rush generation ordering problem; both were fixed, not waived. Springs
now generate before adjacent water-dependent rushes. The original overhead-air
timber assertion was replaced with a genuine side-accessibility check.
These are disposable headless worlds. No persistent play world was opened or
regenerated. Native appearance, performance, ecological balance and human
acceptance remain unverified; noise-based relief is not a geological simulator.
Optional complete audio codec regeneration was not configured.
[Content tests](../tests/content_spec.lua) preserve all previous checks, add
`register_ore` to the mock, reject duplicate nodes/items/decorations, verify ten
unique biome registrations and nine ordered ore definitions, check seasonal
species order and idempotent registration, resolve every recipe/drop and validate
named mineral/species/understory images. Tool capabilities and both window routes
are checked. Art counts are checked by manifest roles rather than assuming every
inventory image is a craftitem (the copper pick is a tool).
[Tooling tests](../tests/tooling.test.mjs) compare game defaults to the pure preset,
verify new-world config emission and seed precedence, check repeat config writes
are exclusive, and assert byte-for-byte unchanged existing world identity/map
metadata. They also cover missing-map-metadata and orphan-metadata opt-outs. These
are Node-only disposable fixtures, not a launch of the original play world.
Previously recorded terrain/content integration results: **136 Lua checks passed** (content 33,
biomes 23, seasons 11, ecology 9, succession 49, diversity 11), with each suite's
expected final marker and empty stderr. The content suite also passed all 33
checks with a numeric flattened target and remapped sibling loader. **24 Node
tooling tests passed**, with zero failures, cancellations or skips and empty
stderr. All three changed JavaScript/test modules passed syntax checks. Editor
diagnostics and the owned tracked-file whitespace check were clean. No previous
content or tooling test was removed.
Resource process/journal follow-up: **54 focused standalone checks passed**:
[hearth processes](../tests/m2_processes_spec.lua) **29** and
[recipe/journal/survey](../tests/recipe_spec.lua) **25**. Both required their exact
named-check count and final suite marker, with empty stderr. Coverage includes
every species fuel, coal capacity/refusal, copper duration and reserve boundaries,
one-output collection, restart/long-offline idempotency, unauthorized interactions,
full/rejecting inventories, invalid metadata and raw-item rejection. UI checks
cover all five species/rock routes, both windows, copper crafting/process search,
eight-page bounds, seasonal guidance, optional/hostile habitat fields and Mocha.
The process fixture's notification closure was corrected to reference its local
hearth instance; no production authorization behavior was bypassed. No full engine
tests were launched for this follow-up, concurrently or otherwise. These mock
tests do not certify new terrain, native rendering or real seed reachability.
Standalone Fengari execution requires named checks **and** the final suite marker
with empty stderr; exit zero alone is insufficient. The content harness resolves
siblings through its mock modpath/dofile boundary, not a replacement of live core.
The recipe-collision regression keeps all **63 registered recipes / 47 distinct
outputs** and verifies exact output names/counts, unique shapeless ingredient
multisets (including repeated inputs), and shaped layouts, including potential
shaped/shapeless overlap. All **25 terrain recipes** remain: single logs/rocks
produce four species planks/bricks; matching pairs produce two canonical logs/
stones. The native smoke must still exercise every recipe through
`get_craft_result`; standalone signature checks are not a native engine pass.
Collision-fix validation passed **84 focused Fengari checks**: biomes **24**,
content **35**, and recipe/journal **25**, with exact named totals, each suite's
actual final marker (content uses `1..35`), and empty stderr. In-memory negative
probes separately restored the old single-log and single-rock conversions;
both were rejected by their regression contracts. No engine was launched and
no running player session was changed for this fix.
Native isolated runners flatten Lua filenames: sibling lookup must use a directory
plus explicit sibling basename, not `gsub("content.lua", ...)` on a numeric staged
filename. Focused registration tests do not generate or certify actual terrain.
No full engine tests were run for this integration. Main must still validate
saved preset values in a disposable native world, all seed starts including
731104, safe spawn heights, actual tree anchoring/media, and water/flint/sticks/
timber/forage/reeds/clay reachability. Existing emergence/resource fixtures limited
to Y=96 can miss high slopes/peaks; canonical-only soil/log searches can miss
species terrain. Adapt native probes and spawn policies rather than declaring
these mock passes proof of seed safety or handing out supplies. Finish native
process and visual/performance review separately. Historical
M4 eight-seed results do **not** certify the new terrain preset.
Security: no secrets, network calls, dependencies, cryptography or arbitrary Lua
execution are added. Bounded declarative registrations retain normal claim and
external-protection checks. Existing guarded filesystem paths, exclusive config
creation, snapshots and mod security remain in use; saved map metadata is read
only for existence and never rewritten by this integration.