The canonical spec of Tactical Reroll's maths (T-535). The public summary is /about/'s "How the scores work"; this note is the long version, for anyone who wants to check our working. Everything here is our own words and our own numbers: no Games Workshop rules text. A change to tools/build_rankings.js, tools/targets.js or an effects file (detfx, leaderfx, unitfx, armyfx) updates this note in the same commit, and tests/unit/scoringdoc.test.js fails if a target, attacker, Utility part, trait, job or delivery constant in the code isn't named here.
Live means it's what the site publishes today. Proposed means it's under test in the Lab (T-523, Tier system v2) and not on the site.
1. One attack, and the table we play on
One attack (live). An attack hits on its BS or WS, wounds by comparing Strength with Toughness (twice the Toughness or more: 2+; more: 3+; equal: 4+; half or less: 6+; otherwise 5+), and is saved on the better of the armour save worsened by AP and the invulnerable save. Each unsaved wound does its Damage. Feel No Pain then ignores each point of damage on its roll. Damage beyond what a model has left is lost; it doesn't spill to the next model. Weapon abilities change the chances along the way: Lethal Hits, Sustained Hits, Devastating Wounds, Anti-X, Twin-linked, Torrent, Blast, Heavy, Rapid Fire, Melta, Lance, Ignores Cover, Psychic, Hazardous. Each keyword is read whole, the way the data spells it (T-582): an ability followed by keywords counts only against a target that meets them ("Lethal Hits: non-Monster/Vehicle" against neither a MONSTER nor a VEHICLE; "Sustained Hits 2: Monster/Vehicle" against either); Anti-X takes a slash list and "non-" the same way, with or without its hyphen or its "+"; Blast X and Cleave X add X attacks for every five models in the target (Cleave on the one target we always pick); Sustained Hits D3 rolls its extra hits on each critical hit, and Rapid Fire D3 or D6+3 rolls its extra attacks at half range; "Twin Linked" is Twin-linked; Conversion makes hit rolls of 4+ critical hits beyond 12" (read as beyond half range: every Conversion gun reaches 24" or more); Psychic Assassin makes 6 attacks against a PSYKER and isn't Psychic; Overcharge fails its hazard roll on 1 to 4. Not read, because they aren't dice: Harpooned (a charge bonus), Reverberating Summons (models returned to another unit), Linked Fire (measuring from another Fire Prism), Plasma Warhead (how the Deathstrike picks targets), Defensive Array and Hive Defences (Overwatch for no CP).
Two engines that agree (live). The calculator rolls the dice (app.js rollSingleSequence, thousands of runs). The rankings use exact averages (docs/ev.js), which walk the whole spread of unsaved wounds through the target's models, so "one unsaved wound against a 2-wound model" kills nothing on average. The unit tests hold the two together (tests/unit/ev.test.js, volley.test.js).
The neutral table (live), the same for every unit (tools/targets.js OPTS):
| Assumption | Value | Why |
|---|---|---|
| Cover | off | Cover changes with the table and the turn. Off is the comparable baseline; the calculator lets you turn it on. Cover worsens the attacker's BS by 1 in 11th edition. |
| Heavy weapons stationary | on | A unit with Heavy weapons is usually placed to shoot without moving. |
| Within half range | off | Most shots in a game come from beyond half range, so Melta and Rapid Fire don't get their bonus. Proposed V2b changes this per unit (section 6). |
| One Shot weapons | count a fifth | Once in a five-round game. |
| Hazardous | priced | Each Hazardous weapon used risks mortal wounds to its own unit (fails on a 1 or 2). That cost is weighed in points per wound against the target's. |
2. The archetypes
Targets (live, tools/targets.js TARGETS): stand-ins for what an army has to kill. Each is matched to a real unit in the calculator (app.js STAND_INS, kept in step by tests/unit/standins.test.js). Each has equal weight today; under Lenses (T-531) the weights would follow the meta.
| Key | Label | Profile | Stands in for |
|---|---|---|---|
chaff | GEQ | 10 × T3 Sv5+ W1 infantry | light infantry (Cadian Shock Troops) |
meq | MEQ | 5 × T4 Sv3+ W2 infantry | Marines (Intercessors) |
teq | TEQ | 5 × T5 Sv2+ 4++ W3 infantry | Terminator-class elites |
lv | Light vehicle | T10 Sv3+ W12 | light vehicles and monsters (a Gladiator Lancer) |
hv | Heavy vehicle | T12 Sv2+ W16 | battle tanks (a Land Raider) |
Attackers (live, ATTACKERS): the profiles units get shot and hit with, per hit.
| Key | Label | Profile |
|---|---|---|
small | Small arms | S4 AP0 D1 (bolter, lasgun) |
special | Special | S5 AP-1 D1 (heavy bolter-class) |
plasma | Plasma | S8 AP-2 D2 (plasma, power fist) |
elite | Elite | S6 AP-2 D3 (elite melee, precision) |
at | Anti-tank | S12 AP-3 D6 (lascannon, melta) |
Proposed (T-529). Swap the heavy vehicle for a big target with an invulnerable save (T11 Sv3+ 4++ W18), add a tough horde (10 × T5 Sv5+ W1), and add a mortal-wounds attacker (D2, ignores saves, Feel No Pain still counts). Weights stay equal. In the test this raised agreement with list share from 0.119 to 0.147. Weighting the archetypes by the meta lowered it, to 0.088.
3. The live scores
Each unit is scored at its smallest size and its points, among every non-Legends unit (the pool).
- Offense. For each target: the expected wounds removed per 100 pts, the better of the unit's shooting and its melee. Melee uses its best weapon per model plus any extra-attacks weapons. Each target is scored with its own best legal squad (section 5) where that beats the default wargear. Each target becomes a percentile over the pool; Offense is the percentile of their mean.
- Defense. For each attacker: the hits needed to destroy the unit per 100 pts,
models × hits per kill ÷ (chance to wound × chance to fail the save) ÷ pts × 100. Hits per kill walks the attacker's damage, after the unit's own Feel No Pain, through each model's wounds. Then percentiles and a mean, as for Offense.- Toughness (T-546). A unit whose models have different Toughness is attacked at the highest T among them (the core rules' Multiple Toughness; on a unit with a Leader attached, the highest among its bodyguard models, never the leader's). Defense scores the unit alone, so it is the highest T among BSData's kinds of model on the datasheet (bsdata.js
models), the first statline when there are none: a Decimus or Aquila Kill Team T6 (its Gravis Veteran), a Traitor Enforcer T6 (its Ogryns). Black Spear Task Force'stMajority(T-545) is a detachment rule and Defense counts no detachment. The calculator and ev.js still take the first statline (open, below). - Heals (T-556). A unit's own heal in each of its Command phases (the coverage files'
healrules to itself withper: "cmd", with kindfx.json's numbers: Reanimation Protocols on every Necron datasheet that lists it, Old One Eye's regeneration) multiplies each attacker's hits to destroy by the heal's closed form below,healLift(models × W, T0, h, 5), the tier test's own. T0 is the turns it lives without the heal, as the tier test counts them: each attacker's hits to destroy the whole unit (def × pts ÷ 100) over half the pool's median, between 1 and 5, the mean of the five. h ishealPerTurn's. A unit that dies in its first enemy turn gains nothing (k = 1), so most lone Necron characters move little. Not counted: heals that need a kill or a fight (Swallow Whole, Digestion Spine), heals from other units (a Technomancer's or a Ghost Ark's repair, a joined character's), and heals the data has no numbers for. rankings.json'sdefstays the bare hits;hlis the lift andhrthe rules behind it; Defense's percentiles, the unit pages' Defense table and the app's Rankings usedef × hl. Feel No Pain was already in (above).
- Toughness (T-546). A unit whose models have different Toughness is attacked at the highest T among them (the core rules' Multiple Toughness; on a unit with a Leader attached, the highest among its bodyguard models, never the leader's). Defense scores the unit alone, so it is the highest T among BSData's kinds of model on the datasheet (bsdata.js
- Value = (Offense + Defense) ÷ 2. Utility and Meta sit beside it, never in it.
- Utility. Four parts, each a percentile over the pool; their mean is ranked within the unit's own army (T-198).
oc, board control: OC × models per 100 pts.act, action economy: 100 ÷ pts (cheap bodies for actions).reach: Move, +2 with Fly, +6 with Deep Strike, +6 with Infiltrators, +4 with Scouts.sup, support:- a Leader counts 1, or, when its effects are known, 0.5 + min(1.5, its lift on its best squad × 5) + 0.5 if it protects the squad, at most 2;
- its auras (at most 2);
- 1 each for Transport, Lone Operative, Stealth, revives and Fights First.
- Traits (read from keywords and ability names, shown as badges):
action(65 pts or less),ds,inf,scouts,fly,leader,aura,transport,lone,stealth,ff,revive.- Rule links as a bare unit has them (T-565, docs/bsdata.js
hiddenBare): a datasheet's rule counts only when the unit has it with nothing taken and nothing joined. A link hidden unless an enhancement is taken or a leader is attached (the Chameleonic enhancement's Stealth, Lord Invocatus's Deep Strike, a Technomancer's Feel No Pain) is not the unit's own; a link hidden only by the army's choices (a detachment, a game mode: the Lictor's Deep Strike outside Ambush Predators) stays. 76 unit rows lost such a rule, 21 of them a trait (Stealth, Deep Strike, Scouts, Infiltrators). - Sizes (T-565,
_raisedByModel): a model's maximum raised once another model in the unit reaches a count (a second Nodebeast at 20 Neurogaunts) counts in the unit's size: Neurogaunts 11 to 22. - Wargear costs are not read. bsdata.js reads a unit's own points (its size breakpoints) and no option's cost; BSData prices about 70 options at the pinned commit (the Tyrannofex's rupture cannon +20 and acid spray +10, the Riptide's ion accelerator +25, unit upgrades). The best-loadout solver picks a paid weapon at the unit's base price (section 8).
- Rule links as a bare unit has them (T-565, docs/bsdata.js
- Meta. The share of the lists that could field the unit that take it,
taken ÷ (lists + 3). The 3 lists of doubt stop one list of one from reading as 100%. Meta itself is shown against the army's most taken unit (100). - Today's letter (T-219; the meta lift, T-226, 26 Sep):
- The rule: tier score = the higher of Value and 40 + 100 × share; S 80+, A 65+, B 50+, C 35+, D below.
- Why: Jordan: "if 40% of winning armies are taking it, it's probably S tier".
- The cost: 264 units wear S (T-524), and a unit's letter mixes the maths with how often it's taken.
4. Effects: leaders, detachments, units' own abilities, army rules
Each file holds what a rule does to the dice, in our own short words and numbers, never its text. Each effect has:
- a side:
attwhen attacking,defwhen attacked; - mods, for example +1 to hit, re-rolls, Lethal Hits, Feel No Pain 5+, −1 to be hit;
- conditions the engine checks: melee or ranged, the target's keywords, the unit's keywords, a weapon's name. Conditions it can't check start on, and the player can switch them off. An effect marked
off: true(a damaged bracket, a once-a-battle or rarely-met condition, T-541) starts off instead, and the player can switch it on. The build tools (rankings, Banner, the tier test) read no unitfx effect yet; a tool that does should leaveoffeffects out.
| File | What it holds | Count (2 Oct) |
|---|---|---|
| data/detfx.json | detachment rules (T-128); since T-541 (Tyranids first) each rule's status and kind, the enhancements as upgrades (enhancements: points, who, effects; not read by the calculator or the letters) and the stratagems by name | 275 detachments in 21 armies, 227 effects |
| data/leaderfx.json | what a joined character does for its unit (T-145) | 368 characters in 32 armies, 296 effects |
| data/unitfx.json | a unit's own abilities (T-384; every Tyranid datasheet since T-541, each rule with a status, a kind for what isn't dice and why it can't be yet) | 1674 units in 36 armies, 1435 effects |
| data/armyfx.json | army rules (T-530, filled army by army by T-542); the calculator loads it with unitfx.json since T-540 for its heals (Reanimation Protocols reaches a unit whose datasheet lists it) | Tyranids, Necrons, Custodes, T'au, Emperor's Children, Orks |
| data/kindfx.json | the numbers behind the coverage files' heal and mortal rules, and the effects of auras noted in words (T-540); since T-545 effects for noted rules in the new vocabulary, patches by label, reach for army rules, keyed like them (file, army, owner, rule); a rule that carries the field itself wins, so an entry goes once the coverage files write it | heals: 5 Tyranid and 3 Necron datasheets, Reanimation Protocols; mortal wounds: 10 Tyranid and 4 Necron datasheets; aura effects: 2 Tyranid datasheets |
| data/mortalfx.json | mortal wounds a unit deals without a weapon, as expected mortal wounds per use against each target (T-524 round 3, proposed, not loaded by the site) | 83 datasheets in 27 armies |
| data/tierfx.json | rules that aren't dice, as the tier test plays them (T-524 round 5, proposed, not loaded by the site): arrival, enemy, shock, aura, spawn, cp, oneUse, chosen and proposed dice effects | Tyranids only: 30 datasheets |
| reports/tiers/2026-10-02-mortals.json | the first build session's per-round mortal-wound estimates for V3 (round 3) | 34 abilities |
- Heals between turns (T-540). A
healrule's numbers:n(a dice expression),per(cmd: each of its own Command phases;kill: n per enemy model its weaponsweaponslay in a fight;fight: once after a fight it slew in),models(slain models come back, one point a model with 1 wound, once none is wounded),to(self;unit: the unit a character leads;near: other units, keywordswho). In the calculator they're chips of their own (on unlessoff) and play only To the death, turn by turn: the side whose turn it is heals first, then fights; a kill heal follows the blows. The answer says how many wounds came back a fight on average; the played-out fight's round strip says who healed how many. ev.js has the closed form (below). - Mortal wounds outside attacks (T-540). A
mortalrule's numbers:ndice (pm: for each model left), each ononor more (0: no roll) dealingdmortal wounds;whenit fires (move,shoot,arrive,fightEndwith its turn's shooting;charge,fightwith its fight;shock,reactstart switched off),range,vs(the target's keywords it needs),near(each enemy unit in range),max, andv(the tier test's expected mortal wounds per use into the five targets, mortalfx.json's field; worked out from n, on and d when missing). In the calculator each is a chip and a "weapon" of its own in the volley: its dice are attacks, each mortal wound a bullet of one damage that skips the wound roll and the save (Feel No Pain and Feel No Pain against mortal wounds apply; damage reductions don't), spilling over models. The funnel's wound gate and the answer read "+N mortal". In a shoot-then-fight fight to the death, a move or shooting rule fires only in the first turn (the turns after are fights). - Auras on other units (T-540). A coverage rule's
auraobject (range,to,not) says who receives it; what they get isaura.effects(kindfx.json, for an aura noted in words) or else the rule's own effects. In the calculator a joined character's auras reach the squad it stands with when the squad's keywords match (range taken as met, as a leader's bonus is), and its enemy-side auras (a rule of kindenemynamed as an aura, a debuff on whoever attacks it) come with it; a rule leaderfx.json already gives the squad isn't given twice. The unit's own aura reaches itself only throughaura.effects(its own effects are already its own). Each is a chip like the rest. - The vocabulary the coverage kept asking for (T-545). Attacking:
tMinus(the target's Toughness −N for the wound roll; not +N Strength, which differs at the doubling steps: S4 against T9 wounds on 6s with −1 T, on 5s with +1 S),rrOneHit/rrOneWound(one hit roll and one wound roll re-rolled a volley, shared by its weapons, fresh each turn of To the death; ev.js adds P(a miss) × a fresh die's chance, per weapon). Attacked:tPlus(+N Toughness),svUp(the Save improved by N, never past 3+: Take Cover!),tMajority(a mixed unit uses the Toughness most of its kinds of model have; BSData gives no counts, so each kind counts once, the lower on a tie). Conditions:sVsTgt/ge/lt/le(the attack's Strength against the target's Toughness, the datasheet's or edited values before other modifiers; unknown, the player's call) andrapid(Rapid Fire weapons only). kindfx.json gives noted ruleseffects, adds an option'sextra,patches an effect or option by its label (Death Guard's contagion from +1 S to −1 T; 24 "Strength above its Toughness" conditions the player had to vouch for), and lets an army rulereachunits that don't list it (Orders). Army rules (armyfx.json) the datasheet lists, or reaches, are chips in the calculator now, each starting switched off (they hang on the board), a rule's choice picked in the Army part. Not in the live rankings (they read neither kindfx.json nor army rules). - A friendly unit nearby (T-551). The calculator's Army part has a Nearby pick: one unit of the side's army that stands near its unit (range taken as met, as for a joined character's aura). Its auras that reach the unit's keywords count (
aura; kindfx.json now gives numbers to 11 Imperial Knights Bondsman duties and Ion Aegis, to an Armiger, and 7 War Dog auras of the Chaos Knights, to a War Dog), and so do the marks it lends its friends: a rule'slend(effects, the friends' keywordsto), each against the marked unit only (T-548's Marked chip): Guide, Doom, Death Hex, Blight Bombardment, the Storm Speeders', Incursors', Exocrine's, Psychophage's and 15 more (23). A unit's own mark (a Norn's prey) isn't lent. Kept per army and unit (hre.det.v1). The unit pages' aura line (T-547) reads the new Knight auras too (15 pages); no score counts them. - Tests a unit takes on itself (T-550). One shape,
selfTest{on,fail,mw}:d6fails onfailor less (Hazardous: 1 or 2, one mortal wound, three for a MONSTER or VEHICLE; ev.jshazardPernow goes through it, the same numbers),ldis 2D6 against the unit's Leadership, failing under it (Dark Pacts),doublefails on a double of 2D6 (the Thousand Sons' Psychic test, each Ritual). Its cost is P(fail) × the mean ofmw, each time it uses the rule (ev.jsselfTestFail,selfTestCost; a line'sselfTest, added to itshazard, whenopts.selfTestsnames them). In the calculator a chip, in play while the rule's dice effects are (a Pact taken, a Ritual cast), and a line under the answer: Leadership 6+ fails 10 times in 36, D3 mortal wounds, 0.56 a volley, once for its shooting and once for its fight. Not in the live rankings (no army rule is). - Resource pools (T-549). A rule that lets a unit replace one of its rolls with a chosen result once a phase (Acts of Faith's Miracle dice, Strands of Fate's Fate dice) is the mod
swapSix, valued by one rule only: the expected gain of turning the volley's worst die of a roll into a 6, on the roll where that gains most (ev.jsswapGain). For n dice of a roll each failing with chance q, a failure happens with chance 1 − (1 − q)^n, and the 6 adds one success of that roll carried through to damage: on the hit roll a critical hit (Lethal Hits: a wound at once; Sustained Hits: its extra hits), on the wound roll a critical wound (Devastating Wounds: past the save), each times the damage of an unsaved wound; the target's own swap turns its first failed save of the volley into a pass. Per volley: unitVsUnit gives the attacker's swap to the weapon and roll that gain most and the target's to the save of the weapon that costs it most; the calculator's dice put it on the volley's first failed roll of the rollsixStagepicks by the same rule (the target's on its lowest save). A pooled die is rolled when it's gained, so the 6 is its best case: an upper bound, no other constant. A pool spent on buffs (Pain tokens, Yield points, the Blessings' eight dice, the Cabal's rituals) keeps the coverage data's hand pick; its rules carrypool(kindfx.json) and their chips say they need the pool. Not in the live rankings. - Marks on an enemy unit (T-548). Condition
chosen: the effect needs the target to be the unit the attacker's rules marked (Oath of Moment's target, a Farseer's guided unit, a Norn's prey, a hexed or judged unit, a quarry). In the calculator the defender's card carries a Marked chip while the attacker has such a rule; it starts off, Oath of Moment's included (T-554, Jordan 2 Oct; T-548 had started an army rule's mark on), the chip deciding; tapped, it holds for that pairing this visit. Conditioncodex({ dets, not }): Oath of Moment's +1 to wound by the 2 Oct errata, in play with one of the Codex detachments (the codex's and the Faction Pack's, as Wahapedia's 11th-edition Space Marines page lists them; none picked counts as Codex) and no Blood Angels, Dark Angels, Deathwatch or Space Wolves unit in the attacker's list (or army). kindfx.json patches 42 effects tochosen(any other words of their condition stay the player's to vouch for). Where the target isn't known (the tools, the list comparator, the tier test), both stay the player's call, as before; the tier test keeps Singular Purpose in tierfx.json. Not in the live rankings (they load no kindfx.json). - Damaged X (T-544). The datasheet's own threshold, read from BSData by bsdata.js (
damaged: the Orks' core rule "Damaged" with X appended to its name, or an older datasheet's "Damaged: 1-X wounds remaining" profile whose effect is -1 to hit; brackets that only halve attacks or lower OC aren't taken; 481 datasheets). In the calculator a chip on each side whose unit has it (on; switching it off drops it); the attacker's and the defender's own attacks take -1 to hit (inside the ±1 cap; psychic attacks and "ignores hit modifiers" skip it) while the squad's last model has X wounds or fewer, so it bites in Fight back's reply and To the death's later rounds, never in a first volley. The coverage's hand-set damaged brackets (unitfx.json, off) aren't shown for a unit that has it, unless the coverage's bracket is something other than -1 to hit (Skarbrand's extra attacks): then the generic reading yields to it (detfx.jsownDamaged). ev.jsdamagedAt(W, X, T)= T × (W − X) ÷ W is the turn-time it's damaged from under typical fire; the tier test'skdmg(--kinds) scales each later turn's damage of a single-model unit by what -1 to hit leaves against each target. Not in the live rankings (one volley at full wounds). - The heal's closed form (ev.js
healLift,healPerTurn). A unit with W wounds in all that the enemy's fire destroys in T turns (the same damage D = W ÷ T each enemy turn) and that gets h back in each of its own turns dies in the first enemy turn k with W − kD + (k − 1)h ≤ 0, so k = (W − h) ÷ (D − h), or lasts the game when h ≥ D; its durability is ×k ÷ T, both at most 5 rounds. h is n's mean, at most one model's wounds less one in a squad that returns no models (a lone model's wounds); a kill heal is n × the models its weapons slay in a fight × the share of its turns it fights. The live Defense uses it since T-556 (Command-phase heals to itself, above); the tier test, behind--kinds, also counts kill and fight heals and heals lent to squads nearby. - Leader lift (live, T-062). A character's effects on each squad it can lead, against MEQ, by Offense's rule. Its best squad's gain feeds Utility's support part. BSData's Supporting links aren't read yet; T-532 fixes that.
- Detachment synergy (live, T-058). Each detachment's effects on each unit of its army, against MEQ. The units it lifts most are listed on the detachment's page.
5. The best-loadout solver (live, docs/loadout.js)
- Legal squads only. Every squad of the unit's smallest size that BSData's wargear choices and caps allow, such as "1 per 5 models" or two weapons that can't go together.
- One kit at a time. A kit is what one model carries. It's scored once into each target, and a squad is the sum of its kits.
- Three answers:
- the best squad into each target;
- the best average share of each target's best;
- the all-rounder, whose weakest share is strongest.
- Limits: 400 kits per kind of model and 200,000 squads per unit and size; past these, the best of those checked.
- Hazardous is priced at the squad's points per wound, one model's share rather than the whole unit's.
- Not cleanly read: a unit whose best squad can't match its own default wargear into every target has choices we didn't read right, and keeps its default.
6. Tier system v2 (proposed, not live)
Tested in the Lab: reports/tiers/, made by tools/tiertest.js, tools/banner.js, tools/archetypes.js. The letter and the job tag would be what counts. Offense and Defense stay the published raw pair under any version.
One army until the variables are found (Jordan, 2 Oct, via the supervisor): "For the purposes of ironing this out, stick to Tyranids until we can identify all the variables." The tier work now iterates on Tyranids alone, judged by the Auspex panel list, Tyranid list share and Jordan's own reading (he plays Tyranids, so he can say when a number is wrong); each missing variable is named and modelled one at a time until the Tyranid table is explained. The Space Marine and Ork panels run only as a check at the end of a round, never to steer it.
The four jobs. The names are Jordan's, our own words, not GW keywords. Each job is a percentile over the pool.
- Hammer, hitting:
- V1: Offense.
- V2: damage before death, damage per turn × turns alive under typical fire, at most 5. Turns alive: each attacker's hits to destroy over half the median unit's, so the median unit lives 2 turns; at least 1.
- V2b: damage delivered before death (below).
- Anvil, holding:
- V1: Defense's hits to destroy per 100 pts × OC.
- V2: Defense per 100 pts × OC per 100 pts × the chance to pass Battle-shock (2D6 against Leadership) × 1.15 for units that heal or return models.
- Known problem: Battle-shock weighs too much here (T-530), because it multiplies all of a unit's durability.
- Runner, the secondaries (V2): the mean of four percentiles: reach, units per 100 pts, a small footprint, and Leadership.
- Footprint is models × base size: infantry 1, mounted 2, walkers 3, light vehicles 4, monsters and battle tanks 5, aircraft 6, Titanic 12; swarms count double.
- Banner, enabling others:
- V1: today's Utility parts, weighted.
- V2: a Leader's lift, auras (up to 2), Transport and revives, per 100 pts.
- T-527's method: the score from section 7.
Composite and letters.
- Composite = 0.75 × the best job + 0.25 × the mean of the jobs.
- A unit's job is its best one, plus a second where another scores 80 or more. Its tag reads "S · Hammer".
- Letters go by quota on the composite's rank: S the top 7%, A the next 15%, B 28%, C 30%, D the rest.
- S and A are split across the jobs by their share of the winning lists' points: lists taking the unit × its points.
V2b's delivery model (tools/tiertest.js V2B). A five-round game on a 44" × 60" table.
| Constant | Value | Why |
|---|---|---|
GAP | 30" | Deployment zones are 24" apart, and units set up a little back. |
INFIL | 9" | Infiltrators set up 9" from the enemy. |
SCOUT | 6" | A Scouts move before the game. |
DS | 9.5" | Deep Strike arrives on turn 2, just over 9" away. |
ENEMY | 3" a turn | The enemy closes too, as both armies contest the middle. |
TRANSPORT | 10" | Infantry in an army with Transports rides this far on turns 1 and 2. A transport shortens a melee unit's charge, so it gets more fighting turns, and it shields the unit from shooting on the way, so more survival. Both are turns-in-range and durability terms. |
OW_TURNS | 1/3 | Overwatch fires on a third of enemy turns from turn 2. It hits on 6s, a quarter of a 3+ hitter's damage, or in full with Torrent. |
ROUNDS | 5 | A game's length. |
- Movement: each turn the unit moves (+2" with Fly; a unit still out of range advances 3.5" more).
- Where guns stop: a gun unit stops at its longest range, or at half range when that's worth over 15% more (melta, Rapid Fire). A melee unit keeps coming.
- Damage each turn:
- its ranged damage when in range (the half-range figure inside half range);
- its melee damage × the chance of making the charge (2D6 against the gap left);
- Overwatch.
- Each turn is weighed by the chance the unit is still alive.
- Detachment credit: a character carrying the keyword a detachment's effects need shares that detachment's best lift with the army's other characters carrying it, up to 1.5 support points. It applies only where 6 or fewer characters carry it.
- Result in test: V2b didn't help (T-524 round 2). Damage per turn still dominates, and assuming every Infantry can ride lets slow elites that can't use most transports reach the fight too early.
V3: delivery modes, the bundle and the round-3 fixes (T-538, proposed; Jordan, 1 Oct (Pacific), via the design session). tools/tiertest.js V3. V2's four jobs; Hammer is damage delivered before death, as in V2b, but each unit is scored under every way it may legally reach the fight and keeps the one with the best composite. The unit page would say which: "S · Hammer, by Deep Strike" or "Best delivered by Rhino (+34% Hammer, 215 pts together)".
- Walk: on the table from turn 1. Scouts move first; Infiltrators start closer.
- Deep Strike: off the table turn 1, arrives turn 2 just over 8" away (the 11th-edition rule: more than 8" from every enemy unit). It shoots at once if its guns reach. A charge from there needs 9 on 2D6, 28%; no re-roll is assumed.
- Strategic Reserves: off turn 1, arrives turn 2 within 6" of a table edge and more than 8" from the enemy (the 11th-edition core rules, read 2 Oct). The 50% points cap on reserves is a list-level limit: noted, not enforced per unit.
- The bundle (the transport rule): the unit plus its best legal Dedicated Transport, priced at both together. Jordan: "when you're buying Berserkers you're also paying for a transport, and when you pay for the transport you also get its guns and its mobility." Its terms:
- delivery: the pair moves at the transport's Move on turn 1, and the unit is out and on its own from turn 2;
- protection: the unit can't be shot for
V3C.SHIELDround inside, so it keeps that turn of its life; - the transport's guns: they add to the pair's Hammer (Firing Deck isn't counted yet: BSData gives the number only in text);
- the transport's body: its hits to destroy and OC add to the pair's Anvil;
- cost: everything per point of the pair.
If the bundle doesn't beat the unit alone, the transport isn't part of the unit's story. Who may ride what is read from BSData's capacity lines at run time (tools/transports.js): the capacity, the keywords a passenger needs, the models it can't carry, and the ones that take two or three spaces. Nothing is stored. Only Dedicated Transports form bundles: a Land Raider or Battlewagon is a unit in its own right, scored alone, and bundling it handed every passenger the big tank's guns. Characters aren't bundled: they ride with the squad they join. Allies are skipped for now.
- Survival: only turns the unit can be shot use up its life (V2's turns alive). A unit off the table or inside a transport keeps it. No terrain model: every shot is taken to have a line (an exposure factor of 1), to be calibrated against the panel.
The standard table (distances, from the 11th-edition Chapter Approved 2026-27 mission deck and core rules on Wahapedia, read 2 Oct; no terrain):
| Constant | Value | Why |
|---|---|---|
V3C.GAP | 30" | Units start 30" apart on a 44" × 60" table: deployment zones 24" apart, units set up a little back. |
V3C.INFIL | 12" | Infiltrators set up more than 8" from the enemy's deployment zone, and the enemy stands a few inches inside it. |
V3C.SCOUT | 6" | A Scouts move before the game (BSData doesn't give the distance for most units). |
V3C.DS | 9" | Deep Strike arrives more than 8" from every enemy unit. |
V3C.RES | 18" | Strategic Reserves arrive within 6" of a table edge, more than 8" from the enemy; typically about 18" from the unit they're after. |
V3C.ENEMY | 3" a turn | The enemy closes too. |
V3C.ADV | 3.5" | A unit still out of range advances (the average of a D6). |
V3C.OW_TURNS | 1/3 | Overwatch fires on a third of enemy turns, as in V2b. |
V3C.ROUNDS | 5 | A game's length. |
V3C.SHIELD | 1 round | A unit inside a transport can't be shot on the turn it rides. |
V3C.BELOW | 0.35 | The share of a game a unit spends below half strength, where Battle-shock bites (fix c). |
V3C.CAP_PER | 6 models | Fix (d)'s scale: a transport's Banner counts its capacity ÷ 6, at most 2. |
The round-3 fixes (each switchable in the tier test, measured on its own):
- (a) Mortal wounds are damage. Abilities that deal mortal wounds outside an attack add their expected mortal wounds a round to Hammer: reports/tiers/2026-10-02-mortals.json, 34 abilities read on 11th-edition datasheets, in our own words. Devastating Wounds was already in ev.js.
- (b) Characters that join a squad aren't Runners. A unit with Leader or Support links, and a unit with no OC, scores 0 as a Runner. Its value is in Banner, as part of the squad.
- (c) Battle-shock only bites below half strength. Anvil's Leadership factor is 1 −
V3C.BELOW× (1 − the pass chance), not the pass chance. - (d) Transport capacity in Banner. Tested and left out: it lowered every yardstick.
- (e) Indirect Fire is in range from turn 1.
Result (2 Oct, T-524 round 3). V3 (every term but d) fits list share at ρ 0.164: V2 0.127, V2b 0.087, V1 0.174. Within the army: Space Marines −0.18 (the least wrong of every system), Orks 0.18. Under V3, 579 units walk, 220 Deep Strike, 233 use Strategic Reserves and 129 ride a Dedicated Transport. reports/tiers/2026-10-02-round3.md.
The Context rule (T-539, a design rule for v2; Jordan, 1 Oct (Pacific), via the design session).
- The letter is the unit's best legal context, because that's what gets fielded:
- its best loadout (today);
- its best delivery (V3);
- its army's best detachment for it: the detachment that most lifts its best job, defensive effects included;
- under the Current meta lens and the meta's disposition mix.
- Leaders don't inflate a squad's letter. Banner already credits the character; the squad page shows "with <leader>: +x%" as information.
- Always with the asterisk: one line under the letter, "S · Hammer, in <detachment>, delivered by <transport>".
- The floor as a range: next to the letter, the letter with no detachment, alone and under the Even lens, shown as "B–S". A wide range means "needs its build"; a narrow one means "good anywhere". The tier list sorts by the ceiling, with a toggle for the floor.
- Axes are shown one at a time, never crossed:
- a unit page has a small table of its letter per detachment of its army (precomputed) and per disposition (recomputed in the browser from stored cells);
- each axis is computed against the others' defaults;
- a specific crossing is the calculator's job.
- The same cells give pages per axis: "best units for <detachment>" on each detachment page, and "best units for <disposition>".
- On /about/ when v2 ships: "we score the build you'd actually field, we say what that build is, and we show how far the unit falls without it."
- Cost, measured 2 Oct: 1,761 units × their armies' detachments with effects = 24,999 cells, plus 8,805 disposition cells, plus 21,132 archetype cells at 6 + 6.
- Today's detachment pass (one target) runs 16,329 cells in 1.4 s. Five targets would add about 11 s, taking the rankings build from 28 s to about 40 s, under a minute.
- rankings.json would grow from 356 KB to under 400 KB gzipped.
V2c: V2b with round 3's six steps (T-524 round 3, 2 Oct, tested, not live). tools/tiertest.js --round3; the report is reports/tiers/2026-10-02-space-marines.md, "Round 3". Each step was measured on top of the last:
- (a) Mortal wounds are damage. Devastating Wounds were already in ev.js: a critical wound becomes mortal wounds with no save, and Feel No Pain still applies. New: data/mortalfx.json holds every 11th-edition ability that deals the enemy mortal wounds without a weapon. Each entry is the expected mortal wounds per use against each target, when it fires (
move,shoot,charge,fight,react,arrive) and its reach. The delivery model adds them, per 100 pts, on the turns they can fire.MW.NEAR= 1.5: an ability that hits every enemy unit within a few inches catches 1.5 units once it's in the fight.MW.REACT= 1/3: one that answers being fought fires on a third of the turns the unit is in combat.MW.RECHARGE= 0.5: one that fires on a charge fires again on half the later turns it fights, as it charges a new target about every other turn.
- (b) Characters who join a squad (Jordan, 2 Oct):
- A Support character (one that joins only through Supporting links) can't take Runner or Anvil as its job. Its value is Banner plus its own attacks inside the squad.
- A Leader may be scored alone, since a Captain or a Lieutenant can run missions on his own. But Runner now counts survival: Runner = (reach + turns alive + Leadership +
V2C.RUNNER_HALF× (units per 100 pts + small footprint)) ÷ 4, each a percentile.V2C.RUNNER_HALF= 0.5, so cheapness and footprint together can't carry Runner.- Turns alive is Hammer's own term, at most 5. A Lone Operative's counts
V2C.LONE= 2 times, because it can only be shot from close by.
- Lone Operatives keep every job.
- A unit with OC 0 can't be an Anvil.
- (c) Battle-shock bites only below half strength. Anvil's Leadership term is 1 − b × (1 − the chance to pass). b = (min(5, T) − T ÷ 2) ÷ 5, never below 0, is the share of a five-turn game a unit that lives T turns spends below half strength: it loses about 1 ÷ T of itself a turn. T is turns alive, uncapped.
- (d) Banner per point, beats bodies, for every unit. Banner = a Leader's multiplier on its best squad (tools/banner.js's
l) + auras + transport capacity + the detachment credit.- An aura (at most 2) lifts
V2C.AURA_UNITS= 2 units. Each is lifted by the median Leader's lift on its squad (32%) and is worth the median unit's points (120), all against the bearer's points. - A transport's capacity is what riding adds to the best non-character squad of its army it can carry and that passes the bundle test (below), against the same points of that squad. At most 2.
- Revives leave Banner. They're the unit's own durability, already 1.15 in Anvil.
- An aura (at most 2) lifts
- (e) Indirect Fire weapons are in range from turn 1. No change in practice: 62 of the 70 units with one already reached the 30" gap.
- (f) Delivery fixed:
- Durability per point. An army's fire spreads over the enemy roughly by points. Turns alive therefore come from Defense's hits to destroy per 100 pts against half the median unit's (the median unit still lives 2 turns; between 1 and 5), not from the unit's whole durability.
- Exposure. A unit uses up its life only on turns it's on the table outside a transport.
- Who rides. Two rules, each with its own job:
- May it ride (legality): a Dedicated Transport of its army can carry it, by capacity, the keywords it takes, what it can't carry and what takes more room (tools/transports.js reads these from BSData at run time). This is what players buy for a squad.
- Does it ride (Jordan's bundle test): the pair (passenger riding plus transport) must beat, per point, both the passenger walking and the transport alone, on Hammer's damage delivered before death per 100 pts. Riding changes nothing else we score. The test is what stops a passenger inheriting a letter from a transport that's better on its own (Scouts in a Land Raider Crusader). The legality list alone doesn't.
V2C.RIDE_COST= 1 is the first cut this replaced (a transport costing no more than its passenger). It's kept only to count what it would have allowed.
- Result:
- Space Marine ρ with the public list −0.24 → −0.08, distance 1.57 → 1.43.
- ρ with list share 0.087 → 0.137.
- Orks 0.06 → 0.01.
- Mortarion C → S.
- Most of the Space Marine gain is durability per point. The report has every step.
V4: the two strands merged, Runner's points gate, solo characters and step g (T-524 round 4, 2 Oct, tested, not live). tools/tiertest.js --round4 (inside --round3's run); the report is reports/tiers/2026-10-02-space-marines.md, "Round 4", and reports/tiers/2026-10-02-tyranids.md. Every part is a switch, measured by leaving it out.
- From V3: the arrival modes (walk, Deep Strike, Strategic Reserves, the Dedicated Transport bundle) and the constants
V3C. The bundle now has to pass Jordan's beats-both-parts test: the pair's Hammer per point must beat the passenger's best way alone and the transport's best way alone. The unit keeps the mode with the best composite. - From V2c: durability per point, exposure only while on the table, mortal wounds from data/mortalfx.json (absolute, on the turns they fire), Battle-shock damped, the Support/Leader rule (with survival in Runner), Banner per point (V2c's raw Banner), and Indirect Fire from turn 1.
- No charge after an advance (11th-edition core rules, read 2 Oct: a unit that advanced can't declare a charge). A melee unit advances only when a normal move leaves it more than
V4C.CHARGE_REACH= 12" away, the farthest a charge can reach. - Runner's points gate: a mission unit must be cheap enough to spend. Runner's raw mean × a factor of 1 up to
V4C.GATE_FULL= 75 pts (tools/hill.js's Light bound), falling in a straight line to 0 atV4C.GATE_ZERO= 260 pts (twice its Middle bound, 130), applied before Runner is ranked. That's 86% at 100 pts, 70% at 130 and 32% at 200. Mortarion (375 pts) scores 0 as a Runner. - Solo characters pay for being alone: a single-model character that joins squads (Leading or Supporting links), scored on its own without Lone Operative and not a MONSTER or VEHICLE, is the enemy's first target. Its turns alive ×
V4C.SOLO= 0.5, in Hammer's delivery, Runner's survival and the Battle-shock share. - Step g, Hammer as enemy points destroyed, weighted by the meta (Jordan, 2 Oct, via the supervisor):
- Each target's damage delivered before death counts as enemy points destroyed: wounds × the stand-in's
ppw(tools/targets.js), per 100 pts of the attacker. - Target classes: the meta's weights are the points share of winning lists' units (lists × points, data/inclusion.json) by the class each unit resembles:
- vehicles, monsters, walkers and aircraft are a heavy vehicle with
V4C.HV_W= 14 or more wounds, and a light one below that; - every other unit is chaff with 1 wound, TEQ with a 2+ save or 3 or more wounds, and MEQ otherwise.
- On 2 Oct the weights are GEQ 10%, MEQ 6%, TEQ 38%, light 22% and heavy 23%.
- vehicles, monsters, walkers and aircraft are a heavy vehicle with
- Hammer = 0.75 × the peak target + 0.25 × the meta-weighted mean. The peak counts a target in full when its class holds at least an even share (20%), and in proportion below that.
- The tag: "S · Hammer (anti-tank)", "(anti-elite)" for MEQ or TEQ, "(anti-chaff)", from the peak's class.
- Each target's damage delivered before death counts as enemy points destroyed: wounds × the stand-in's
- Result (2 Oct):
- Space Marine ρ 0.04 (V2c −0.08, V3 −0.18), the first positive one, with both distances at 1.33.
- Tyranids 0.19 (both strands 0.21).
- Orks −0.19 (V3 0.18).
- List share 0.104 (V2c 0.137, V3 0.164).
- Mortarion S (V2c) → B, as a Hammer, not a Runner. The Lieutenant with Combi-weapon stays C. Eradicators D → C (anti-tank).
- The Chaplains stay B or A: now Banner carries them, not Runner.
- A panel list's ρ has a standard error of about 0.15 to 0.19 (30 to 45 units), so most single-panel differences are noise; list share (1,105 units, about 0.03) is the reliable yardstick, and V4 is below both strands on it.
V5: eight variables, Tyranids first (T-524 round 5, 2 Oct, tested, not live; Jordan's variables, via the supervisor). tools/tiertest.js --round5 (inside --round4's run) with --colist (tools/colist.js's counts of units listed together in winning Tyranid lists, grimstat-corpus, CC BY 4.0); the report is reports/tiers/2026-10-02-tyranids.md, "Round 5". V4 plus eight switches, each measured alone and stacked, on the Tyranid units only. Each run ranks the Tyranid units against one all-units run at its scale: the switches that rescale every unit (1, 3, 9) rescore the pool; the others are Tyranid rules ranked against V4's pool. With every switch off it reproduces V4 exactly.
- Survival absolute (Jordan: incoming fire from a typical army turn doesn't scale with the unit's cost). Turns alive come from each attacker's hits to destroy the unit, over half the median unit's, between 1 and 5, as V2's, not from hits per 100 pts. Damage stays per point. It's used in Hammer's delivery, Runner's survival and the Battle-shock share; Anvil stays per point.
- Arrival rules (data/tierfx.json
arrival). A unit that goes back into Strategic Reserves at the end of its own Fight phase when unengaged (the Red Terror) is off the table in the enemy turn. Its fight ends unengaged when the charge failed or the target died: its melee wounds against the target's total, the five targets' mean. A unit that goes back at the end of the enemy turn (Raveners) has already been shot; it re-arrives only when that beats staying, which in our game it never does. Both reach any objective each round, so Runner's reach part is 100. - A mortal-wound attacker and the meta's incoming fire. A sixth attacker,
mortal:V5C.MW_D= 2 mortal wounds a hit, no save. Feel No Pain counts, and Feel No Pain against mortal wounds too (tierfx.jsonproposed; the Norn Emissary's 4+).- The six are weighted by the meta's incoming fire: every weapon on the default wargear of every unit in winning lists, weighted by the lists taking it.
- Each weapon is sorted by its profile: Damage 3.5 or more, or Strength 10 or more, is anti-tank; Damage 2.5 or more is elite; Damage 1.5 or more is plasma; AP or Strength 5 or more is special; the rest is small arms.
- Each is weighed by its expected damage into the five stand-in targets. Devastating Wounds' critical wounds and data/mortalfx.json's mortal wounds go to
mortal. - On 2 Oct: small arms 8%, special 20%, plasma 37%, elite 7%, anti-tank 22%, mortal 6%.
- The weights apply to turns alive and to Anvil's Defense mean.
- Enemy debuffs and Battle-shock pressure (tierfx.json
enemy,shock), into Banner as points lent per point of the unit.- A −1 to hit on enemies near it touches
V5C.NEAR= 50% of the attacks on the unit itself (its own Defense) and on its 2 nearest friends. It's worth 2 × 50% × (4/3 − 1) of the median unit's points; a −1 to wound below half strength adds the below-half share. - A forced Battle-shock test fails at the meta's rate: the Leadership of winning lists' units, 36% at no modifier.
- Each Battle-shocked enemy unit-round is worth
V5C.SHOCK= 10% of the median unit: its OC, stratagems and actions for one round of five, about half its round. That's ×V5C.SAB= 2 while the Neurolictor's aura is near (−1 to hit them, +1 to wound them). - An army-wide test made one harder (the Neurotyrant's Psychic Terror) counts over
V5C.ENEMY_UNITS= 10 enemy units. - The rounds a unit spends in range come from its V4 delivery profile. A Lone Operative working from 12" or more counts its turns alive ×
V2C.LONE. - A modelled aura replaces V2c's stand-in for it (tierfx.json
replaces).
- A −1 to hit on enemies near it touches
- Buff auras through the engine (tierfx.json
aura).- The two squads most often listed with the bearer in winning Tyranid lists that it can lift at all (tools/colist.js) are run through docs/ev.js with and without the aura. A squad's lift is on its whole output: the better of shooting and melee into each target.
- Each squad's lift × its points is lent. An aura on the unit the bearer shot (the Exocrine, the Psychophage) counts
V5C.MARK= 50% of two friends' attacks. - Synapse (+1 Strength in melee) is credited the same way to every SYNAPSE unit, shared over the Synapse units an average winning list carries (5.7 on 2 Oct).
- Leader pairs: each squad's best leader and its lift on the squad's damage (leaderfx.json; the Hyperadapted Raveners' from unitfx.json). Shown, never in the letter (the Context rule).
- Detachment context (the Context rule). Each unit is scored under each of its army's detachments (detfx.json) and keeps the best: the ceiling. The floor is no detachment under the Even lens (no meta weights).
- Dice effects whose condition the engine can't check count for a share of the game: within Synapse range
V5C.SYN= 75%; below half strengthV3C.BELOW; below Starting Strength the same, for units of more than one model; a Battle-shocked target 20%. - A pick made each battle round counts each option for a round in five.
- Movement and OC rules come from a rule's
tierkey:arrival"tunnel" (reserves arriveV5C.TUNNEL= 7" away), "advCharge" (charge after an advance), "ds" (Deep Strike forwho);oc,protean,upgrade,regen,surge. The Tyranid coverage card (T-541) wrote them under a rule'smovekey, which V5 doesn't read: renamed totierthey move 15 Tyranid letters and take V5's ρ with Auspex from 0.38 to 0.28 (tunnels and Crusher Stampede's OC most), so the constants behind them come first (reports/tiers/2026-10-02-tyranids-coverage.md). Round 6 reads them (mv, below). - Units' own abilities (
--own-out, T-541, a report only): each Tyranid unit's dice effects from unitfx.json in every context. Effects markedoffare left out, conditions are counted at the shares above (an objective 50%), and Singular Purpose, the enemy-side rules and Feel No Pain against mortals are left to tierfx.json. On 2 Oct it moved one letter (Venomthropes C → B) and left ρ at 0.38. - Singular Purpose (the Norns, tierfx.json
chosen) runs here because the Talons of the Norn Queen's swap needs it. It's re-roll hits and wounds into the best chosen target all game, or OC 15 and Feel No Pain 5+ on an objective all game; with the swap, half each.
- Dice effects whose condition the engine can't check count for a share of the game: within Synapse range
- Small fixes.
- A one-use unit (tierfx.json
oneUse) or an immobile one (Move "-", not AIRCRAFT) can't be a Runner or an Anvil. - A CP is worth
V5C.CP_PTS= 15 pts, so CP gained, saved or cost to the enemy count in Banner. A CP-cost aura replaces its stand-in. - A unit that spawns another instead of shooting (Biovores' Spore Mines) spawns on turns 1 to 4 and shoots on turn 5; the better of that plan and shooting counts. It adds
V5C.SPAWN= 50% of the spawned unit's own Runner for each round one is on the table.
- A one-use unit (tierfx.json
- Banner's smooth start (found this round). Most units lend nothing, so any positive Banner raw ranked above all of them: a 0.04 jumped to the 57th percentile. Below the median positive raw, Banner's percentile now rises in a straight line from 0.
- Result (2 Oct, Tyranids):
- ρ with Auspex's order 0.19 → 0.38; the same letter 14 → 16 of 44, within one 26 → 31; ρ with Tyranid list share 0.12 → 0.24.
- Today's letter: 0.65, 21, 37.
- Alone, the largest gains are the small fixes (ρ 0.26, list share 0.19) and the detachment context (ρ 0.25). Survival absolute lowers ρ (0.15) but raises the letters (16 and 29).
- The end-of-round check: Space Marines ρ 0.04 → −0.01, Orks −0.19 → −0.12, list share 0.104 → 0.129.
Engine kinds on V5 (T-540, --kinds, tested, not live). The kinds the dice engine now plays, read from the coverage files with kindfx.json's numbers, switched in on top of V5 one at a time and cumulative, on the Tyranid units against round 5's pool; without --kinds V5 is unchanged. The report section is "Engine kinds" in reports/tiers/2026-10-02-tyranids.md.
heal: a unit's own heal lifts its durability by ev.js'shealLifton the turns alive it has without it (so turns alive and Anvil both rise), and replaces the flat ×1.15 revive for that unit; a unit with the revive trait and no heal in the data keeps ×1.15. A kill heal counts the models its weapons slay in a fight (ev.js, the five targets' mean) × its engaged rounds over its turns alive. A heal on units near it (the Tervigon's Termagants) is lent in Banner like an aura: the lift on the two squads most often listed with it that it reaches, × their points.aura: variable 5 reads a Tyranid bearer's buff auras from unitfx.json (range, to, not; effects from the aura object or the rule), each through the engine on the two co-listed squads it reaches; tierfx.json's aura stays for the marks (the Exocrine, the Psychophage).mortal: V4's delivery reads a unit's mortal wounds outside attacks from its numbered coverage rules (after a Fight phase counts as once a round in range, as mortalfx.json had the Harpy; Battle-shock and Fall Back triggers left out); mortalfx.json stays for every unit without them.
Every army scored (T-552, --every, tested, not live). Round 5 scored only the Tyranids with their own abilities, kinds and detachments; the pool's other units were bare, so every percentile and quota was set against bare units. With --every each unit of the pool is scored as a Tyranid is, four switches (ev { own, kinds, army, det }), cumulative: its own abilities (unitfx.json, a chapter's from the Space Marines' entry; effects marked off left out; the same condition shares as round 5's variable 7), the engine kinds (heal, mortal through mwkOf, aura on the squads its army's winning lists take most where no co-list counts exist, Damaged X, T-545's vocabulary), its army rules (DetFx.armyRules, a chapter's with the Space Marines' too; Synapse's pilot shape, an aura from a keyword, stays variable 5's; Oath of Moment's Codex +1 to wound only outside the excluded chapters; a rule with a pick takes its best option per target and per attacker, as a leader's options are taken; swapSix goes through ev.js's swapGain) and its army's best detachment (the Context rule: each of the army's detachments detfx.json has, the best composite against the bare pool at the same scale). No constant changes. --own-kinds adds the Tyranids' own abilities and every kind as one row of the Engine kinds table; --v5dump <file> writes every unit's V5 letter, job, jobs, percentiles and detachment. --tyr4-out now keeps hand-appended sections when it regenerates (writeKeeping). Results: reports/tiers/2026-10-02-tyranids.md, "Every army scored"; reports/tiers/2026-10-02-v5-every.json.
Round 6: Jordan's settings and the movement rules (T-557, --round6, tested, not live; Jordan, 2 Oct, via the supervisor). Four switches on top of the every-army run (T-552's end state), each measured alone and cumulative: cp0, tmax, pos, mv. Report: reports/tiers/2026-10-02-tyranids-round6.md.
- A CP is worth
V6C.CP_PTS= 30 pts for now (round 6b, Jordan, 2 Oct; round 6 ran it at 0). A CP gained, saved or cost to the enemy counts 30 pts in Banner, per point of the unit as every lent worth. A CP-cost aura still gives up its V2c stand-in. T-558 is to replace this with a CP's worth taken from the stratagems each unit can use, measured with the engine.--r6yard <file>writes the yardsticks (round 5, round 6, today's live letters) as JSON. Report: reports/tiers/2026-10-02-tyranids-round6b.md. - Tunable constants, kept as they are and to revisit if they count too much or too little (Jordan, 2 Oct):
- Battle-shock's worth,
V5C.SHOCK= 10% of the median unit for each enemy unit-round Battle-shocked. - The enemy debuffs' share,
V5C.NEAR= 50% of the attacks on the unit and its two nearest friends.
- Battle-shock's worth,
- A mixed unit's Toughness (
tmax). The tier test's own hits-to-destroy (htk5: the defensive effects' ratios, Singular Purpose's hold) uses the highest Toughness among the unit's kinds of model, as the live Defense does since T-546. - The position track (
pos): the same ways in as Hammer's delivery, followed round by round on the line from the unit's start to the enemy's (V3C.GAP):- walking: Infiltrators start
V3C.INFILfrom the enemy and Scouts moveV3C.SCOUTfirst; each turn the unit moves its Move plus an Advance,V3C.ADV; - Deep Strike: turn 2,
V3C.DSfrom the enemy; - Strategic Reserves: turn 2,
V3C.RESfrom the enemy; - tunnels: turn 2,
V5C.TUNNELfrom the enemy, for either. - An objective X" out is held from the first round the unit stands at X or beyond. The unit keeps its best way in.
- Anvil × (
V6C.POS_FLOOR+ (1 −V6C.POS_FLOOR) × the share of the game it holds the midfield objective,V6C.OBJ_MID= 15", and the one in the enemy's half,V6C.OBJ_FAR= 21").V6C.POS_FLOOR= 0.5 is what an Anvil is worth without getting anywhere: its home objective and the nearest ground. - Runner's reach is that share over the two objectives and the enemy's deployment zone,
V6C.OBJ_DEEP= 27", as a percentile over every unit. It replaces Utility's fixed reach (Move, +2 Fly, +6 Deep Strike, +6 Infiltrators, +4 Scouts). - Transports aren't on the track yet.
- walking: Infiltrators start
- The detachments' movement rules, read in full (
mv). A rule'smovekey (the Tyranid coverage's, T-541) is read astieralways was, so its reach feeds three jobs through the closed forms above, not Runner alone:- Hammer's turns in reach: tunnels bring an arrival to
V5C.TUNNEL; a Deep Strike grant adds that way in; a surge adds to Move; a charge after an Advance (Vanguard Onslaught) lifts V4's no-charge-after-Advance rule. - Anvil's position and Runner's reach: the same changes on the track.
- The non-movement
movekeys are read too:- Crusher Stampede's +2 OC at Starting Strength, at the coverage's 0.9 share;
- the Norns' re-pick;
- Feed the Swarm, now through the heal closed form,
EV.healLift: one regeneration a Command phase (wounds back on one model, an Infantry model returned, or up to 3 models of an Endless Multitude) on whichever of the two squads most often listed with the Harvester it helps most, × that squad's points, lent in Banner like the Tervigon's heal.
- Only the Tyranid coverage writes
movekeys so far. Enhancements' movement (re-deploys, +2" Move) and Synaptic Nexus's +1 to Advance and Charge aren't written as keys yet.
- Hammer's turns in reach: tunnels bring an arrival to
- Result (2 Oct):
- Tyranids: ρ with Auspex 0.37 → 0.34; same letter 13 → 12 of 44; within one 23 → 26; ρ with Tyranid list share 0.28 → 0.27.
- Every unit's list share 0.155 → 0.169. Space Marines −0.06 → −0.03. Orks −0.14 → −0.16.
- The position track alone gives 0.41 and 0.36.
- On top of it, the movement keys hold (tunnels: ρ 0.40, list share 0.36). Crusher Stampede's OC (0.35) and Feed the Swarm (0.38) cost agreement.
- Read in Hammer only, the same rules give 0.27.
Round 7: best-only grading (T-559, the r7 switch, --r7json <file>, tested, not live; Jordan, 2 Oct). Round 6b's run with three changes:
- Best-only grading (Jordan's rule). A unit's score is its best allowed job's percentile plus a bonus that can only add: for each other allowed job above the bar
V7C.BAR= 60,V7C.BONUS= 0.25 × (percentile − 60); at most 100. It replaces the composite (0.75 × best + 0.25 × mean of four) in round 7. 92/10/10/10 scores 92; 80/80/80/80 scores 80 + 3 × 5 = 95; the Tyrannofex's 89/93/16/0 scores 93 + 7.25 (capped at 100). A weak job never lowers a unit. Allowed jobs are the ones a unit may hold (no Anvil at OC 0; Hammer and Banner only for a joining Support character; no Anvil or Runner for a one-use unit), as for the best job. Letters stay by rank quota on the score, S and A split by job demand. - Feed the Swarm's lend capped. The healed squad keeps the regeneration's worth; the Harvester is lent at most what V2c credits an aura on
V7C.REGEN_UNITS= 1 squad (the median Leader's lift on the median unit's points, 38 pts), one squad a phase. The healed squad's own Anvil doesn't count the heal yet. - A one-use transport delivers once. deliver's
drop: the cargo is off the table on turn 1 and set down on turn 2 atV3C.DS, as Deep Strike, then walks; a transport with tierfx.jsononeUse(the Tyrannocyte) has its Banner capacity credit from that, not from V2c's ride on turns 1 and 2. - Yardsticks, every round from now on: ρ with the panel's order and its standard error (Bonett and Wright's); strict on our ruler (the panel's graded units in its order, each letter a tied block, cut at our quota; a block that straddles a cut takes the letter most of it falls in; then the same letter as ours), with the raw same-letter count beside it; lenient (within one letter, raw letters); and beside the strict and lenient counts their shuffle baselines, the mean over 2,000 permutations of our letters against theirs. Ungraded units stay out.
- Result (2 Oct): Tyranids ρ with Auspex 0.39 → 0.50 (SE 0.12); strict on our ruler 19 → 20 of 44 (chance 10.3); raw 12 → 12; within one 27 → 29 (chance 20.4); Tyranid list share 0.32 → 0.39; every unit's list share 0.171 → 0.164; Space Marines −0.03 → −0.05, Orks −0.16 → −0.13. 291 of 1,161 letters move. Report: reports/tiers/2026-10-02-tyranids-round7.md.
Round 8: step grading on fixed cuts (T-560, the r8 switch over r7, --r8json <file>, --r8sliders <file>, tested, not live; Jordan, 2 Oct). Round 7's run (its Feed the Swarm cap and one-drop Tyrannocyte kept) with its grading replaced:
- Steps, no cap (Jordan's rule). Score = the best allowed job's percentile +
V8C.ELITE_STEP= 5 for each other allowed job atV8C.ELITE= 90 or above, +V8C.STRONG_STEP= 2 for each atV8C.STRONG= 80 to 89, nothing below. Never capped (90/90/90/90 scores 105). Ties and the order inside a letter go to the mean of the other allowed jobs. 90/10/10/10 → 90; 90/70/70/70 → 90, ranked above it; 95/10/10 → 95 beats 85/60/60 → 85; 90/90/10/10 → 95; 90/90/90/10 → 100; Tyrannofex 93/89 → 95; Norn Assimilator 96/77 → 96; Hormagaunts 99/64 → 99. - Letters, all armies (the default): fixed cuts on the score, S ≥
V8C.S= 95, A ≥V8C.A= 88, B ≥V8C.B= 80, C ≥V8C.C= 65, D below; no quota, no job-demand split. - Letters, within this army: the same scores ranked inside one army, lettered by position: top
V8C.AS= 10% S, nextV8C.AA= 15% A, nextV8C.AB= 25% B, nextV8C.AC= 30% C, the rest D (rounded to the nearest unit; an army of 10 or more units has at least one S). - Yardsticks: strict on our ruler compares the within-army view with the panel re-cut at the within-army quota (a public tier list is a within-army view); the all-armies view keeps round 7's ruler; raw and lenient for both views, each with its shuffle baseline. The Lab's sliders page (/lab/reports/tiers/sliders/) re-letters the Tyranids live from the four bar and step values.
- Result (2 Oct): Tyranids ρ with Auspex 0.50 → 0.47 (SE 0.13); strict on our ruler 20 → 20 within army (chance 10.6), 16 all armies on round 7's ruler (chance 8.6); raw 12 → 19 all armies, 13 within; within one 29 → 31 all armies, 30 within; Tyranid list share 0.39 → 0.41; every unit's list share 0.164 → 0.162; Space Marines −0.05 → −0.18, Orks −0.13 → −0.12. 561 of 1,161 letters move (520 up): 246 units are S on the fixed cuts, against round 7's quota of 81. Report: reports/tiers/2026-10-02-tyranids-round8.md.
Round 9: Anvil divides by points once, a survival gate, three panels (T-562, the r9 switch over r8, --r9json <file>, --sweep, tested, not live; Jordan, 2 Oct, from the independent critique's points 4, 5 and 9). Round 8's run with Anvil changed:
- One division by points. Round 8's Anvil was Defense per 100 pts × OC per 100 pts, i.e. hits to destroy × OC ÷ points², so halving a unit's cost quadrupled it. Round 9: hits to destroy × OC ÷ points (Defense per 100 pts × the unit's OC), × the same Battle-shock, revive and position factors. Not the geometric mean of the two per-point terms: √(hits × OC) ÷ points is the square root of round 8's product and ranks every unit the same, so a percentile wouldn't move. The measure now grows with a unit's models (twice the bodies, twice the hits and OC, for twice the points), so large minimum units gain.
- The survival gate (removed in round 10). × 0.5 when the unit was removed in one typical enemy turn, × 0.8 in two, × 1 for three or more, on Hammer's own turns alive
Tu. Round 10 took the gate and its constants out of the code; ther9switch now runs round 9 without it. - Constants named for the sweep (values unchanged): Hammer's weight on the peak target
V9C.PEAK= 0.75 (step g's split); the flat revive liftV9C.REVIVE= 1.15; the closest a transport's cargo gets out to the enemy after the first turn's ride,V9C.SETDOWN= 3". --sweep: each hand-set constant at ×0.5 and ×1.5 (a share capped at 1; the bonus bars ±10 points; the letter cuts ±5, re-lettering only), alone, against round 9: letters moved over every unit (all-armies view) and the Tyranid ρ with Auspex.reset9drops what was worked out with the old value between runs. Not swept:V3C.ROUNDS,V3C.GAP,V5C.MW_DandV4C.HV_W(read when the pool is built), and V2c's transport constants (worked out before round 5).- The three-panel history: every version still runnable (V2b, V3, V4, round 5, T-552, round 6 at CP 0, 6b, 7, 8, 9), rerun in one run, against Tyranids (Auspex), Space Marines (Tista Minis) and Orks (Sprues & Brews), ρ with SE, plus every unit's list share; a chart beside the report. From round 9 every round's report leads with all three panels.
- Cut calibration (a proposal; the default stays S ≥ 95, A ≥ 88, B ≥ 80, C ≥ 65): the scores that give 8 / 15 / 27 / 30 / 20% of all units under round 9: S ≥ 98.79, A ≥ 94.49, B ≥ 86.13, C ≥ 71.15, to be set once and frozen as absolutes if Jordan takes them.
- Result (2 Oct): Tyranids ρ 0.47 → 0.49 (SE 0.13), Space Marines −0.18 → −0.10, Orks −0.12 → −0.12; every unit's list share 0.162 → 0.077; Tyranid list share 0.41 → 0.45; 13 Tyranid letters and 240 of 1,161 move. Anvil: Neurogaunts 99 → 89, Termagants 100 → 96, the Norns 96 → 100, Tyrannofex 92 → 96. The sweep's biggest movers are Runner's points gate (399 letters), the Advance (288) and the objectives' distances (286); a CP's worth moves 3. ρ between an army's S share and its top-quarter lists: −0.37 (round 8), −0.39 (round 9, current cuts), −0.24 (proposed cuts). Report: reports/tiers/2026-10-02-tyranids-round9.md.
Round 10: Anvil as OC-turns per point, a fieldable pool, the final rank on frozen cuts, the list-share headline, the explainer (T-563, the r10 switch over r8, --r10json <file>, --explain, tested, not live; Jordan, 2 Oct, from the method appraisal's experiments 1 to 4). Round 8's run (step grading) with:
- Anvil = OC × min(turns alive,
V10C.TMAX= 5) ÷ points (per 100 pts) × Battle-shock × position × revive, no gate: objective-control turns bought per point. Turns alive are turns5'sT(each of the six attacker classes' absolute hits to destroy against half the median unit's, held to 1 to 5, mixed by the meta's incoming fire; × 0.5 for a lone character), so survival stops counting at the game's length and a 3,500-pt Titan can't buy its way up. A transport bundle: the pair's OC and points, the squad's turns alive. The Norns' chosen-objective branch: OC 15 on the variant's own turns alive. - The pool: fieldable units only. A unit over
V10C.MAXPTS= 2,000 pts at its listed size can't be fielded in a 2,000-pt list and leaves the pool before any percentile (Legends were never in): 8 units (the six Titanicus Titans over 2,000 pts, the Phantom Titan, the Manta), 1,161 → 1,153. The medians fixed when the pool is built (half the median unit's hits to destroy, Runner's Leadership and footprint percentiles) keep the whole pool. - The final score: the pool percentile of the composite (best allowed job + round 8's steps): the share of the fieldable pool scoring below it, 0 to 100. A monotone transform: no ρ moves (ties aside), and the best-of-four pile-up (369 units in the 90s, 50 above 100) spreads to about 115 a bin.
- Frozen cuts (calibrated 2 Oct on round 10's run, the lowest final score inside each share S 8%, A 15%, B 27%, C 30%, D 20% of 1,153 units): S ≥
V10C.S= 92.02, A ≥V10C.A= 77.02, B ≥V10C.B= 49.96, C ≥V10C.C= 20.03, D below. Set once: a later round that lifts scores shows as more S. The within-army view is unchanged (position inside the army, round 8's shares). - The list-share headline (from round 10 on): over the units some winning list could field (armies with 5 or more winning lists), the median of each army's ρ with list share (armies with 10 or more such units), the Tyranids' own ρ beside it (the overfit gauge), the AUC for units winning lists take against units they never take, the hit rate (taken among our top quarter, against the base rate) and ρ among taken units only. The pooled ρ stays as a secondary line.
- The explainer:
node tools/tiertest.js --explain "<unit>" [--army <army>] [--out]: one unit's points, letters (both views), final score, four job percentiles, the raw quantities behind each (damage per 100 pts against the five targets, hits to destroy under the six attackers, OC, turns alive, position share, reach, Leadership, points lent by kind), best detachment and way in, list share and panel letter, beside its three nearest peers (same best job, nearest in points, its own army within ×2 first); then each raw quantity's biggest gap from the peers' median (a log ratio with a small floor per quantity). Derived numbers only. - Result (2 Oct): Tyranids ρ 0.49 → 0.51 (SE 0.12), Space Marines −0.10 → −0.07, Orks −0.12 → −0.18; every unit's list share (pooled) 0.077 → 0.157; per-army median 0.113 → 0.165 (round 8 0.188); AUC 0.536 → 0.582; Tyranids' own ρ 0.45 → 0.46. Anvil's ρ with points 0.41 → 0.19 (the target was ±0.15). No unit over 1,000 pts is S. The pool cut moves every panel ρ by under 0.01. S per army against top-quarter lists −0.39 (round 9) → −0.16. Report: reports/tiers/2026-10-02-tyranids-round10.md.
The Tyranid workbench (T-564, tools/tierbench.js over --rawdump tyranids; a report, not live; Jordan, 2 Oct: no more every-army runs until the Tyranid table is within one letter of Auspex for 85% of the 44 graded units). The method appraisal's layers, built for one army.
- Layer 1, the raw table:
node tools/tiertest.js --rawdump tyranids(about 35 s) runs round 10, then scores every Tyranid in every context tyrRun tries (no detachment and each detachment, the Norns' branches) at every datasheet size and with every leader BSData's canJoin allows (the pair as one unit: the leader's attacks inside, its leaderfx.json effects on both, its defensive effects on the squad, its wounds behind it, both OCs and costs), plus each leader's own attacks delivered with the pair's turns alive ("inside" rows), plus every pool unit's chosen context. It writes build/tier-raw-tyranids.json, reports/tiers/<date>-tyranids-raw.json and a flattened .csv. Columns: id, army, unit, ctx {det, branch, kit, size, leader, inside}, pts, models, allow {H, A, R, B}, per way in (ways): Hammer raw, damage per 100 pts into the five targets, inRange per round, Anvil raw, effective OC; hits to destroy per attacker class (htd), turns alive per class before the floor (x: hits to destroy ÷ half the median unit's),T,Tu, the solo factor, OC, position share (hold), reach per objective band, Leadership pass, below-half share, units per 100 pts, footprint, lends in points by kind, Runner's parts, Banner raw and its leader multiplier with the fixes' alternatives (banAlt, tools/banner.js's onSquad withlendOnlyormodels), list share, most-listed size (reports/tiers/2026-10-02-tyranids-sizes.json) and leader, the Auspex letter. Null: the kit (one loadout), the Battle-shock lend (inside the debuff lend), the spawn lend (Runner's). - Layers 2 to 4,
compose(raw, config): pure; rebuilds the pool's percentiles from the pool rows, scores each row by job5's rule (best allowed job + steps, the tie key), picks each Tyranid's best context, letters within the army and on the frozen cuts, and gives the yardsticks against Auspex (within one, the same letter on our ruler, raw, ρ with SE, the gaps). Config knobs:target.w,hammer.peak,fire.w,price.cp(price.shock,price.debuffinert),anvil.tmax,runner(half weight, the gate's ends, Lone Operative factor, spawn share),steps,ceiling,letters. With every fix off it reproduces round 10 exactly (all 52 Tyranids and every other unit's composite). - The fixes (one per residual report's finding, default off):
bannerLendOnly,bannerModelCount,turnsHarmonic(Anvil's turns alive and Battle-shock share as 1 ÷ Σ wᵢ ÷ turnsᵢ, no floor),reArriveAfterKill(tiertest.js goRe'salt),bestSize,bestLeader,reArriverGateExempt,auraToNeighbours,spawnShare75,offTableSurvival. - First pass (2 Oct): baseline 31 of 44 within one (70%); all ten on 30 (68%, ρ 0.51 → 0.71); best subset 36 (82%); the 85% line is 38. Report: reports/tiers/2026-10-02-tyranids-bench-1.md.
- The bench's
banOf(T-565): the Banner switches take off the stored multiplier (banLead), not today's banner.js value (banAlt.cur).--rawdumptakes build/tier-raw-tyranids.lock and writes through a per-process temporary file renamed into place;--raw-out <file>writes elsewhere.
Round 11: the workbench's fixes made permanent, every army (T-565, o.r11 over round 10, --r11json <file>, tested, not live; Jordan, 2 Oct: a unit's context is its best legal size, turns alive capped at 5, a CP 30 pts). Round 10's run (V10C, the fieldable pool, frozen cuts) with each fix a switch in o.r11 (the code's R11F names them), all on, applied to every unit of the pool, not only the Tyranids:
bannerLendOnly(lend): Banner's leader multiplier is tools/banner.js's onSquad withlendOnly(the character's own attacks left out), today's value replacing the --banner file's; the leader's own attacks get an "inside" context, its Hammer delivered on the turns alive of the pair with the squad that keeps it alive longest (at that squad's listed size). Its Anvil and Runner stay its own.bannerModelCount(models): banner.js'smodels, a multi-model character at its real model count.turnsHarmonic(harm,turnsH): Anvil's turns alive and its Battle-shock share are 1 ÷ Σ wᵢ ÷ turnsᵢ over the six attacker classes (no per-class floor or cap), capped atV10C.TMAX= 5 in Anvil (Jordan: the game's length). Hammer and Runner keep turns5's.reArriveAfterKill(kill): a fight-phase re-deployer goes back to reserves only after a kill (goRe'salt).reArriverGateExempt(gate): a unit that re-arrives each round skips Runner's points gate.lendOnBestSquads(best2): every lend (a data aura, tierfx.json's auras and marks, Synapse, a heal for others, the −1-to-hit shield, Feed the Swarm) is worth its lift on the two squads of the bearer's army it lifts most by points lent (lift × points), from every non-character unit of that army in the fieldable pool that it reaches. A defensive lift counts as the turns alive it adds inside the game, min(5, T × (1 + l)) ÷ min(5, T) − 1. Feed the Swarm is the mean of its two best squads (one regeneration a phase), round 7's cap gone. A unit whose lending is measured loses V2c's aura stand-in (and the CP block's stand-in swap); a unit with none keeps the stand-in, counted with the widened aura pattern (auraN11: "(Aura)", "(Aura, Psychic)" and the like). One rule in place of the benches' Hive Tyrant, Pyrovores and Maleceptor special cases.stealthSurvival(stealth): a unit with the Stealth trait takes 4/3 the attacks to destroy from each ranged attacker class (htk5's cover factor; Stealth gives the benefit of cover, T-131), unless its own abilities already give it cover. ev.js has the hook (a defender'scover), but the tier test's incoming fire is htk5's closed form, so this lives in the tier test only.bestSize(size): every size on the datasheet (sizeVariant: damage, durability and OC scaled per model), in every detachment; the best by the tie key.bestLeader(leader): each leader BSData's canJoin allows (pairVariant), at each size, in the squad's best unpaired detachment. The pair's Banner is the squad's plus the leader's lending other than its multiplier, per point of the pair. A leader takes the pair as its own context when it is a multi-model unit or (Tyranids) joins that squad in most lists that take both.sameLoadout(kit, a bug fix): an effect's ratio into each target is worked out on that target's best squad (rankings.json'slt/lw, the squad the damage uses) at the listed size, not on the default wargear (kitAt, throughratioOfandlendRatio).- A context at another size or as a pair holds its Banner per point of its own cost.
- Result (2 Oct, every army): Tyranids ρ 0.52 → 0.66 (round 10 on today's data), Space Marines −0.07 → 0.14, Orks −0.19 → −0.15; per-army median 0.139 → 0.173, AUC 0.582 → 0.585, ρ among taken units 0.094 → 0.105; the Tyranid table within one 31 of 44 on the within-army ruler, 36 on Auspex's shape (the 85% line is 38, not reached); 537 all-armies letters move. Alone,
sameLoadoutlifts the Marines most (−0.07 → 0.10),bannerLendOnlythe Tyranids (0.62); withoutbestSizethe Tyranids would read 0.70 and 39 on the shape. Report: reports/tiers/2026-10-02-tyranids-round11.md. - Charge distance (checked 2 Oct, T-566): in the 11th edition a charge target must be within the 2D6 roll, so a charge from a gap of d" needs a roll of d, not d − 2 (engagement range, 2", is where the move must end).
pChgstands.
Round 12: compose-only experiments (T-581, tools/round12.js over tools/tierbench.js; tested, not adopted). Three new compose knobs, all at today's values by default (--check still reproduces round 10 exactly):
cost.alpha(α, default 1): Hammer, Anvil and Banner become raw ÷ points^α. The raw holds raw ÷ points, so it is multiplied by (points ÷ 100)^(1 − α).cost.runner(default "both"): Runner's two points terms, the points gate (75 to 260 pts) and the cheapness part (units per 100 pts,act). "gate" keeps the gate and drops the cheapness part (Runner = (reach + survival + Leadership + half × footprint) ÷ (3 + half) × gate). "cheap" keeps the cheapness part and drops the gate.composite(default "best"): "allowed" takes each job's percentile among the pool units allowed that job; "log2" scores each job as log₂(raw ÷ the median positive raw of the units allowed it), the floor −8 at zero, the best allowed job with no steps.fixDet: the Tyranids scored in one detachment only (the option-premium what-if).- Result (3 Oct): nothing passes the gate. With the gate dropped (the choice rule's pick), ρ(score, points) goes −0.16 → +0.10 pooled, but unseen agreement falls 0.27 → 0.16 and big models return as mission units (round 3's failure). With the cheapness part dropped it goes −0.16 → −0.10, agreement is unchanged (+0.01), and 116 letters move. α 0.75 alone is cost-neutral pooled. No knob makes the per-army lean neutral. Report: reports/tiers/2026-10-03-round12.md.
Round 13: the every-army raw table, the config file and compose over every army (T-583; tested, not adopted).
- Layer 1 for every army:
node tools/tiertest.js --rawdump allrecords, while round 11 runs (o.r11 all on), every context it scores: the bare pool that picks each unit's context (base), every context everyRaw tries for every fieldable unit (prows: detachments, other legal sizes, joined pairs from either side, a leader's attacks inside), every context tyrRun tries for a Tyranid (trows: the Norns' branches too), and the joined pairs on every other plain context. Each row holds, per way in, Hammer's and Anvil's raws (and the damage per 100 pts into the five targets,v), Anvil's bare raw, turns alive, Runner's parts (reach, Leadership and footprint percentiles, units per 100 pts, the points gate, the re-arriver exemption), Banner, the jobs allowed, a spawn's parts, the engine's key, and features for the factor analysis (f: turns alive per attacker class, OC, Leadership, footprint, models, lends by kind). Full precision; build/tier-raw-all/<hash12>.json (the hash covers every input file, line endings normalised), written through a per-process temporary name;latest.txtnames the newest. It also stores the engine's own keys for B0 and B1 as a check. At 374f505: 70,376 rows, 73.6 MB, about 40 s, peak memory 2.0 GB. - tools/tierconfig.json: every knob of layers 2 to 4 with
value,default,source,date,ownerandlayer(compose: truewhere compose reads it):runner.half,runner.gateFull,runner.gateZero,runner.lone,runner.spawn,cost.alpha,cost.runner,curve,bsmooth,composite,steps.*,ceiling.*,letters.cuts,letters.within,context.bestSize,context.pairs,tolerance; the layer-1 constants it bakes in (round 11's fidelity switches, the turns cap, the lends, a CP's price, the target and fire weights, Advance, the objectives' and reserves' distances, the revive, below-half, Synapse and near shares) underlayer1for provenance. Profiles: B0 (round 11 exactly) and B1 (Jordan's frozen conventions: minimum size,context.bestSizefalse; the turns cap and the lends on the two best squads are round 11's already). - compose over every army (tools/tierbench.js
composeAll,loadConfig(profile),loadRawAll()): the bare pool's percentiles pick each unit's context (ties: the engine's 1e-9), the chosen contexts make the pool's percentiles, a Tyranid takes its own pick under them (ties 1e-12), the final score is the pool percentile of the key, letters by the frozen cuts and the within-army shares. Knobs baked into layer 1 throw. Reproduces round 11's published JSON with 0 differences over 1,153 units and 52 Tyranids, and both stored engine runs with a key gap of 0; the battery rerun from compose is identical. About 130 ms a run. - Result (3 Oct): frozen round 11's ρ(score, points) is −0.414 (Spearman, every fieldable unit); B1 −0.30. Round 12's experiments on B1, chosen by rules that read no panel: Runner's cheapness part dropped and α 0.6 take the lean to −0.01 pooled (16 of 29 armies outside ±0.15, from 24) and the unseen pooled ρ 0.33 → 0.36, a rise inside its interval: not adopted. Report: reports/tiers/2026-10-03-round13.md.
Army rules (T-530, proposed).
- Aura grants: a unit that grants an aura always has it, and one that receives it is in range 75% of the time.
- Effects: melee mods lift Hammer, more Battle-shock dice lift Leadership, and granting an aura counts in Banner.
- Not in letters yet: only when every army's rules are written, because the first written inflates its army.
Lenses (T-531, proposed). A lens is a weight vector over the stored targets and attackers. Letters recompute in the browser: 35 ms for 1,241 units at phone speed. The default lens is the one that best predicts what wins. The custom lens is a future supporter perk; the built-in lenses stay free.
Disposition lenses (T-537, tested, not recommended yet). tools/dispositions.js sorts each primary's VP by the job that earns it: holding an objective is Anvil; taking new ground, their half or their home is half Runner and half Anvil; an action is 70% Runner and 30% Anvil (it completes only if the unit still holds the objective); a kill is Hammer. The counts assume a five-round game: a line every round counts 5, from round 2 counts 4, rounds 2 to 4 count 3, once at the end counts 1. "Each objective" means 2 besides your home, or 3 with it; "each kill" means 1.5 a turn; "each unit that acted" means 1.5. A disposition's demand is its five primaries, weighted by how often the field plays the opposing disposition each one answers. The lens's S and A split gives each job half today's split plus half the demand, with Banner kept at today's share. The lens moves only the S and A quotas; scores don't change. The check failed (2 Oct): the lists that play each disposition don't carry what its primaries pay for (Anvil ρ −0.70 over the five), because an army can only pick the dispositions its detachments offer.
7. Banner, scored from effects (T-527, proposed)
For each character and each squad it can lead or support:
- Damage: the joined unit's wounds removed into the five targets, with the character's effects on and its own attacks included, against the squad alone.
- Durability: the hits to destroy it, with the character's defensive effects on the squad and its own wounds behind it, against the squad alone.
- Bodies: the same points spent on more models of the squad, at its next size up or its own rate per point.
- Multiplier: (damage added ÷ what bodies would add + durability added ÷ what bodies would add) ÷ 2. Above 1, the character beats bodies.
- Score: the best squad's multiplier, percentiled; the squad is recorded.
- Auras, measured (T-547): where the coverage data gives an aura its effects, tools/aurafx.js plays them on each squad of the army they reach; the 2 best squads' multipliers vs bodies count, ×
AURA_IN_RANGE= 0.5 for being in range. - Proxies: any other aura is worth half the median leader's gain over a bare body, across 2 units. A transport is worth a quarter of a squad's damage.
- Not modelled: army-wide effects and CP.
7b. The attacker × defender matrix (T-568, built, not live)
tools/matrix.js; the build spec is design/matrix.md (sections 2 to 5), the plain-English account design/tier-engine.md. Nothing here reaches the site or the live rankings; T-569's field, allocation and jobs will read it.
- Profiles. An attacker profile is one weapon's dice with its name thrown away (kind, A, skill, S, AP, D, the keyword flags ev.js reads, plus Lance, Indirect Fire and Assault, and every keyword not read in full kept as
x:<keyword>: since T-582 only the six that aren't dice; a condition on an ability iswhen:<ability>:<keywords>, Blast Xblast:X, Cleave Xcleave:X, dice Sustained Hits and Rapid Fire keep their dice). A defender profile is one allocation group of a datasheet: T (the unit's highest), Sv, Inv, W, Feel No Pain, its own unconditional defensive effects, Stealth, and the keywords an Anti or a condition names. Equal keys are one row or column. - The cell, one attack into a fresh defender, by ev.js
profileVsas is (section 1):uunsaved wounds,rdamage with each wound capped at a model's W,ewounds removed in the long run (the renewal count: N(w) = [1 + Σ P(D = k) N(w − k)] ÷ (1 − P(D = 0)); e = u × W ÷ N(W), normal and mortal wounds apart),v= E[K] Var(X) + Var(K) E[X]² with K the unsaved wounds of one attack and X = min(D, W). - Contexts. Precomputed layers: base, cover (BS worse by 1), half range (Melta), half range in cover, the charge (Lance +1 to wound). Every other context is a pair of modset keys, H = the first 16 hex of SHA-256 of the canonical merged effects; a unit's contexts are its own and army rules always × no detachment or each of its army's (every way to answer their choices, at most
PICK_CAP= 32 a source) × alone or joined; marks off. - Vouched conditions (round three; round two met them all game). A condition the engine can't check (
when.manual) is a flag on the modset,vouch: [class, id], and a cell read for that modset mixes the branches with and without it by the share of the game it holds, independently per condition (effects with the same words are one condition): near an objectiveVOUCH.objective= 0.5, in Synapse rangeVOUCH.synapse= 0.75 (V5C.SYN), below half strengthVOUCH.belowHalf= 0.35 (V3C.BELOW; "isn't below half" 0.65), below Starting StrengthVOUCH.belowStart= 0.35 (never for a unit of one model), a Battle-shocked targetVOUCH.shocked= 0.2, any other conditionVOUCH.other= 1 (met all game, as the tier test reads it). The mixture's u, r and e are means; its v holds the between-branch part. - Reading a volley from the cells. n models with weapon g into m models of W wounds: A = n × (mean A + Blast's one per five models) × One Shot's fifth; E = Σ A e, R = Σ A r, V = Σ A v. Wounds removed μ = E + (1 − E ÷ R) × min(R,
VOLLEY.FRESH× W): the model in progress when the volley ends has had no killing blow, and holds on average half its wounds (VOLLEY.FRESH= 0.5, the renewal argument's mean, not fitted; 0.75 and 1 tried and worse on Terminators). Then the cut at the unit's m × W wounds, the volley taken as normal: μ − (μ − c) Φ(z) − σ φ(z), z = (μ − c) ÷ σ, σ = √V. The one thing a sum of cells can't see is mixed damage: one weapon's chip damage making another's big hits overkill (killDP plays the order). - The cached build. build/matrix/<hash12>/ (git-ignored), named by a hash of the BSData commit, the engine files, the effects files, rankings.json and the scenario; the three newest kept. Incremental (step 6): a cell depends on its two keys and the cell hash alone (the engine, the effects files and the layers; not the commit, not rankings.json), so a build copies every cell an older folder with the same cell hash holds and computes only keys it lacks; the unit table likewise by row (the whole datasheet record at its size) and column (target key and points per wound). An army's catalogue edited: its new rows and columns only, and the result equals a build from scratch.
- The check (step 7,
--check).CHECK.CELLS= 10,000 random real cells: r againstprofileVstoCHECK.TOL= 1e-9 in memory,CHECK.F32= 1e-6 relative read back from the float32 files. Today's Offense: each pool unit into the five stand-ins with the squad the unit pages score into each (rankings.jsonlt), summed from the cells and read as above, against rankings.jsonoff: Spearman ρ ≥CHECK.RHO= 0.995 and median |difference| ≤CHECK.MEDIAN= 3% per target, every pair beyondCHECK.OUTLIER= 15% named with its cause. On 3 Oct: ρ 0.9999, 0.9988, 0.9968, 0.9995, 0.9998; medians 0.02% to 1.57%; 2 pairs beyond 15% (the Corvus Blackstar into Terminators, mixed damage).
8. Known gaps
Fed by the calibration reports (T-533) and the public-list comparisons (T-524).
| Gap | How we'd model it | Status |
|---|---|---|
| Stratagems (each detachment's dice stratagems as a unit's added value) | tools/stratfx/ catalogue (16 armies), tools/stratagems.js spend and credit as a post step | Measured and not kept (T-742, 6 Oct): held out −0.6 [−1.8, +0.4], placebo-level; stays out of Value for the time being (Jordan); the catalogue serves the calculator |
| The effect vocabulary (T-541's count, Tyranids) | Each army's coverage report lists what the engine lacks, by how many units need it. For Tyranids: movement 16 units, Stealth read from the datasheet 12, mortal wounds outside attacks 10, auras on other units 9, command points 8, enemy Battle-shock 7, arrival 6. Single-unit gaps: selfFnp, a Toughness mod, an attacks-minus on defence, Precision as an effect, critical on any wound | Open (T-542) |
| A mixed unit's Toughness (11th edition core rules: the highest T among its models, a bodyguard's when a character is attached) | The rankings' Defense uses the highest T since T-546. The calculator (seedDefence) and ev.js still take the datasheet's first statline (often a sergeant's): a Decimus Kill Team with a Gravis Veteran reads T4 there, not T6. Black Spear Task Force's tMajority (T-545) lowers it back where that detachment is in play | Partly (T-546: rankings done, calculator open) |
| Healing and returning models | The coverage files' heal rules with kindfx.json's numbers: To the death plays them turn by turn, ev.js's closed form lifts durability, the tier test (--kinds) uses it in place of the flat ×1.15 revive where the data has a heal. The rankings' Defense counts a unit's own Command-phase heals (T-556). Not yet: kill and fight heals and lent heals in the rankings, heals the data gives no numbers for (the Necron Resurrection Orbs and Ghost Ark, Assimilation Swarm's Feed the Swarm, Canoptek Spyders), the other armies' heals until their coverage | Partly (T-540) |
| Returning models in the points ledger | Since T-745 a rule that brings slain models back counts × 1 (r.return) unless the Spawn line measures it (the Tervigon, the Apothecary). T-747 measured nine armies' rules (hibernated files) and nothing moved: the Spawn line is divided by each army's own median spawner (T-608's line scale), so any spawning rule adds about wSpawn's worth whatever its size, and a leader's returns land on joined forms the ranking doesn't read | Open (T-747's report: a cross-army Spawn scale or a leader's credit, each its own step) |
| The datasheet signals in Value | T-748's datasheet model helps averaged with the ledger (+3.9 on 11 unseen human lists) but its signals as multipliers on Value, one step each (T-751: sheetSpeed, sheetEpicPsyker, sheetInfantry, wSoak ×2/×4, rules.lone), all fail the held-out exam; speed within its kind comes closest (+1.1 [−0.6, +2.7]) and shuffled letters pick it too. Open: more human lists for the single-list armies (T-733's drafts) to narrow speed's interval; Toughness against the army's median as a flag (T-748's fallback, never run) | Measured, reverted |
| Overwatch | A fraction of a volley on enemy turns (V2b) | Proposed |
| Melta and Rapid Fire inside half range | A per-unit share from the delivery model (V2b) | Proposed |
| Delivery, transports | Turns in range from Move and arrival rules (V2b); who may ride and capacity read from BSData (tools/transports.js), the bundle test for who does (V2c, round 3) | Proposed |
| Leader and support synergy | T-527's Banner; Supporting links in the live score (T-532) | Proposed |
| Passive damage (mortal wounds from abilities, Host of Plagues) | data/mortalfx.json, added to Hammer's damage on the turns it can fire (V2c, round 3); since T-540 the coverage files' numbered mortal rules take over a unit's entry (5 Tyranid units in the pool, the same numbers), mortalfx.json stays for the 101 others until their armies' coverage carries numbers; the calculator plays them in the volley. Not yet: the defender's mortal wounds in its strike-back, rules needing Battle-shock or a Fall Back | Partly (T-540) |
| Buffs to nearby units (lords, auras) | Leader-lift's method over 2 units in range; since T-540 the coverage files' auras (with kindfx.json's effects where noted in words) through the engine on the 2 co-listed squads in the tier test (--kinds), and on a joined character's squad in the calculator. Since T-547 tools/aurafx.js measures an aura with effects on every squad of its army it reaches (damage into the standard targets, hits to destroy from the standard attackers, cover against shooting only): the unit pages' aura line, and tools/banner.js in place of its proxy (its 2 best squads by multiplier vs bodies × AURA_IN_RANGE 0.5). Not yet: the Support score, auras on units that never join in the calculator (one unit a side) | Partly (T-540, T-547) |
| Army rules | armyfx.json for every army before letters use it (T-530) | Pilot |
| CP economy and stratagems | A CP at V5C.CP_PTS = 15 pts in V5 (tierfx.json cp); 0 in round 6, 30 pts since round 6b (V6C.CP_PTS, Jordan, 2 Oct). Next: a CP's worth from the best stratagems each unit can use in each detachment, measured with the engine (from a Command Re-roll on one die to a re-roll-hits stratagem) | Open (T-558) |
| Fights First timing | A share of fights won by striking first | Trait only |
| Indirect fire | In range from turn 1 (V2c): changes nothing, since the delivery model has no line of sight; the real gap is line of sight itself | Tested, no effect |
| Lone Operative's survival | Twice the turns alive in Runner's survival (V2c); Anvil and Hammer not yet | Partly |
| The price of slowness | Delivery's turns in range, durability per point and the bundle test (V2c) | Proposed |
| Mission actions | Runner's action economy and Leadership | Proposed |
| How to price size | Durability per point (V2c) drops big centrepieces (the Defiler, Knights) and the Orks review disagrees more; a third panel list should decide | Open |
| Runner for big durable models | Runner's points gate (V4): no S or A Runner over 130 pts; it costs the big warlords the review rates (Ghazghkull, Wazdakka), whose Hammer per point is middling | Tested (V4) |
| Leaders that no one fields | Banner credits a leader with its best squad's lift even when that squad is in no list (the Chaplain with a Tactical Squad, 0 of 84, ×2.0); count the lift only on squads worth fielding and against the other leaders a squad can take | Open (V4) |
| Units that re-deploy | Raveners and the Red Terror return to Strategic Reserves (V5's arrival rules). The Red Terror's leaving after its fight shields it from the enemy turn; Raveners' leaving after the enemy turn buys position only. Rapid Ingress and the re-deploy stratagems aren't played | Tested (V5) |
| Defensive auras on the enemy | Enemy debuffs as durability lent and Battle-shock as OC and actions denied (V5); the worths (V5C.SHOCK, V5C.NEAR) are tunable constants Jordan kept on 2 Oct (10% and 50%), to revisit if they over- or under-count | Tested (V5) |
| Auras on very cheap units | An aura's credit is divided by the bearer's points, so a 30-pt unit's aura looked huge (Ripper Swarms); V5 runs Tyranid auras through the engine instead of the stand-in (Ripper Swarms A → C) | Tested (V5, Tyranids) |
| A one-use transport's capacity | V2c's capacity credit rated the Tyrannocyte S in Banner (what a ride adds to Warriors or Pyrovores per point); 0 of 23 lists take it. Round 7 credits one drop (deliver's drop): Banner 91 → 21, A → D | Tested (round 7, T-559) |
| Detachment movement rules | Read in full since round 6 (mv): their reach feeds Hammer's turns in reach, Anvil's position and Runner's reach through the delivery closed forms and the position track. Tyranids only (the only army whose coverage writes move); enhancements' movement and Synaptic Nexus's +1 to Advance and Charge not yet written as keys. Crusher Stampede's OC share (0.9) is the worth to recheck; Feed the Swarm's lend is capped at one squad's aura worth since round 7 (V7C.REGEN_UNITS), the healed squad's own Anvil not yet credited | Tested (round 6, T-557; round 7, T-559) |
| Wargear costs | bsdata.js reads a unit's size breakpoints, not its options' costs (about 70 priced options at the pinned commit); the best-loadout solver picks a paid weapon at the base price (the Tyrannofex's rupture cannon). Record each option's cost in units.json and price a squad by its kit in docs/loadout.js and the rankings | Open (T-565) |
| Strategic Reserves everywhere | Every unit may arrive on turn 2 at 18", and 290 do under V4; the list-level 50% cap and the arrival restrictions aren't enforced | Open (V4) |
| The panel's noise floor | One list's ρ has a standard error of about 0.15 to 0.19; more panel lists before any choice between systems | Open |
| Rules that make or split units | Spore Mines from Biovores as spawn (V5: the spawned unit's Runner at V5C.SPAWN); the Venom's split squads and Tyrannocytes' cargo still not | Partly (V5) |
| Specialists diluted by the five-target average | Step g (V4): enemy points destroyed, the meta's target weights, peak plus breadth; Eradicators D → C, Hive Guard A → S. The tag reads "anti-tank" for 348 of 400 Hammer units, because points per wound favour vehicles: name the peak by the unit's rank within each target instead | Tested (V4) |
| Conditions the player vouches for, in the matrix | Since round three a flag on the modset, met for the round 5 shares (VOUCH); the other class (4,301 unit-conditions: the turn it charged, disembarked or arrived, staying still, a target within 12"…) is still met all game, as in the tier test | Open: T-569's reference battle can price most of them |
| Weapon keywords that aren't dice (T-582) | Harpooned's charge bonus belongs to delivery (V2b); Reverberating Summons to returning models (heal); Linked Fire and Plasma Warhead to reach; Defensive Array and Hive Defences to Overwatch (above). Conversion is read as beyond half range, so a 48" gun inside half range but beyond 12" loses it | Open |
| Mixed damage in a sum of cells | Each weapon's cell is exact alone; one weapon's chip damage making another's big hits overkill needs the order of fire (killDP). 2 pairs beyond 15% on 3 Oct | Named (T-568) |
9. Changelog
| Date | Change | Card | Measured | Report |
|---|---|---|---|---|
| 26 Sep | Utility and Meta ranked within the army; Meta replaces "taken anyway" | T-198 | – | – |
| 26 Sep | The meta lift on letters (40 + 100 × share) | T-226 | 264 S units by 2 Oct | reports/tiers/2026-10-02-space-marines.md |
| 27 Sep | Leader lift from leaderfx effects | T-062 | – | – |
| 29 Sep | Each target's own best squad | T-360 | – | – |
| 2 Oct | Tier system v2 tested: V1, V2, V2b against a public list and list share | T-524 | ρ with list share: Value 0.113, V1 0.174, V2 0.127, V2b 0.087 | reports/tiers/2026-10-02-space-marines.md |
| 2 Oct | Banner from effects; Supporting links included | T-527 | ρ among characters 0.060 | reports/tiers/2026-10-02-banner.md |
| 2 Oct | Archetype review, Lenses design | T-529, T-531 | Recommended set: ρ 0.119 → 0.147 | reports/tiers/2026-10-02-archetypes.md |
| 2 Oct | Army rules pilot (Tyranids) | T-530 | V2 ρ 0.127 → 0.146; Tyranid S 6 → 25 | reports/tiers/2026-10-02-armyfx.md |
| 2 Oct | Round 2: within-army yardstick, V2b, a second panel list (Orks) | T-524 | ρ with their order, Space Marines / Orks: today −0.31 / 0.24, V1 −0.27 / 0.22, V2 −0.23 / 0.12, V2b −0.24 / 0.06 | reports/tiers/2026-10-02-round2.md |
| 2 Oct | Tyranid coverage: every datasheet ability in unitfx.json (status, kind, why not yet), off effects start switched off | T-541 | 61 of 64 Tyranid datasheets; Offense and the letters unchanged (no live tool reads unitfx) | reports/tiers/2026-10-02-tyranids-coverage.md |
| 2 Oct | Tyranid detachments: every rule's status, 41 enhancements as upgrades, stratagems by name | T-541 | 14 detachments (10 matched play, 4 Boarding Actions); nothing live reads enhancements | reports/tiers/2026-10-02-tyranids-coverage.md |
| 2 Oct | The Tyranid coverage in the tier test: units' own abilities (--own-out) and the detachments' movement rules as a what-if | T-541 | Own abilities: 1 letter, ρ 0.38 → 0.38. Movement rules read as tier: 15 letters, ρ 0.38 → 0.28, so they wait under move | reports/tiers/2026-10-02-tyranids-coverage.md |
| 2 Oct | Engine kind heal: the coverage files' heals with numbers (kindfx.json) in To the death, ev.js's closed form, the tier test's turns alive and Anvil in place of the flat ×1.15 revive where the data has one (--kinds) | T-540 | Tyranids, V5 → V5 + heal: ρ with Auspex 0.38 → 0.38, the same letter 16 → 16, within one 31 → 30, ρ with list share 0.24 → 0.23; Old One Eye A → S | reports/tiers/2026-10-02-tyranids.md, Engine kinds |
| 2 Oct | Engine kind mortal: the coverage files' mortal-wound rules with numbers (kindfx.json) as their own bullets in the calculator's volley; the tier test's Hammer reads them in place of mortalfx.json where the data has them (--kinds) | T-540 | Tyranids, V5 + heal → + mortal: ρ with Auspex 0.38, the same letter 16, within one 30, list share 0.23, unchanged (the same numbers, now kept with the rule) | reports/tiers/2026-10-02-tyranids.md, Engine kinds |
| 2 Oct | Engine kind aura: the coverage files' auras (range, to, not, effects) on a joined character's squad in the calculator, enemy-side auras with their bearer; the tier test's variable 5 reads them in place of tierfx.json's auras (--kinds) | T-540 | Tyranids, + aura: ρ with Auspex 0.38, the same letter 16, within one 30, list share 0.23, unchanged (the same squads and lifts) | reports/tiers/2026-10-02-tyranids.md, Engine kinds |
| 2 Oct | Necron coverage: every datasheet ability and detachment rule, 42 enhancements, Reanimation Protocols in armyfx.json | T-542 | – | reports/tiers/2026-10-02-necrons-coverage.md |
| 2 Oct | Adeptus Custodes coverage: every datasheet ability, 10 detachments written from Wahapedia (none in BSData's list), Martial Ka'tah in armyfx.json | T-542 | – | reports/tiers/2026-10-02-adeptus-custodes-coverage.md |
| 2 Oct | T'au Empire coverage: every datasheet ability (wargear included), 9 detachments, For the Greater Good in armyfx.json | T-542 | – | reports/tiers/2026-10-02-t-au-empire-coverage.md |
| 2 Oct | Dark Angels coverage: their 19 datasheets and 8 detachments | T-542 | – | reports/tiers/2026-10-02-dark-angels-coverage.md |
| 2 Oct | Emperor's Children coverage: every datasheet ability, 10 detachments, the army rules in armyfx.json | T-542 | – | reports/tiers/2026-10-02-emperor-s-children-coverage.md |
| 2 Oct | Ork coverage: every datasheet ability, 17 detachments, Waaagh! in armyfx.json | T-542 | – | reports/tiers/2026-10-02-orks-coverage.md |
| 2 Oct | Chaos Daemons coverage: every datasheet ability, 9 detachments, The Shadow of Chaos in armyfx.json | T-542 | – | reports/tiers/2026-10-02-chaos-daemons-coverage.md |
| 2 Oct | Death Guard coverage: every datasheet ability, 10 detachments, Nurgle's Gift in armyfx.json | T-542 | – | reports/tiers/2026-10-02-death-guard-coverage.md |
| 2 Oct | Adeptus Mechanicus coverage: every datasheet ability, 10 detachments, Doctrina Imperatives in armyfx.json | T-542 | – | reports/tiers/2026-10-02-adeptus-mechanicus-coverage.md |
| 2 Oct | Astra Militarum coverage: every datasheet ability, 13 detachments, Voice of Command in armyfx.json | T-542 | – | reports/tiers/2026-10-02-astra-militarum-coverage.md |
| 2 Oct | Aeldari coverage: every datasheet ability, 15 detachments, Battle Focus and Strands of Fate in armyfx.json | T-542 | – | reports/tiers/2026-10-02-aeldari-coverage.md |
| 2 Oct | Chaos Space Marines coverage: every datasheet ability, 17 detachments, Dark Pacts in armyfx.json | T-542 | – | reports/tiers/2026-10-02-chaos-space-marines-coverage.md |
| 2 Oct | Thousand Sons coverage: every datasheet ability, 9 detachments, Cabal of Sorcerers in armyfx.json | T-542 | – | reports/tiers/2026-10-02-thousand-sons-coverage.md |
| 2 Oct | Adepta Sororitas coverage: every datasheet ability, 8 detachments, Acts of Faith in armyfx.json | T-542 | – | reports/tiers/2026-10-02-adepta-sororitas-coverage.md |
| 2 Oct | Blood Angels coverage: their own datasheets and 8 detachments | T-542 | – | reports/tiers/2026-10-02-blood-angels-coverage.md |
| 2 Oct | Grey Knights coverage: every datasheet ability, 11 detachments, Gate of Infinity in armyfx.json | T-542 | – | reports/tiers/2026-10-02-grey-knights-coverage.md |
| 2 Oct | Drukhari coverage: every datasheet ability, 9 detachments, Power from Pain in armyfx.json | T-542 | – | reports/tiers/2026-10-02-drukhari-coverage.md |
| 2 Oct | Leagues of Votann coverage: every datasheet ability, 10 detachments, Prioritised Efficiency in armyfx.json | T-542 | – | reports/tiers/2026-10-02-leagues-of-votann-coverage.md |
| 2 Oct | World Eaters coverage: every datasheet ability, 8 detachments, Blessings of Khorne in armyfx.json | T-542 | – | reports/tiers/2026-10-02-world-eaters-coverage.md |
| 2 Oct | Ultramarines coverage: their own datasheets and 2 detachments | T-542 | – | reports/tiers/2026-10-02-ultramarines-coverage.md |
| 2 Oct | Imperial Knights coverage: every datasheet ability, 8 detachments, Code Chivalric in armyfx.json | T-542 | – | reports/tiers/2026-10-02-imperial-knights-coverage.md |
| 2 Oct | Space Wolves coverage: their own datasheets, 7 detachments, Curse of the Wulfen in armyfx.json | T-542 | – | reports/tiers/2026-10-02-space-wolves-coverage.md |
| 2 Oct | Space Marines coverage: the 161 shared datasheets, 16 Codex detachments, Oath of Moment in armyfx.json | T-542 | – | reports/tiers/2026-10-02-space-marines-coverage.md |
| 2 Oct | Black Templars coverage: their own datasheets, 6 detachments, Templar Vows in armyfx.json | T-542 | – | reports/tiers/2026-10-02-black-templars-coverage.md |
| 2 Oct | Chaos Knights coverage: every datasheet ability, 8 detachments, Harbingers of Dread in armyfx.json | T-542 | – | reports/tiers/2026-10-02-chaos-knights-coverage.md |
| 2 Oct | Genestealer Cults coverage: every datasheet ability, 11 detachments, Cult Ambush in armyfx.json | T-542 | – | reports/tiers/2026-10-02-genestealer-cults-coverage.md |
| 2 Oct | Deathwatch coverage: their own datasheets, Black Spear Task Force, Mission Tactics in armyfx.json | T-542 | – | reports/tiers/2026-10-02-deathwatch-coverage.md |
| 2 Oct | Agents of the Imperium coverage: every datasheet ability, 5 detachments, Assigned Agents in armyfx.json | T-542 | – | reports/tiers/2026-10-02-agents-of-the-imperium-coverage.md |
| 2 Oct | Salamanders coverage: their own datasheets and Forgefather's Seekers | T-542 | – | reports/tiers/2026-10-02-salamanders-coverage.md |
| 2 Oct | Raven Guard coverage: their own datasheets and Shadowmark Talon | T-542 | – | reports/tiers/2026-10-02-raven-guard-coverage.md |
| 2 Oct | Imperial Fists coverage: their own datasheets and Emperor's Shield | T-542 | – | reports/tiers/2026-10-02-imperial-fists-coverage.md |
| 2 Oct | Iron Hands coverage: their own datasheets and Hammer of Avernii | T-542 | – | reports/tiers/2026-10-02-iron-hands-coverage.md |
| 2 Oct | White Scars coverage: their own datasheets and Spearpoint Task Force | T-542 | – | reports/tiers/2026-10-02-white-scars-coverage.md |
| 2 Oct | Adeptus Titanicus and Titanicus Traitoris coverage: the four Titans, their army rules in armyfx.json | T-542 | – | reports/tiers/2026-10-02-adeptus-titanicus-coverage.md |
| 2 Oct | Dispositions as job demand; the lens tested | T-537 | 73 units change letter between the Take and Hold and Purge the Foe lenses; the check against the lists fails (Anvil ρ −0.70) | reports/tiers/2026-10-02-dispositions.md |
| 2 Oct | V3: delivery modes, the Dedicated Transport bundle, mortal wounds, joiners aren't Runners, Battle-shock below half, Indirect Fire | T-524, T-538 | ρ with list share 0.107 → 0.164; Space Marines −0.26 → −0.18; Orks 0.13 → 0.18 | reports/tiers/2026-10-02-round3.md |
| 2 Oct | The Context rule written, its cost measured | T-539 | about 25,000 detachment cells; build about 40 s; under 400 KB gzipped | – |
| 2 Oct | Round 3: V2c (mortal wounds, joining characters, Battle-shock damped, Banner per point, Indirect Fire, delivery fixed) and the first session's V3, against the three panel lists and list share | T-524 | Space Marines ρ −0.24 → −0.08 (V3 −0.18), list share 0.087 → 0.137 (V3 0.164), Orks 0.06 → 0.01 (V3 0.18); Tyranids (third panel list) 0.07 → 0.21; Mortarion C → S | reports/tiers/2026-10-02-space-marines.md, Round 3 |
| 2 Oct | Round 4: V4 (the strands merged with every part a switch, no charge after an advance, Runner's points gate, solo characters, step g: points destroyed with meta weights) and the Tyranid comparison | T-524 | Space Marines ρ 0.04 (V2c −0.08, V3 −0.18), Tyranids 0.19 (0.21), Orks −0.19 (V3 0.18), list share 0.104 (V2c 0.137, V3 0.164); Mortarion no longer a Runner; Chaplains still B or A | reports/tiers/2026-10-02-space-marines.md, Round 4; reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | Round 5: V5 on Tyranids (survival absolute, arrival rules, a mortal-wound attacker and meta-weighted fire, enemy debuffs and Battle-shock, buff auras and Synapse through the engine, leader pairs shown, detachment context with Singular Purpose, small fixes; Banner's smooth start), each alone and stacked; data/tierfx.json, tools/colist.js | T-524 | Tyranids: ρ with Auspex 0.19 → 0.38, same letter 14 → 16 of 44, within one 26 → 31, ρ with Tyranid list share 0.12 → 0.24; check: Space Marines 0.04 → −0.01, Orks −0.19 → −0.12, list share 0.104 → 0.129 | reports/tiers/2026-10-02-tyranids.md, Round 5 |
| 2 Oct | Damaged X from the datasheet: the calculator's -1 to hit by the wounds left (Fight back, To the death); the tier test's kdmg (--kinds) over five turns | T-544 | Tyranids, V5 + damaged alone: ρ with Auspex 0.38 → 0.41, the same letter 16 → 17, within one 31 → 31, ρ with list share 0.24 → 0.25; cumulative with heal, mortal and aura 0.38 → 0.39; Toxicrene and Haruspex A → B, Trygon A → C | reports/tiers/2026-10-02-tyranids.md, Engine kinds |
| 2 Oct | The effect vocabulary: tMinus, tPlus, svUp (not past 3+), one-die re-rolls, majority Toughness, S-against-T and Rapid Fire conditions; kindfx.json effects, extras and patches; army rules as calculator chips (off by default) | T-545 | Calculator only: 24 defensive -1-to-wound rules now apply only when S beats T; Tyranid tier table unchanged (no letter or composite moves); live rankings unchanged | reports/tiers/2026-10-02-tyranids.md, Engine kinds |
| 2 Oct | An aura's worth measured by the engine (tools/aurafx.js): unit pages' aura line; Banner's aura in place of its proxy where the data has the aura's effects | T-547 | Banner: 3 characters measured, ρ among characters 0.060 → 0.060; the Support score and the live rankings unchanged | – |
| 2 Oct | Marks on an enemy unit: the chosen condition and the Marked chip, Oath of Moment's Codex +1 to wound from the army's detachments and list (codex) | T-548 | Tyranid table (--kinds): nothing moves (the tier test plays Singular Purpose from tierfx.json); live rankings unchanged | reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | Resource pools: one die a phase as a 6 (swapSix, ev.js swapGain: the expected gain of the volley's worst die of the best roll turned into a 6) for Acts of Faith and Strands of Fate; pool notes on the buff pools | T-549 | Tyranid table (--kinds): nothing moves (no Tyranid pool); live rankings unchanged | reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | Tests a unit takes on itself: selfTest (d6, Leadership, doubles) for Dark Pacts and the Psychic test, Hazardous through the same shape | T-550 | Tyranid table (--kinds): nothing moves; Hazardous's numbers and the live rankings unchanged | reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | A friendly unit nearby: the Army part's Nearby pick (auras that reach the unit, marks lent to friends); Bondsman and War Dog auras and 23 lent marks in kindfx.json | T-551 | Tyranid table (--kinds): nothing moves; live rankings unchanged; 15 Knight unit pages gain the aura line (shown, not scored) | reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | Every army scored in the tier test: own abilities, kinds, army rules and the best detachment for every unit, four switches (--every), --own-kinds, --v5dump, --tyr4-out keeps hand sections | T-552 | Every switch on: Tyranids ρ Auspex 0.39 → 0.37 (same 17 → 13, within one 30 → 23), Tyranid list share 0.24 → 0.28; Space Marines ρ −0.01 → −0.05 (0.07 with own abilities alone); Orks −0.12 → −0.14; every unit's list share 0.129 → 0.156 (0.173 before detachments); 423 of 1,161 letters move | reports/tiers/2026-10-02-tyranids.md |
| 2 Oct | Marks start off in the calculator, Oath of Moment's included (Jordan); the chip works the same when ticked | T-554 | Default matchup back to the datasheet's numbers; live rankings and the tier test unchanged (neither reads the calculator's default) | – |
| 2 Oct | Live Defense counts a unit's own Command-phase heals by the tier test's closed form (healLift on the turns alive without it); rankings.json keeps def bare and adds hl, hr | T-556 | 991 of 1,241 pool units' Defense moves (most by a point or two as the Necrons rise); 50 rows lift (49 Necron, Old One Eye ×1.11; 39 in the pool), lone characters that die in a turn gain nothing; 19 pool letters change: 7 Necrons up a band, 12 units elsewhere down one at a band edge | reports/tiers/2026-10-02-defense-heals.md |
| 2 Oct | Live Defense attacks a mixed unit at its highest Toughness (the core rule), not its first statline | T-546 | 13 rows (6 in the pool) take a higher T: Decimus and Aquila Kill Teams 4 → 6, Traitor Enforcer 3 → 6, Talonstrike 4 → 6; 612 pool units' Defense moves (most by under a point); 7 pool letters change (Kill Teams and Traitor Enforcers up a band, the Artillery Team down at the B/C edge) | reports/tiers/2026-10-02-defense-heals.md |
| 2 Oct | Round 6: CP worth 0 (V6C.CP_PTS), Battle-shock 10% and debuffs 50% kept as tunable, a mixed unit's highest Toughness in the tier test, the position track (Anvil's position, Runner's reach from the delivery modes; V6C), the detachments' movement rules read in full (move), Feed the Swarm through the heal closed form | T-557 | Tyranids ρ Auspex 0.37 → 0.34, same 13 → 12, within one 23 → 26, Tyranid list share 0.28 → 0.27; every unit's list share 0.155 → 0.169; Space Marines −0.06 → −0.03, Orks −0.14 → −0.16; position alone 0.41 / 0.36; movement in Hammer only 0.27 | reports/tiers/2026-10-02-tyranids-round6.md |
| 2 Oct | Round 6b: a CP gained or saved is worth 30 pts (V6C.CP_PTS 0 → 30, Jordan, 2 Oct; T-558 stays the method to price it from stratagems); --r6yard | T-557 | Tyranids ρ Auspex 0.34 → 0.39, same 12 → 12, within one 26 → 27, Tyranid list share 0.27 → 0.32; every unit's list share 0.169 → 0.171; Space Marines −0.03 (unchanged); letters: Hive Tyrant C → B, the Swarmlord B → A, the Lictor B → A | reports/tiers/2026-10-02-tyranids-round6b.md |
| 2 Oct | Round 7: best-only grading (best allowed job + V7C.BONUS × each other allowed job above V7C.BAR, at most 100; Jordan's rule), Feed the Swarm's lend capped at one squad's aura worth (V7C.REGEN_UNITS), the Tyrannocyte's one drop (deliver's drop); the yardsticks strict on our ruler, raw, lenient and their shuffle baselines, ρ with its SE (--r7json) | T-559 | Tyranids ρ Auspex 0.39 → 0.50, strict on our ruler 19 → 20 (chance 10.3), raw 12 → 12, within one 27 → 29 (chance 20.4), Tyranid list share 0.32 → 0.39; every unit's list share 0.171 → 0.164; Space Marines −0.03 → −0.05, Orks −0.16 → −0.13; 291 of 1,161 letters move | reports/tiers/2026-10-02-tyranids-round7.md |
| 2 Oct | Round 8: step grading (best allowed job + V8C.ELITE_STEP for each other allowed job at V8C.ELITE, + V8C.STRONG_STEP at V8C.STRONG, never capped; ties by the mean of the others; Jordan's rule), letters on fixed cuts (V8C.S, V8C.A, V8C.B, V8C.C) and a within-army view by position (V8C.AS, V8C.AA, V8C.AB, V8C.AC); strict on our ruler against the within-army view; the Lab's sliders page (--r8json, --r8sliders) | T-560 | Tyranids ρ Auspex 0.50 → 0.47, strict on our ruler 20 → 20 within army (chance 10.6), raw 12 → 19 all armies, within one 29 → 31; Tyranid list share 0.39 → 0.41; every unit's list share 0.164 → 0.162; Space Marines −0.05 → −0.18, Orks −0.13 → −0.12; 561 of 1,161 letters move, 246 S on the fixed cuts | reports/tiers/2026-10-02-tyranids-round8.md |
| 2 Oct | Round 9: Anvil = hits to destroy × OC ÷ points (one division, not two) × a survival gate (V9C.GATE1 0.5 removed in one typical enemy turn, V9C.GATE2 0.8 in two); V9C.PEAK, V9C.REVIVE, V9C.SETDOWN named; --sweep (each constant ×0.5 / ×1.5); the three-panel history; proposed frozen cuts S 98.79, A 94.49, B 86.13, C 71.15 (not adopted) | T-562 | Tyranids ρ 0.47 → 0.49, Space Marines −0.18 → −0.10, Orks −0.12 → −0.12; every unit 0.162 → 0.077; 240 of 1,161 letters move | reports/tiers/2026-10-02-tyranids-round9.md |
| 2 Oct | Round 10: Anvil = OC × min(turns alive, V10C.TMAX) ÷ points × Battle-shock × position × revive, round 9's survival gate removed (V9C.GATE1, V9C.GATE2 gone); the pool cut to units of V10C.MAXPTS pts or less; the final score = the pool percentile of the composite; letters on frozen cuts V10C.S 92.02, V10C.A 77.02, V10C.B 49.96, V10C.C 20.03 (8/15/27/30/20%, calibrated 2 Oct); the list-share headline (per-army median ρ, AUC, hit rate, ρ among taken, the Tyranid overfit gauge); --explain | T-563 | Tyranids ρ 0.49 → 0.51, Space Marines −0.10 → −0.07, Orks −0.12 → −0.18; pooled list share 0.077 → 0.157; per-army median 0.113 → 0.165; AUC 0.536 → 0.582; Anvil's ρ with points 0.41 → 0.19; S-share ρ with top-quarter lists −0.39 → −0.16 | |
| 2 Oct | The Tyranid workbench: --rawdump tyranids (the raw table per context: detachment, size, leader, way in) and tools/tierbench.js compose(raw, config) with ten switches from the residual reports | T-564 | Baseline reproduces round 10 exactly; within one 31 → 30 all on, best subset 36 of 44 (the line is 38) | reports/tiers/2026-10-02-tyranids-bench-1.md |
| 2 Oct | Round 11: the workbench's fixes made permanent as o.r11 switches on every army (bannerLendOnly, bannerModelCount, turnsHarmonic, reArriveAfterKill, reArriverGateExempt, lendOnBestSquads, stealthSurvival, bestSize, bestLeader, sameLoadout), turns capped at V10C.TMAX = 5, a CP 30 pts; bug fixes: bsdata.js rule links read in the bare state, Neurogaunts 22 models, the aura pattern widened, banner.js's case-blind squad match, tierbench's banOf, the raw dump's lock; --r11json | T-565 | Tyranids ρ 0.52 → 0.66, Space Marines −0.07 → 0.14, Orks −0.19 → −0.15 (round 10 on today's data); per-army median 0.139 → 0.173; AUC 0.582 → 0.585; Tyranid within one 31 (ruler) / 36 (Auspex's shape) of 44; 537 letters move | reports/tiers/2026-10-02-tyranids-round11.md |
| 3 Oct | The baseline battery: tools/tierbaseline.js scores list share alone, points alone (both signs), frozen round 11 and the shuffle on every panel (ρ with a bootstrap 95% interval, within one and same on the reviewer's shape, each as lift over 2,000 shuffles; fixed seeds), the pooled held-out ρ, round 11's per-army median and the two-reviewer ceiling; a panel with "locked": true is counted, not scored, without --final-check. No scoring change | T-570 | Held-out pooled ρ (Space Marines + Orks, 75 units): list share 0.21 [−0.03, 0.44], points ±0.01, round 11 −0.03 [−0.27, 0.20]; round 11 beats list share on 0 of 3 panels; the Ork shape gives 37.7 of 45 within one to a shuffle | reports/tiers/2026-10-03-baselines.md |
| 3 Oct | Step 1 closed. Outcome yardstick added, not used in scoring: tools/outcomes.js, each unit's placing lift (its army's lists that take it minus those that don't, in mean finishing percentile; Student's t 95% interval with pooled variance), and win rate with and without the unit wherever game records exist (none today) (T-571). Panels: Auspex's Space Marines (T-575, with the reviewer's seven-step grade ord) and Hivemind Hobbies' Tyranids (T-576), both fitting; Astra Militarum the one locked panel (T-574); both Votann lists reference only, 10th edition (T-577, T-578). tools/tierbaseline.js leaves a panel's patchDrop units out (points moved more than 10% since the reviewer's date, read from BSData at both commits) and gives each ceiling a bootstrap interval. No scoring change | T-571, T-575 to T-578 | Held-out pooled ρ (4 panels, 166 units): list share 0.41 [0.28, 0.53], points ±0.02, round 11 0.19 [0.04, 0.34]; ceilings √ρ 0.83 (Space Marines, 15 shared) and 0.86 (Tyranids, 38); 33 of 418 units' placing lift clear of zero against about 21 by chance | reports/tiers/2026-10-03-step1.md, reports/tiers/2026-10-03-outcomes.md |
| 3 Oct | The panels re-sorted and the gate written (Jordan, via the design review): Sprues & Brews' Orks retired to reports/tiers/panel/retired/ (a sanity list, --sanity, outside every pool, ceiling and gate); a third Tyranid reviewer (two creators' lists, both current); "held out" is panels of armies never tuned on (the two Space Marine panels), "same army, new reviewer" the new Tyranid lists, "unseen" both; the gate: pooled lift over shuffle on the unseen panels rising above frozen round 11's, no fitting panel more than one SE below it (tools/tierbaseline.js gates); 38 of 44 a bench sanity number; the list share these numbers use is entrants' (any placing), not top-quarter; an army with three reviewers has the ceiling √ of the mean pairwise ρ | T-580 | held out (76 units): entrants' list share 0.23 [0.00, 0.43], round 11 0.30 [0.07, 0.50]; same army, new reviewer (86): 0.72 and 0.38; unseen (162): 0.49 and 0.34; Tyranid ceiling √0.65 = 0.80 (pairs 0.73, 0.67, 0.54) | reports/tiers/2026-10-03-step1.md (addendum), reports/tiers/2026-10-03-battery-t580.json |
| 3 Oct | Round 12, compose-only (tested, not adopted): three compose knobs, the cost exponent α (cost.alpha), Runner's points terms (cost.runner: both, gate, cheap) and the composite (composite: best, allowed, log2), chosen on criteria that read no panel (Runner by reasoning, the composite by best-job flatness, α by cost-neutrality) and checked by the gate; list share both ways (entrants, top quarter); the Space Marines' mentioned-against-not AUC; the option premium; a compose sweep with owners; the Tyranid table in a fixed layout (tools/tyrtable.js) | T-581 | nothing passes the gate. Chosen candidate (gate dropped): ρ(score, points) −0.16 → +0.10 pooled, unseen pooled ρ 0.27 → 0.16 (frozen round 11 0.34). Gate kept and cheapness part dropped: −0.10, 0.27 (+0.01 [−0.03, 0.04]). α 0.75 alone: +0.01, 0.23. Per army 18 to 22 of 29 outside ±0.15 in every version. Option premium +0.33 [−1.26, 1.94] per log-context. The order of rounds is the same both ways of counting list share, within one SE | reports/tiers/2026-10-03-round12.md, reports/tiers/2026-10-03-tyranids-round12-table.md |
| 3 Oct | The attacker × defender matrix, rounds one to three (section 7b): profiles, the cell (u, r, e, v), contexts, the cached build, the unit table; incremental rebuilds by content keys (the cell hash); --check; a volley read from the cells (VOLLEY.FRESH = 0.5 and the taper); round two's vouched conditions now a flag met at the round 5 shares (VOUCH), not all game. Not live; no live number moves | T-568 | Parity 1.8e-15; today's Offense ρ 0.9968 to 0.9999, medians 0.02% to 1.57%, 2 pairs beyond 15% (mixed damage); one army's edit computes 1 row and 1 column of 1.44 M cells (1.7 s against 9.5 s); the vouch fix removes 574 of 20,441 pooled wounds per 100 pts (the lift over never-met 3,409 → 2,834) | reports/tiers/2026-10-03-matrix.md |
| 3 Oct | Round 13, compose over every army (tested, not adopted): the every-army raw table at round 11's exact settings (--rawdump all, build/tier-raw-all/<hash>.json), tools/tierconfig.json (every knob with its provenance; profiles B0 and B1), tools/tierbench.js composeAll; tools/tyrtable.js shows the baseline when nothing is adopted, the trial in a last column, the site's job names | T-583 | Round 11 reproduced with 0 differences (1,153 units, 52 Tyranids); battery identical. ρ(score, points): frozen round 11 −0.414, B1 −0.30, the trial (Runner's cheapness part dropped, α 0.6) −0.01. Unseen pooled ρ: round 11 0.34, B1 0.33, trial 0.36 (rise +0.01 [−0.10, 0.13] against round 11) | reports/tiers/2026-10-03-round13.md, reports/tiers/2026-10-03-tyranids-round13-table.md |
| 3 Oct | The 30 Sep balance update in the data: BSData 374f505 → 8b91e6b (the Munitorum Field Manual and 14 faction packs); detfx.json's Frenzied Host, Frantic Focus: Sustained Hits 1 for Battleline after an Advance or Fall Back, in place of +1 S (the same condition, when.unitKw BATTLELINE and the manual switch); Legion of Excess's stratagem note names Rapturous Agony for Thieves of Pain. The points ledger reads its frozen inputs (T-603) and doesn't move | T-579 | 241 units changed (188 points, 132 profiles), 21 letters move (/meta/patch/); Frantic Focus moves no unit's score (the live scores read no detachment), only the detachment's synergy line (ds, damage against MEQ, T-058): Tormentors 18 → 25, Infractors 23 → 25, Daemonettes 21 → 20 | reports/dataslate/2026-10-03-refresh.md |
| 3 Oct | Keywords with a condition on the target read in full (T-582): Lethal Hits, Devastating Wounds and Sustained Hits followed by keywords ("Lethal Hits: non-Monster/Vehicle") count only against a target that meets them; ev.js and the calculator read them unconditionally. Into the stand-in vehicles the Orks' shootas lose Lethal Hits; the Painboy's and Leystalker's Devastating Wounds and the Beastboss's Sustained Hits 2 stop counting where they don't apply | T-582 | Each keyword alone, every other read: Lethal Hits 36 units' Offense moves (31 live; Blitza-bommer −15.6%, Dakkajet −15.4%, Burna-bommer −10.1%); Devastating Wounds 8 (6 live; Leystalker −9.1%, Painboy −6.0%, Warbuggies −4.6%); Sustained Hits 2: Monster/Vehicle 1 (the Beastboss −16.6%) | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Cleave X read (T-582): X more attacks for every five models in the target, in ev.js and the calculator; "Cleave 2+" (a misprint) as Cleave 2 | T-582 | 28 units' Offense moves (25 live), all Orks: Deffkilla Wartrike +31.9%, Warboss in Mega Armour +30.0%, Gunwagon +27.4%, Trukk +24.5% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Sustained Hits D3 read (T-582): a critical hit's extra hits rolled (ev.js mixes the kill walk over the roll; the calculator rolls it); was read as Sustained Hits 1 | T-582 | 15 units' Offense moves (13 live): Trazyn the Infinite +16.3%, Knight Defender +9.0%, Doom Scythe +7.0%, Haarken Worldclaimer +4.3% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Blast X read (T-582): X attacks per five models (was 1, as plain Blast) | T-582 | 18 units' Offense moves (14 live), all Orks: Mek Gunz +10.4%, Killa Kans +7.0%, Burna-bommer +3.6% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Conversion read (T-582): hit rolls of 4+ are critical hits beyond half range (the rankings' table is beyond half range); the calculator starts it on for the weapon | T-582 | 7 units' Offense moves (all live): Knight Defender +14.8%, the Acastus Knights Asterius +7.8% and +8.5%, Brôkhyr Thunderkyn +4.4%, the Moirax +3.2% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Anti-X in every spelling read (T-582): slash lists ("Anti-Monster/Vehicle 4+"), "non-" ("Anti-non-Monster/Vehicle 2+"), no hyphen ("Anti Vehicle 3+"), no "+" ("Anti-fly 2"); the calculator now reads every weapon's Anti-X against the target's keywords (it read none, only the manual pick) | T-582 | 12 units' Offense moves (11 live): Stonesinger +57.2%, Squighog Boyz +13.7%, Ancient in Terminator Armour +10.4%, Gunwagon +7.2% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Rapid Fire D3 and D6+3 read (T-582): the extra attacks at half range rolled with the weapon's own (there were none) | T-582 | No live number moves: the rankings' table is beyond half range; Army vs Army and the calculator at half range gain them | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | "Twin Linked" without its hyphen read as Twin-linked (T-582) | T-582 | 6 units' Offense moves (5 live): Night Spinner +22.8%, Warlock Skyrunners +9.8%, Farseer Skyrunner +5.9% | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Psychic Assassin read (T-582): 6 attacks against a PSYKER; no longer read as Psychic (so cover counts against it) | T-582 | No live number moves (no stand-in target is a PSYKER, the table has no cover) | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Overcharge read (T-582): its hazard roll fails on 1 to 4 (was 1 to 2) | T-582 | Arkanyst Evaluator −6.1% (its overcharge profile costs more) | reports/tiers/2026-10-03-keywords.md |
| 3 Oct | Four Space Marine reviewer panels (Auspex's full transcript and Brother Tobias fitting; Grimdark Breakdown and TacticalRock40K reference, partial); the Auspex summary superseded (tools/tierbaseline.js and matrix.js treat a use starting "superseded" as reference: never scored); the two fitting lists on the Space Marine ledger as comparators (auspexFull, tobias, tools/ledger-merge.js); tools/ledgerstep.js --lists. The yardstick's lists unchanged | yardstick step 11 | Ledger at the step-6 baseline: Auspex summary ρ 0.41, pairwise 68%; full transcript ρ 0.28, 63% (0.40, 68% on the summary's 46 units); Tobias ρ 0.20, 55%. Reviewers' leave-one-out ceilings 0.73 (Auspex), 0.63 (Tobias) | reports/tiers/2026-10-03-space-marine-reviewers.md |
| 3 Oct | Batch 3's reviewer panels: Astrategas Wargames' Tyranid list (April 2026, 10th edition, fitting and flagged 10th like Maelstrom's) on the Tyranid ledger as a comparator (astrategas, tools/ledger-merge.js); the CSV's three 11th-edition Tyranid lists are the ones we hold (panels unchanged); 14 reference panels for 11 other armies (no ledger for them yet). The yardstick's lists unchanged | batch 3 | Ledger at the step-6 baseline against Astrategas: ρ 0.38, pairwise 66%, 2+ apart 70% (n 48), the weakest of the five Tyranid lists. Leave-one-out ceilings: Maelstrom 0.92, Auspex 0.86, HivemindHobbies 0.78, Astrategas 0.78, Into the Hive Mind 0.69 | reports/tiers/2026-10-03-batch3-reviewers.md |
| 4 Oct | The fuller transcriptions of three Tyranid lists (Auspex Tactics, HivemindHobbies, Into the Hive Mind; batch 3's CSV) as new panels, the three summaries superseded (the frozen inputs keep them, so the engine's auspex, hivemind, second keys are unchanged); the three on the Tyranid ledger as comparators (auspexFull, hivemindFull, secondFull, tools/ledger-merge.js, which now respects every comparator's patchDrop); the Auspex transcription tuned on (tools/tierbaseline.js TUNED_ON). Proposed as the yardstick's Tyranid lists; the yardstick unchanged until adopted | yardstick step 24 (T-640) | Ledger at the step-6 baseline: Auspex ρ 0.662 → 0.688 (n 44 → 52), HivemindHobbies 0.622 → 0.664 (45 → 48), Into the Hive Mind 0.587 → 0.644 (41 → 48); the seven-list mean ρ 0.472 → 0.490, pairwise 70.1% → 70.8%. Tyranid leave-one-out ceilings, mean ρ 0.80 → 0.83 | reports/tiers/2026-10-04-tyranid-transcripts.md |
| 4 Oct | Step 24 kept: the headline yardstick is the seven lists with the Tyranid transcriptions (tyr.auspexFull,tyr.hivemindFull,tyr.secondFull,tyr.maelstrom,tyr.astrategas,sm.auspexFull,sm.tobias), every tool's default (tools/ledgerstep.js, ledgerfit.js and ledgerrefit.js, diagnose.js, progress.js, roles.js; the ledger page's first columns); the step-13a lists stay selectable (--lists, diagnose.js --summaries). No setting, benchmark or frozen input changed | yardstick step 24 (T-640) | The new reference: step-6 baseline mean ρ 0.490, pairwise 70.8%; re-fitted base 0.486, 70.5%; diagnose held out against the new consensus (a) 74.5%, (a1) 71.8%, ceiling 90.4% | reports/tiers/ledger-steps.md, reports/tiers/2026-10-04-diagnosis-tables.md |
| 4 Oct | The points ledger's secondaryVP switch, off: each form's expected secondary VP a game from the mission deck's 13 non-kill cards (reach, alive at the scoring time, OC, an action less a turn of its ranged Kill), shared over a typical list of 12 at the margin, at 2,000 ÷ 65 = 30.8 points a VP, onto Value at the median unit's Value per point, in place of the Actions line and its own bodies in Presence; per-form secvp { move, indirect } from tools/secvp.js through tools/ledger-merge.js (design/ledger.md section 19) | T-641 | Not run: off, every number as before (the fingerprint test); step 27's prediction written first | reports/tiers/ledger-steps.md |
| 4 Oct | The points ledger's missionVP switch, off: every non-kill line of the mission deck (the 13 tactical secondaries and the 25 primaries' lines, tools/missions.js → tools/missions.json → meta.missions) scored per form: its chance at each check from reach by round (Move, Scouts, Infiltrators, arrival), survival against fire in proportion to its points (half when Hidden or Indirect), control (OC against the OC-weighted OC of its army, by the objective's depth), Leadership and an action's cost in shooting; credited at the margin of a 12-unit list spread over the five objectives; primaries weighted by the field's dispositions, each source held to what a typical player takes from it; at 2,000 ÷ 65 = 30.8 points a VP onto Value at the median unit's Value per point, in place of Score, Hold, Actions and its own bodies in Presence; secondaryVP off while on; per-form mission from tools/missionvp.js through tools/ledger-merge.js (design/ledger.md section 20) | T-647 | Not run: off, every number as before (the fingerprint test); step 28's prediction written first | reports/tiers/ledger-steps.md |
| 5 Oct | The points ledger's active weights fitted to within-army tournament inclusion (tools/hedonic.js; tools/ledgerfit.js takes a numeric label, pairsOfScores): 11 armies with 12+ lists (grimstat-corpus, CC BY 4.0), pairs 2+ lists apart, each army weighted alike, ridge toward step 30 with λ chosen by leaving one army out on inclusion. No transfer: held-out inclusion 59.1–59.7% at every λ against step 30's 59.6%; the chosen fit (λ 0.3) barely moves a knob. A CANDIDATE benchmark only; nothing adopted | T-651 | seven lists 73.2% → 73.3%; held-out Tyranid units 75.3% → 75.1%; the 14 59.7% → 59.6%; list share vs reviewers 70.2% (16 armies) against the ledger's 61.1% | reports/tiers/2026-10-05-hedonic.md |
| 5 Oct | The points ledger's missionBudget sub-switch, off (step 28b): with missionVP on, the mission line reaches Value at R ÷ M (R the median reference form's Score + Hold + Actions + own-bodies Presence contribution with the switch off, M the median reference form's mission line) in place of P ÷ 100, so it re-ranks within the replaced lines' budget; the fitter carries R(θ) (design/ledger.md section 20.1) | T-647 | Not run: off, every number as before; step 28b's prediction written first | reports/tiers/ledger-steps.md | |||
|---|---|---|---|---|---|---|---|
| 5 Oct | The points ledger's shockPressure and cpRefile switches, off (step 34, T-653): every Battle-shock and command-point rule on the 16 ledgers' forms classified in our words (tools/shock-classes.json: a, no damage needed first; b, only after a hit, a fight or a hurt unit; c, not on the enemy, or for cp a cheaper reaction move); shockPressure adds each class a rule's W = 31 points a VP × tests a game × fail chance × 1.538 turns shocked × 0.65 VP a shocked turn (1.25 when the rule picks its unit or it stands on an objective) per 100 of the form's points, at the median unit's Value per point (Neurolictor 83.4, Neurotyrant 46.5); cpRefile takes the cp multiplier off the class c cp rules (the Leapers' counter-charge and ten others); constants reasoned before any run (design/ledger.md section 22) | T-653 | Not run: off, every number as before (the fingerprint test); step 34's prediction written first | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's preferredTargets switch, off (step 36, T-655): each solo form's Burst by target class (tanks and monsters, elite, horde, characters; tools/burst.js --prefer) against the typical army with its characters leading their squads at 0.8 (behind the bodies, alone only to Precision), spent best class first over N = 4 activations, each class capped at C = 4 × its share of the field (tools/ledger-field-classes.json, pooled; T-656 swaps it) × 100 points per 100; read back so the median ranking form keeps its Kill; in place of burstKill's Burst; constants reasoned before any run (design/ledger.md section 23) | T-655 | Not run: off, every number as before (the fingerprint test); step 36's prediction written first | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's attachChars switch, off (step 36b, T-655 split after step 36 wasn't kept): only the characters-attached half: burstKill's Burst (best 3 copies' worth of the whole typical army, no classes or caps) against the army with its characters leading their squads at 0.8 (behind the bodies, alone only to Precision), each solo form's prefer.attached × meta.preferKill ÷ the ranking forms' median; in place of burstKill; preferredTargets (attach and preference) wins over it, so step 36c is the preference on top; no new constant (design/ledger.md section 23.1) | T-655 | Not run: off, every number as before; steps 36b and 36c predictions written first | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's supportMeasured switch, off (step 37, T-657): Synapse, command points, buffs, debuffs and heals stop multiplying the form's Value and are measured instead on the friends they reach (tools/supportfx.js → supportfx through tools/ledger-merge.js): auras and marks played on the army's typical friendly unit with and without them (its Kill and Soak through the ledger's kernel), × 2/3/4 units within 6"/9"/12" × 0.5 in range, a mark 1 friend; Synapse as the list's worth (+1 Strength in melee, Battle-shock on three dice at 1 test a game, 1.538 turns, 0.65 VP, 31 points a VP) shared by its sources; a CP 30 points × the CP a game each rule yields (tools/ledger-support.json; tools/shock-classes.json's class a 2, b 0.5, c 0); heals no other line counts on Soak; rules known only in words 0. Onto Value: the friends' Kill × wKill and Soak × wSoak at the lines' scales, points a game × P ÷ 100; wins over supportCredit; constants reasoned before any run (design/ledger.md section 24) | T-657 | Not run: off, every number as before (the fingerprint test); step 37's prediction written first | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's vpLedger switch, off (step 38, T-658): every line in one currency, VP a game at 2,000 ÷ 65 = 30.8 points a VP, no fitted weight: Kill as the enemy VP its kills deny (0.6 of the game's scoring left × 65 ÷ 2,000 = 0.0195 VP a point) plus the kill cards (30 × 0.29 + 35 × 0.123 = 13.0 VP a game), read as the median reference form's share of the 1,200 points a typical game destroys (1.82 VP a game per 100 at the median Kill); Soak as our own VP kept at the same 0.0195 (1.17 at the median Soak); Spawn a point kept over three rounds; the mission line as missionVP built it (on with the switch, its bridges unused); Battle-shock W ÷ 31; what no rate prices (spawned bodies with the Biovore dial; Score, Hold, Actions without mission data) at its share of the median unit (× Pnew ÷ P); rates reasoned before any run (design/ledger.md section 25) | T-658 | Not run: off, every number as before (the fingerprint test); step 38's prediction written first; median line shares with it on, Tyranids Kill 0.37, Soak 0.22, mission 0.29; Space Marines 0.36, 0.24, 0.43 | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's lifeKill switch, off (step 39, T-660; Jordan's colleague, Tyranids first): each solo form's points killed over its life, characters dropped as targets: K = 0.5 × Burst (best 3 copies' worth of the field's non-character units) + 0.5 × Average (every non-character unit, by copies), × L = 1 + (1 − q) + (1 − q)² + (1 − q)³, q the chance the typical army finishes it in one enemy turn (fire in proportion to points, step 27b; an Indirect Fire form half seen; the defend walk's chances); read back so the median ranking form keeps its Kill; replaces whichever Kill is active (burstKill's, or preferredTargets' and attachChars' when on); Tyranids only (tools/life-tyranids.json), other armies unchanged; constants reasoned before any run (design/ledger.md section 26) | T-660 | Not run: off, every number as before; step 39's prediction written first | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's lifeKill as dials (T-660 follow-up): lifeBlend w (0..1, 0.5 as built: K = w·Burst + (1 − w)·Average where it supplies the Kill), lifeSurvive s (0..2, 1 as built: × (L ÷ the ranking forms' median L)^s on whatever Kill is active, its own rescaled), lifeMode (0 auto: with preferredTargets on, its allocation kept and only the survival factor applied; 1 replace, step 39 as built; 2 survival only); off and as built reproduce the numbers exactly (design/ledger.md section 26.1) | T-660 | Not run: off, every number as before; Track B with lifeKill on now composes by default (lifeMode=1 is step 39's 76.4%) | reports/tiers/ledger-steps.md | |||
| 5 Oct | The points ledger's strength dials (T-661; Jordan's colleague: "dials, not verdicts"): every switch since step 18 keeps its on/off and gains a dial in ledger.js DIALS, each scaling the switch's own effect relative to off or through its own constant: arrivalKillW (ARRIVE_W × w, the arrival reach back below 1), scarceAnswersW (Kill_off + w(Kill_on − Kill_off)), wCarry (reused for carryDedicated), scoreFloorW (line and curve blended), killClassWeightW (CLASS_TOUGH_W read as 1 + w), secondaryVPW and missionVPW (the line × w, the replaced lines × (1 − min(w, 1))), vpMissionW and vpPerUnit (the VP ledger's mission weight, and the share of mission VP counted per unit rather than per point: the screens-and-secondaries dial), threatSoakW (the exponent k), shockPressureW (W × w), supportMeasuredW (the measured credit × w), preferC, preferN (preferred targets' C and N), attachRate (attachChars' Burst between plain and attached), and T-660's lifeSurvive and lifeBlend read the same way; tools/knobsweep.js sweeps them (design/ledger.md section 27) | T-661 | At the defaults every number as before (a fingerprint made with the pre-dial code, 17 settings); the sweep on Track B: reports/tiers/2026-10-05-dials.md; nothing adopted | reports/tiers/2026-10-05-dials.md | |||
| 5 Oct | The designers' price list (T-663, a report; tools/pricelist.js): log points at the minimum size of 829 datasheets of the 16 ledger armies regressed on rankings.json's capabilities (damage into the five stand-in targets, durability against the five stand-in attackers, total OC, Move, all absolute) and 73 perk variables; ridge on within-army deviations, λ by leaving one army out, 500 bootstraps; the engine's dice credit for a weapon keyword or Feel No Pain from the frozen ev.js with and without it; the ledger's credits by toggles at Track B. No live score, ledger number or setting changed | T-663 | Left-out R² 88.4%; Tyranid residual alone 50.9% on the five lists (Track B 77.7%); weapon keywords 1.12× of their dice credit, Feel No Pain 0.23× | reports/tiers/2026-10-05-pricelist.md | |||
| 5 Oct | Reviewer grades on an older game measured (T-667, tools/panelstale.js): each panel's BSData commit at its date against the frozen one, per unit points at every size (10%+), datasheet fields by name (BSData's bookkeeping evened out) and edition; the Tyranid yardstick (Track B) with and without the flagged units | T-667 | No number moves (a yardstick check): dropping stale units narrows the ledger-to-reviewers gap (12.7 points) by at most ~0.7 beyond random drops; the yardstick stays as it is | reports/tiers/2026-10-05-panelstale.md | |||
| 5 Oct | The datasheet profile as dials and the points exponent (T-662): ledger.js profileDials (a form's Value × Π (1 + m x) over its binary features, held at 0.05 or above, × exp(Σ m z) over its numbers, + Σ F x points at the median unit's rate), profileLines (the same, each feature on the parts of Value its family affects: Kill on arrival, the Kill that needs the unit alive ((L − 1) ÷ L, 0.5 without a life), the rest of Kill, Soak, Score, Actions, Hold, Spawn, Presence, the support credits, Battle-shock, secondary VP, the rest), both off, and the dial pointsExp e (Value × (points ÷ 100)^−e, 0); the reference medians are taken with all three off; the features come only from the search tool (tools/ledgerprofile.js) | T-662 | No number moves (off; the page carries no features). The search: reports/tiers/2026-10-05-crack.md, nothing adopted | reports/tiers/2026-10-05-crack.md | |||
| 5 Oct | Ingredients from the cross-army misses (T-670): ledger.js dials aircraftBoard (an aircraft's Kill × (1 − 0.2a), its Score, Hold and Presence × (1 − a)) and smallPiece (Value × (points ÷ the army's median reference points)^e), both on the ledger page and off by default; leaderCredit (a leader ranks at its Value alone + λ × the gap to its worth at the margin leading) and loneOpSoak (Lone Operative adds σ × its shooting Soak, ungated) as code only, off. 0 is today's ledger exactly | T-670 | Held out on the 15 armies (chosen on 10, scored on 5, 3 seeds): aircraftBoard +0.2 ± 0.1, smallPiece +1.2 ± 1.0 (Tyranids −3.1), with attachChars +2.2 ± 1.3; leaderCredit −0.8, loneOpSoak 0.0 | reports/tiers/2026-10-05-ingredients.md | |||
| 5 Oct | An army's own quirks as dials (T-672, World Eaters the test bed): ledger.js dial modeScarcity (ranged Kill × r^−m and melee Kill × (1 − r)^−m, r the army's ranged share of Kill over its reference forms, scaled so the army's summed Kill is kept), on the ledger page and off by default; armyPick (Burst blended toward burstPick, the Burst with an army rule's own choice taken: tools/ledger.js setArmyPick, tools/burst.js --field --army-pick, merged by tools/ledger-merge.js) as code only, off. 0 is today's ledger exactly | T-672 | World Eaters, one list left out: modeScarcity 0.2 +2.4 held out (with smallPiece 0.15 +4.5); the other 14 armies −0.1 ± 0.4, Tyranids +0.0; armyPick chose 0 (−2.2 at 1) | reports/tiers/2026-10-05-world-eaters.md | |||
| 5 Oct | Screens and cheap scorers (T-675): ledger.js dials screenArea, screenBlock, screenTrade, screenScore, screenHide (each w × Q × P ÷ points, Q a worth in points: board denied to arrivals, frontage × speed, enemy fire to remove it with a one-activation floor, a scoring slot × OC, Infiltrators/Scouts/Stealth/Lone Operative) and the screenJob switch; screenTrade on the ledger page, off; the rest code only, off. 0 is today's ledger exactly | T-675 | Held out (10 armies choose, 5 score, 3 splits): screenTrade +0.15 ± 0.06 at 0.01 (exam +0.1 [−0.3, +0.7]); area −0.02, block −0.05, score −0.95, hide −1.29. World Eaters alone +4 to +6 (area, block, score), at a cost of 1 to 3 pooled | reports/tiers/2026-10-05-screens.md | |||
| 5 Oct | Screen slots (T-677): ledger.js screenSlots k (only each army's top k units by screen worth take the T-675 screen credit), screenNext x (the next ones x, x²), screenRank (per point among units able to do the job, or by worth overall); all 0 = today exactly. Battle-shock's reference Value now leaves the screen credit out. Held out across armies: no positive setting (k 1 to 3, −0.6 to +0.03); World Eaters alone +6.7 held out at a third of the unslotted cost elsewhere. Not on the page; reports/tiers/2026-10-05-screen-slots.md | ||||||
| 5 Oct | Transports by their cargo on the page (T-679): ledger.js switch carryCargo (off) and dials carryRide, carryShield, carryFrag, carryFragRef, carryPer, carryDedOnly, carryCap, carryOnce, carryArrive, carryNeed, carrySquads (all 0), T-674's research line (tools/carrycargo.js) in the model: a transport worth what a ride adds to its best rider (meta.carryRiders from tools/carry.js ridersOf through tools/ledger-merge.js, all 16 armies), in place of the capacity line; on the ledger page in "Transports (T-674)". Off or at Transports 0 is today exactly | T-679 | Shape A (w 0.5, shield 0.4, frag 2 at 150, dedicated only, cap 1) reproduces carrycargo.js unit for unit: exam pooled +1.2 [−0.1, +2.8], Drukhari +14.0, Tyranids −1.7; not adopted (−0.0 ± 0.5 held out, T-674) | reports/tiers/2026-10-05-transports.md | |||
| 5 Oct | Every character and its special rules as dials (T-673, phase 1): ledger.js CHAR_KEYS charLead, charMove, charArrive, charOC, charShock, charShockAmp, charCP, charPsychic, charAura, charDebuff, charEpic, charEnh, charLone, charHome, each 0 to 3: a CHARACTER carrying the kind adds w × CHAR_PTS (50) × P ÷ its points, P the army's median reference Value a hundred with the dials at 0; charHome's worth is 50 × clamp(V ÷ P − 1, −1, CHAR_HOME_CAP 2), V its best pool squad's reference Value; charShockAmp's is SHOCK_AMP (0.4) × the army's other shock rules' shockW (+ SHOCK_ARMY rules as SHOCK_ARMY_TESTS 10 tests at SHOCK_ARMY_FAIL 0.35) × shockPressureW. cpOnce (0 to 1): a Command-points rule that can't stack (same rule, or any CP gain, CP_GAIN; own-unit discounts CP_STACK stack) keeps r.cp only on the army's best carrier, the others 1 + (1 − c)(m − 1). The kinds per character are ledger.js CHARS, from tools/characters.js (tools/characters.json). On the ledger page, all 0; 0 is today's ledger exactly | T-673 | Not measured (phase 2, after T-680 and T-681) | reports/tiers/2026-10-05-characters.md | |||
| 5 Oct | Typical version against best version (T-683, phase 1): tools/typical.js dials typicalSize (ws) and typicalDet (wd), typicalW setting both, all 0 = today to the bit: a unit's Value B + ws(1 − wd)(S − B) + (1 − ws)wd(D − B) + ws·wd(T − B), B today's best form, S the typical squad (smallest size, datasheet wargear) in its best detachment, D the median over detachments of its best form, T the median of the typical squad; a preview over compute(), no ledger file or page changes | T-683 | not yet (after T-673) | reports/tiers/2026-10-05-typical.md | |||
| 5 Oct | One per job (T-682, phase 1): tools/rivals.js, a preview, the dial rivalW (0 = today): Value × (1 − rivalW × the largest likeness × gap among a unit's better same-army rivals); likeness = kill² × mode × type × speed^½ (target tilt by cosine, ranged share, body/Character/Fly, Move), gap = (V_rival − V) ÷ V capped at 1 (twice as good per point); with a scrambled-likeness placebo. Not in ledger.js, nothing adopted | T-682 | not yet (after T-673); Tyranids at 0.5 in sample 79.3 → 78.9 | reports/tiers/2026-10-05-rivals.md | |||
| 5 Oct | Jailing and the objective steal (T-684, phase 1): tools/steal.js previews two dials, jailW (turn-one reach into the enemy's zone × the width a unit holds there, coherency-capped at 9" plus engagement range, as a share of the zone, Q = 0.1 × 2,000 × that share × 0.5 for going first) and stealW (arrives anywhere, moves after shooting, takes an enemy-held objective on OC: Q = 4.5 VP × P(reach) × OC ÷ (OC + 8.26) × 2,000 ÷ 65 points a VP), each Value + w × Q × P ÷ points as the screen dials; 0 = today exactly; not in ledger.js. Steal qualifies 5 datasheets in 16 armies; Tyranid preview at jail 1, steal 0.5: lists 79.3 → 79.9 (placebo 79.0), Gargoyles 46th → 37th | T-684 | Not measured (after T-673) | reports/tiers/2026-10-05-steal.md | |||
| 5 Oct | Space Marines' scarcity and Soak effects (T-681): tools/scarcity-space-marines.json (scarcity.js unchanged formula, β 6: heavy infantry 2.35 … chaff 0.18), tools/soakfx-space-marines.json from tools/soakfx-rules-space-marines.json (every form exposed 1; Self Repair, Narthecium own heals; Blessing of the Omnissiah healMult only), merged by ledger-merge.js; live files, no re-freeze (snapshot eb3590a) | T-681 | Space Marines Track A 64.5 → 60.3 (scarcity −4.2 [−9.1, +0.7], Soak 0); pooled 59.4 → 59.1; Tyranids unchanged | reports/tiers/2026-10-05-refreeze-sm.md | |||
| 5 Oct | One exam hook for the previews (T-685): tools/exam.js takes a setting's optional post: { module, args } (or --post, --post-args): the module's post(D, run, sliders, args) rewrites unit values after compute(), and the exam re-sorts and scores them with its paired bootstraps. tools/rivals.js, tools/typical.js and tools/steal.js export post over what they had. No number moves: without post the path is unchanged, and each preview at 0 gives Track A to the bit. | ||||||
| 5 Oct | The span match, a second yardstick (T-689, Jordan's rule with partial credit): tools/spanmatch.js and tools/exam.js --span. A unit's span is every letter from the best to the worst of its squad sizes' letters (each size at its best detachment and loadout, cut by the run's own cutS..cutC; the ranked row's letter always in); a reviewer's letter inside scores 1 ÷ the span's width, outside 0; beside it the strict letter match and a same-width placebo (three seeds). Without --span the exam's output is byte-identical. No Value moves | T-689 | Pooled 14 armies span / strict / placebo: A 25.2 / 25.2 / 18.9, B 26.5 / 26.8 / 19.2, trio 26.1 / 26.3 / 19.3; Tyranids 36.5 / 36.7 / 22.3 (A); span − strict about 0 everywhere | reports/tiers/2026-10-05-spanmatch.md | |||
| 5 Oct | Detachment corrections from the T-690 audit (T-694). docs/data/detfx.json: the six choices that are really a roll, a ladder or a once-a-battle pick carry pick ("roll", "ladder", "once"), pickNote and a share per option, the part of a five-round game it holds (Pledges to the Dark Prince a fifth per step; Master of Wolves a fifth per pack, Ferocious Strike's two halves a tenth each; Mission Tactics a fifth each; Unpredictable Genius by its D6; Try Dat Button! as two dice, a third per pair, hazard not counted; Blood Tithe nothing in rounds 1–2, Enraged Abjuration round 3, Boon of Blood rounds 4–5). The calculator ignores the shares and still offers every option; tools/ledger.js mixes them: one variant per detachment whose numbers are its parts' (each option, and none for the rest) weighted (variantParts, mixNumbers; tools/burst.js mixes --field, --prefer and --life the same way). Noted rules' multiplier reaches only the units a rule names (units, notUnits in the data, else its effects' and its choice options' unit keywords, so Idols of Khorne is the Jakhals' and Goremongers'); a rule marked army (Rad-bombardment, Miasmic Bombardment, Artillery Support) acts once for the army and reaches no unit. New conditions notTargetKw and notUnitKw (docs/detfx.js check, tools/matrix.js unitLevel and cells; docs/ev.js reads no conditions, its callers settle them through DetFx.check): Born Soldiers' Regiment half, Exacting Cruelty and Contracted Harvest "not against MONSTER or VEHICLE"; Wrath of Khorne not for Epic Heroes. Dark Age Arsenal by when.weapon (plasma); Dutiful Tenacity, Stitchflesh Abominations and Darkest Artifice by sVsT: "gt"; Enraged Abjuration as fnpPsychic/fnpMortal 5+. The site's rankings.json isn't rebuilt here (no stamp; its detachment synergy line ds will move for Dark Age Arsenal, now plasma only, when it next is); the ledger takes these with the T-687 re-freeze | ||||||
| 5 Oct | The ledger re-frozen on today's engine and T-694's corrections, on the pre-dataslate data (T-687): tools/ledger-inputs.lock.json is code 8eb69bc7af with index.json and the panels kept as at eb3590a (from) and three inputs built (built: detfx.json = eb3590a's plus T-694's corrections, the 30 Sep update's Frantic Focus and Legion of Excess changes left out; detachments.json, a new input, at BSData 374f505 with today's reader; rankings.json from eb3590a's data with today's engine); inputs hash a20dbd2c3316; the old lock kept (tools/ledger-inputs.lock-eb3590a.json, LEDGER_INPUTS_LOCK). tools/ledger.js matchedOf takes an army's detachments from detachments.json (a Detachment Points cost, its only, effects found under its own key or, for one kept to it, any army's, no Boarding rule): the same lists for 15 armies, the Drukhari's nine for them. Track A: Tyranids 79.3 → 79.1, exam 59.1 → 59.0; reports/tiers/2026-10-05-refreeze-engine.md | ||||||
| 5 Oct | Unavoidable burst (T-712): tools/surefire.js, a post step through the exam's hook, dial sureFire w (0 = today to the bit): Value + w × K × (d − d̃), K the best form's Kill contribution to Value (Burst under burstKill), d a unit's delivery (the share of the enemy's zone its natural mode reaches by our turn 2 by its best way: walk R + 2M, Scouts, Infiltrators, Deep Strike and other arrivals 1, strategic reserves from the 6" edge strip, a transport in its army; melee with a 9" charge in place of R), d̃ the army's median d; variant reserves: 0. A report; no ledger file or page changes | T-712 | Held out +2.7 ± 0.6 (placebo 0; without reserves +3.5); exam at 0.5 +1.8 [−0.0, +3.6]; Tyranids +0.2; not adopted, for the next cascade at 0.25 and 0.5 | reports/tiers/2026-10-05-surefire.md | |||
| 5 Oct | A character's army-wide kinds on its own share (T-715, fix 1): on a joined form a total-line kind only a character member carries (rules tagged from) is kept out of the form's total multiplier; Value = (Σ weighted lines + Σ_k (Π x_k − 1) × L_k × pts_k ÷ pts) × total, L_k the character's weighted lines alone (its solo form alone at the same size, loadout and detachment), shown as memberRules | T-715 | Joined forms only: T-709's g on Hellblasters + Apothecary 6,113 → 886, Hearthguard + Ûthar 2,730 → −57, Thunderkyn + Iron-master 3,111 → 409; Track A unchanged by it | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | One Kill scale (T-715, fix 2): every joined form takes a Burst (tools/burst.js --field walks it, the joined unit with its characters' lend) and burstKill reads it like a solo form's, on the solo ranking forms' burstScale | T-715 | No solo number moves | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | Leaders and Supports apart (T-715, fix 3): matrix.js contextEnv leaders and supports (a Supporting link wins); forms squad + Leader, squad + Support, squad + its best Leader (Kill ranged + 0.6 melee + Soak × metaKillRate at β 6) + each Support, every character lending | T-715 | 35 Support characters, 149 pairings, 160 three-member bases in 7 armies | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | Healing scoped and counted once (T-715, fix 4): unitfx.json heal self / to; Narthecium inSpawn (healMultOwn leaves it out); the Dark Angels' Narthecium on the Space Marines' spawn rule; a heal the Soak effects count by the form itself is measured: "soak" (no ×heal); a spawning rule measured only on forms of a datasheet that carries it | T-715 | Old One Eye, the Red Terror, the Rhino −45%; the Dark Angels' Apothecary 78 → 88; Tyranids 82.45 → 81.61 | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | Lone Operative on a joined form only when every member has it (T-715, fix 5) | T-715 | Joined forms only | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | The lend priced apart from joining (T-715, fix 6): the engine writes each joined form's Kill and Soak without each character's leaderfx effects (lend); tools/leadercomp.js g = (contrib.kill × ΔK ÷ K + contrib.soak × ΔS ÷ S) × pts ÷ 100 × 100 ÷ the character's points, K = ranged + melee × lands × r.first (β of the form), Leaders against Leaders, Supports against Supports on the squad's best led form; prices dice (default), lend (with grants and +OC), lendown, joined (T-709's) | T-715 | Reviewers' check 25.8% of 151 → 50.9% of 172 by role (chance 38.7%); T-709's penalty half held out +0.58 ± 0.11 (placebo 0) | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | The missing grants (T-715, fix 7): unitfx.json grants (Deep Strike, Fights First for the attached unit; leading), ocPlus/ocTo (+1 OC a model of the unit, or the bearer) into ocPer100; a granted Deep Strike is a charge-model way in (landsNoGrant beside it); a leaderfx lend needing "charged this turn" met in melee (the page scales melee by lands) | T-715 | Command squads +8 to +25%, Company Heroes 41 → 34; the Teleport Crest moves no lands (deploying reaches as often) | reports/tiers/2026-10-05-leader-fixes.md | |||
| 5 Oct | "Alone" at the joined form's own loadout (T-715, fix 8): partnerAlone reads alone (same size, Auto-equip squad and detachment) before the best solo form | T-715 | Toggles only; none holds after the fixes (leaderCredit at 1 pooled −3.76 → −1.88) | reports/tiers/2026-10-05-leader-fixes.md | |||
| 6 Oct | A second yardstick behind a flag: the GEMINI AGGREGATE lists at half weight, read at scoring time (tools/yardstick.js; consensus pairs: human-agreed 1, one human plus Gemini 1, Gemini only 0.5; the exam's list mean: Gemini one more list at 0.5); scoring only, no ledger number moves | T-731 | Track A 61.9 → 61.7 (consensus, 16), 59.3 → 58.4 (list mean, 15) | reports/tiers/2026-10-06-yardstick-exam.md | |||
| 6 Oct | Held-out exam of Track A, C1, C5, #3 and line weights solved to Kill-share targets (30, 50, 70%) | T-734 | held out over C1 +0.0 ± 0.8; every share target below its base | reports/tiers/2026-10-06-yardstick-exam.md | |||
| 6 Oct | The new recipe, step 1 (T-739, step 41, kept as Track A2, candidate): Track A + charEpic 0.5 + aircraftBoard 1 + typicalSize 0.25 (mean rule) through the post hook; measured by tools/recipestep.js (held out on the 15 exam armies, leave one army out, paired unit bootstrap, Gemini at half, three shuffled letter sets; keep if the gain > 0, its interval's low end > −0.5 and 9 of 15 armies don't fall) | T-739 | held out +1.2 [−0.4, +2.6], 11 of 15 not falling; adoption is Jordan's call | reports/tiers/2026-10-06-recipe-steps-1-2.md | |||
| 6 Oct | Reach (T-739, step 2, reverted): tools/reach.js, a post step, wReach 0 = today to the bit; r a form's board share by the end of our turn 2 by its best way in (M + ADV 3.5" twice from our zone; Scouts; Infiltrators; arrivals more than 8" from the enemy's zone; reserves; a transport's two moves + OUT3 3"; surefire.js basicsOf()), on a 1" GRID; Value + wReach × (r × 100 ÷ points − the army's median), or with reachKind 1 Value + wReach × P̃ × (r − the median r of the army's units of its kind, KINDS Vehicle, Monster, Mounted, Infantry, other). tools/postchain.js chains post steps | T-739 | as briefed: fitted wReach 0 in every fold; by kind: held out +0.6 [−1.7, +2.7], 8 of 15 not falling; both reverted | reports/tiers/2026-10-06-recipe-steps-1-2.md | |||
| 6 Oct | The unit-kind layer (T-740, step 43, reverted): tools/kindlayer.js, a post step chained after the stable layer, every dial 0 = today to the bit; Value × exp(kInfantry·Infantry + kMonster·Monster + kVehicle·Vehicle + kFly·Fly + kEpic·Epic Hero + kPsyker·Psyker) × (M ÷ M̃)^kSpeed, the flags and M from the unit's own datasheet, M̃ the median Move of the army's ranked units of its body kind (BODY Vehicle, Monster, Mounted, Infantry, other); fitted by tools/kindstep.js on each training fold from the grid LEVELS {−0.3, 0, +0.3} and SPEED {−0.5, 0, 0.5, 1} (2,916 candidates, the base first), recipestep.js's protocol | T-740 | held out +0.2 [−1.6, +1.9], 7 of 15 not falling (fixed at the modal pick +2.0 in sample); reverted | reports/tiers/2026-10-06-recipe-step-43.md | |||
| 6 Oct | The stratagem pilot (T-713, steps 44 and 44b, not adopted): tools/stratagems.js, a post step chained after the stable layer, w 0 (or an army without a credit file) = today to the bit; the catalogue tools/stratfx/<army>.json and core.json (dice stratagems as engine effects, our words); tools/stratuplift.js the uplift (Burst or Soak with one use added, minus without; a melee phase × the form's lands; points saved = pts × (min(1, E ÷ S) − min(1, E ÷ S′)), E the typical army's mean unit, S the enemy points to remove the unit); the spend: CORE_CP 2 a battle round × ROUNDS 5, the typical list by Value within LIST_PTS 2,000, uses bought by points per CP (fractional greedy); Value′ = Value + w × (Kill rate × kill credit + Soak contribution × Soak credit + the army's median Kill rate × a CP source's credit), the best detachment per unit; W_GRID {0, 0.25, 0.5, 1, 2, 4, 8} fitted on one army, scored on the other | T-713 | Tyranids −0.1 at w 1; Votann +9.5 (44) / +12.4 (44b) on one list, placebo credits +4.7 / +7.2; cross-test Tyranids → Votann +0.0 / +3.8, Votann → Tyranids −0.1; fails its rule | reports/tiers/2026-10-06-stratagem-pilot.md | |||
| 6 Oct | Winning-list shape as unit features (T-743, a report, nothing adopted): tools/listshape.js (his six Toughness bands with the ledger's exact dice into the typical army, one activation, shooting or fighting; 80+ points of a representative target, wound and models-destroyed readings; cost tiers at 115 and 200; anchor ratio = Soak at β 6 shooting ÷ 100; coverage credit Σ 1 ÷ (1 + other army units clearing the band)) and tools/statlearn.js's shape features; nothing in the live scores or the ledger moves | T-743 | held out on 15 armies: bands and coverage +1.0 [−1.4, +3.4], anchor −0.7, tier −0.2, rank in tier +0.2; none declared | reports/tiers/2026-10-06-list-shape-internal.md | |||
| 6 Oct | Fire Support in the calculator (T-744, Jordan approved 6 Oct): a transport whose passengers re-roll wound rolls against the unit it hit is a lend in kindfx.json (rrWound all; ranged, but the Falcon's lasts the turn; the getting-out a manual condition, the target the Marked chip) and partly in unitfx.json, on the Death Guard Chaos Rhino and the same rule's other bearers read on the 11th-edition pages: Razorback and Relic Razorback, Coronus Grav-carrier, Skorpius Dunerider, Falcon, Manta (Aggressive Deployment), Goliath Truck, Crassus and Valkyrie Sky Talon (Astra Militarum, Genestealer Cults), Grey Knights Relic Razorback | T-744 | The calculator only; the rankings and the frozen ledger don't read it (their copies move at a re-freeze) | reports/tiers/2026-10-06-death-guard-checks.md | |||
| 6 Oct | The bug-fix snapshot (T-745; a re-freeze, b3c416933e / 1b88e955b9b3): a unitfx.json heal with returns: true (a rule that brings slain models back to a unit) is the ledger kind "Returns slain models", the page's r.return (× 1 unless set; SPAWN_HEADS keeps the Spawn line's measured ones measured), no longer r.heal's ×1.805; T-723's excl pairs in build/units.json; the squad-wide rules in tools/ledger.js SQUAD_SAME (one option family per squad, as loadout.js packages: pkg group "same"); ledger-merge.js leaves panels that join no yardstick out of the comparators. Track A2 (step 41) is the ledger's benchmark | T-745 | Track A exam 59.3 → 59.7, consensus 60.0 → 60.2, Tyranids unchanged; step 41 held out +1.1 [−0.3, +2.7] over A, 12 of 15 | reports/tiers/2026-10-06-bugfix-snapshot.md | |||
| 6 Oct | The stratagem step (T-742, reverted, nothing adopted): tools/stratagems.js wires all 16 armies; a new shared parameter, the shoot-back share AGAIN_SHARES {0.25, 0.5, 1}: a stratagem with an again version (shooting in the enemy's phase, or once more) counts that share of its points in the spend; the grid STEP_W {0.25, 0.5, 1, 2, 4, 8} × the share after step 41 (Track A2), core re-roll in the menu, chosen on the training folds (tools/recipestep.js's protocol); the placebo hands each army's adds to random units of the army, PLACEBO_SEEDS 101 to 120, through the same fit; the keep rule adds "above the placebo's 95th percentile". tools/postchain.js keeps each step's result per input run (same numbers) | T-742 | Held out −0.6 [−1.8, +0.4], 5 of 15 not falling, placebo 95th percentile +0.4 (beats 3 of 20); fitted w 2, share 1 in 6 of 9 folds, all from Votann (+21.9; the other 14 lose at every w); face value +0.3 [−1.0, +1.7]; Tyranids 82.6 → 82.5 | reports/tiers/2026-10-06-stratagem-step.md | |||
| 6 Oct | The ensemble's confirmation (T-748, a report, nothing adopted): tools/statlearn.js takes --bench and --out (and configure()), and applies a setting's post step before reading the feature table; tools/ensconfirm.js re-implements T-736's x_ens_sheet (the SHEET features, pairwise L2 logistic, λ by inner leave-army-group-out, percentile of the fit + percentile of Value) and scores it on the GEMINI AGGREGATE letters, the T-733 Orks candidate and leave one list out in the multi-list armies; no ledger number moves | T-748 | over Track A2: 11 held-out human lists +3.9 [+1.3, +6.6]; Gemini +5.3 [+1.8, +9.1]; leave one army out +2.4 [−0.8, +5.6] on 15 | reports/tiers/2026-10-06-ensemble-confirm.md | |||
| 6 Oct | Returning models on the Spawn line (T-747, measured and reverted; the files hibernated): tools/spawn-rules-<army>.json for nine armies (Genestealer Cults, Astra Militarum, Agents of the Imperium, Death Guard, Dark Angels, Drukhari, Thousand Sons, World Eaters, Space Wolves; our words), read by tools/spawn.js only with LEDGER_SPAWN_RETURNS=1 (or useArmy(key, { returns: true })); a returned model at the receiving unit's points per model at its smallest size, rounds [0.5, 1, 1]; new counts: objective (a better count on a held objective, its share of Command phases 0.5, the Cult Icon), big (from a squad size on: Krieg's two medi-packs at 20, D3+1), per: "modelsKilled" (Curse of the Walking Pox: the form's kill['6'].byClass ÷ classPpm(), the step-1a field's points per model by class: monster 246, heavy vehicle 259, light vehicle 90, character 95, heavy infantry 35, cavalry and beasts 30, elite infantry 14.3, chaff 8.75; MONSTER and VEHICLE classes left out; gated by lands), into: "unit" (the bearer's unit: the led squad on a joined form, its own models alone); constants in the files: Fleshcraft's Pain share 0.5, Rebind Rubricae 5/6 a Command phase; a one-model receiving squad takes nothing back; tools/recipestep.js --base-dir / --cand-dir (the same setting on two folders of ledgers) | T-747 | Off by default: every ledger as T-745 built it, Tyranids and Space Marines unchanged to the byte. With the files on: held out +0.0 [+0.0, +0.0] over step 41, 15 of 15, no graded pair moves; returning units +15 to +37 Value, leaders 0 | reports/tiers/2026-10-06-spawn-returns.md | |||
| 6 Oct | Stratagems in the calculator (T-749, Jordan approved 6 Oct): tools/stratcalc.js writes docs/data/stratfx.json from the catalogue (tools/stratfx/*.json and core.json): per detachment the site knows, the stratagems that change the dice (not noted, not a version that only acts again), each { id, cp, ph, vs, one, who, whoAll, notWho, attached, label, tip, v }, a sum stratagem's main version (largest share) only, a best one's versions all; docs/detfx.js strats(), coreStrats(), stratOpts() (versions told apart by their conditions are one option, true alternatives one each, a unit's own fuller version replaces the plain one) and stratEffects() (ids `strat | <id> | <slot> | <n>, its own turn's gated to ranged or melee by the phase, a defence one's by the enemy phases it covers); in play only while the player uses one (app.js S.attStrat/S.defStrat, detInPlay`), the condition the catalogue counts as a share taken as met | T-749 | The calculator only; the rankings and the frozen ledger don't read it | design/mockups/2026-10-06-calculator-stratagems.html |
| 6 Oct | The datasheet signals as ledger steps (T-751, steps 46 to 50, all reverted; nothing adopted): tools/sheetlayer.js, a post step chained after the stable layer, every dial 0 = today to the bit, on each ranked unit's own datasheet (tools/kindlayer.js featuresOf): sheetSpeed k, Value × (M ÷ M̃_kind)^k (M̃_kind the median Move of the army's ranked units of its body kind); sheetEpicPsyker a, × exp(a) for EPIC HERO or PSYKER, taken once, on top of charEpic; sheetInfantry b, × exp(b) for INFANTRY; and two ledger sliders, wSoak and rules.lone. tools/sheetstep.js STEPS holds each step's grid: sheetSpeed {0, 0.25, 0.5, 1}, sheetEpicPsyker and sheetInfantry {0, 0.15, 0.3}, wSoak ×1/×2/×4, rules.lone {1.93, 2.5, 3}; chosen on the training folds (tools/recipestep.js's protocol); the keep rule adds a fourth part, the real held-out gain above the mean of the three shuffled controls' | T-751 | held out over step 41 (Track A2): speed +1.1 [−0.6, +2.7], 10 of 15 (k 1 in 9 of 9 folds; shuffles pick 1 too, mean +0.3), the floor fails; Epic Hero or Psyker −0.3 [−1.2, +0.5], 8; Infantry −0.2 [−1.0, +0.7], 8; Soak ×2/×4 −0.1 [−0.3, +0.0], 7; Lone Operative +0.0, 15 (only the Orks move); the five together at their modal picks (a diagnostic) +1.3 [−0.6, +3.1], 9. Track A2 stays the benchmark | reports/tiers/2026-10-06-datasheet-steps.md |