Project

Roadmap & backlog

Everything the mod still has to do, ordered by priority — most urgent first, endgame last. Broken things before missing things, foundations before the features that sit on them, content before polish.

This page is work still to be done — not a description of the program

Nothing on this page is built. When something ships it is deleted from here and written up on its own page (the genetics model, a gene-*.html page, the horse’s body, breeding, horse care, the carrot family, items, the horse dimension…). “Marked shipped” is not the same as “moved”, and only moving it keeps one source of truth.

To be verified is the near end — built, not yet seen in-game. That is a different list from this one. And this page is work, not reasoning: the why lives in Philosophy, and anything here needing a justification longer than a clause belongs there.

Section numbers were renumbered 2026-09-06

The page was reordered by priority, so the old numbering (“§14 the carrots”, “§21 settled”…) no longer applies. A reference elsewhere to a roadmap §-number predating this date should be re-pointed at the section that now covers it, or at the wiki page the work moved to. Sections are named as well as numbered; link by anchor, not by number.

§10 is down to colour and glow — the masks, the canvas and the dial are all in

FRACTAL and PATH shipped on both sides in September, and the drawing canvas that PATH was waiting for is now the creator's points control: the format page documents it. It changed no format, no engine and no parity fixture, exactly as the entry predicted — it is a second control over an array that already existed.

So the question this note used to park — whether the textarea was good enough to wait behind the Java gene API — is moot, and the API shipped on its own merits.

Erase-down and the expression preview are in too, and they turned out to be one feature seen from two ends. A knob may now be marked "dial": truethis is how much of itself the gene is showing — which lets the creator put a slider under the preview instead of making you re-roll horses until one lands near an end, and lets a PATH carry pointsMin: the same shape at the gene's weakest, morphed point to point, so a drawn marking gets smaller rather than fainter. Both sides, with an answer table in the parity fixtures, because the probe cases do not reach a drawing on a flank. See the dial and pointsMin.

Glow intensity is in as well. A layer's emissive is a level rather than a bit — any number or knob in [0, 1], scaled by the mask's coverage, so a soft edge fades its glow out instead of ending it on a line at coverage 0.5. It reverses the old "there is no half-lit" call deliberately: the emissive pass blends rather than replaces, so the level is written as the second texture's alpha and a fraction means something.

What is left of §10 is per-region colour ranges and gradients — and one honest gap beside it: the creator cannot show a glow. It writes one, validates it and round-trips it, but its preview is a flat sheet with no lighting to be brighter than, so a glow is something you have to go and look at in game. Fixing that means shading in the preview, which is a different job from anything in this section.

Where to start

If you have one session, spend it on the top of this list. Each item is picked for blast radius — how much else is wrong, or blocked, until it is done.

  1. Look at the three dialled genes (§0-CP) — Starburst's emblem now scales per horse, and Lantern and Tron burn at a level their dial sets. They are the first genes whose variation is the point rather than their pattern, and nothing but a person can say whether the range is right.
  2. Play-test the backlog — the two items that stood at the top of this list both shipped, and neither has been seen by a person. A great deal else is built and unplayed: see To be verified, which is longer than this page's top section.
  3. What is left of the visual marking designer (§10) — the canvas, the dial, the minimal shape and glow intensity have all shipped, so what remains is per-region colour ranges and gradients: colours are literals in the format today rather than Values, so the first question is whether a colour becomes knob-drivable at all.
  4. Deepen the thin science tabs (§science) — every natural gene page now has one, so the work is no longer absence but depth: 23 predate the pass that wrote the rest, and 17 of those read as stubs beside it — starting with the ones the new tabs cite and cannot get an answer from.

The gameplay layer (§§13–20) touches the genetics in only three places — carrots bias a gamete draw, jars carry a genome, and the database and carrot recipes read gene metadata — so it can proceed in parallel with the gene work above.


Part 1 — Things that are wrong now

1. Defects in shipped genes and the coat

All of these are built features behaving incorrectly, so they cost nothing to schedule and everything to leave. Anything here that moves a coat wants coat-golden.txt regenerated and WhitePatternGenesTest’s monotonicity ladder re-checked in the same commit.

The white-pattern calibration is done — all of it

Both painters measure against a topline reference (WhitePattern.toplineHeight) rather than the whole-horse AABB, so the fractions in them mean something anatomical: 0.05 is the coronet, 0.26 the knee, 0.52 the underline, 1.0 the spine. See the pipeline and EDNRB.

The two items that stood here after the splash fix are also shipped and were simply never deleted, which is what this page exists not to do. EDNRB’s frame band is measured on the barrel’s own height now, with a separate band on the neck’s (the naive per-part fix did strip frame’s legitimate neck white, exactly as the entry warned). And every cover knob is an area fraction by construction: both EdnrbGene.paintFrame and TobianoGene score every eligible texel, sort, and cut at the quantile matching cover, so the knob cannot drift when the field or the geometry moves under it.

Medicine hat is not on this list and is not a gene (owner’s call). A near-white sabino keeps its ears and the back of its poll because WhitePattern.sabino never paints the ears; whether that reads as a bonnet on any given horse is left to fall out of the draw. It is not being modelled, retained for, or rolled.

1.2 Genes drawing the wrong thing

GeneProblemFix
Leopard complex“White finds white” is not applied. Leopard composes at priority 73, before the four white loci, so leopard + sabino simply stacks rather than compounding.Decide whether the appaloosa patterns should read the coat they are handed like the other white painters do. Multi-pattern appaloosas are unverified either way. The spot / blanket / hoof-stripe constants are also first-guess and want a play session.

1.3 Behaviour that silently does nothing


An "over" flag, so a layer can say it paints on top

The root cause behind gap 169, and the only thing that would actually stop it recurring. A magical gene's layers each measure their delta against the colour the gene started from and the deltas are summed. Authors — human and model — write files as though each layer painted over the one above it, because that is what layers mean everywhere else, and the format gives them no way to say it. So they write the thing that looks like stacking and get summing, and the result is a solid black horse (dorsal wing), a white one (contour), or a star with no core (starburst).

The proposal is one optional per-layer flag: "over": true applies the delta accumulated so far before this layer measures. Everything without the flag behaves exactly as it does now, so no existing gene moves — which is the property that makes it worth doing rather than changing the default. Dorsal wing's original file would have been correct as written — and so would eight of the twenty-four genes in the 2026-09-10 evening intake, every one of which arrived nested and had to be rewritten disjoint by hand (gap 169). That is the rate this is costing.

The cost is why it is here and not done: it is a format change, so it is the five-file contract — the engine, SpecSchema, the fixtures, the creator's JS twin and the designer — plus a decision about whether expected.json and the goldens move. DeadLayerTest is the cheap half and is already in; this is the expensive half and wants the owner's call.

2. What horse resizing broke

Attributes.SCALE — written by the size genes and the breed stat bands — changes the model and the hitbox, and a pile of vanilla assumptions do not follow it. None of it is game-breaking; all of it is cosmetic or feel, and all of it needs a pass before 1.0.


Part 2 — Decisions

3. Decisions still open

Each of these changes what gets built, so answering one is worth more than a day of building around it. Settled decisions are at the bottom of the page (§22) so a later session does not relitigate them.

QuestionWhere it stands
Should Condition gain a severity / onset model?The mod’s health model is binary: a locus is LETHAL_AT_BIRTH / LETHAL_AT_CONCEPTION, or a flat heart reduction. The naturalgeneref.md disorder table is richer — each gene carries a health %, a speed % and a jump %, and distinguishes episodic, chronic and progressive-onset conditions. HERDA, PSSM1, HYPP and CA (§12) all fit that shape and none fits “fewer hearts” cleanly. Two ways: (a) keep the binary model and render each as a flat heart cost plus a flat speed / jump multiplier — cheap, loses the “flares up under exertion” character; (b) give Condition a 0–1 magnitude and an EPISODIC / CHRONIC / PROGRESSIVE kind that the health resolve and a future status tick both read. (b) is the reference’s model and the natural companion to the effect architecture (§7). Still not decided — but all four of those genes have now shipped under (a), so the question has changed from “which model” to “is (b) worth a migration”. Building them also settled one thing the question did not anticipate: the reference’s percentages could not be used as arithmetic at all. Read literally against a 22-health baseline they make an affected but living HYPP horse worse than several of the mod’s outright lethals, so every one of the new loci is calibrated against the disorders that already ship and uses the reference only for the ordering. Whatever (b) turns out to be, it does not get to inherit those numbers.
How is a cutie mark chosen — and should the gene be polygenic?The hook is built (2026-09-06): CutieMarkContribution lets any gene modify the mark, and markFor folds every implementor over the base emblem in code order — the light locus is the first user and makes the mark glow. What is still open is the content: which genes and breeds should bias the item pool (a milk horse leaning toward bucket and bottle icons), and whether mark colour is worth having — a per-instance tint is not renderable through ItemStackRenderState.submit, so it would need a custom render type. Wants more fictional breeds (§19) to be worth doing.
The 1.12.2 backport.Not a question so much as a standing constraint. Everything on this page is common/-side except entity scale, gait animation, the health tick handler and the gene registration hook — those four are the only places the backport goal should shape a design.

Part 3 — Foundations that unblock the rest

4. Sex-linked inheritance — what is left

Shipped 2026-09-06

The scaffolding and its proof are built. Gene.inheritance() declares AUTOSOMAL / X_LINKED / Y_LINKED; Genotype.breedWith routes the sire's copy by the foal's own sex; Gene.sexConsistent keeps impossible combinations out of the catalogue; a hemizygous copy is stored in a reserved slot and displayed with an X- prefix; founder tables are sex-aware. Brindle is the gene that proves it. See the brindle page.

What is still open here:

Not planned at all: imprinting, mosaicism, crossing over, linkage.

5. Eye colour — what is left

Shipped 2026-09-06

Everything this section used to list is built, and the channel now has its own page: Eye colour & heterochromia. Green and hazel irises (champagne's epigenetic shade and cream–pearl's blue-green), the blue-eyed creams, complete heterochromia (one blue eye) and sectoral heterochromia (a blue wedge) off a per-horse EyeSpread, and the magical sectoral heterochromia locus.

What is still open here:

7. Group traits, and the rest of the effect architecture

7.1 Traits that come from a group of genes

Wanted, and distinct from the cut polygenic idea: two or more genes, each with their own alleles, that only together trigger an outcome. This is epistasis / complementation — still fully Mendelian — and it needs a home. The leopard complex got what it needed without one (expressionIn is handed the whole genotype), but that is a single-gene read, not a rule of its own.

Cream + pearl looks like this case and is not: they are one physical locus, and MATP merges them rather than writing a rule.

7.2 The rest of the effect architecture

A first slice is built — eight effects verbs with boolean when conditions, usable from a gene file and from a built-in Java gene through the same vocabulary. What is left is everything else on the trait & effect architecture: triggers, selectors, auras, resource pools, goals, trait relations, on_change, and the 0–1 scalar conditions the built version approximates as booleans. The capability interfaces should not be considered final until that lands — and the severity model question in §3 is the same shape of problem.

Two known weak points in the shipped slice: spread converts at most one block a beat off a narrow, hand-written block list, which is the piece most likely to be wrong in play (the risk is a horse eating something a player built), and walk_on_water is surface buoyancy rather than a real collision plane. Wiring the inert attribute verb is §1.3.


8. The Java gene-authoring API, and an open registry

A gene that fits the format is already a JSON file — no Java, no rebuild (the format, the creator). That covers the common case, so this is not urgent; it pays for itself on the next hand-written gene, and there are a lot of those still to come (§§1012).

Built — the bases, the open registry and the event all shipped

AbstractNaturalGene, AbstractMagicalGene and the TwoAlleleGene skeleton under them answer seven of the interface's eight methods from a declaration; the short path is the write-up, and mushroom is the worked example. AbstractAbilityGene — which is where the shape was first noticed, seventeen genes ago — was moved onto the same skeleton, which is the evidence it generalises rather than being a second copy of it. Genes.register takes any Gene, validates the namespaced key, and freeze()s; neoforge.api.RegisterHorseGenesEvent is the way in, and registering from another mod says when it fires and why it has to be an event.

What is actually left

The allele rules and the contract a modder must honour are on Writing a gene. One thing a third-party gene still stresses: CoatTextureId encodes the whole genotype into an Identifier path, so more genes means longer paths — see §21.


10. The visual marking designer

The owner wants this, and it is the blocker for the complex patterns

Markings like peacock and laced tobiano cannot be described to an AI in words — they have to be drawn. And a visual editor is simply more fun to use than writing JSON. This is the largest single job on the page, and it is on the critical path for the 1.0 pattern set rather than optional.

9.1 The smaller creator work

The three items that used to sit here — the gene-metadata form fields, an effects editor, and an in-page parity check — all shipped 2026-09-06, along with a fix for the reason they mattered: the creator’s geometry port had silently missed the top/bottom UV swap and the committed parity fixtures predated it too, so the terminal check had been reporting green against a stale baseline while the preview drew every horse with its spine and belly texture patches exchanged. The in-page check is exactly what makes that class of rot visible.

What is left of them is one honest limit rather than a task list: the when form edits a flat all / any of (optionally negated) condition flags, which is every condition any shipped gene uses. A nested condition is preserved byte-for-byte and shown read-only, because silently flattening someone’s tree is worse than declining to edit it. A real tree editor is only worth building once a gene needs one.

9.2 A usability pass on the creator

Owner asked for this 2026-09-06, right after confirming the rebuild

“We’ll edit it more to make it a little more user-friendly later.” The tool is correct now — it loads, it previews a real horse, it writes every part of the format, and it proves its own engine against the game’s on boot. What it has never had is a pass for whether it is pleasant to use.

Nothing here is specified yet, deliberately — the point of the pass is to look at it with fresh eyes rather than to implement a list written in advance. Known rough edges to start from:

The constraint that does not move: it has to keep working from file://. That is why every script is a classic one and every asset is inlined — see the format. A UI framework that needs a bundler or a dev server is out.

Breeds as packages shipped 2026-09-07 and is no longer on this page: a breed is a JSON file, there is a loader beside GeneSpecLoader, and the breed designer is the editor for it. What that leaves here is only the marking half above. See the breed file format.


Part 4 — Genes still to build

Finished genes are not listed here — that is all forty-eight of them, rostered on the genetics model with a page each, and any residual tuning lives on the gene’s own page. What follows is only what no gene does yet. Natural genes all exist in real life, so they all belong in the 0–99 priority band and run before any magical gene; the scientific allele names are legal tokens as written.

11. Natural genes

The naturalgeneref.md audit — a standing task

naturalgeneref.md in the repo root is a cleaned extract of another horse game’s natural-genetics guide, and it is the reference the natural side should be complete against. It already carries a level of game-ready abstraction, which is why it is worth diffing against rather than primary sources. Standing task: read it end to end, diff it against the registered genes, and turn each gap into a row here.

Last run 2026-09-06. Every base colour and dilute in the reference is modelled at least in mechanism. What it turned up is below: six genes that do not exist, several shipped genes whose variation vocabulary is narrower than the reference describes, a phenotype-naming surface the mod has no equivalent of, and a disorder table (§11).

10.1 Genes that do not exist at all

GeneWhat it isWhat it needs
Wild bay (and At as a real allele)An agouti variant pushing the black points down — black only to the fetlock rather than the hock, with a gap between the knee/hock point and any fetlock point, and a more yellow body.Cleanest as a third agouti allele (A+, dominant to A). And if A+ becomes an allele, At (seal) should too — then agouti is the reference’s four-allele A+ > A > At > a, and seal stops being an epigenetic edge case (next row).
Natural (polygenic) face and leg whiteThe reference is explicit that a horse with no paint gene can still carry a star, stripe, snip, blaze, coronet, sock or stocking. The mod only draws face and leg white as part of a KIT / MITF / PAX3 / EDNRB outcome, so a bay with no white gene is always cleanly solid.A small always-on marking draw — a handful of epigenetic values, no allele — feeding the shared WhitePattern.faceMarking and leg vocabulary at low strength. The vocabulary already exists; this is a caller, not a painter.
DMRT3 — gaitDominant. Ambling / running-walk / pace.The gene is trivial; the value is the animation, which is renderer and movement work. That is why it is last in this group. Wanted by both Paso Finos, Tennessee Walking, Standardbred, Icelandic and Hackney.

10.2 Alleles missing from loci that ship

LocusMissingNotes
Extension (MC1R)eaPurely additive now that multi-allele support exists. ea is phenotypically red like e, so all the interest is in the code string and the carrier display.
KIT — the rest of the W seriesW1W3, W6W9, W11, W12, W14, W16W19, W21, W24W28, W30, W31, W33Twelve of thirty-plus are modelled — W15, W32, W34 and W35 landed with the booster group, which was the important part of the remainder: W32/W34/W35 are common, not rare, and the locus had none of them. What is left is genuinely the long tail — one founder or one family each, frequencies that round to zero. The owner wants the full set mapped eventually, redundant alleles included, as a completeness goal — so this is a “do it” item, not a “not worth it” one. Each is a line in alleles(), a row in expressionOf and a frequency; ones whose published phenotype is indistinguishable from a modelled allele should collapse onto that allele’s outcome (the SW6SW8 precedent) rather than getting their own row. Watch the combinatorial cost: each allele adds n combinations to a locus already at thirty-six, so do the hash-keyed texture id (§21) first.
The splash seriesSW9, SW10; possibly splitting SW6SW8SW6SW8 are folded into SW5 on purpose — the source describes all four in word-for-word identical terms, so four alleles would be four indistinguishable rows. Split them when they become distinguishable. SW9 / SW10 need a locus check first: which of MITF / PAX3 they belong to is not settled in the reference used.

10.2b Ordinary white markings have no gene of their own

Most stars, snips, socks and blazes in life are polygenic — many small-effect variants, plus plain developmental variation in how far pigment cells migrated. There is no single locus for them, and the study that identified SW1 found no splash allele at all in 112 horses deliberately picked for minimal white.

The mod has no such system, so SW1 stands in for one: it is the one real allele that genuinely does hide in plain sight, its single copy is painted over a range from a snip to a full splash, and a majority of founders carry one. That gives the world its ordinary marked horses at the cost of attributing them to a locus that mostly does not cause them.

The honest fix is a small markings contribution — a per-horse score with no allele behind it, or a low-effect additive locus in the shade / sooty dosage shape — drawn from the shared face-marking vocabulary and a leg ramp, running before the white loci so they stack onto it. Then SW1’s frequency drops to what its own evidence supports and the two stop being the same claim. It is a new system, which is why it is here and not in the gene.

10.3 Shipped genes whose vocabulary is too narrow

GeneWhat the reference describes that is not drawn
DunGuard hairs — the pale hairs at the base of a dun’s mane and tail — which want a hair-level treatment the mane box does not have. And d1 should carry faint bars and shoulder shading, not the dorsal stripe alone; the blocker is that d1 does not dilute, so there is nothing on a leg to countershade a bar against. (The dilution, points, leg bars, shoulder bar and face mask / cobwebbing all ship — see the gene page.)
FlaxenShips as a uniform lightening with strand mixing - a fixed noise field spares some hairs. What it does not draw is the root-to-tip gradient the reference describes: dark at the roots, palest at the ends. That wants a coordinate along the hair rather than across it, which is what HairPattern.axesBySpan already finds for the magical mane colours, so the seam exists.
Silver dappleShips as the dilution only — the dapples the gene is named for are not drawn. Wants a deterministic fixed-seed BodyNoise modulation, like grey’s but lighter and per-genotype. The flaxen mane also currently reads a little gold rather than pale.
RoanCorn spots — small islands of solid base colour left inside the roan field. The per-texel dither has no notion of them; wants a second, low-frequency mask pinning a few texels fully coloured.

10.4 Base-aware phenotype naming

A surface, not a gene, and it serves three separate gaps. The reference names gold / amber / sable / classic champagne and chestnut / bay / black / cream pearl as distinct phenotypes by base, and expects cream×champagne and cream×pearl to read differently again. Separately, it treats seal bay as its own base that sable champagne rides on — but seal has no gene in this mod, it is the top of agouti’s epigenetic distribution.

So the mod needs a way to resolve and name “this genotype is an amber champagne” or “this horse is seal” for the info panel, the paper dump and the gene dictionary — and champagne needs to read “is this horse seal” off the agouti epigenetics to paint sable rather than amber. One base-aware phenotype resolver serves all of it. Making At a real allele (§10.1) removes the seal half of the problem outright.

Capability tests, not planned genes

“Add a red border to every white area” and “turn all the black to pink”. Neither is a committed gene; both are the acceptance test for whether a magical gene can actually see what is underneath it.


12. Health and disorder genes

The reference table’s disorder list is now covered. Sixteen loci ship along with the health system they were blocked on: a lethal foal is born and then dies, everything sub-lethal is fewer hearts and a slower horse, and no founder is ever born dying. Machinery on the horse’s body; each locus has its own page.

The last batch brought two shapes the mod did not have. HYPP (SCN4A) is the first locus that is both a survivable heart reducer and a homozygous lethal. PSSM1 (GYS1) is the first dominant sub-lethal — and between them they broke the rule that no founder is ever affected, because a dominant with no silent carrier that never appeared in a founder could never appear at all. A wild-caught horse can now be visibly unwell, which is the only disorder shape a player can see before breeding from it.

Two of the nine, CVM and megaesophagus, have no confirmed causal variant in the literature. They are keyed on the condition rather than on an invented gene symbol, and both pages say plainly that one recessive locus is the mod’s simplification rather than a claim about horse genetics.

What else is left on the health layer


13. Magical genes

Invented genes, phase 3, priority 100+. This list has no upstream source to be complete against — add to it freely. Each needs a priority, an allele set with n as wild type, a founder distribution and a delta function. Fixes to the magical genes that do ship are in §1.2.

12.1 More of what already works

Two mask parameters the 2026-09-10 evening intake asked for

Both arrived as tool gaps in the authoring notes, both were read after the approximations had been seen on a horse, and both describe a shortfall that is really there. Each is one new parameter on an existing mask, defaulting to today's behaviour, so no shipped gene moves - but each is still the mask contract: the painter, SpecSchema, the creator's twin, both tables, a prismatic case, fixtures and parity.

12.2 Behavioural, diet and shapeshifting genes

A family that changes what a horse does rather than how it looks, riding the effects path plus whatever new verbs each needs.

The batch has shipped — twenty-seven genes, and this section is nearly empty because of it

A twenty-nine-gene proposal was specified one gene at a time, two were cut, and the remaining twenty-seven are built, registered and documented. Each has its own page carrying the settled inheritance, the rejected alternatives, and its game-breaking, compatibility and performance hazards on the coding tab. Those pages are the source of truth; nothing about them belongs here any more. None of it has been seen in gameTo be verified is the authority on that, and is where the batch now lives.

The two that were cut. Moon-sick was already shipped as the Aga/Aga allele on night temper, and a second locus doing the same thing is not a gene. Electric cannot be built as described: redstone power comes from blocks and never from entities, so the honest version is either per-tick block placement or pressure plates, which already respond to every horse in vanilla. Neither should be reopened without a new argument.

What the batch cost, for the next time somebody estimates one. Seven new verbs (sound, produce, teleport, summon, temper, bond, ward), two new triggers, four new condition flags, five existing verbs widened, and three base classes that carry twenty-three of the twenty-six between them. The earlier estimate of “about one verb per behaviour” was roughly three times too high: behaviours cluster, and the base classes were worth more than any individual verb.

What is left on this family

Gene / familyWhat it doesWhat it needs
Diet genesA carnivore horse — eats or is fed meat, refuses or is unaffected by plants. The hook for vampire and werewolf breeds.Partly built: HorseDietHandler and the diet locus ship. What is missing is the rest of the vocabulary and the breeding / taming side. Food preference now deliberately overrides it, and that ordering is a contract rather than an accident.
Vampire horsesHeal only by damaging other living mobs; optionally take sun damage like a skeleton.Suppress the gated regen for these horses and add a lifesteal-on-attack effect. Sun damage is a burn-in-daylight tick reusing the skeleton condition. The temper verb and the on_hurt trigger both exist now, so this is cheaper than it was.
A guardian that answers a playerA guardian currently never retaliates against a player attacker, only against mobs.A deliberate limitation rather than a gap: 26.1.2 exposes no server-side PvP flag to gate it on, and a horse joining a fight between two people without either agreeing is the wrong default. It wants a mod config option, not a code fix.
Lycan onto MobRosterThree loci have an allele per mob; two read one table and lycan still keeps its own copy.The drift this is designed to prevent. Lycan's allele order is baked into the genotype code and two checked-in goldens, so migrating it moves every saved horse — a real change with a real diff, not a tidy-up. See known gaps.

12.3 Attached model parts

The owner wants a batch of these — “a HUGE win for how cool they look”

Blockbench meshes attached to the horse model, gene- or breed-driven, with no independent animation needed. High priority: unicorn horns, spikes / dorsal spines, crystalline growths — small models, head- or spine-parented, big visual payoff. Lower: pegasus wings (body-parented), lion and tufted tails, hoof feathering (already wanted by the draught breeds), tusks, antlers. Do a batch of the head-parented ones first — one render layer, many models.


Part 5 — The gameplay layer

Sections 13–20 come from two design documents handed over whole: a system summary of the gameplay features, and a specification for a trading villager. Together they describe a layer sitting on top of the genetics. The items, carrots and database, bond and herds and seed jar slices that are built are documented on those pages; what follows is the remainder. Settle the custom-entity question (§3) before designing any of it.

14. Items, stalls and the objects nobody specified

The full item roster, every recipe and what each one does is on the items page. What is missing:

13.1 Named in the design documents, never specified

ThingWhat is knownWhat is missing
Stalls and holding pensDefinition and its consumer are both built — see stall signs and tickets.Auto-return — a horse that takes itself home, rather than one sent by a ticket. Cleanup beyond breaking the exact sign block: rebuilding a wall elsewhere, or removing the horse, leaves a stale record. Holding pens as distinct from stalls. A real stall-sign block instead of a repurposed oak_wall_sign. A persistent client wireframe rather than the F7 particle flash, which needs a RenderLevelStageEvent renderer against the changed 26.1.2 pipeline.
WhistlesBuilt — recall your tamed horses within 16 / 32 / 64 blocks.Bond gating (§14); whether they should path rather than teleport; and what “echo” adds beyond range. All three are answered by callable horses, below.
Double-wide gateCrafted via braided rope.Presumably a two-block-wide fence gate. A vanilla-shaped block problem, unrelated to the genetics.

Callable horses — the whistle, bound

The whistles are an area recall: blow one and every tamed horse of yours inside 16 / 32 / 64 blocks comes. The wanted end state is the RPG one — press a thing, and your horse arrives, wherever it is. The reference implementation is the Callable Horses mod: sit on a horse and press P to make it your personal horse, press V to call it (it walks if near, teleports if far, optionally across dimensions), one personal horse per player, with permanent death and a maximum call distance both configurable.

Taking the feature is right. Taking its shape is not, on three counts, and each disagreement points at the version this mod should build instead.

One personal horse is the wrong limit — bind the whistle, not the player

A player of this mod has a stable of horses with pedigrees, and picking a single favourite is exactly the choice the mod exists to make hard. So the binding lives on the item: a whistle is bound to one horse, a player carries as many whistles as they have horses worth calling, and an unbound whistle keeps today’s area recall unchanged.

Keybinds: the item is the interface

This mod has exactly one production keybind — H for the horse browser, in HorseBrowserKeyBindings — and everything else a player does is done by holding an item and clicking. That is a pattern, not an accident, and a feature that arrived with two new default keys would break it.

The three tiers already are the config

Callable Horses exposes maxCallingDistance, callableInEveryDimension and a dimension whitelist as options. We have three crafted tiers that already mean range, and an open question on this page about what the echo whistle adds beyond reach. This answers it:

WhistleUnbound (today)Bound (proposed)
Basic16 blocksCalls a horse in a loaded chunk, same dimension
Golden32 blocksAny distance, same dimension — including unloaded chunks
Echo64 blocksAny distance, across dimensions

That gives the echo whistle a real identity, gives the crafting ladder a reason to exist, and keeps the numbers in the recipe rather than in a config file, which is the house style. A server that wants Callable Horses’ restrictions still gets them — as a config that caps the usable tier, not as a distance in blocks.

It had to be settled against the tickets, and it was: a whistle brings the horse to you; a ticket sends the horse to its stall. Two directions, two items, no overlap — and the interdimensional ticket and the echo whistle are the same idea pointed opposite ways. The tickets shipped on that reading in 0.3.7, with the tier as reach rather than as a binding.

Walk, then teleport — and gate it on bond

The one real technical unknown: calling a horse you cannot see

Everything above is design. This is the part that might not work. HorseRoster states the problem already: whereabouts are entity facts, so they are only knowable for a horse in a loaded chunk. A whistle that calls a horse two thousand blocks away has to find an entity that is not ticking.

Option C looks right, and it is shared infrastructure rather than whistle infrastructure — so it should be scoped as its own piece of work and the whistle built on top of it, not the other way round.

What we should not take

Left open

13.2 Art and coverage


15. Bond, herds and horse care

The core shipped — a per-horse bond number with four behaviour tiers, an emergent herd id, one shared 30-tick scan, and the comfort buff as passive regen. The tier table, gain rates, daily cap and herd rule are on horse care. What is left:

More bond sources

Herds, and testing any of it


A research paper names an allele, not a gene

Owner's design, 2026-09-11. Stage one is built; the rest is not.

The wanted end state: research papers pull out individual alleles rather than whole genes, the equine research shelf lets you pick two of them and binds them into one book, and that book is what the carrot recipes take. The crafting recipes themselves do not change.

Stage one shipped and is the load-bearing half: CarrotEffect.KnownGeneSplice carries two allele tokens instead of a gene key and a het/hom flag, so a carrot already names exactly the pair it grants. That fixed a limitation nothing had recorded — the pair used to be built from gene.alleles().get(0), the first-declared allele, so on the forty-allele particle locus no carrot could ever hand over anything but dust, and KIT could only ever give one of its thirteen.

What is left, in the order that keeps the game working at each step:

Note the interaction: the carrot's homozygous-by-default rule, also settled 2026-09-11, is a stopgap that this design deletes. Once the player picks both alleles there is no default to choose.


16. The carrot content pass

The mechanism is complete. What is missing is content across every registered gene, not machinery.

Every built-in gene needs a real carrot, not the minimal fallback

The parameterised recipe means a gene can have a carrot; it does not mean the carrot is balanced. Today every built-in falls back to the minimal recipe and the uniform splice draw. Each gene wants a hand-tuned carrot block: a rarity tier matching how strong the gene is, flavour ingredients that read as the gene (a nether wart for lava milk, a glow ink sac for light, an amethyst shard for a LUT palette…), and a splice table producing a sensible outcome rather than a coin-flip on a forty-allele locus.

Note the recipe currently takes exactly four items with no flavour slot, so shipping flavour lists means re-opening the recipe as well as writing the data.


17. Assisted reproduction: gestation, and the later tiers

16.1 Finishing the seed jar

The cut-down flow is built and written up on breeding — fill a jar from a breeding-mode stallion, use it on a breeding-mode mare, foal bred through the ordinary path with the draw happening at impregnation. What is left:

16.2 The later tiers

Embryo extraction, gene screening, gene splicing, cloning, cross-species. Each is a block with an inventory and a screen, and each is endgame by intent. Three notes that change how they should be scoped:


18. The horse browser

The H-key screen is a real container menu with My horses, Gene database, Breeding preview and Crafting tabs. The full plan is six: the horse list and the gene database are built, and what is left below is the vial inventory, the herd view, the bonding view and a generated crafting tree — plus out-of-band actions (teleport a horse to a stall, whistle for bonded horses, recall to a holding pen).

The index is still owed, and the horse list is running without it

The expensive part was never the UI. A proper per-player owned-horse registry — updated on tame, breed, death and transfer, holding enough denormalised data (name, sex, age, genotype, bond, herd) that horses in unloaded chunks still appear — does not exist. The My horses tab ships on HorseRoster instead, which walks the whole ancestry table on request, cuts the result at HorseRosterPayload.MAX_ENTRIES and sends it, and the client sorts and filters what it got.

That is exactly the “do not filter it client-side” this note used to forbid, and it was chosen with eyes open: the cap is the whole of the difference, the tab says so in its footer when it bites, and the drawing code takes a list of HorseListings and does not care who filtered them. What is still owed is the registry, sort and filter running server-side over it, and pagination. HorseQuery is already game-free, so the same predicate can run on the server the day the index exists.

The tab the owner has still asked for

The rest

Cut the “limited custom egg”

A creative-only item that sets extension and agouti plus one heterozygous custom gene is a strict subset of what the custom horse spawn egg already does, with its own validation code to maintain. If a placeable, giftable object is genuinely wanted for events and contest prizes, give the spawner an “export as spawn egg” output instead. One screen, one validator, one code path.

A natural / magical filter on the Breeds tab

The owner's note (2026-09-10): once magical breeds exist, the Breeds tab needs a way to show the natural ones, the magical ones, or both. Breed.magical() is already on every breed, so the filter is a toggle beside the list and a clause in HorseBrowserScreen.drawBreedList. Not built yet because there are no magical breeds to filter - build it with the first one, so it can be seen doing something.


19. More generated stables

Three ship, and the owner has said more are coming. The machinery is deliberately finished before the content: adding one is an NBT and a JSON, with no Java, so this section is a content backlog rather than a build one.


20. Breeds

The breed system shipped — 49 breeds, biome-weighted herd spawning, cross / spliced / mixed labels, per-breed stat bands feeding the four magical body-stat genes, and (2026-09-07) a data-driven file format so a breed needs no Java. No new gene came with it, and the breed definitions reference genes and cosmetics the mod does not have. Each is noted in the breed’s notes; the gene-shaped ones are rows in §§1011 already. What is left here:

Cosmetics that are not genetics

Explicitly not modelling: the Akhal-Teke / Karabakh metallic coat sheen (a shader), the Marwari’s inward-curving ear tips (a mesh change), and dished / convex / Roman head profiles. Noted on the breeds and left there.

Breed-system follow-ups


21. The horse dimension and the creative spawner

Both are built — the dimension and the spawn egg. Two pieces of rework remain.

20.1 Split the corridor

The owner wants the dimension to read as a gallery again, without going back to a catalogue-length corridor:

If a systematic gallery is ever wanted again, the shape that scales is a wing per locus — each gene’s pairs on a fixed wild-type background, bounded by alleles rather than by their product, extending naturally to a modded gene adding its own wing.

20.2 The per-copy epigenetics editor

The spawner’s whole-genome Rnd epigen. covers the creative use; the per-copy view is the debugging one — each allele copy’s priority and seed shown individually, with a type-it-in field for an exact value. It is the only way to ask “which copy is expressing, and what does that seed do” without reading a log. Two things to design around: at forty-odd genes that is eighty fields, so it wants a per-gene expander rather than a flat list, and a hand-typed seed has to survive Epigenome.parse or be rejected visibly.


Part 6 — Long range and reference

22. What breaks at scale

Forty-six genes ship (forty-eight in-game with the two example gene files), of which twenty-two paint and several carry many alleles. The gene backlog above is not a linear addition to that.

The wiki is load-bearing, so it can rot

api-reference.html hand-transcribes public signatures and each gene-*.html hand-transcribes that gene’s constants. Neither is generated, so both drift silently the moment a signature or a tuning number changes. The gene creator is the one place this is guardedcheck-parity.mjs compares its schema mirror and its whole preview engine against the real Java, and it has already caught a mis-ported nextLong() and four drifted schema defaults. The cheap version elsewhere is a :common:test that greps the wiki for the handful of numbers the code can compute (Genes.codeOrder().size(), GenotypeCatalog.size(), totalGenotypes()) and fails when a page disagrees. Prose about how a gene works survives a change; a number in prose almost never does.


23. Settled decisions — do not reopen

Kept here so a later session does not relitigate them. These are answers, not work.

Settled 2026-09-10

Settled 2026-09-08

Settled 2026-09-07

Settled 2026-09-06

Coat pipeline

Genetics model

Health and aging

Care, bond and the gameplay layer

When something here ships, write it up on its own page and delete it from this one. A section marked shipped is a second description of built behaviour, and it will drift.

The 23 science tabs that predate the pass

The original backlog is gone. All 25 natural gene pages that had no science tab have one, and wiki/tools/check-gene-tabs.mjs now runs with an empty exempt list, so a new natural gene page without a science tab fails immediately. What follows is the work that closing it created.

The 25 new tabs run 1,200–2,300 words each and share a shape: the locus and the variant with coordinates, the mechanism, the real inheritance table, breed-by-breed frequency where anyone has measured it, an established / inferred / unsupported split, and an explicit statement of where the mod departs from the literature. Measured against that, 17 of the 23 tabs that already existed read as stubs — most are a single <h2> and one or two paragraphs, and several are shorter than the lede above them.

Word counts below are from python over the data-tab="science" panel of each page — recount rather than trust them, they will drift the moment anything here is written. Magical genes are excluded throughout: they have no real-world counterpart and having no science to write is correct rather than a gap.

Tier 1 — cited by the new tabs and unable to answer

These are the worst, and not because of their length. Each is named as background by one or more of the new pages, so a reader follows a link expecting the story and finds two sentences.

Tier 2 — foundational loci carrying a paragraph

Tier 3 — short, and arguably finished

Shade (382) and natural zebra (394) are short because they are complete arguments rather than surveys, and sex (203) is a locus with no variant story to tell. Flaxen (279), sooty (321) and pangare (175) are the three that already named breeds before this pass. Leave all six alone unless something specific is wrong — padding a finished argument to match a word count is the opposite of the point.

The breed problem, which is separate

20 of the 48 natural science tabs name no breed at all. For some that is correct — extension, agouti, shade and sex are universal loci. For the rest it is a real hole, because “which breed do I look in” is one of the two questions a reader brings to a genetics page, and the mod has a breed system that could act on the answer:

pagethe breed story it is missing
leopard complexAppaloosa, Knabstrupper, Pony of the Americas, Noriker
EDNRBPaint and frame lines — the concentration is the health story
ACANMiniature Horse dwarfism
megaesophagusFriesian
silverRocky Mountain Horse, Icelandic, Shetland — and the MCOA link is breed-concentrated
manchadothe Argentine breeds it was described in
LCORLthe draught-versus-pony spread that makes it a size locus at all
MITFSW1’s cross-breed distribution — the entire contrast with SW2
KIT, roan, grey, brindle, CVM, RYR2, PDK4, natural zebravaries; check each against a source before asserting one

How to do one

The 25 written this pass came from owner-supplied source files, not from the model’s memory, and that is the only reason they can state coordinates and frequencies. Do not write one of these from memory. A veterinary claim invented to fill a section is worse than the stub it replaced, and worse than the honest absence the stub replaced before that.

When one is written: re-run node wiki/tools/sync-page-views.mjs, node wiki/tools/build-search-index.mjs and node wiki/tools/check-links.mjs. The shape to copy is any of the 25 — mushroom is the cleanest short one and dun the fullest. Note that every one of them ends by saying where the mod and the literature disagree; that section is the reason the pass was worth doing, and a rewrite that omits it has missed the point. Three of those disagreements turned out to be substantive enough to become gap 134.