A Soul pass measured the thing three cuts assumed. FireControl's per-shot seed
feeds CultMath's xorshift32, whose NextFloat returns the top 24 bits of the
FIRST round -- and one round cannot carry ShotId's low-bit variation into the
high bits. Every zone's hit roll spans 0.1249. A shot is a step function whose
threshold is fixed when the zone is created: below the band it never hits, above
it always does. An unaided shooter hit 0 of 18,926 shots.
That is the operator's "no hits registering," and being stable per zone is why
it came and went.
It is this map's own prescription, written by Self in Cut 6b, and the reason it
survived is that no test in the campaign measures a distribution -- every
fixture uses accuracy 1 or 0, and a constant satisfies a determinism test
perfectly.
Also takes pOnHull collapsing to zero above Precision ~4 (no shipped hull's
centre of mass is integral, so a tight sigma underflows every cell weight), and
the LockWeapon crash Cut 8 did not actually fix -- that code only runs on an
active entity, so the _active guard was never what would prevent it. Docking
still reaches it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The operator's play smoke crashed in LockWeapon reaching EntityInfoGathered as a
ship vanished. Cause: Cut 5.6 added death removal from the zone but not the
matching Deactivate, so a dead entity kept living subscriptions and stale
references while every survivor dropped it -- and because Zone.Update iterates a
snapshot, it still got one more Update after the world had forgotten it. Nothing
in Entity.Update consults _active.
TryDock has always paired removal with Deactivate; the death path just did half
of it. The fix is that pairing plus an _active guard, not a TryGetValue in
LockWeapon, which would silence one call site and leave every other behaviour
running on a corpse.
Also records the symptoms this does NOT explain -- the heat spike, motionless
ships and shots landing nothing -- as open, with the unclamped dt and the
unguarded division by it as the place to probe rather than patch.
And re-anchors the seven mutations stranded by the diagnostics refactor, which
rewrote the lines four harnesses pin. Two of the seven are no-op controls, so
those harnesses currently defend nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merging 6b and 6c bricked the catalog -- a new non-nullable float at a new
MessagePack key cannot read records written before it existed, so
AetheriaStores.Open threw and the game could not load its own data. Both
branches were green: one never opened the real catalog, the other never had the
field.
Cut 7's live-catalog test therefore has to enumerate every document type rather
than just look for a design, because a lazy read that never touches
WeaponItemData would have passed the broken merge too.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Precision is currently a coin flip between landing exactly on the aimed item and
landing uniformly anywhere on the hull, so aiming at a stern thruster scatters
its misses across the bow. Operator direction: misses should cluster near what
you aimed at, like throwing a dart at the grid -- and aiming should therefore be
a real tradeoff, where a thin limb risks missing the ship entirely and centre
mass is the safe play.
One Gaussian kernel over the hull schematic answers both halves: its on-hull
mass prices the stray into HitProbability, so the risk is legible on the HUD
before the trigger, and its per-cell weights place the hit. One function, so the
probability and the placement cannot drift apart -- Cut 3's named risk was
exactly two functions answering where a shot goes.
Records the rejected draft that clamped a stray dart to the nearest hull cell,
which would have quietly removed the tradeoff, and the two consequences worth
catching early: pOnHull may double-charge with the existing pSpread term, and
every AI gates on this number so they will hold fire more once it lands.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cut 6b: the combat roll stops drawing from the shared ItemManager.Random stream
and becomes a pure function of (zone identity, shot id), so adding an NPC or
opening a shop can no longer reorder an existing fight's dice. Airburst resolves
in the simulation rather than going back into Projectile, which would be exactly
the presentation authority Cut 3 spent itself deleting.
Cut 6c: reviewing Cut 6a's landed catalog found the premium targeting system
strictly worse than the cheap one, because Resolution reads as a cost while its
name promises a benefit. Operator ruling: fix the formula, not the handle -- it
becomes reciprocal, higher stays better, no rename. Also: both designs ship from
one seller, and galaxy generation draws a random subset of factions, so ship
generation still throws in any galaxy that misses that draw.
Cut 7: the mutation harnesses for Cuts 1-3 that the map declared and nobody ever
wrote, plus the fifth mutation Soul left standing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Soul's campaign pass confirmed eleven findings. Seven of them are code defects
of one shape -- a rule implemented on one path and left off the path beside it
-- and belong to this cut. Catalog authoring is Cut 6, alongside airburst and
the shared combat RNG; the missing mutation harnesses are Cut 7.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
32 of 51 designs declare roles, 183 stats point at one, 28 of 37 products
author matching role quality. Adds the validation that refuses a stat
naming a role its design lacks, and roles-migrate alongside the other
catalog tools. Product means are placeholders pending operator review.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
roles-migrate apply, run once: 32 of 51 designs now declare roles (183
stats pointed at the role that governs them; the other 19 designs' kinds
either carry no quality-bearing behaviour at all, or every candidate stat
is authored flat with no observable role-vs-workmanship difference). 28 of
37 products authored matching ProductRole quality; the rest sell an
unrolled design or a design no product sells (Core Power, Industrial
Thermostatic Heater, pswarm, plight -- all already flagged unsold in the
Cut 1 census).
docs/stats-power-cut7-roles.md is the legible review table the map's O7
calls for: every design's roles and which stat took each, grouped by item
kind, plus every product's authored mean/deviation and its basis (one real
brand identity -- Arctica/Alakrita on heat efficiency, from
item-provenance-target.md -- the rest generic placeholders flagged for
operator review).
Verified before/after: AetherDb dangling/station-fit/hardpoint-fit output
is byte-identical; `loadout 1` output is byte-identical (no generation
behaviour moved); census reports 0 designs with roles and no matching
product spread; 144 Aetheria.Shared.Tests pass (was 141); the six-mutation
harness in mutation_tests_stats_power_cut8.py all behave as declared.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
S1/S2 re-authored (Tractor Beam plus 13 curve-less designs), S5/S6 validation gaps
closed, S7's four surviving mutants pinned, S8 confirmed already correct, and the
zero-ConsumableItemData answer to Cut 0's question recorded. Also names two designs
outside the operator's named 15 (Earp, The Bat) found while enforcing the new
plateau-clamp rule -- the catalog would not open without touching them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f4d5659d landed with StatValidation's OptimalTemperature-bounds check replaced by
`if (false)`: the mutation harness was running concurrently against this same file
and a `git add`/`git commit` caught it mid-mutation. Restores the real check. Caught
because the harness's own "not yet reached" scars in doctrine are what prompted a
by-hand recheck of the just-committed diff rather than trusting the terminal output
that said 80/80 green a moment earlier.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Migrated by a two-phase scratch console (neither kept): phase A dumps the
four retired exponent fields plus a curve fit (peak, optimum, near-peak
band) from the pre-Cut-1 code; phase B applies them as declared StatTerms
and authored OptimalTemperature/PlateauWidth under the new schema, in one
Commit, refusing to write anything if a single record fails to resolve.
348/348 stats and 51/51 EquippableItemData records migrated; zero
failures. AetherDb's census/factions/dangling/station-fit/hardpoint-fit/
loadout-1 are byte-identical before and after (captured with the matching
pre/post binary against the matching pre/post catalog, since neither
binary can open the other's catalog shape -- the pre-migration catalog no
longer opens under the new code, confirmed and explained in the report).
37 items fitted from an authored curve; 14 had none and got a full-range
plateau (reproducing the old "always full performance" behavior exactly).
281 of 348 stats evaluate identically at quality .5/full durability/optimum;
67 diverge upward (toward Max), the intended balance change Cut 0 flagged --
max delta ~73 units on a 750000-1750000 stat. Full table:
docs/stats-power-cut1-migration.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>