Gain stays the one detection rule: both branches are scaled by the fraction
of the signal that survives the clouds between observer and target
(Zone.Obscuration, exactly 1f with none, so the pre-cloud trace is
bit-identical). The entity loop passes it for pings and passive ticks and
PassiveRate for the chunk position. Entity.cs is untouched: a lock falls by
the existing detection-threshold rule when info does. Adds the sensor-level
facts to VapourCloudTests. Builds; not yet run (verify job follows).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zone.Vent is the one adder, StepClouds the one remover, Zone.Obscuration the
one reader: the product of (1 - opacity) over clouds whose disc the segment
touches (closest point of the segment to the centre within Radius), 1f when
none. Derived from live clouds at each call, never cached. VapourDump vents
once on its first run, drifting with its venter. Nothing reads Obscuration
yet (Sensor.Gain takes it in the next commit); this commit builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tutorial-seed scan for a zone with no genuine Lagrange candidate ran
once per test; it now runs once behind a Lazy. The leak test regains
Assert.NotSame(galaxy.Entrance, otherZone), and the scan's miss path uses
Assert.Fail (xUnit2020).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the target's fit written out the jinking price is .383 against .440
coasting, but 200 rolled shots gave 93 hits jinking against 78 coasting: the gap
between the prices is smaller than the noise of two 200-shot volleys. 2000 shots
put the expected gap near four standard deviations; the assertion is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EvRangeLaunch placed stage.Generated("Djinni"), whose fit follows the galaxy; at
CultMath 0.3.0 the generated target gave 95 hits jinking against 78 coasting.
The target now carries an explicit Talaria/cockpit/reactor fit, so the hit
comparison does not depend on generated content.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EAC-7089 and EAC-2733 were generated-content names that CultMath 0.3.0 re-rolled
away. The no-Lagrange-candidate zone is now found by its property (planets that
are all rosette members, so no genuine candidate) by scanning seeds, and the
zero-natural-station zone by its isTutorial: false roll. Every assertion keeps
its claim; the candidate predicate is shared with the leak test's fixture check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The noise kernel changed at cultmath-unity-v0.3.0, so the fixed seed gives a
different tutorial. TutorialGalaxy_unchanged keeps its claim (a fixed seed
gives a fixed tutorial) against the regenerated shape. Does not pass the whole
suite: the RestoredHullsTests and the evasion test follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backfilled Large Drives differ in quality, so a held forward thrust is a net torque and TurnRate never settled to zero. Release the movement demand with the turn demand.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AetherDrive.cs: master deleted the behaviour (2cfdc728); the branch only added a
TurnRate line to it. Deletion kept. Thruster remains the one rotation actuator
and feeds Entity.TurnRate. No sim stepping outside the clock on master
(mines presenter, Pirates AI, lot-product all step through Zone.Update).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Large Drive and Small Drive shipped with unnamed Quality terms on their flat stats; the command keeps those exponents. The reset stripped them, so the new exponent check read the Thruster precedent instead.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A non-flat stat must carry exactly one Quality term, named, declared, with a positive exponent; a flat stat may not name a role. The check is one function with its own synthetic-stat test.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ExponentFor drew its pool from items.Except(targets), so growing the targets from six to twelve changed the exponents a rerun on master's catalog writes. The pool is now snapshotted once, from every design that declares roles and names a Quality term, before the loop mutates anything. Describe prints each named term's exponent, one test pins Autocannon's and LRMM72's exponents against the shipped blob, and one clears a single role of a two-role seller and expects only that role re-authored.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ShippedCatalogRolesAreLive checks every design of every kind: each non-flat stat reads one declared role,
declared roles are read, sellers author each once, role-mapped designs are not all flat (the tool answers
which, via Program.HasRoleMap). RolesBackfillIsAuthored pins ratios and roles, with the Autocannon
Penetration, Mine Range and LRMM72 LockAngle asserts. RolesBackfillCommandTests resets the backfilled designs
on a scratch catalog, applies, and expects the shipped catalog back, then replays as a no-op.
EveryShippedProductHasAMaker. TheEnvelopeComesFromTheGear bounds each drive by the catalog's Large Drive
Thrust range; ShippedWeaponOperabilityTests reads the catalog's DefaultEntitySettings.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
DrawAhead leaves a ship in a wormhole animation where the step put it. The clock is
one static instance; a zone entered inside a step ends that frame's stepping and the
clock resets between frames (SimClock.Reset throws inside Advance). DrawAhead.Time had
no consumer.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Each fitted Talaria has its own lot's thrust, so Left and Right are the two flanks'
accelerations, not both the larger one.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ShippedCatalogRolesAreLive skips gear with no PerformanceStat at all (Tractor Beam is a
thruster kind with none). TheEnvelopeComesFromTheGear fits the Longinus by name: the
generator's picks follow the item stream and every authored ProductRole draws from it, so
the generated hull stopped carrying Large Drives (Medium Drive and RevvITup instead). Its
forward bound is the drives' own thrust, since a Large Drive now rolls 0.8x to 1.2x.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AetherDb roles-backfill gives Autocannon, LRMM72, SRMM72, Mine Launcher, Large Drive
(and Small Drive, which declared roles no stat read) live roles: each mapped flat
stat becomes a 0.8x..1.2x range read through a Quality term naming its role, and
every seller authors a ProductRole per role from its maker profile. MineLayerRoles
is new; the maker profile table is hoisted so pd-gear and this command share it.
ShippedCatalogRolesAreLive and RolesBackfillIsAuthored read the shipped catalog.
The catalog blob lands in its own commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A StatReference naming WeaponData.Damage validated and attached to nothing,
because TargetsOf compared exact types. All three filters now use
targetType.IsAssignableFrom; no exact-match path remains.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AetherDb Program.cs: both sides appended a command (pd-gear/mine-launcher, pirates-faction);
kept all, one usage line. GameData/Aetheria.cc: master's blob kept here, pirates-faction
apply replayed on it in the next commit (follow-up catalog-blob-merge-order).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
DrawAhead.Rotation delegates to Turned(pose, angle) so the turn is testable on a tilted pose, where the flat Duel poses make the quaternion product's off-axis terms vanish. Unverified at this commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The catalog is regenerated from master's catalog with pd-gear apply (next commit).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
# GameData/Aetheria.cc
# tools/AetherDb/Program.cs
Stryker's one survivor in the first sweep was the guard's `true ?` mutant: the
cache's Get(ref) extension already returns null for an unset reference, so the
guard was a second path. Adds the removed-product fact the spec names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lands retire-longinusx on master after gear-without-presence. The catalog
is regenerated from master's catalog with retire-longinusx apply (next commit).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
# GameData/Aetheria.cc
The first verification showed the rotation sense wrong and no shot resolving in 30 s of Duel; both tests now pin what they claim. Unverified at this commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings gear-without-presence up to master ahead of landing it, with
eureka/aetheria-release-retire-longinusx following.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SimClock (engine-free) turns real frame seconds into whole fixed steps; ActionGameManager.Update feeds it outside the pause gate and Zone.Update(Time.deltaTime) is gone, with IntroCutscene (dead, Unity-driven pose writes). Entity.TurnRate is the sum of the rotation actuators' applied turn per sim second, zeroed each Update; DrawAhead reads it so EntityInstance and ShipInstance draw the latest sim state ahead by Lead. Unverified at this commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first commit's new fact built a second Faction and Game() requires exactly
one; that commit's ALotsProductSurvivesTheRunSave failed (1004 of 1005 passed).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brand no longer re-derives the product from maker and design (key-first pick);
CreateLot(product) is the one writer of Lot.Product. The census duplicate-brand
block and the key-order tie-break test go with the derivation they policed.
Unverified at this commit; build and tests follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entity.UpdatePerformance sets ThermalOnline only when performance exceeds EntitySettings.ShutdownPerformance.
A weapon at 0.006 performance at a hull's starting temperature passed the old "> 0" test but could never fire.
The threshold is read from production (new EntitySettings().ShutdownPerformance).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kills the five Stryker survivors of the first pass on LoadoutGenerator.cs
availability and preference. Tests only; builds against the prior commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>