Compare commits

...
Sign in to create a new pull request.
Author SHA1 Message Date
soul
a4be037a42 LFS lives on the Eureka forge: .lfsconfig points every clone at it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 03:12:31 +01:00
soul
152b9251a9 Research: release pipeline prior art (Unity CI, Personal licensing, Forgejo runners and releases, versioning tools)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:00:49 +01:00
soul
01bed8d447 AetheriaBuild: -aetheriaTarget win64|linux64, one entry point for both players
The target names the Unity player, its executable and the runtime AetherDb is published for.
Without the argument it builds win64 as before. Built 0.2.0 for both targets on Starfire
(Linux cross-built with Mono); both stop at the aetherdb step, because Aetheria compiles
CultMath from two CultLib pins and dotnet publish refuses the duplicated shader files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:51:42 +01:00
soul
3f3c59e27d Dithered Particles: a Deferred pass, so particles reach the depth texture the nebula fogs by
The shader dithered and wrote depth, but its one pass had no LightMode, so under the deferred
camera it drew in the forward pass, after the depth texture is taken from the G-buffer. The
nebula march read no depth there and fogged straight over every dithered particle (missile
trails, explosions, lasers, guns). Same cause and cure as Stardust (2e9d97661): black,
unreflective and emissive in the G-buffer. The colour pass is now ForwardBase only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 11:18:37 +01:00
soul
36d9d94e81 fly: unbind the ship you leave, so its death is no longer yours
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 10:29:13 +01:00
soul
26daac398a Console command "fly <hull>": a fitted ship beside the current one, and you in it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 10:20:44 +01:00
soul
f3927e24db Pin a docked ship to its parent before the inactive return; no flight while docked
Docking deactivates the ship, and Entity.Update returned before the parent pin, so a docked ship
kept integrating its own velocity and gravity (Ship.Update) for as long as it sat in the bay, and
undocked wherever it had fallen to at whatever speed it had reached. Drag used to bleed that
off; with no drag below top speed it flung the ship into the void.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 10:18:20 +01:00
soul
7a3c0c8fb8 Aim at infinity along the view's pitch; delete the terrain intersection
The horizon fault was the level XZ projection, not the distance (operator, 2026-10-29). The untargeted look point is 10000 along the aim again, so the camera no longer jumps where the view ray crosses a terrain discontinuity; group aim points and crosshairs lift each planar firing bearing by the aim's pitch. Reverts the surface march of aba02182b and the field-height crosshair of a9bbea509.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:45:37 +01:00
soul
ffdba39ac2 ThrustScale scales a thruster's push only; turning keeps authored strength
The 10x nerf reached yaw through Torque * thrust and made turning painfully slow (operator, 2026-10-29). Column and Execute apply the scale to the push; Thrust and NominalThrust read the authored stat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:39:18 +01:00
soul
845f6c3aad No drag below top speed: ships coast and orbits no longer decay; drag acts only on the excess over the hull's top speed
Carries out aetheria-gravity:ruling:no-drag-below-top-speed (2026-10-14), which the code never implemented (operator, 2026-10-29). The VelocityLimit clamp still caps speed; the soft cap is the ruling's remaining half.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:33:26 +01:00
soul
e0c1daa4ec Thrust is a tenth of authored, the ratio gravity fell by; ThrustScale and DragScale are global flight tuning in GameplaySettings
Most ships cannot climb straight out of a well and use orbits; an overspecced hull like the Longinus still can (operator direction, 2026-10-29). DragScale defaults to 1, unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:30:48 +01:00
soul
c6f7e0c8a4 Player turn input is banded by thruster: each band of equal yaw-to-translation ratio fills an equal share of the turn axis
The allocator already serves a turn by the best-ratio thrusters first; the axis was a fraction of total yaw, so a hull whose best-ratio pair holds little of it (the Longinus's front pair) saturated them in the first tenth of input and lurched on its drives. Ship.BandedTurn maps the player's axis so each band joins over an equal share of travel; full input is still full yaw. AI and the allocator are unchanged (operator request, 2026-10-29).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:22:04 +01:00
soul
633ae3353a Keyboard turning ramps down on release at the same rate it ramps up, so tapping at a rate holds a gentle turn; reversal still cuts to zero
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:09:29 +01:00
soul
5e2a9efc8a Keyboard turning ramps to full over KeyboardTurnRampTime (0.4 s) so a tap feathers the turn; analog turn passes straight through
Release or reversal starts the ramp again from zero (operator request, 2026-10-29: the Longinus lurches).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:07:30 +01:00
soul
562ba5c8eb Default weapon-group binding runs once per ship, on its first use; after that the action bar is the player's
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:01:29 +01:00
soul
c4911a4c96 Action bar binds weapon groups by default: mouse left/right/middle fire groups 1-3, number key N fires group N
Only slots the input settings define, only groups with weapons, and never over gear or consumables the player placed. Runs on binding to a ship and after a save's bindings restore. Replaces a lazy Zip that never ran (operator request, 2026-10-29).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 07:57:42 +01:00
soul
2e9d97661c Stardust draws into the G-buffer so the nebula fog attenuates it by depth
At BeforeImageEffectsOpaque the dust was drawn after the depth texture the nebula march reads, so the fog treated dust pixels as far background and wiped them out (operator report, 2026-10-29). A Deferred pass writes black, unreflective, emissive G-buffer texels and depth at AfterGBuffer. FlowFieldSceneVerify still expects the old event and needs updating.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 07:47:20 +01:00
soul
aba02182b7 Untargeted aim lands where the view ray meets the field, not 10000 out at the horizon; weapon-group aim points ride the field
With no target the look point sat 10000 along the camera direction, so crosshairs and shot visuals aimed at the horizon (operator report, 2026-10-29).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 07:44:56 +01:00
soul
a9bbea5091 Weapon crosshairs ride the gravity field: the aim point takes its own field height, not the ship's level plane
On a slope the level projection floated over downhill aim and sank into uphill aim (operator report, 2026-10-29).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 07:33:28 +01:00
soul
293e3a33fd Research: hyperbolic in-between space (H2 rendering, motion and precision, curved Kepler, HyperRogue scaffolding, getting lost, Aetheria's Euclidean gravity body)
Serves the operator's musing on hyperbolic inter-zone travel, 2026-10-28.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:22:25 +01:00
soul
257a34939e Delete Vault/: a stale 2025 copy of the lore; the live lore is GameCult/AetheriaLore
The copy had drifted far behind (no Megiddo or Wavecrafters pages) and an agent
edited it as if it were canon on 2026-10-28.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:36:54 +01:00
soul
6e5be44613 Revert lore merge 28c076b1e: it edited the stale Vault copy in this repo; the live lore is GameCult/AetheriaLore
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:35:25 +01:00
soul
28c076b1e6 Merge lore: cognition-anchored aether, ARI spectrum, Megiddo doctrine (operator direction 2026-10-28)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:29:16 +01:00
soul
c4a2ce36be Lore: the aether is anchored by its residents' cognition; ARIs are a spectrum; Megiddo's doctrine
Aether gains what the field answers to (consensus, load-bearing belief, a self not
compute, unopposed small effects, density, attention). Necrotech gains the ARI
spectrum from factory stamps to bound espers. Megiddo gets a page: right about the
mechanism, wrong that there is a way back. Pseudospace ties flatness to consensus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 06:29:08 +01:00
soul
8fa1fc21b2 Merge one exit per region: after boss placement each boss zone keeps only its exit-path link into the far side; distances recomputed before faction homes; saves load the borders they stored (aetheria-living-world). Soul held s1 and s2; Unity batch compile clean on Starfire at 2822a583e.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 21:33:40 +01:00
soul
2822a583ea Pin CrossingLinks far-zone ordering and a boss zone at the start of the exit path in hand-built graphs (cut one-exit, finding pure-helper-survivors)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:24:02 +01:00
soul
97aa371872 Provinces.ExtraExits throws when a boss zone has no exit-path link to keep instead of silently keeping every link (cut one-exit, finding silent-keep-all-fallback)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:23:47 +01:00
soul
9fd0fe96e7 One-exit tests require every sector seed to build; a generator exception fails instead of skipping the seed (cut one-exit, finding trybuild-masks-generator-crash)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 20:23:32 +01:00
soul
0182570200 DistancesAreOfTheFinalGraph builds its own galaxies so the pruning's distance recompute is under its coverage (cut one-exit)
Stryker's per-test coverage credited the shared galaxy cache's first builder
alone with Galaxy.OneExitPerRegion's CalculateDistanceMatrix call, so deleting
the call survived. Fixture fix, no rule change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 18:50:45 +01:00
soul
84acc9e563 Galaxy.OneExitPerRegion: sector generation prunes each boss zone's extra exits, then recomputes distances (cut one-exit)
Ruling one-exit-per-region: one exit to defend per region. Called once in
PlaceFactionsMain after the boss loop and before home placement; BuildProvinces
and the pruning share ZoneGraph. Saves and the prelude never prune. Tests pin the
rule on sector seeds 1-60, the pure helpers on hand-built graphs, and save/load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:28:09 +01:00
soul
5df9960343 Provinces.ExtraExits: the crossing links to prune so a boss zone keeps the one on the exit path (cut one-exit)
Pure. Reads CrossingLinks; nothing calls it yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:28:08 +01:00
soul
4f93c0de68 Provinces.CrossingLinks: one definition of a boss zone's crossing link, Regions reads it (cut one-exit)
Moves Regions' inline exit-side loop into a public CrossingLinks so the
pruning that follows reads the same definition. Behaviour unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:25:19 +01:00
soul
bef6a90f58 Merge ore geography: provinces inside boss-bounded regions, region decks deal province types, field kinds and yield read the province (aetheria-living-world). Unity batch compile clean on Starfire at the merge; Soul held.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 17:11:49 +01:00
soul
674baa95ae Merge eureka/aetheria-living-world-economy-model: living-world Body map, economy section
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 12:16:36 +01:00
soul
3e98238cf0 Living-world map: the economy's catalog records, owners and checks after recipe role inputs
Owner, inputs, outputs, derived state, forbidden writers, shared paths and
verification layer for RecipeData, Recipes.RoleInputsOf/Fillers and
EconomyChecks, read at 30030af6e. Notes the two stores of a recipe's role
slots behind one reader, filler choice at production time as unowned, and
stale docs: the target prose is not on master and target r2's L-recipe
wording predates intermediate role inputs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 12:16:07 +01:00
soul
30030af6e4 Merge eureka/aetheria-living-world-recipe-role-inputs: recipes take role inputs any filler satisfies; offered designs demand their roles
Soul s1 (aetheria-living-world:verdict:cut-recipe-role-inputs.s1) holds all five promises; its two Medium findings are pre-existing test races, deferred to their follow-ups. Suite 2867/0 at e93f53166; shipped report 146 faults (consumer demand: Ballistic Powder, Nitric Acid, Nitrocellulose, Potassium Nitrate). Unity compile not yet run; it rides with the ore-geography compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 12:11:20 +01:00
soul
e93f531669 Economy tests: a null list beside RoleInputs does not drop them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:44:30 +01:00
soul
1efd8343da Economy tests: pin the survivors of the diff (null RoleInputs keeps the rest, key-ordered recipe-less designs, unoffered recipe designs name roles, mixed takes line)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 11:30:14 +01:00
soul
ccd9792d2f Economy tests: role inputs persist, are read by every rule as any filler, offered recipe-less designs demand their roles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:56:21 +01:00
soul
3fb5e0e0e6 Economy: RecipeData.RoleInputs, Recipes.RoleInputsOf as the one reader of role slots, checks read a role input as any filler and offered recipe-less designs as demanding their roles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:56:01 +01:00
soul
1ed3579025 Merge eureka/aetheria-living-world-economy-checks: consumer demand from shared uses, a weapon's draw is a sink, upkeep walked, economy command tail
Soul s1 (aetheria-living-world:verdict:cut-economy-checks.s1) holds; s2 holds the fixes except one Low (dry-run test cannot see apply), filed as a follow-up. Suite 2848/0 at dc4838bd9; shipped report 144 faults, consumer demand nitric-acid only. Unity compile not run (no Unity-side change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:29:05 +01:00
soul
dc4838bd9e Economy checks: upkeep walk test gets a control case and a baseline that is actually shared
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:07:40 +01:00
soul
3c3ecd40da AetherDb economy: pin Run's report and author dry-run branches on the shipped catalog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:06:17 +01:00
soul
da067a34a2 Economy checks: the consumer walk follows upkeep edges; pin upkeep into a consumer good and a role filler
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:06:15 +01:00
soul
6ba77aafe7 OreGeographyTests: restore the file the previous commit replaced with a stale copy; the three sector-galaxy tests and their helpers on top of the guard test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:00:42 +01:00
soul
154b71160d OreGeographyTests: a multi-region sector galaxy's provinces survive save and continue and re-derive from an older save
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 09:59:24 +01:00
soul
4b7e5476c0 FieldKinds.Assign: a kind needs a positive kind weight and a positive province factor; two negatives no longer draw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 09:59:15 +01:00
soul
8e6fd43d23 Economy checks: ConsumerDemand tests recipes, not keys; pin upkeep reached through a chain
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 09:32:13 +01:00
soul
8d23a378d6 Economy checks: gearRoles reads roles of non-commodity recipes; pin use order and batch list
Mutation testing found IsRoleRecipe redundant in the gear-role set (RolesOf is empty for a
design without roles) and the message's use order, join and the unknown-batch count unpinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 09:19:00 +01:00
soul
1db250fb10 OreGeographyTests: the duplicate-listing fixture's yield-only kind is never drawn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 08:55:07 +01:00
soul
8774bd8a97 OreGeographyTests: pin seed order, tie-breaks, duplicate listings, deal key order, kept and saved first-load kind
Kills the survivors of the first Stryker run on FieldKinds and Provinces that were not equivalent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 08:50:01 +01:00
soul
c81a83ef2c OreGeographyTests: regions, partition, deal, yields, belts, save
Not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 06:43:00 +01:00
soul
4848c5332f Ore geography: yields, provinces cut inside boss-zone regions, types dealt per region
FieldYield and FieldKindData.Yields (key 3), ProvinceData, FieldKinds.Pick/Assign/Ensure/Yield
with a province type, Provinces.Regions/Partition/Deal, Galaxy.Provinces built once by the
generation and save constructors, SavedGame key 15 and SavedZone key 6, ProvinceZones setting.
Not yet built or run; tests follow in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 06:42:58 +01:00
soul
d92d77483f Retire BodyData.Resources key 4 and the commented ResourceValue
No reader or writer remains; FieldKinds.Yield (this cut) is the owner of a belt's yield.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 06:34:12 +01:00
soul
b375cfc8ec Research: ore geology and regional resources prior art (Dwarf Fortress, EVE, Elite/X4/Starsector, real asteroid taxonomy), for ruling ores-are-regional
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 05:11:18 +01:00
soul
26bea2cb14 AetherDb economy: unknown batch names are not echoed; held-cycle rise is relative
Run takes the output writer like Report and Author do. The unknown-batch refusal says how
many names matched no batch and lists the compiled batches. Introduced compares a held
cycle's radius relatively with RiseNoise = 1e-12, replacing the bare absolute 1e-9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 04:38:08 +01:00
soul
7df0a0943f Economy checks: consumer demand derived from shared uses; a weapon's draw is a sink
ConsumerDemand drops the two-or-three-step window (rulings consumer-demand-shared-only,
consumer-demand-skips-final-assemblies): a processed good owes a consumer use when it is
shared, derived from the recipe graph each check. A weapon's draw of a round is one use
(ruling draw-is-one-use). SourceSink counts a drawn commodity as sunk. Drawn is the one
reader of offered designs' WeaponData.AmmoType. Tests are unrun at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 04:38:05 +01:00
soul
c6a49e5568 Merge eureka/aetheria-living-world-economy-content-b1: economy batch 1 (Zhestokost munitions) applied; one owner of drawable station hulls
Operator approved the batch (aetheria-living-world:ruling:batch-1-munitions-approved). Soul s2 holds; suite 2836/0 at the merged head; catalog LFS oid 68b37cb5 on GitHub and the Yggdrasil cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:09:35 +02:00
soul
dd1031ce6a StationKindTests: a maker-less or Price 0 station hull is unreachable by the draw; the stand-in check is exercised on Zhestokost
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 18:16:48 +02:00
soul
b481363b9b StationKinds.HullKindFor takes a stand-in's kind only when some maker offers it
The any-maker fallback in Choose could seat a faction on a kind it has a dead stand-in for; the hull draw then looked for the dead stand-in's kind and returned
null. A stand-in no maker offers is no longer followed, so a kind Choose places is a kind the hull draw can fill. FieldableKindsOf reads the same two helpers.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 18:04:24 +02:00
soul
e3824360aa StationKindTests: stand-ins judged from the catalog, zones test against an oracle, the partial and fallback-spread cases pinned
Deletes the name-keyed AwaitingFirstModel exemption: AssertStandInsLive derives liveness from the sold hulls (live exactly when some maker sells the
target kind; otherwise the kind leaves the pool and the any-maker fallback is observed in the log). GeneratedZonesPlaceStationsByKind checks against
a records-level oracle and asserts the fallback case. New: a kind is kept exactly when a hull of it can be drawn (Price 0, no maker), a faction with
one fieldable and one unfieldable kind places only the first, the fallback spreads over every offered kind.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 18:02:48 +02:00
soul
e403905e12 LoadoutGenerator.IsDrawable is the one definition of 'a maker offers this design'; StationKinds keeps a kind by it
AvailableProducts (Price > 0, a set Manufacturer, offered) and StationKinds.OfferedKinds (offered only) disagreed, so Choose could keep a kind
whose hull draw returns null. Both now ask IsDrawable; OfferedKinds and OfferedStationHulls read the same drawable station products.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 18:02:47 +02:00
soul
78b176a0ff Merge remote-tracking branch 'origin/master' into eureka/aetheria-living-world-economy-content-b1 2026-10-23 17:58:47 +02:00
soul
d5c0063b7e CommodityRecordsTests: the compound commodity count follows the batch (51 to 63)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 17:29:50 +02:00
soul
b1b5031e4b Economy batch 1 (munitions): apply Munitions to the shipped catalog; re-pin what the catalog stales
economy author Munitions apply: 49 added, 4 changed. The pins that name the shipped catalog's contents follow it: the kind list gains
munitions-works, the simple commodity count, the retirement check counts only its own stand-in, the stand-in liveness check exempts
a faction awaiting its first station model (Zhestokost), and generated stations draw from the fieldable kinds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 17:23:26 +02:00
soul
fce8c66284 StationKinds: FieldableKindsOf is the pool Choose draws from
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 17:23:24 +02:00
soul
fe7ea72c9b StationKinds.Choose: a kind the faction places but no maker can field leaves its pool and falls back to any maker
A stand-in whose hull kind no offered station hull carries (Zhestokost's depot, whose model has not landed) used to leave the
tutorial entrance with no station. The existing no-kinds fallback now covers it: one rule, no faction special case.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 17:20:04 +02:00
soul
37677c4893 Research: recipe-graph structure in factory games (shared vs single-use intermediates)
Prior art for aetheria-living-world❓consumer-demand-gear-specific-intermediates: Factorio 1.1 and Space Age, Dyson Sphere Program, Satisfactory, No Man's Sky.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:05:31 +02:00
soul
722e618cac Merge eureka/aetheria-arena-sim-rate h7: Combat releases every held weapon it no longer commands, beams and locks included
Soul pass 5 (aetheria-arena:verdict:cut-sim-rate.s5) holds all five promises. Unity compile and feel unproven.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 16:00:00 +02:00
soul
9b56bf0136 Digest pin comment names both causes of the h6 repin
The candidate-predicate change and the release sweep each move the digest alone (b559789a, d9493bbe); releasing beams and locks
moves nothing.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 15:31:43 +02:00
soul
780e68be71 Combat lets go of every held weapon it no longer commands: beams and locks, not only AutoWeapons; its end releases a same-step pull
One sweep over what is held (Firing, or pulled this step): released when uncommanded, and on exit regardless of
command. Tests through Minion and Zone.Update for a beam, direct for a lock, the not-the-pick group, the cooling
candidate clause by gun kind, the same-step pull on exit, and PilotCommand.Commands.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 15:25:11 +02:00
soul
8ca5425fcc Merge eureka/aetheria-arena-sim-rate h6: the AI releases a held automatic gun it no longer commands
Soul pass 4 (aetheria-arena:verdict:cut-sim-rate.s4) holds all three promises; suite 2822/2822 on Yggdrasil. Unity compile and feel unproven.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 15:21:21 +02:00
soul
163bdf9b79 Test: Combat releases a held AutoWeapon whose target moves out of reach
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:46:37 +02:00
soul
3715c9edf0 Repin the two-AI digest once: Combat releases a held AutoWeapon it no longer commands
Measured 85e85c46 on linux-x64 (55ecd858 before), on two full runs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:39:43 +02:00
soul
d4bec37c6a Combat's release sweep leaves a weapon it already commanded alone: PilotCommand.Commands
One command per weapon per step: the sweep released a gun the group loop had already released.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:34:18 +02:00
soul
d2c293b799 Test: the semi-auto floor is the 0.1 s constant, not a multiple of the step
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:27:54 +02:00
soul
65b0e00cd6 Test: a behaviour created from a consumable AutoWeaponData honours Automatic
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:27:53 +02:00
soul
848ff83cd7 Combat releases a held AutoWeapon it no longer pulls: no target, no track, other group, exit
The weapon holds a down trigger; Combat's early returns issued no release and had no exit hook, so a held
Slug Rifle, Autocannon or Flak Gun fired on at nothing. Combat is the one owner of the AI's trigger level:
every held AutoWeapon it does not pull this step is released. A held gun stays a group candidate between
rounds so cooling does not drop it. Tests run through Minion/Combat.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 13:27:52 +02:00
soul
5177154c17 Economy batch 1: Zhestokost munitions chain (unapplied, for operator review)
Dry run on the composed catalog: zero shape faults introduced; 49 records
added, 4 changed. Review page published separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:45:20 +02:00
soul
bd7cf4b5d4 Merge eureka/aetheria-living-world-economy-authoring-command: AetherDb economy author and report; the batch gate refuses every shape fault a batch introduces
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 07:23:04 +02:00
soul
dd7f40b559 Merge origin/master into economy authoring command
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 07:16:44 +02:00
soul
6befccce74 Economy command: L-productive is one fault per unproductive component; a held-open catalog is a named refusal at the first read too
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 07:15:59 +02:00
soul
ae3e4a7c58 Economy command tests: a held cycle whose radius falls still applies
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:48:22 +02:00
soul
fe7c5226cc Economy command tests: a cycle that moves to a lower radius is still a changed membership
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:43:56 +02:00
soul
2da2afd468 Economy command: refuse a read-only catalog before the trial; the trial copy is writable
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:38:50 +02:00
soul
f403485dc0 Economy command tests: the summary line counts removals
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:36:54 +02:00
soul
e5099c0363 Economy command: escape the refusal line breaks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:32:52 +02:00
soul
ade0b0fbf3 Merge eureka/aetheria-arena-sim-rate: the game ticks at 30 Hz; one owner of the rate; timers carry overshoot; guns fire every round their cooldown allows; plain guns are semi-auto
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 06:31:10 +02:00
soul
352a94fe21 Economy command: faults keyed by rule, record and message; L-productive by cycle members with a rising radius refused; removals listed, counted and applied; pending only for the recipe-less; swap failures named, read-only refused, file mode kept
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:28:20 +02:00
soul
a90ec3d450 Economy command tests: fault identity by rule/record/message, cycle members and radius, removals listed and counted, pending only for the recipe-less, swap failure and file mode (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:27:54 +02:00
soul
9036d39f30 Two-AI digest repinned once for arrival-order application (commits of a step precede its applies)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:22:01 +02:00
soul
62a641bf15 Catalog: Slug Rifle and Long Slug Rifle are AutoWeapons (auto-guns apply on master's catalog)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:12:57 +02:00
soul
1f7b971966 Fire mode is one property of a weapon's data (Automatic): creation and the semi-auto floor read it, the floor holds guided, mine, launcher and charged kinds and consumables; a step's rounds apply in arrival order, ties by shot id
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:12:55 +02:00
soul
e92c2140b4 SemiAutoCatalogTests: the shipped catalog holds no plain gun, only guns
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:10:07 +02:00
soul
d3da985290 Fire mode is the design: Slug Rifle and Long Slug Rifle are AutoWeapons; tap and hold tests for both kinds at 15, 30 and 60 Hz; the semi-auto cooldown check
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:10:06 +02:00
soul
5367c899a6 auto-guns: copy the plain gun's fields
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:53 +02:00
soul
35ef321ff3 A plain InstantWeapon is semi-automatic; AutoWeapon repeats while held; the shortest semi-auto cooldown is a named constant with a catalog check; auto-guns command
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:52 +02:00
soul
0d8457bc34 SignatureTests: only a gun is tapped; a beam burns while its trigger is held
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:46 +02:00
soul
1aceaa576d Two-AI digest repinned once for resolving a step's rounds in fire-time order (the trigger change alone moves nothing)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:45 +02:00
soul
43042177d6 Tests that press a trigger once release it: a held trigger keeps firing now
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:44 +02:00
soul
46912a20c8 A trigger is the weapon's own state: a tap fires one burst and a held trigger fires its cooldown's rounds at any tick; a step resolves its rounds in fire-time order; the idle-clamp test really idles
InstantWeapon repeats while its trigger is down (Activate to Deactivate), not when it was pulled this step; AutoWeapon's override of that is gone. FireControl keeps the shot queue in fire-time order (ties by shot id) and Step walks it oldest first.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:43 +02:00
soul
37a7bb76f7 Scenario tests step the arena at SimClock.GameStep, the rate the game runs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:42 +02:00
soul
99f5820565 SimRateTests: a zero cooldown ends its step 2026-10-23 06:09:41 +02:00
soul
2b09e87733 SimRateTests: rounds leave from the shooter's pose at their moment; a zero cooldown fires at the shortest cycle 2026-10-23 06:09:40 +02:00
soul
aeac4e2958 SimRateEquivalence: survivor hull and first kill are held to the 95% interval of their difference, as the win rate is 2026-10-23 06:09:39 +02:00
soul
b679a38edc Two-AI digest repinned once for rounds-per-step; the step-cost test measures a round's birth with the shot queue grown 2026-10-23 06:09:36 +02:00
soul
7c9a970c81 Economy command: drop the untested second fingerprint check before the swap
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:35 +02:00
soul
c1f9c05c48 Entity.GetBehavior walks Equipment by index: the per-round targeting-system reads no longer allocate an enumerator 2026-10-23 06:09:35 +02:00
soul
b1380204a3 SimRateTests: split the step cost into a round's birth and its resolution 2026-10-23 06:09:34 +02:00
soul
d038ee393a SimRateTests: the fixture gun's round costs what the fixture reactor can pay at 0.01 s 2026-10-23 06:09:32 +02:00
soul
a1519c9b2b diag (temporary) 2026-10-23 06:09:31 +02:00
soul
c00be8b35c SimRateTests: probe the fast-gun capacitor on failure 2026-10-23 06:09:30 +02:00
soul
93f69ecb80 Rounds per step: a held weapon asks the bus for its step's whole inflow; mine-laying test cooldown stays inside one activation's two steps
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:29 +02:00
soul
1870e23bfd Rounds per step: a gun's capacitor holds a step's inflow so every round of the step is paid; the mine-laying test's cooldown no longer pins the one-lay-per-step cap
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:28 +02:00
soul
04128e2f81 InstantWeapon: a pull is held through its step 2026-10-23 06:09:26 +02:00
soul
3b466f8c9b SimRateTests: step-cost test compiles 2026-10-23 06:09:25 +02:00
soul
de9e1ba2f9 Projectile: a round is told of its shot by its manager's one subscription, and first seen where its barrel was when the sim fired it inside the step
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:24 +02:00
soul
95b7aeb7a2 Rounds per step: a held gun fires every round its cooldown allows in a step, each born at its own moment inside it; the shortest-timer pin is gone
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:22 +02:00
soul
3d4508d196 ChargedWeapon: a failed charge's cooldown restarts through InstantWeapon.StartCountdown and carries its overshoot
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:21 +02:00
soul
5adaef4697 Two-AI digest repinned once at the game step (step-exact rules, 30 Hz); shortest-timer test pins the four guns authored below two steps
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:20 +02:00
soul
ed5dd92283 Game tick lowered to 30 Hz (ruling tick-rate-stays-30); digest repin follows
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:19 +02:00
soul
48ba0a6204 SimRateTests: idle banking, magazine cadence, glowing passive target; equivalence and shortest-timer tests; ping-arm trace repinned for the exact decay
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:18 +02:00
soul
549437536a Cooldowns shorter than a step end in it; tests that pinned the old tick-quantised cadence and Euler decay follow the exact rules
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:17 +02:00
soul
b9e0e5b5eb SimRateTests: whole-step counts by MathF.Round
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:15 +02:00
soul
f0362025d9 Step-exact rules: timers keep their overshoot, passive sensing decays exactly (group B, 60 Hz, digest not repinned)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:14 +02:00
soul
e2f0fc9dc4 SimClock owns the game tick: TickRate, GameStep, ForGame(); the 60 default and ActionGameManager's literal step are gone
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:12 +02:00
soul
a19d0eb73b Arena: sim-rate map and target section 7 (sim rate cut, step part of A-pure)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:09:11 +02:00
soul
7f3b06222d Economy command: run the batches once on the trial, check that copy, replace Aetheria.cc with it atomically; refuse introduced shape faults by rule and record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:03:44 +02:00
soul
dc69f5dc5b Economy command: run the batches once on the trial, check that copy, replace Aetheria.cc with it atomically; refuse introduced shape faults by rule and record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:03:29 +02:00
soul
3092ce81cd Economy checks: null outside-market Rows or row and a null Fills entry are L-recipe faults; a missing recipe is marked pending
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:02:06 +02:00
soul
98aef507f1 Economy command tests: a later batch closing a cycle, in-place edit, one run, real-catalog write, throwing batch, null market rows and Fills (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 06:01:59 +02:00
soul
0394e33ed8 Economy command tests: pin the printed report, the written set and the trial cleanup (Stryker survivors)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:40:51 +02:00
soul
b31595add2 Economy command tests: an edit naming two items is refused (kills the ambiguity mutant)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:36:28 +02:00
soul
7367f21c8a AetherDb economy: report and author, dry-run gated by the catalog checks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:28:42 +02:00
soul
b4510d5737 EconomyChecks: the key check reads the record key, not the cache's reference to a sound copy
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:27:50 +02:00
soul
94a14b8dec Economy command: contract and tests, skeleton throws (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:26:47 +02:00
soul
dccac5047d EconomyChecks: a recipe with a null list or entry is an L-recipe fault; every other rule reads it as empty
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:25:24 +02:00
soul
88a36fff4e Economy null guards: a recipe with a null list is an L-recipe fault, not a throw (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 05:25:13 +02:00
soul
a487f6c0a4 Merge eureka/aetheria-living-world-recipe-schema-and-checks: recipe and outside-market records; catalog checks for sources and sinks, productivity, recipes, lore and consumer demand
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 05:21:37 +02:00
soul
e2e01b2266 Merge eureka/aetheria-release-nakovalnya-boss-loadout: Zhestokost's demo boss is the Nakovalnya Boss loadout
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 05:15:41 +02:00
soul
084c77fb12 Boss loadout tests: shipped catalog now holds the demo boss; tests that wrote their own loadouts count only those
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 04:38:27 +02:00
soul
79caa8b32d Zhestokost boss: the Nakovalnya Boss Loadout, committed through loadout-commit --boss-of; RunGoal tests reach it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 04:32:46 +02:00
soul
5584c0d7c8 Merge eureka/aetheria-release-loadout-commit: AetherDb loadout-commit with --boss-of; Loadouts.Commit accepts package designs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	tools/AetherDb/Program.cs
2026-10-23 04:27:12 +02:00
soul
6b89019c02 Economy checks: an undefined radius refuses; factor refusal says why 2026-10-23 04:24:32 +02:00
soul
c6c8b4465b Economy checks: pins from mutation testing; drop two redundant guards 2026-10-23 04:14:42 +02:00
soul
cdee1a27f8 LoadoutTests: a commit over a loadout written after the read writes nothing (kills the dropped-Expect mutant)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 03:43:55 +02:00
soul
3506d48b1f Spectral radius: converge on the vector, not on two equal maxima 2026-10-23 02:50:57 +02:00
soul
91f9b5553c Economy fixture: keyed writes through UpsertAsync 2026-10-23 02:46:19 +02:00
soul
263fa02a73 EconomyFixture is public for the theory data 2026-10-23 02:45:24 +02:00
soul
bacb56c613 Recipe schema and catalog checks: RecipeData, OutsideMarketData, role counts, EconomyChecks over fixture catalogs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 02:43:35 +02:00
soul
d233194cb2 Merge eureka/aetheria-living-world-station-kind-datum: station kinds are one catalog list; stations and fields are placed by seed; bad station packages are excluded by name
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 02:14:33 +02:00
soul
0e50c1d101 RunGoalTests: a boss Loadout on a removed package's hull still boots and fails closed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:48:34 +02:00
soul
37de26291d AetherDb loadout-commit, with --boss-of, validated against the composed package stack
Ported and narrowed from 90f977bf (evidence only; no boss-hull code). Names resolve
exactly against ShipModCatalog.ResolveCatalog over GameData/Aetheria.cc and GameData/Mods,
composed into a scratch file, the catalog the game boots; validation is one
Loadouts.Materialize on a throwaway ItemManager; the commit goes into Aetheria.cc only,
through Loadouts.Commit, with --boss-of in the same batch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:48:33 +02:00
soul
48606e4253 Merge eureka/aetheria-release-scenario-picker: New Game is a two-pane scenario picker
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:44:07 +02:00
soul
f920cd7052 Revert the TextMesh Pro fallback font asset Unity re-serialised
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:43:04 +02:00
soul
2fb8e88fcf ScenarioPicker: find the list's ScrollRect while the panel is still inactive (play mode builds it before showing it); verify builds the real list inactive
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:43:03 +02:00
soul
9961a0df6d ScenarioPicker.Reveal: content moves against the row (the sign the first fix kept inverted)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:43:01 +02:00
soul
ca24a32028 ScenarioPicker: Reveal moves the content the right way; Launch is one-shot; the scrollbar takes no focus; the picker holds focus itself so the scene's background-click deselect is back on
ScenarioPickerVerify builds the real scenario list after a layout pass and arrows to every row, up and down, requiring each wholly visible; Launch by click, second click and Submit runs once.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:59 +02:00
soul
169679dbc4 ScenarioPicker: viewport span from the rect's own corners so FitViewport and Reveal see the real mask; Launch chrome stretched to its 220-wide button
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:58 +02:00
soul
585942259d Scenario picker attempt 2: body heading instead of a second giant title, small left group labels, chrome Launch in the accent, tight Seed/Ambient block, capped brief, visible scrollbar track
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:57 +02:00
soul
09de7e5eb2 ScenarioPicker: selected row in the menu accent, title is group over name, panes docked 128 apart; verify and capture run green in Unity; metas
The prefab row tint is nearly invisible on the row's graphic, the long scenario name overflowed a 480-wide title, and the list scrolls to keep the selection in view.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:56 +02:00
soul
79a3a62fc1 ScenarioPicker verify and capture: selection and key rules through real UI events, and a 1920x1080 render of the screen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:55 +02:00
soul
3bfac25027 New Game is a two-pane scenario picker: names by group, selected brief/seed/ambient, one Launch, arrows and Enter
MainMenu.AddScenarios and the per-scenario launching buttons are deleted; the seven Clear+Title pairs collapse into Next. The main menu EventSystem no longer deselects on background click so the arrows keep working.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:42:54 +02:00
soul
80283d18a9 Loadouts.Commit takes bossOf: the Loadout and Faction.BossLoadout land in one batch
With bossOf set, the same conditional batch Expects the faction unchanged and Upserts it
with BossLoadout = KeyOf(Name), so both land or neither does. The batch lives in an
internal overload over a caller's cache; tests pin that a faction changed on disk after
the read refuses both, and that a missing boss faction writes nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:42:50 +02:00
soul
7f1337167d Loadouts.Commit stops refusing package designs (ruling catalog-is-a-package-stack)
The catalog is a stack of packages, the shipped content included, so a Loadout may
name any design the stack holds. The mod-design refusal (from 54917bb3, backed by no
ruling) is deleted, and its test now pins that a package design commits under its key.
The IsModKey comment no longer claims the shipped catalog never references a mod.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:42:49 +02:00
soul
bd628de3bf Merge eureka/aetheria-release-cultlib-2-0-adopt: Aetheria on CultLib 2.0.1 and CultMath 0.5.0; LockWeaponData is a BehaviorData arm; 1.0.x saves open
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:41:50 +02:00
soul
02d60691dc Same-seed belt test: fixed kind keys through a batch
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:37:40 +02:00
soul
b1ca2ead90 Same-seed tests: authored kind keys are fixed; the station sample spans eight zones
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:32:34 +02:00
soul
d9bc465355 Packages: lock regenerated by Unity at cultlib-unity-v2.0.1 (b8fc5eb0)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 01:26:14 +02:00
soul
4918fcd993 AetherDb is disposable: it owns the cache it opened
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:26:00 +02:00
soul
b878734158 station-kinds hull: the dry-run and applied lines are one line each
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:23:59 +02:00
soul
d2f4b2c347 A bad package station kind excludes the package; AetherDb opens a catalog with a kindless station hull, names it, and station-kinds hull sets it; the raw opener is gone
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:21:04 +02:00
soul
37a8110907 Station and belt kinds are seeded: the pick hashes the zone seed and the place in generation order, not a minted key
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:21:02 +02:00
soul
17e2da0092 AetherDb tests: a kindless station hull does not lock the tool out; station-kinds sets a hull's kind (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:18:21 +02:00
soul
d55ac30905 Station kinds tests: a bad package kind is excluded not fatal, same seed gives the same station and belt kinds, the stand-in check can fail (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:18:20 +02:00
soul
ea3e983aa2 StationKindsCatalog: OpenCatalog takes a path; tests pin Zenith's kind, the ids and the command's report 2026-10-23 01:16:22 +02:00
soul
0a468f24a8 Station kinds: tests pin the log text, a null faction, and one-hop stand-ins; kind strings default to null 2026-10-23 01:16:21 +02:00
soul
ac4b771f5e StationKindTests: worlds carry the run store zone generation writes orbits to 2026-10-23 01:16:20 +02:00
soul
353ca96b5e StationKindTests: the any-maker log is the hull draw's, not Choose's 2026-10-23 01:16:19 +02:00
soul
a7364ed13e GameData: 17 station kinds and Zenith as a trade-hub (station-kinds apply)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:16:17 +02:00
soul
fba7bd1b47 Station kinds: StationKindData catalog list, HullData.Kind, placed station Kind; GenerateStationLoadout takes a kind (the kindless draw is deleted)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 01:16:17 +02:00
soul
7886f0a231 ShipAuthoringStore.Load names the file when its store format is newer than this runtime reads
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:14 +02:00
soul
e045af344f Pins: cultlib-unity-v2.0.1 at b8fc5eb0 (1.0.x saves with ref lists open as compatible drift)
packages-lock.json follows from the Unity resolve. caching-unity stays at v2.0.0; cultmath at 7a8933b0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:12 +02:00
soul
da5ba653cb Tests (red at 42dce361): a CultLib 1.0.60 run.cc opens; Load names a ship file of a newer store format
tests/vectors/cultlib-1.0.60/run.cc is the run store Soul wrote with the base build (cl2-old-run-save-refused).
Both new tests fail at the 2.0.0 pin; the first needs 2.0.1, the second needs ShipAuthoringStore.Load.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:11 +02:00
soul
f448957f3a Brush: name AnimatedSimplexBrush and RadialWaveBrush as arms; pull-failure test asserts the record key
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:09 +02:00
soul
e518a0b3d1 packages-lock: regenerated by Unity at the 2.0.0 / 0.5.0 tags
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:08 +02:00
soul
fbf88e85c5 ship_cc.read owns its unreadable-path refusal, naming no path
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:07 +02:00
soul
fb8f2ea2fb ShipAuthoring: Load follows the pull's InvalidDataException, RefuseLegacyEmbeddedHull the nil-stamp NotSupportedException
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:05 +02:00
soul
bd0293d683 BehaviorData: LockWeaponData is arm 52; union-closure and null-gear tests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:04 +02:00
soul
1dce24a226 Pin CultLib 2.0.0 (42dce361) and CultMath 0.5.0 (7a8933b0): manifest tags and build revisions
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:03 +02:00
soul
8b0b50382a WeaponData: drop the dead [Union] list; BehaviorData's union owns behavior arms
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:35:01 +02:00
soul
00e60344ab Merge eureka/aetheria-release-cargo-store-owns-quantity: the cargo bay owns stack quantity; restore splits oversize stacks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 23:10:00 +02:00
soul
c986adcf20 Cargo restore tests: only the oversize stack's own bay is full, so the spill has another bay to go to
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:54:52 +02:00
soul
9958fe55ab Cargo purchase: a bay stack is one lot, so the lot loop is deleted; stock above MaxStack from outside a bay is refused up front
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:50:24 +02:00
soul
b027b36ab4 Cargo restore: a saved stack above MaxStack splits into MaxStack stacks, the same bay first, then the others; only what fits nowhere is dropped, logged
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:50:23 +02:00
soul
d66b2a2c3c Cargo restore tests: an oversize saved stack splits into MaxStack stacks and drops only what fits nowhere (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:49:22 +02:00
soul
fd50f02f1b Cargo purchase tests: a purchase of no units is refused, not bought
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:29:24 +02:00
soul
f7ba043b13 Cargo restore test: share the fixture's provenance ledger
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:21:08 +02:00
soul
fa5820f516 Cargo give: the bay no longer holds a stack below one, so the give's positive-stack filter and its zero-stack test go
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:15:41 +02:00
soul
ddae55759d Cargo bay owns stack quantity: TryStore refuses below 1 and above MaxStack, TryBuyLots owns the stock limit, restore logs dropped stacks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:01:42 +02:00
soul
ffe43b41e8 Cargo store tests: the empty-stock purchase test reaches the charge (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 22:01:39 +02:00
soul
708fbeee59 Cargo store tests: the bay owns stack quantity, purchases charge units moved, restore drops bad stacks (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:59:06 +02:00
soul
689dbfa9d0 Merge eureka/aetheria-release-cargo-quantity-guards: cargo moves refuse quantities below 1; purchases charge the lot delivered; a give ends when its giver leaves
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:55:02 +02:00
soul
4d462c771c Give: Zone.Remove ends the leaving giver's give GiverGone
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:10:09 +02:00
soul
f0d7c12cbd Trade: the purchase loop moves to StationServices.TryBuyLots, charging each lot it delivers; the Buy Quantity field clamps to at least one
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:10:07 +02:00
soul
f9a09e0d0a Cargo: TryTransferItem and Remove refuse a quantity below one and change nothing
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:10:04 +02:00
soul
66671cf036 Cargo tests: quantities below one, give routing and ends, purchase lots (red); soul-tv probes P4-P6, P9 adopted
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 21:09:30 +02:00
soul
7e2fff1ff1 Merge eureka/aetheria-release-transfer-verb: give-only ship-to-ship transfer; partial cargo moves conserve units
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:03:37 +02:00
soul
c37fbdb3b9 Cargo transfer tests: drop the two-bay receiver test; the fixture hulls take one bay
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 20:11:38 +02:00
soul
b43b238d6a Merge readme-front-door: README opens with value, problem, entry points, live versus planned 2026-10-22 20:10:22 +02:00
soul
1691f47cc6 README: front door with simulation entry points, demo in progress, directions and package hulls
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:09:53 +02:00
soul
00d34e5ab5 Cargo transfer tests: the second receiver bay is a one-cell bin
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 20:05:33 +02:00
soul
3f265b6c73 Cargo transfer tests: fill the one-cell bay the way the other fixtures fill a shape
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 19:59:19 +02:00
soul
dadb6f327d Cargo transfer tests: long steps after the receiver leaves or strays move nothing; a full first bay hands on to the next
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 19:56:54 +02:00
soul
0267a191c4 Merge eureka/aetheria-arena-view-seam: one PilotView per side; brains reach other ships only through their side's sensors; unaffiliated ships are sides of one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:50:35 +02:00
soul
488b3fa434 PilotView enforces its own rules: members only, fire-control readouts only on the member's own track; constructor and View setter internal
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:26:07 +02:00
soul
961bdafade Determinism ledger: the TwoAiDigestIsPinned comment names both causes of the second repin
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:26:03 +02:00
soul
d38ee7cdd6 Approach track-loss test: warm up before reading the follower's aim (the 60 km anchor is lost by the sensors)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:25:58 +02:00
soul
70aa1ed037 Transfer verb: drop the redundant pre-check, let range, step length and quantity edges show in tests
TryStore already takes all of a part or none, so the pre-check in TryTransferItem changed nothing observable.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:22:43 +02:00
soul
c40a6e8229 View seam tests: per-shooter aim, view gates, sees-hostile, honest track loss (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:21:12 +02:00
soul
19901c1a92 Merge eureka/aetheria-living-world-catalog-subtraction: DemandProfile and the commodity categories go
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:01:45 +02:00
soul
ae52857a91 SimpleCommodityData: name key 10 as the removed stored Category (Soul s1 simple-key10-comment-misnamed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 18:01:23 +02:00
soul
5b599f66bf Merge eureka/aetheria-release-kit-schematic: agent hulls get schematic lines from their kit; the Nakovalnya package lands
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 17:35:42 +02:00
soul
d3cd7813d7 Catalog subtraction: commodity records lose DemandProfile and both stored categories; the trade menu stops filtering by them
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 17:31:08 +02:00
soul
66c38d9506 Build asks for the marks part only when the kit drew lines (OpenSCAD refuses a part that draws nothing); hull_source documents marks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 17:17:40 +02:00
soul
8d58bca27a Nakovalnya: casemate guns and plate seams emit their lines from the frame that draws them; the copied offsets are gone (geometry and lines unchanged)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 17:11:38 +02:00
soul
98b4f4f946 Build checks that every kit line is drawn in the frame of its geometry: lp_line's marks part meets its lines part
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 17:11:35 +02:00
soul
71b12d594b Kit lines tests: a line drawn outside its geometry's frame fails Build; side-facing fittings emit no line (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 17:09:04 +02:00
soul
dab415ad87 Package: her art's takeover leaves no retired hull lines in the .cc (state decides the source; the slot is cleared)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:55:50 +02:00
soul
87dc0f013f Capture Ship Lines frames the ship as Package does, so kit and Grease Pencil lines land in ship.glb's frame
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:54:13 +02:00
soul
bb38036e51 Cargo transfer tests: build the second stack with a second store
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:54:12 +02:00
soul
2b053b34c2 Smoke: a retired hull's lines are not hers, and Capture writes the kit's lines in Package's frame (red)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:52:17 +02:00
soul
bcfc776513 Cargo transfer tests: two stacks of one design come from a commodity that stacks two to a stack
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:50:35 +02:00
soul
4e559d822e Cargo transfer tests: the second bay goes where the hull has room
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:46:35 +02:00
soul
c1aab929b1 Give verb: a stop is a verb with no receiver, and the type pattern skipped it; tests: second bay at a free cell
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:42:42 +02:00
soul
7ac8f38901 Cargo transfer tests: the give verb's rate, ends, instance choice and press order
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:38:18 +02:00
soul
cada2fde3e Transfer verb: a pilot gives cargo to a ship alongside, committed through the conserving bay move
TryTransferItem(SimpleCommodity) checks the target can take the part and stores the part removed, not the stack
left behind (it duplicated and lost units on every partial move, the player's commodity buy among them).
TryTransferItems goes. CargoTransfer.Step owns a give's progress and end; PilotCommand.Give and StopGiving are applied
by PilotApplier; TransferRate is the new tunable, DockingDistance the range.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:38:17 +02:00
soul
3fa4768d1c Cargo transfer tests: a partial commodity move duplicates the stack left behind (red), also through the buy path
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:31:18 +02:00
soul
c1d55952eb Smoke: Build records the kit lines and retiring the hull source deletes them
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:31:11 +02:00
soul
4a6ddaa413 hull_source tests: a non-UTF-8 byte in the drawing, an unreadable number
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:17:00 +02:00
soul
970155a8ac Nakovalnya package rebuilt through the add-on: schematic lines from the kit (silhouette plus 102 kit lines)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:12:17 +02:00
soul
0cb78d2610 hull_source tests: pin style, echo parts, contour area, even-odd and edge tolerance, process refusals, check details
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:11:53 +02:00
soul
b064051efd Retarget test: east is staged knowing the third ship (ruling retarget-test-stages-the-track)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:11:03 +02:00
soul
0350255237 PilotSeamTests: drop the probe text
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:07:35 +02:00
soul
fd1188a797 hull_source: the silhouette is the zones' top view, what Rasterise reads
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:06:59 +02:00
soul
66c69cdc90 Smoke: sideways-facing kit parts draw no lines (octagon and line counts of the Nakovalnya)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:06:19 +02:00
soul
1a2a24ceb1 Staged knowledge: repin the two-AI digest for fighters staged knowing each other; LockOnSituation drops the no-track premise
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:05:39 +02:00
soul
5bb4ad5f0f Smoke: the silhouette may be several contours, all before the kit's lines
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:02:53 +02:00
soul
d5d94fb483 Staged Approach: the pilot starts knowing its anchor, through the sensors' own info state (ruling stage-states-pilot-knowledge)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 16:00:08 +02:00
soul
905074defb Add-on: schematic lines are hers (one Grease Pencil) else Build's from the kit; smoke and C# fact
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:59:56 +02:00
soul
b982fb9cd0 hull_source: kit lines echo, SVG silhouette projector, SchematicLine, three line checks
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:57:44 +02:00
soul
5c38029ec0 Research: crafting chains and non-gear demand, prior art (serves follow-up crafting-chains-and-demand)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:56:21 +02:00
soul
63e71a1f30 PilotView tests: sides, tracks, handles, designation, fire-control readouts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:56:00 +02:00
soul
28ed24b28e Zhestokost kit and Nakovalnya emit schematic lines from their own frames (outline, step, seam, fitting)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:54:27 +02:00
soul
bd343b2a4e Kit frames: mates are lp_at placements that track the Ship Root frame; zone OFFs unchanged
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:53:20 +02:00
soul
a18d3b812f Merge Nakovalnya package head a67711b3 into kit-schematic
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:50:10 +02:00
soul
2ad52e7e9e PilotView: brains reach other ships only through their side's view, by opaque handles
One view per side over its members' sensors and books. Flight, Combat, Follow and Minion read contacts as ContactId
and fire-control readouts as view calls; FollowTask.Anchor is a handle. Own-ship reads stay direct.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:48:02 +02:00
soul
6252c29efa Determinism ledger: repin TwoAiDigestIsPinned for the side split (the fighters were one side and followed themselves)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:42:12 +02:00
soul
9b4b46e243 Zone: a side is a faction or one unaffiliated ship; each unaffiliated ship flies a flight of its own (brain-one-per-side-r2)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 15:39:02 +02:00
soul
33103ce5da Seam fix tests: a neutral declaration drops the target, so a second press in that step finds none, as before the seam
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:44:28 +02:00
soul
8692cf8600 Command seam: the stance press resolves its target at the step, after the step's target verbs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:39:46 +02:00
soul
2f15c79176 Seam fix tests: the stance press resolves its target at the step, flips the belief, and the ping press pings once (red)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 08:39:15 +02:00
soul
cfbd044551 Command seam fixes: drop the ping observation, which this fixture's uncharged sensor cannot show
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 06:29:02 +02:00
soul
87f29cb0c8 Command seam fixes: the ping pin waits for the ping's cooldown and charge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 06:18:32 +02:00
soul
a7477e679d Command seam fixes: the ping pin runs before any switch is thrown; a stance set is pinned as a set beside the flips
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 05:51:10 +02:00
soul
72ad1b8036 Command seam fixes: the shield switch is pinned on a shielded target; the Longinus has none
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 05:07:25 +02:00
soul
bc05417450 Command seam fixes: the player's switches, ping and stance flips are PilotCommand presses; triggers, switches and ping are internal
ActivatedBehavior replaces IActivatedBehavior so Activate/Deactivate can be internal under Unity's C# 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 04:33:20 +02:00
soul
25750c225b Command seam fixes (red): stance flips and the player's switches and ping are presses on PilotCommand
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 04:32:17 +02:00
soul
30bcabf172 Command seam fixes: pin Combat's release of a pulled lock, its commanded-aim pricing, and the order and count of same-step presses
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 04:31:47 +02:00
soul
b180fd732d Command seam, player: the Previous and NearestEnemy pins start from no target, where no other verb gives their answer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:47:57 +02:00
soul
d8a4e1567d Command seam: the trio's third ship sits in east's sensor cone; the lock pin holds the guns so the lock completes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:31:44 +02:00
soul
76e4e6f58f Command seam: the trio fixture waits for its contacts, and the lock pin for any launcher's lock
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:30:53 +02:00
soul
06435bdefa Command seam: the lock-pull pin carries the target past the launchers' minimum range
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:29:58 +02:00
soul
bee079b1c8 Command seam, player: the reticle verb's pin answers a target no other verb would
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:28:16 +02:00
soul
6f4dbff317 Command seam, player: the control setters and pilot methods are internal, so no Unity script can write them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:27:30 +02:00
soul
394c13a099 Command seam, player: ActionGameManager and ActionBarSlot write only Entity.Command (the 18 direct writers)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:27:29 +02:00
soul
76143e50d1 Command seam, player: PilotCommand gains Tractor, the target Verb, CycleAim and Iff; HelmInput.Demand returns a TurnCommand resolved each step
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:27:28 +02:00
soul
9d9a8ed031 Command seam: the applier is the only writer from PilotCommand; the pilot reads back its own pending decisions (Soul finding only-reader-comment-false)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:27:08 +02:00
soul
7427a70971 Command seam: pin the Release path, Combat's lock pull and release guard, and the retarget step's pending reads (Soul findings release-path-untested, retarget-step-pending-reads-untested)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 02:26:28 +02:00
soul
b519fbd3d0 Merge remote-tracking branch 'origin/master' into eureka/aetheria-arena-command-seam-agents 2026-10-22 02:12:19 +02:00
soul
bbb1dc717e Merge remote-tracking branch 'origin/master' into eureka/aetheria-gravity-laned-belts 2026-10-22 02:03:21 +02:00
soul
67e2647753 Gravity: restore the swarm hosts' Empty guard; a standing binary's bodyless node keeps its mass and hosted swarms (finding swarm-on-bodyless-node)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:40:28 +02:00
soul
dc36b8400f Gravity tests: no swarm rides a binary's bodyless node; lane filters on a tuned sample; a lane splits rocks by band area (red)
NoSwarmRidesABinarysBodylessNode is red at 95903ab0 (finding swarm-on-bodyless-node). The tuned LanedBeltTests
sample reaches the swarm-host and one-shape-per-parent filters (lane-filters-unexercised); ALaneSplitsItsRocksByBandArea
pins LaneRocks' area share (lane-split-unpinned).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:40:15 +02:00
soul
a67711b3d3 aetheria.nakovalnya: side flak rows and radiators are 2x1 in the grid frame (drive.py rerun through the add-on)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:31:16 +02:00
soul
c7e85676fe ship_cc: replace_layout refuses on hull_grid.MAX_CELLS, the grid limit's one owner
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:28:07 +02:00
soul
da77380a04 Hull source: build refuses a hull type that is not a HullType name, before reading the source
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:28:06 +02:00
soul
efeadec265 Blender ships tests: build refuses a hull type that is not a HullType name; the grid limit is hull_grid's (red)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:27:38 +02:00
soul
d76563dd5a NakovalnyaPackageTests: every mount takes its gear through Takes; rows inside the shape and disjoint; no footprint-count pin (red)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:25:22 +02:00
soul
8bfb06ed64 Hull source tests: a Station 32 cells long fits the grid (height bound, not only width)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:15:11 +02:00
soul
28496f27df Hull source smoke: HullType gate (refused as Ship, built as Station, Station refused on the grid)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:07:54 +02:00
soul
2267d8beec Hull source: language proportions judge Ship hulls only; zones must fit the layout grid
build() takes the hull's HullData.HullType, with no default; the add-on reads
it from the bound ship.cc. A Station or Turret lists no proportion check; every
hull keeps symmetry, length, budget and anchor checks and gains the grid check,
judged over zone meshes through hull_grid.grid_size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:03:27 +02:00
soul
0a70e0cf93 Blender ships: hull_grid.grid_size; ship_cc reads HullData.HullType, pinned to C#
grid_size is rasterise's grid arithmetic without its MAX_CELLS refusal, so a
check can judge the bound; rasterise calls the same private filter and sizing.
ship_cc gains HULL_TYPE_SLOT (Key 25), HULL_TYPE_NAMES and read_hull_type;
ShipSchemaPinTests ties both to HullData.HullType and the HullType enum.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 01:00:06 +02:00
soul
321e34a0da PilotSeamTests: an agent's command lands before the next agent decides
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:46:10 +02:00
soul
95903ab00e Merge origin/master (arena cut 1: ItemManager takes a seed) into eureka/aetheria-gravity-laned-belts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:44:50 +02:00
soul
0e9b9c71e2 Gravity: lane half-width 1.5 body radii (ruling lane-narrow), code default and Settings.asset
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:44:36 +02:00
soul
74257926b1 Gravity: a parent's outermost child never hosts a lane (ruling lane-not-outermost); one host filter, an only child pinned
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:44:35 +02:00
soul
f7314b2661 ShipProductTests: stats --top-speed refuses a hull with two VelocityLimits and leaves it untouched
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:41:12 +02:00
soul
07bd57d9e1 ConsumablesFirstSetTests: the vent's smallest cloud holds every sold ship hull
Ruling vapour-cloud-sold-hulls; the radius is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:41:12 +02:00
soul
bc53361ff9 Census tests: sold hulls are LoadoutGenerator.SoldHulls; a hull's asset is its Prefab or its mod-ship Visual record
Ruling census-tests-read-the-owners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:41:10 +02:00
soul
9ac8f23307 RunStartTests: the own-maker and factionless reach claims hold for every product LoadoutGenerator.IsOffered offers
Ruling census-tests-read-the-owners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:41:09 +02:00
soul
487c45f2bd PilotSeamTests: price the commanded aim item after the guns come online
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:39:43 +02:00
soul
2f71975194 PilotSeamTests: the seam's rules (agent writes only its command, held and one-shot fields, apply order, lone-ship side, commanded aim item)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:36:15 +02:00
soul
3795bdb066 Tests: Flight and Steering fixtures drive pilots through the seam (apply after a direct update; scripted demands are commands)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:36:14 +02:00
soul
26a25fce3a Tests: drive agents through the seam (apply after a direct agent update; the duel's scripted player commands)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:32:12 +02:00
soul
9a2a9390e1 Command seam, agents: one PilotCommand per entity, applied once per step by PilotApplier in Zone.Update
Agent, Flight, Combat, MoveTo and Follow write only Ship.Command. Entities
with no agent apply first, then each agent applies right after it decides.
A pilot reads its own pending designation and aim item back from its command;
FireControl gains Refuses/AgentFires/HitProbability overloads that take them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:32:11 +02:00
soul
85e539af2b NakovalnyaPackageTests: import System.Collections.Generic
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:29:47 +02:00
soul
95f89a38a6 NakovalnyaPackageTests: the package composes, its Zhestokost product is never offered or drawn, and its layout is the brief's
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:28:59 +02:00
soul
b13aa7385a Command seam, agents: delete the 17 direct pilot writes in Agent, Flight, Combat, MoveTo, Follow
Each write is replaced by a /*DEL*/ marker; the next commit routes every
marked site through the entity's PilotCommand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:28:53 +02:00
soul
7cb6fb0c9d Mods: aetheria.nakovalnya, the Zhestokost boss hull package (hull.scad, ship.cc, ship.glb)
Built from hull-bench Nakovalnya B by the Starfire job: New Ship --like Djinni, ship-authoring stats (mass 60000, durability 8000, armor 40, drag 0.35, top speed 25), price 60000000, a not-offered Zhestokost product, Build, Rasterise (19x30), 27 layout rows, Package. The validator accepted it and compose excludes nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:28:31 +02:00
soul
0bccb395a4 ShipProductTests: compare the stats hull by its MessagePack bytes (Newtonsoft loops on Shape)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:22:44 +02:00
soul
2fd8cbe8e9 AetherDb: ship-authoring stats sets a package hull's mass, durability, armor, drag and top speed, judged before the file opens
Ruling ship-authoring-stats-command. --top-speed writes a fixed top speed (Min = Max) on the hull's one VelocityLimit and refuses a hull with none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:17:59 +02:00
soul
3efc8cddd7 Merge remote-tracking branch 'origin/master' into eureka/aetheria-arena-determinism-ledger 2026-10-22 00:01:30 +02:00
soul
ad05486388 Zhestokost kit: zh_z keys a donor's zones 'zhestokost:<zone>' when HULL_DONOR is zhestokost
zh_key in ewanhart.scad's form, not AU's either-name match: a Pirate hull's own zone named like a Zhestokost
zone no longer receives Zhestokost geometry. Closes the gap in follow-up zhestokost-kit-donor-routing.

Spec: aetheria-release:cut_spec:cut-zh-kit-landing.r1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:41:15 +02:00
soul
2fe4129777 Zhestokost kit: land the hull-bench kit; zh-ammo-tender fixture rebuilt from Oboz A with one defensive mount
factions/zhestokost.scad is the bench draft byte for byte (battered masses, typed mates, five zones with cream
marking), its lang comment naming the maker element. The fixture is bench Oboz A plus Gun.D on T[2]'s deck
centreline aft of its hatches; the smoke's palette, shadow colour and turned-mount pair follow.

Spec: aetheria-release:cut_spec:cut-zh-kit-landing.r1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:40:26 +02:00
soul
462adf2693 determinism-ledger: pin each scatter draw's ordinal and bounds, and the zero item-seed refusal
Three origin drifters, each placed at For(CombatSeed, ScatterStream, k) within half the radius;
a galaxy seed whose ContinueStep item seed wraps to zero is refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:38:03 +02:00
soul
a46c0536cc release map: ProductWeight's line share counts only offered bins
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 23:25:26 +02:00
soul
25c2a18ab3 Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-product-not-offered 2026-10-21 23:25:16 +02:00
soul
f102b082fd Gravity: laned belts, a belt on a copy of a light body's rail filling its slot less a visual lane
Place records every child's slot; GenerateEntities marks belt candidates. After the swarm pass, a lane pass on its own
stream gives a candidate that kept its body, has a band at least the lane's half-width on both sides, carries no swarm and
whose parent has no other belt shape, an annulus on a copy of its rail: rocks over [slot inner, D - E] and [D + E, slot
outer], E = LaneBodyRadii body radii. ZoneGenerationSettings gains LaneProbability (0 in code, 0.5 authored) and
LaneBodyRadii (5). LanedBeltTests pins it; EveryBeltIsKindedAtGeneration moves there and asserts lanes; BeltShapes.Lanes
lands with it; both TrojanSwarmTests fixtures draw no lane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 22:42:49 +02:00
soul
f7cdb766cd LoadoutGenerator: IsOffered reads a bin's line, and BinShares counts only offered bins, so an off-market bin leaves its line the whole weight
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 22:01:41 +02:00
soul
f2cd036890 ProductChoiceTests: rig bins honour the not-offered list; an off-market bin leaves its line the whole weight, and an off-market line's bin is never drawn or stocked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 22:00:55 +02:00
soul
749bdb09f5 ShipProductTests: the product grammar refuses a misnamed flag or a dangling description, and the on-market line is the off-market one without its clause
Kills the four Stryker survivors of the --not-offered parse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:58:09 +02:00
soul
d0fc8adb70 Gravity: a wider zone fingerprint, one copied-rail helper, belts kinded at generation, adjacent belts pinned
ZoneFingerprint digests rock spin and periods, orbital entities (type, position, rail), other entities by type, the
pack radius, a 9x9 height grid at two times and optionally PopulatedRadius (finding fingerprint-omits).
TrojanSwarmTests.BaseDigest is repinned with it on Yggdrasil at C1's generator, swarms off.

BeltShapes.CopiedRail replaces StationPlacementTests.SwarmRail and the RidesRail slot filters of
ChildrenWithinReachTests: a rail a belt rides that copies a body's rail is never a placed slot.

The Zones fixture counts the belts the generator writes and those with no field kind, before Zone's own
FieldKinds.Ensure; EveryBeltIsKindedAtGeneration pins it at zero (finding ensure-unpinned).
AdjacentBeltsKeepTheirSpacing places two belts side by side and pins the second's inner edge a sibling spacing
outside the first's outer edge (follow-up belt-after-belt-edge-pin).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:43:23 +02:00
soul
73d1cee9de Gravity: one belt extent rule, read by Zone, the generator's clearance tree and the station tests
AsteroidBelt.Extent(data, rail) is now static over the belt's data and the only spelling: the clearance tree's
'Distance + BeltHalfWidth' and the instance Extent are gone. The swarm host filter loses its dead '!p.Empty'
(no bodyless node has a parent). Findings extent-second-spelling and dead-empty-guard (trojan-swarms-residuals).

The clearance tree now reads the outermost rock, not the rail plus half-width, so 29 of the 1920 zones of seeds
1-30 place a station or turret differently. TrojanSwarmTests.BaseDigest is repinned for seeds 3-6, which hold such
zones; seeds 1 and 2 are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:38:43 +02:00
soul
51a3fd0bc9 Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-delete-muzzle-facing 2026-10-21 20:38:06 +02:00
soul
aea0ce823d release map: AH-P1 checks line no longer lists the deleted nose-ward rule
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:37:59 +02:00
soul
0c6f359cb5 ProductLinesCatalogTests: FactionProductData's wire pin covers slot 8, and a record written before it is on the market
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:34:50 +02:00
soul
bd5d27c52b test_hull_source: a mount is not paired by another gun's muzzle
Kills the surviving and->or mutant in the kept pairing rule's unmuzzled list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:31:47 +02:00
soul
3d005ab559 LoadoutGenerator: IsAvailable's off-market comment names no boss term
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:30:04 +02:00
soul
9cedb4efe6 AetherDb ship-authoring product --not-offered writes the package product off the market
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:28:41 +02:00
soul
9c50b7499b FactionProductData.NotOffered: an off-market product is never drawn, stocked, chosen or a gear home
One reader, LoadoutGenerator.IsOffered, read by IsAvailable (ahead of the no-faction
shortcut), the AvailableProducts candidates (so the any-maker fallback cannot reach one)
and SoldHulls. A Loadout that pins the product still builds it. Rulings
off-market-is-unoffered-product and boss-hulls-exclusive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:28:40 +02:00
soul
51e82624d5 test_hull_source: pin that a muzzle facing any way passes the hull source
Muzzles aft of and beside their mounts pass every check, so a reintroduced
facing judgement fails a test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:26:17 +02:00
soul
6f12283dc0 gravity map: laned-belts mapped and admitted; lane host and half-width cells filled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:26:15 +02:00
soul
ee78b85fd0 hull_source: delete the nose-ward muzzle rule; gun facing is HullData's
The Blender scene cannot know which way a hardpoint points: HullData's
hardpoint rotation owns that (ruling aetheria-release:ruling:gun-facing-is-hulldata).
Deletes the forward list and its term in the muzzle check, the two facing
tests, and the smoke's nose-ward require. Pairing stays whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 20:26:02 +02:00
soul
0524d3729d determinism-ledger: pin the two-AI digest captured on Yggdrasil (linux-x64)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:09:20 +02:00
soul
ced96568bc determinism-ledger: the ItemSeed test's expected values wrap as the formula does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:06:49 +02:00
soul
cc5d498b7e determinism-ledger: tests for the seeds, the scatter, Scenario.Id and the two-AI fight
DeterminismLedgerTests (a RunStartTests partial): ItemManager refuses seed 0;
ItemSeed is the run seed and step; the unpack scatter ignores the item stream
and differs per zone; the SimulationDice streams are distinct; scenario Ids are
unique kebab; a two-AI fight is one history, and its digest is pinned for
linux-x64 (pin lands in the next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:04:51 +02:00
soul
9379712c78 determinism-ledger: Scenario.Id, a stable kebab identity for matches and replays
Every scenario, and the test Scripted scenario, names an Id; Name is
display only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:01:43 +02:00
soul
cc0c164574 determinism-ledger: every ItemManager states its seed; scatter on the zone's dice
- ItemManager(uint seed, ...) refuses seed 0 and seeds Random from it.
- RunStart.ItemSeed(galaxy, step) is public (formula unchanged), refuses a
  zero result; named steps ArenaStep, StageStep, ContinueStep and NoRunSeed.
- Continue seeds the item stream from the saved run's seed (ContinueStep);
  a scene with no galaxy uses NoRunSeed.
- Zone's unpack scatter draws SimulationDice.For(CombatSeed, ScatterStream,
  1-based pack ordinal), never the item stream.
- Loadout's scratch manager and AetherDb's catalog command take fixed seeds;
  every test and Editor construction gains 1u (mechanical rewrite).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 19:01:41 +02:00
soul
c13bb2368e determinism-ledger: delete the clock-seeded item stream and the item-stream scatter
ItemManager no longer seeds itself from DateTime.Now, and Zone's unpack no
longer scatters ships with _itemManager.Random. Deletes before adds: this
commit does not build (the scatter and every ItemManager seed return in the
next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:59:52 +02:00
soul
3df3a9549a aetheria-arena target: deterministic headless matches between swappable brains
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:48:50 +02:00
soul
d52b50f911 Research: strategic AI arena and living world prior art (persistent faction worlds, bot tournaments, believability, restricted play, fun proxies, off-screen combat models), for rulings arenas-explore-the-metagame and colosseum-feeds-matchup-model
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:06:49 +02:00
soul
2f4b617e50 Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-package-agent-hull-guards 2026-10-19 14:25:09 +02:00
soul
a9207abba9 smoke_hull_source: pin H10, H6 all-edited, maker-less record, collider-alone and the unbuilt exit text
Soul s4 survivors: the zone test keyed on hull.scad, an edited-zones exclusion, the maker-None branch, a
collider counted as art, and the unbuilt refusal losing its exit text or becoming the agent state.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:45:09 +02:00
soul
2882907f66 smoke_hull_source: pin agent hulls with no zones and no art (1.9a), her art over an unbuilt hull.scad (3.1) and a plain hull (3.2)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:11:10 +02:00
soul
82dab50ab5 Aetheria ships: _hull_state is the one owner of a hull's state; Package's guard and retirement read it
Deletes _art_takes_over and _refuse_wrong_maker's hull.scad branch. Her art over a hull.scad Build never ran now ships and retires the source (operator ruling art-over-unbuilt-hull-source-takes-over).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:11:09 +02:00
soul
96cb6d20f1 Research: prior art for agent-authored stand-in hulls (render-critique loops, part libraries, self-judging limits)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:01:22 +02:00
soul
1ecddc0e69 Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-boss-loadout 2026-10-19 02:45:13 +02:00
soul
3ac185a84e aetheria-release map: hull collection states (HS) and the agent-built row
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 02:07:26 +02:00
soul
f121b46463 Package's art exemption keys on Build's maker record, not hull.scad; case-variant Manufacturer and attack maker keys pinned in smoke_hull_source
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:44:15 +02:00
soul
f3719d9943 Boss refusal tests: compare the serialized ledger, not the pack (pack bytes differ between identical runs)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:30:10 +02:00
soul
820ec73f76 Boss refusal tests: a mismatch prints both zones and the log
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:29:03 +02:00
soul
66510b003f Boss refusal tests: gear projection reads ships only (turrets are not ships)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:25:40 +02:00
soul
8ae052bb47 Materialize refuses an unbuildable Loadout before minting or drawing; delete the boss item-stream restore
Materialize now settles what the catalog alone decides, tries the cells on a
throwaway ItemManager (own ledger and stream, designs built unbranded), and only
then asks the chooser and mints lots. ZoneGenerator's copy-and-restore of
itemManager.Random is deleted, and the boss faction's LoadoutGenerator is created
on the first choice instead of as an argument. Resolve keeps its signature and is
Settle then Build.

Tests: an unbuildable boss zone equals the no-boss zone (serialized pack, ledger,
roster and gear, next item draw) for one failure, several failures and design-only
slots, across every faction as boss faction.

Not yet built or run when committed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:22:38 +02:00
soul
70c366b541 smoke_hull_source: update the view layer before comparing world positions around a refused Package
matrix_world is stale after a location edit until the depsgraph runs, so the
scene snapshot taken after moving Ship Root compared stale to fresh.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:15:26 +02:00
soul
8a1125f1fc ShipSchemaPinTests: remove a stray line left in the maker-key pin
The previous commit does not compile (a/2284391b: ShipSchemaPinTests.cs line 118).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:10:42 +02:00
soul
a2284391ba Pin the three language maker keys to the catalog; pin product_makers' exact comparison; fix a stale derivation line
ShipSchemaPinTests reads each factions/*.scad maker literal against its Faction
record key in GameData/Aetheria.cc. test_ship_cc pins that Manufacturer keys are
not case folded and that a bare string product body is refused, not read as a
maker. hardpoint-sizes-prior-art.md no longer describes the deleted derivation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:09:12 +02:00
soul
399dc769df Package's maker guard keys on Build's record, not on hull.scad; smoke_hull_source fixes
_refuse_wrong_maker returned early when hull.scad was absent, so a built hull
packaged with any product once the file was deleted. It now keys on
aetheria.hull_maker; only art takeover (which retires both) and a package that
never held a built hull are exempt.

smoke_hull_source: ATTACKS lang literals gain the eighth (maker) element; new
refusal steps for hull.scad gone and for a right-maker plus a wrong-maker
product; a refused Package must leave the scene untouched (guard order).
Unrun at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 01:09:11 +02:00
soul
8a6816ed3e test_ship_cc: a product body one short of the Manufacturer slot is refused, not an IndexError
Kills mutant short-body-reads-past-end.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:25:31 +02:00
soul
af993acf07 ZoneGenerator: an unbuildable boss Loadout restores itemManager.Random, so the zone's later draws equal the no-boss zone's
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:21:11 +02:00
soul
7f35c79ecc Package refuses an agent-built hull unless its product is by the language's maker
Language files carry their Faction record key (eighth element of the lang echo);
Build records the maker it judged (aetheria.hull_maker); Package compares it with
ship_cc.product_makers before writing anything (ruling hull-faction-is-product-maker,
finding hull-names-its-own-faction). _art_takes_over is shared with _retire_hull_source.
Unit tests untested at this commit until the Yggdrasil run; bpy smokes not run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:20:00 +02:00
soul
adaa8b8865 Build and Package refuse objects that share an aetheria.id, by selection
One _refuse_shared_ids: a copy of the collider, an emitter, a radiator or a mount
selects the original and the copy and names a count, not an object
(follow-up hull-copy-refusals). smoke_hull_source covers it (not run: bpy smokes).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:17:18 +02:00
soul
eaf7b799d4 Package moves no row: delete the schematic-from-model derivation
Remove _plan_mounts/_apply_mounts, _derived_position, CENTRELINE, hull_grid.cell_at,
mounted_position/mounted_cell and their tests (ruling remove-package-schematic-derivation).
Add Weapon makes a default-Position row; Mirror Mount mirrors each space within itself.
smoke_mounts rewritten (not run: bpy smokes are held off Starfire).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:16:35 +02:00
soul
35c93dd6ab aetheria-release map: body facts and rationale for cut-package-agent-hull-guards
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 00:13:44 +02:00
soul
1950397630 RunGoalTests: Soul's s1 probes as behaviour tests (referenced Loadout wins on a shared hull, refusals fly no catalog Loadout, no maker fallback, boss path draws only what Materialize draws)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 00:04:45 +02:00
soul
5acbaa1b2f Merge eureka/aetheria-release-agent-hulls (head 3c4ea230)
Agent-built hulls, first cut: per-faction form-language files, per-hull sources, Build From Hull Source (rulings hull-art-communicates-form, zhestokost-language-lore-text). Reports cut-agent-hull-source.h1, h2; Soul s1, s2 hold on the fixes (open: question who-names-a-hulls-faction, follow-up hull-copy-refusals). The branch touches only tools/blender, which master did not change since base d28ce42d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:58:46 +02:00
soul
3c4ea230bc test_hull_source: a fingerprint tells nested empty lists apart
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:36:54 +02:00
soul
d5491c1c57 test_hull_source: a genuine language echoed after an altered one, and a faction name that escapes the library
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:35:14 +02:00
soul
1e7678526a Agent hulls: the faction file owns its language; Build owns what it recorded, not what is marked
hull_source.build reads the faction's and donor's language from factions/<faction>.scad run alone and only compares the
hull's own lang echo with it; a hull that reassigns, re-echoes or shadows a language fails a check.

Build records what it made on the collection by name and fingerprint instead of marking objects. A copy (another name) or an
edit (another fingerprint) is the author's: Build refuses and deletes nothing. Package retires hull.scad when render meshes
that are not Build's remain and no zone mesh of Build's does, so keeping Build's anchors and collider no longer blocks
takeover.

Unit tests cover the runner (arguments, exit status, OPENSCADPATH), non-string names, the width/length bound, own-zone
colours and the language ownership; the smoke pins world poses of mounts, emitters and emitter meshes (a mount turned 90
degrees included), the language attacks with the real OpenSCAD, copy and edit, Build after Package and the takeover.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:34:41 +02:00
soul
5a050f0fca Merge eureka/aetheria-release-run-seed (head cb1c093e)
Reports cut-run-seed h1/h2; Soul verdicts s1, s2 hold.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:29:04 +02:00
soul
d83cacc6a7 Merge eureka/aetheria-release-product-tiers (head e6a17a5e)
Reports cut-product-tiers h1/h2; Soul verdicts s1, s2 hold.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:29:02 +02:00
soul
f9acdc1e9c smoke_hull_source: the collider is the language's body zone mesh (a hand mutant took the first zone and survived)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:08:53 +02:00
soul
2e597b0715 test_hull_source: the survivors of the first hand-mutant round get tests (vertex bound, exact bilateral bound, emitter triangles in the budget, non-mount muzzle parent, donor colours, missing donor language, empty silhouette)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:04:42 +02:00
soul
24f057d18f Build From Hull Source: zone meshes, mount anchors and a collider from the package's hull.scad; Package retires a hull.scad that operator art replaces
Build refuses a source that breaks its language or brief, and a collection holding render meshes it did not make;
it replaces only objects marked aetheria.hull_source and writes no layout row. Package deletes hull.scad, and says so,
once the collection holds art and none of Build's objects. OpenSCAD path is an add-on preference.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 22:00:15 +02:00
soul
763fa0987f hull_source: reads a hull.scad through OpenSCAD and judges it against its faction's form language
One language file per faction (Zhestokost, Rossum & Douglas, Pirate) owns the shape kit, proportions, symmetry rule and
palette; the Zhestokost palette follows the lore page (ruling zhestokost-language-lore-text). The two probe hulls are
ported as fixtures. Checks: zones, emitter and radiator meshes, donor, body proportions, top-view mirror overlap,
length, triangle budget, muzzles nose-ward. Fixture-text tests need no OpenSCAD.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:57:47 +02:00
soul
f17b04ec1a FlightTests: Faction's wire array ends at slot 22 (BossLoadout), so it is 23 long
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:31:57 +02:00
40db8291d8 Exit_open_only_in_the_exit_zone: the gate boss pins its hull's brand, so any faction builds it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:25:21 +02:00
d8afb9d184 Exit_open_only_in_the_exit_zone: a failed boss build reports the log
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:24:46 +02:00
f235eea3d9 Exit_open_only_in_the_exit_zone: the faction with the boss Loadout is one that can get its hull's brand
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:22:05 +02:00
3ad3fcc505 RunGoalTests: using GameCult.Caching.MessagePack
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:19:14 +02:00
d2ec3a6678 RunGoalTests: using GameCult.Caching
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:18:49 +02:00
ad503059e5 RunGoalTests: LoadoutCells reads the fixture's cache
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:18:20 +02:00
e5485bb3e0 aetheria-release map: agent-built hulls replace the stand-in section (form languages, probe, first cut)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:17:42 +02:00
e2b1b9ca7b RunGoalTests: the boss flies its faction's boss Loadout; refusals, exact cells, brand by context, market rule, main-galaxy pick
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:17:05 +02:00
e6a17a5e01 ProductLinesCommandTests: the bins of a removed line go with it, as the catalog read now requires
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:14:14 +02:00
352e221453 Faction.BossLoadout (key 22): the boss is its faction's Loadout, resolved by Loadouts.BossOf and built by Materialize
BossOf refuses typed (BossRefusal Unset or Missing, Describe names the field and echoes no input).
ZoneGenerator builds the boss from the Loadout with ChooseProduct as the chooser; a refused or
unbuildable boss logs and spawns none. Galaxy picks boss factions through BossOf; AetherDb factions
prints the boss Loadout. Loadout vocabulary: no preset, no variant. Production builds; the tests
project does not until the next commit (RunGoalTests still sets BossHull).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:14:09 +02:00
900fa51e43 Delete Faction.BossHull (key 10 retired), GenerateBossLoadout and the three tests that pin its fallback
A boss is a Loadout the faction references, never drawn (rulings faction-boss-is-a-loadout-reference,
boss-gear-is-a-loadout, demo-boss-hull-invented). This commit does not build: ZoneGenerator, Galaxy,
AetherDb and the tests still read the deleted members; the next commit replaces them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:12:58 +02:00
0769314ee6 aetheria-release map: boss loadout replaces boss hull derived (Faction.BossLoadout, off-market by product)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:11:01 +02:00
8d65e957f8 sensor-stat-set skips a bin, as the other role writers do; it takes an optional root for its test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:08:11 +02:00
f73507ff2f Catalog read refuses a bin with a non-finite Floor, a missing Line or a Line that is a bin; a bin mints from exactly its named line (tested)
The runtime no longer trusts the authoring tool for a bin: a NaN Floor weighed NaN and nulled every
draw of its design. AetheriaStores.Open names the field and echoes no value.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:08:10 +02:00
129e5ff4dc ProductWeight is the one weight of every design-only draw; a line's bin shares are read once per pass
The all-weights-zero branch of ChooseProduct and the required-item fallback of RandomProducts weighed
every product 1, so a bin doubled its maker's presence there. Both now weigh by Share alone (the
preference drops out, the bins' shares do not). The sum of a line's bins' pass fractions is computed
once per weighting pass instead of scanning the product table per candidate.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 21:08:09 +02:00
d28ce42df9 Research: faction form language and role readability for agent-built hulls, for ruling hull-art-communicates-form
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:37:22 +02:00
a40072d9ab aetheria-release map: mark the stand-in section superseded by ruling hull-art-communicates-form
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:30:06 +02:00
096f833c24 Merge eureka/aetheria-gravity-trojan-swarms (head de3ecd9b)
Trojan swarms: belts riding their host's rail period at L4/L5 (rulings trojans-first, trojans-ride-host-period-with-stations). Report cut-trojan-swarms.h1; Soul s1 holds (four Lows deferred to follow-up trojan-swarms-residuals); GravityFieldParityVerify passes. Master's commits since base 67517f40 are docs only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:24:12 +02:00
cb1c093e84 ConsumableAiTests: open the run store so a scene can continue a run at a fixed seed
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 20:21:31 +02:00
0ed0605aa5 Pin the run seed's edges: AI dice stay on CombatSeed, full-width seed, refusal names its field, refusal test cannot hang
- ConsumableAiTests.ThePilotsDiceDoNotMoveWithTheRunSeed: sample offset and patrol circuit equal at different run seeds.
- RunSaveTests.TheRunSeedRidesTheSave uses a seed with the top bit set.
- RunStartTests.AGeneratedGalaxyRefusesSeedZero builds from authored settings (small ZoneCount) so a constructor that stops refusing fails by assertion, and pins ParamName and no ActualValue.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 20:13:03 +02:00
9457e4c8f9 ProductBinTests: the search's 64-draw bound and its stop at the first clearing draw, and the missing-line log, are pinned
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 19:51:40 +02:00
beb733f4b5 Census role gaps become RoleGaps, so a bin skipped by the census has a test; a bin authored on another line is refused
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:46:05 +02:00
de3ecd9bb0 Trojan swarm tests: host class, rock side parity, width and arc reach
Stryker survivors on the generator showed the host-mass gate, the side of each
rock and the width/arc scale were unpinned. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:42:44 +02:00
112dd24536 aetheria-release map: boss hull derived r4 (fixed Loadouts), stand-in hulls (SI) probe and cut sequence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:20:07 +02:00
fb7b95fb06 ProductChoiceTests: a bin takes nothing from another maker's product
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:19:00 +02:00
aec7b3c019 product-lines tiers lists every row, present or new, before it reports there is nothing to do
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:16:27 +02:00
9b7a1c00dc Catalog: the six tier bins (product-lines tiers apply); TierRowsAreShipped; the tier step pinned from both sides
Aetheria.cc written only by the command, on the pinned CultLib. Replay the command at merges; never merge the blob.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:11:11 +02:00
6768cdcb95 product-lines tiers: authors the six bins from a table of (line, bin, floor, text)
A bin gets its line's design and maker, Bin = { Line, Floor }, and no roles or assembly. Resolve-then-write
as the other lines do; a replay is a no-op. The catalog is not yet applied.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:08:56 +02:00
2806b443c9 Census, roles-migrate and roles-backfill skip a bin: it authors no roles, it reads its line's
RolesMigrate takes an optional root, as RolesBackfill does, so its bin skip has a test.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:06:07 +02:00
7f09b05725 ProductWeight: a bin takes its pass fraction of its maker's preference and its line the rest (ruling bin-share-by-floor)
Phi comes from CultMath's math.erf.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 18:04:08 +02:00
49853d3166 ProductBin: a binned product names its maker's line and a floor; the mint draws above that floor
FactionProductData slot 7 Bin (schema id unchanged, additive as slot 6). Mint derives a bin's
distributions from its line on every lot, truncated by NextGaussianAbove (64 tries, then the cutoff).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:58:51 +02:00
b19d6add89 aetheria-release map: product tiers follow ruling bin-share-by-floor (spec r2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:51:50 +02:00
47f834ea23 Pin all five pre-run-seed drops of the dice zone (the first pin kept three)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:39:52 +02:00
727c409659 Pin the dice of a zone without a run seed at their pre-run-seed values
A zone with no galaxy and a zone of a save written before run-seed (seed 0)
drop the items and scatter the mines they did at eb27ced1; values computed
at that base.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:33:11 +02:00
f23d3c6542 Drops roll on the run's seed: Zone.DropSeed feeds the loot and mine dice
DropSeed = CombatSeed ^ Mix(Galaxy.Seed), derived at construction. A zone with
no galaxy, or a restored seed of 0, keeps its dice bit for bit; CombatSeed
still roots shot, patrol and range-sample dice. RunSeedFixture builds a test
zone's galaxy through RunSave.Commit and the Continue constructor.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:30:50 +02:00
020dc58a81 The run's seed rides the save: SavedGame key 14, written by Capture, read by Continue
Galaxy.Seed on a continued run is the saved seed instead of zero. A save
written before run-seed decodes Seed 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:29:17 +02:00
8779304499 Galaxy generation refuses seed 0: delete the clock fallback and the seed defaults
GalaxyStage.SeedFrom is the one minter of a run's seed; both generation
constructors now take progressCallback and seed without defaults and throw
ArgumentOutOfRangeException on zero instead of reading the clock.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 17:28:36 +02:00
6d10331c05 aetheria-release map: boss hull derived, product tiers, run seed (body facts BH/PT/RS, cut sequence; InfluenceScale moves to SavedGame key 15)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:24:54 +02:00
ac835a8ab2 Research: agent-built hull art prior art (LLM 3D workflows, ship generators, low-poly style, internal fit), for ruling hull-programmer-art-stopgap
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:52:32 +02:00
9cdd885af0 Trojan swarms: tests for the period rule, stations, the unmoved zone and the save format
ZoneFingerprint pins a swarmless zone to digests computed at 67517f40 over seeds
1-6. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 16:28:44 +02:00
92d6153c2e Trojan swarms: a belt on a copy of its host's rail whose rocks ride the rail's period
Rulings trojans-first, trojans-ride-host-period-with-stations. AsteroidBeltData
key 11 RidesRail; AsteroidBelt.Extent is the one belt extent rule (replaces
Zone's inline farthest-rock loop and the Math.Max at the well node); a swarm's
Periods are its rail's period. The generator draws swarms from a stream of its
own (TrojanStream), so no other draw in the zone moves. Tuning defaults are the
spec's proposals; the code default TrojanProbability 0 draws none. Existing
annulus tests skip swarm rails. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 16:28:42 +02:00
eb27ced147 Research addendum: why BattleTech keeps BV apart from C-bills (operator's examples)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:25:25 +02:00
06a173a5b2 aetheria-gravity map: trojan swarms (body fact B61, belt-shapes cells, rationale, cut sequence)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:24:07 +02:00
0f7ae88e26 Research addendum: outfitting budgets are usually a value currency (BattleTech BV vs C-bills)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:05:36 +02:00
67517f407f Merge eureka/aetheria-release-quality-readers (head e95a3657)
Every reader of item quality reads Lot.EffectiveQuality (ruling effective-quality-mean-of-roles). Reports cut-quality-readers.h2, h3; Soul s1, s2 hold. Master's commits since base 70c7a497 are docs only, so the merged code equals the verified head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 11:22:04 +02:00
e95a365719 ItemData role-validation comment: the fallback is the effective quality
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 11:06:46 +02:00
8cc7f1bc85 Pin GetTier: it hides an over-specced part, and its tolerance and upgrade step at the shipped thresholds
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 11:06:45 +02:00
7206c5fdf4 StatsReadTheLot: drop the upgrade count of the lot below the first tier
Its effective quality .15 sits under Common's .2, which GetTier counts as -1; not a rule this test is for. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 10:28:11 +02:00
b6075b776f Tier and wear tests pin the tolerance, the upgrade steps and the direction of the quality term
Kills the Stryker survivors in the lines this cut touches that a quality-reading test can reach. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 10:27:46 +02:00
d820e155ff GetPrice test: a lot of two parts, one above its assembly, prices as the mean of the capped parts
Kills the hand mutant that prices a lot at its best part (the single-fill sleeper could not tell max from mean). Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 07:34:13 +02:00
f3044718c1 Stage the drive lots with the ship deactivated: an active entity refuses unequip and equip
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 07:22:04 +02:00
349a226c72 MismatchedDrivesHoldHeading stages its two drive lots at .55 and .85
Heat now reads effective quality, which narrowed the Generated fit's drive spread below the test's 5 percent premise (probe: thermal exponents 1.227/.809 at base, 1.623/1.318 at head; NominalThrust ratio 1.0525 then 1.0436). The test fits the two Large Drives with lots staged at the low and high end of the makers' assembly range, chosen before any run, through the ship's own unequip and equip, and asserts the spread as a premise with its own message. Unverified until the Yggdrasil run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 07:18:37 +02:00
174bdaded1 Every reader of an item's quality reads Lot.EffectiveQuality
Price, tier, equipped thermal and durability exponents, wear and the unequipped durability exponent now read the one effective quality; no reader keeps a path to the assembly alone. Tests pin each reader against a lot whose part sits below its assembly. Unverified until the Yggdrasil run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 07:09:31 +02:00
96911ffc4b aetheria-gravity map: belt shapes (body fact B60, model sub-table, rationale, cut sequence)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 07:06:47 +02:00
db3043a5d2 Research: NPC outfitting selection and quality-for-cost mechanics, for chooseproduct-affordability and quality-paid-in-cost-or-throughput
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 07:06:23 +02:00
38198b6e00 Lot.EffectiveQuality: the item's one quality, the mean of min(part, assembly) over its fills
QualityForRole's unnamed, roleless and unfilled fallbacks read it. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-18 07:04:15 +02:00
39aef82f47 aetheria-release map: quality readers at 70c7a497 (body facts QR1-QR5, model row, cut sequence)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 07:01:06 +02:00
70c7a49739 Merge eureka/aetheria-gravity-bodyless-node-places-children (head 49c6e3f8)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 05:52:45 +02:00
49c6e3f837 StationPlacementTests: the bodyless-node rule runs on a wide light sample of the production generator that holds standing binaries under bodies
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 04:22:31 +02:00
5a63094035 ZoneGenerator.Place: a folded family joins a bodyless target as a child and AtLeast reads its target through OneBody; direct-Place theories pin OneBody, the heavy member, the margin and the ringless settle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 04:22:30 +02:00
55bda75ac3 Merge faction-curated-place-names (7da0d414), --no-ff
Code from eureka/aetheria-release-faction-curated-place-names. Conflicts kept both sides: Faction holds Assembly (key 19) and Places (key 21); AetherDb dispatches assembly-from-maker, place-names and doctrine-catalog, and its usage names both; FlightTests counts the Faction wire at 22 slots (19 is Assembly, 21 is Places).

The two LFS files are the merge's resolution, replayed on the post-assembly bytes, never merged as text or by side.

GameData/Aetheria.cc, per h1's two-step replay: (1) AetherDb place-names apply built at the branch's commit 1 (740e1ee7, merged onto the assembly merge so key 19 survives), run on the post-assembly catalog: purges the Markov NameFile records while their type exists and authors 15 place lists; (2) place-names apply built at this merged tree, run on step 1's output: authors Miss Terri's list (1 list). Each step's second apply said nothing to do and left the bytes identical; the whole chain run twice from the assembly catalog gave bytes equal except the record write timestamps (masked, both hash alike). Decoded independently with cultcache-py: 16 factions, key 19 Assembly filled on the 15 makers (Ewan Hart has none), key 21 Places 20 names on all 16, key 9 nil on all, no namefile type among the 321 records.

Assets/Resources/Settings.asset: the post-assembly file (Rarity values removed) with the four NameGeneratorSettings lines removed (NameGeneratorSettings, MinLength 5, MaxLength 10, Order 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 02:16:57 +02:00
430eb307a3 Merge assembly-from-maker (a899432d), --no-ff
Code from eureka/aetheria-release-assembly-from-maker-r2. The two LFS files are not merged as text or by side; they are the merge's resolution, made as follows.

GameData/Aetheria.cc: master's catalog (0f5def17's, sha256 a4ff0eff...ebee9) is unchanged by master since, so the branch's blob was checked against the replay. AetherDb assembly-from-maker apply, built from this merged tree, run on master's catalog twice from fresh copies and once more on its own output: 15 factions written; the second pass said No changes and left the bytes identical. The replayed bytes equal the branch's blob (sha256 2b18ff7f...90e... ) except for the 333 record write timestamps, each of which a fresh write restamps (masked to a constant, both hash alike). The branch's blob, which h5's full suite tested, is taken.

Assets/Resources/Settings.asset: master's file (b004d902..., which dropped AsteroidVerticalOffset) with the branch's Rarity cleanup replayed: the five Rarity values (1, 0.5, 0.15, 0.05, 0.01) removed, nothing else touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 02:13:23 +02:00
408b1c45bd ZoneGenerator.Place: a bodyless node is one body of its family's mass wherever a mass is read, and ChildrenWithinReachTests widens to seeds 1-30
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 02:01:09 +02:00
cacd926182 ZoneGenerator.Place: Settle recurses into each placed child; the queue, its guard and the settled set are deleted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:59:06 +02:00
827f11c6df aetheria-gravity map: B59 bodyless binary members left at distance 0; why Settle recurses (spec bodyless-node-places-children.r1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:56:43 +02:00
6fcdb9cfea Merge eureka/aetheria-gravity-asteroid-floater-layer (head 01d3058d)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:26:03 +02:00
f30f15cd41 Merge eureka/aetheria-release-studio-underlay-fits-hull (head 1030e719)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:25:58 +02:00
b9e16872c7 Merge eureka/aetheria-gravity-ring-roche-final-heavy (head 390a5958)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:25:54 +02:00
a899432d46 Tests: the AI streams in both directions; sampling and admitting take nothing from the item stream, and each pilot's circuit is its own
Pins the survivors soul-ai-consumes-item-stream and soul-patrol-same-for-every-pilot of verdict s1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:54:01 +02:00
997172af17 Tests: the assembly derive rule at fifteen part means and across products, not at the fixtures' two
Pins the survivors soul-derive-quadratic-agrees-on-fixtures and soul-derive-floored-mean of verdict s1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:54:00 +02:00
05417f832e Tests: the role ceiling has no floor and no tolerance band; a product's own assembly replaces the maker's spread too
Pins the survivors soul-cap-assembly-floored, soul-cap-tolerance-band and soul-product-override-mean-only of verdict s1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:53:56 +02:00
14d3327c19 LockOn: the hostile is ordered to close on the player; the warning is measured against the poses it was stamped from
ScenarioStage.Approach(entity, target) states a piloted entity's task as a follow task on the target, passed through Zone.Admit to the flight as the member's baseline task; it replaces Patrol(entity, orbit) and the orbit index, and RunStart's post-admit circuit overwrite. LockOn stages at .6, the quality Crossing and the other RunStart scenarios use (its brief states none), not .8 picked by outcome.

The bearing check keeps well-law r4's intent (measure against the hostile's actual pose, not the staged line) but reads the poses of the tick before the paint was first seen, which is the tick it was stamped in, with a .05 deg limit for float error; the live-pose check at .5 deg spent its budget on the paint inbox's deliberate one-tick delay. LockOnHoldsUnderOnePercentOfEachStagedInput moves hostile x, y and quality by 1% each way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:51:33 +02:00
Meta Vens
01d3058d21 BeltFloaterLayerVerify: both belts the same length, so a draw list built from the other belt is measured as wrong sizes rather than an index fault
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:34:50 +02:00
Meta Vens
b320a8cf6d BeltFloaterLayerVerify: two belts loaded through ZoneRenderer with ARPG.unity's meshes; every drawn rock's reach and top measured from the instanced matrices and the mesh's vertices
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:29:04 +02:00
Meta Vens
72e2383ea4 DrawAhead.BeltDraw keeps the belt's meshes by the belt's key; empty candidates and a zero kept count are named refusals; ZoneRenderer draws through DrawBelts and one DrawInstanced seam
The unseeded Random.Range prune leaves ZoneRenderer: the kept set is a function of the candidates, the kept count and the belt key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:23:47 +02:00
Meta Vens
f5f0634b14 DrawnPoseTests: the renderer's remaining lines are pinned whole (the draw call, the pose, the scale, the slot)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 23:16:32 +02:00
Meta Vens
c5ad4676f7 DrawAhead.BeltDraw owns the whole per-rock draw list; ZoneRenderer iterates it with no mesh choice, sort or index arithmetic
Replaces RockMeshing/AssignRockMeshes and the renderer's slot bucketing (findings scale-lookup-unpinned,
renderer-index-wiring-unpinned). The build gate message names the mesh and the field, not the radii.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 23:12:33 +02:00
Meta Vens
390a5958c9 ChildrenWithinReachTests: sample seeds 1-9 so the ring Roche defect cannot hide behind six
Seeds 7, 11 and 12 reproduce the ring-inside-Roche-margin defect on the base
generator; seeds 1-6 do not. Seed 10 shows a separate defect (a bodyless
non-ring node whose children are never placed), so the range stops at 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:18:34 +02:00
Meta Vens
d805c32092 Research: belt shapes prior art (embedded planetoids and gaps, Trojans, Oort-like edges), for ruling belt-shapes-direction
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:17:54 +02:00
Meta Vens
7da0d414cb PlaceNamesTests: assert on names, not zone graphs; pin invalid entries, homeless factions, runs of taken names, EAC- case and same-length restore
A failed Assert.Same or Assert.All over cyclic Galaxy objects overflowed xunit's formatter and crashed the host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:14:26 +02:00
Meta Vens
ac259c6259 Place names: one validity rule (FactionPlace.IsValidName) for NamePlaces and the place-names command
NamePlaces treats an invalid entry as absent; the command refuses a table holding one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:14:22 +02:00
Meta Vens
c576e0ac18 DrawnPoseTests: four rocks over two meshes split two and two (the mesh count decides the run length)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:07:57 +02:00
Meta Vens
eb752a49c9 LockOn stages its fit at .8: the lock then holds the test's bearing check; probe files dropped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:00:42 +02:00
Meta Vens
dbe4525a02 probe (scratch 5, reverted next) 2026-10-17 21:58:59 +02:00
Meta Vens
203093bcbd probe (scratch 4) 2026-10-17 21:57:33 +02:00
Meta Vens
2d61afa40f RockMeshRadiusBuildGate: a player build fails when an AsteroidMeshes radius is unfilled or stale (finding verify-not-gated)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:44:46 +02:00
Meta Vens
8412aa0dc3 DrawAhead.RockMeshing owns the mesh ranking and each rock's scale; a mesh with no radius is refused by name (finding renderer-wiring-unpinned)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:44:43 +02:00
Meta Vens
8ee159914b ZoneGenerator: a ring is judged on its members' settled masses
The Roche-margin check on a rosette's ring read heavy.Mass before any member had
settled; each member's own Settle later folds its overflowing children into it,
so a ring could stand with a member inside its Roche margin. Settle now places
and settles the ring's members first and judges the ring on ring.Max(Mass); the
queue skips members already settled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:40:01 +02:00
Meta Vens
f0cb87277b LockOn patrols orbit 3 by index; the probe file is dropped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:38:50 +02:00
Meta Vens
5f1fa7d63b probe (scratch 3) 2026-10-17 21:37:12 +02:00
Meta Vens
244e98e463 probe (scratch 2) 2026-10-17 21:35:54 +02:00
Meta Vens
77207ec73c aetheria-gravity map: B58 ring Roche margin read before members settle (spec ring-roche-final-heavy.r1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:35:22 +02:00
Meta Vens
6216b50d6f probe (scratch) 2026-10-17 21:33:33 +02:00
Meta Vens
f7c933c08e probe (scratch, to be removed) 2026-10-17 21:30:31 +02:00
Meta Vens
bbfd816851 LockOn states its hostile's patrol order and fit quality; dice streams, patrol circuit and projector range pinned
ScenarioStage.Patrol(entity, near) states a piloted entity's patrol order (the orbit nearest a point) and RunStart applies it over the drawn circuit. LockOn stages its fit at .6 and the hostile on the orbit by the player. Tests: every SimulationDice stream draws independently of every other (they already did: the stream is mixed into the hash), the pilot's sample offset is on its own stream's grid, a patrol circuit does not move with items minted first, Crossing.ProjectorRange is read against the live range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:28:35 +02:00
Meta Vens
27be39284f Tests: the zone gives each admitted pilot its own id
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:56:28 +02:00
Meta Vens
5a16a2751c Crossing: ProjectorRange re-measured at the staged fit, 997 m (was 1216 at 0f5def17)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:55:50 +02:00
Meta Vens
ed6463dca0 DrawnPoseTests: expected mesh runs for five distinct rocks over three meshes (the last run takes the remainder)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:55:09 +02:00
Meta Vens
e894bde146 Agent.Id is a plain setter: netstandard2.1 has no init accessors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:47:09 +02:00
Meta Vens
72d7e25df0 AI draws from its own dice: the range-sample offset and the patrol circuit leave ItemManager.Random
Combat.SampleDps and Zone.CreateAgent's patrol circuit drew from the item stream, so minting items moved
how a pilot fights and where it patrols. Both now draw SimulationDice.For(CombatSeed, stream, Agent.Id);
Agent.Id is the zone-scoped ordinal Zone.NextAgentId gives a pilot at admission (ruling
ai-sample-offset-off-item-stream).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:46:37 +02:00
Meta Vens
64d5e4534d ARPG.unity: measured rock mesh radii (RockMeshRadius.Fill), 30 meshes, 0.958 to 2.430
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:44:28 +02:00
Meta Vens
d592ca3223 Rocks take meshes by size and are scaled by gameplay radius over mesh radius (ruling rock-meshes-by-size)
DrawAhead.AssignRockMeshes ranks rocks by unworn size onto meshes in ascending radius; RockScale divides the
gameplay radius by the mesh's measured radius; ChunkAt is the one rock position for the renderer and the reticle
(ChunkHeight folded into it). InstancedMesh.Radius is filled and verified by RockMeshRadius. Tests pin the
assignment, the scale and that the renderer and reticle call DrawAhead (finding owner-not-pinned).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:44:13 +02:00
Meta Vens
26c44020a1 Catalog: place-names apply adds Miss Terri's list
Built from a5a81993 on the previous commit's catalog; a second apply printed
'nothing to do'. The merge pass replays the command twice: built at commit 1
(with the purge leg) on master's catalog, then built at the tip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:36:48 +02:00
Meta Vens
a5a8199321 Place names: Miss Terri's gets a draft list (ruling miss-terris-improvised-places)
Real Australian place names, Indigenous-derived and English, in the old
Australia file's spirit; a draft Emily may replace. The test that pinned her as
designation-only now clears her list in memory to prove the fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:35:37 +02:00
Meta Vens
2891b9a807 Tests: the drawn assembly clamp, Resolve at a stated quality, and the staged hull
Hand mutants of the previous head survived in three places: the clamp on a drawn assembly, Loadouts.Resolve ignoring a stated quality for a product or an unbranded design, and Materialize not passing it to the hull. Each now has a test through the production path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:18:09 +02:00
Meta Vens
1eb828d53a PlaceNamesTests: a name another faction used is skipped, whatever its case
Mutation triage: skipping used names, and comparing them case-sensitively,
both survived because the table refuses repeats before a galaxy sees them. A
list that did not come through the table (a package's factions) can still
repeat one, so the draw rule's skip now has a test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:03:27 +02:00
Meta Vens
198bf147d2 Catalog: assembly-from-maker apply (15 factions)
AetherDb assembly-from-maker apply on master's 0f5def17 catalog, after every product and faction apply: 15 makers of roled products get Assembly = part mean + .1 (capped at 1) and the mean part deviation. Ewan Hart Inc has no roled product and stays unauthored. A second apply reports No changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:57:54 +02:00
Meta Vens
0367f9d1fd Fused Rounds stages its shooter; FlightTests counts the Faction wire slots at 20
FusedRounds.StagedQuality (.6) states the shooter's quality so the Cluster Cannon's damage in TheDirectWeaponKillsTheFragileHullWhileASmokeRoundIsStillInTheAir does not ride the item stream. The Faction wire now has 20 slots (Assembly at 19); the Doctrine-at-17 rule is unchanged. LockOn is not staged here: see the question raised on the spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:57:39 +02:00
Meta Vens
7bd11f882b FlightTests: Faction's wire array is 22 slots long, repinned from 18
Places rides at key 21, so the serialized Faction array grows from 18 slots to
22 (keys 18-20 empty). Slots 16 and 17 are unchanged. Base value 18, new value
22, reason: the new member; no zone content is involved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:35:05 +02:00
Meta Vens
9481e541ca PlaceNamesTests: a home zone shared by two factions takes its owner's capital
The prelude puts the quest faction's home on the buffer faction's, and a zone
has one owner (the nearest home in faction order), so the first full run showed
Adrasteia's home zone named Ishtar Studios, Lucent's capital. The rule stands;
the test said the wrong thing about the shared home.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:35:04 +02:00
Meta Vens
1d689adfa6 Delete the Markov name generator, its data and settings, NameFile and GeonameFile
The NameFile records went with commit 2's apply, so the type, Faction key 9
(left as a retired-key comment), NameGeneratorSettings and its parameter on
Galaxy and GalaxyStage, the Settings.asset block, the Name Tools editor
window, the Geonames resources, the purge leg of place-names and the
minor-power and Pirates commands' name-file lookups all go. The Pirates
missing-name-file test pins a retired rule and goes with it. Factions shows a
places count where the geonames column was. Unity compile owed at merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:26:15 +02:00
Meta Vens
0a6bbdde13 Catalog: place-names apply on master's catalog (15 place lists, Markov data purged)
Built from 740e1ee7 with AetherDb place-names apply on 0f5def17's catalog; a
second apply printed 'nothing to do'. The merge pass replays the command, not
this blob.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:25:47 +02:00
Meta Vens
740e1ee781 Place names: Faction.Places, Galaxy.NamePlaces and the place-names command
Each faction names the zones it owns from its own curated list (ruling
faction-curated-place-names): the home zone takes Places[0], the rest follow
in distance order, a spent or absent list falls back to unique catalogue
designations. Galaxy.NamePlaces replaces the Markov GenerateNames body. The
place-names command authors the 15-row table and, until commit 3, purges the
NameFile records and GeonameFile links while their type still exists.

The shipped catalog carries no Places yet (commit 2), so the tests that read
shipped lists fail at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:10:17 +02:00
Meta Vens
5b49a2bbf6 AssemblyFromMakerCommand: restore the \n escapes in its two WriteLine strings
The previous commit (30597b0e) wrote real line breaks inside two interpolated strings, so tools/AetherDb did not compile at it. Aetheria.Shared and the test project do not reference the tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:07:12 +02:00
Meta Vens
1030e7198a SchematicUnderlay tests: the bounds extremes sit in different lines
A mutant fitting to the first line only survived because every other point lay inside it. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:04:44 +02:00
Meta Vens
7b2a6d064d Staged fits: a scenario states the quality of a fit its checks rest on
ScenarioStage.Fit(hull, quality, slots) mints every lot of the fit at the stated quality through Loadouts.Materialize/Resolve, so Crossing's fighter and EvasionTermTests' hand-fitted Longinus and Djinni do not ride the item stream. No seed changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:03:20 +02:00
Meta Vens
30597b0e45 Assembly is an AssemblyDistribution: Faction key 19, optional per product, stated-quality mint
Replaces h1's AssemblyMean/AssemblyDeviation floats with one Faction.Assembly (key 19, null = not authored) and adds FactionProductData.Assembly (key 6, null = its maker's). CreateLot(product) draws from product.Assembly, else the maker's, else AssemblyDistribution defaults; CreateLot(product, quality) mints the lot and every fill at a stated quality and draws nothing. assembly-from-maker now seeds part mean + .1 and writes only a null Assembly.

The shipped-catalog test is red until the catalog commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:03:12 +02:00
Meta Vens
f948992d94 aetheria-release map: faction curated place names at 0f5def17 (probes P1-P7, draw rule, model rows; spec faction-curated-place-names.r2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 19:00:04 +02:00
Meta Vens
57952dbfb7 Settings.asset: drop the five Rarity values; RarityTier is display bands only
The type lost its Rarity field with the roll; Unity would otherwise keep serializing orphan values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:55:53 +02:00
Meta Vens
d23038f53c Assembly is the maker's: re-land of h1 on 0f5def17 (net diff of ae300c6a..5187a59d)
Applies the net diff of eureka/aetheria-release-assembly-from-maker (5187a59d) without its catalog blob and RunStartTests residue, git apply -3, overlaps resolved on master's side. 066fb581's message ('git log --oneline -1') was a heredoc slip; the old branch stays as it is. Drops the Rarity = fixture member from the tests master added since ae300c6a. Faction keys 19-20 here are h1's; the next commit reshapes them to one Assembly at 19.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:55:16 +02:00
Meta Vens
ed40d26dd0 aetheria-release map: assembly-from-maker r2/r3 at 0f5def17 (probes AFM1-AFM5, model rows, quality-readers line)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:52:17 +02:00
Meta Vens
f69c997a85 Studio: HullUnderlay draws the texture or the hull's line art under both cell grids
The hull Shape grid and the footprint painter draw the underlay through HullUnderlay.Draw; the inline texture draw moves into it. Editor assembly: Unity compile not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:47:52 +02:00
Meta Vens
59cbdd1f3d SchematicUnderlay.Fit: the line art stretched onto the hull Shape's Width x Height
Engine-free rule in ServerShared with five behaviour tests. Builds (ServerShared and tests only; Editor wiring follows in the next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:47:35 +02:00
Meta Vens
5283d4de57 aetheria-release map: Studio underlay fits the hull's Shape bounds (spec studio-underlay-fits-hull.r1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:39:19 +02:00
Meta Vens
8074d724a5 ChunkHeight comment names what the renderer does with pose.w
Comment only. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:38:58 +02:00
Meta Vens
72ed5cc15f ChunkHeight puts a rock's top on the floater layer: its centre is a drawn radius below (ruling asteroid-tops-at-layer)
DrawAhead.ChunkHeight subtracts pose.w, the radius the renderer scales the rock by; reticle and renderer both read it. DrawnPoseTests pins top == layer at radii 2..9. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:34:20 +02:00
Meta Vens
da2a7cc56a Merge origin/master into asteroid-floater-layer 2026-10-17 18:25:01 +02:00
Meta Vens
0f5def1794 Catalog: replay minor-power-factions, pirates-faction, product-lines minor-powers, product-lines gear on master's catalog
Regenerated through AetherDb on the merged tree, never a branch's blob (follow-ups catalog-blob-merge-order, catalog-merge-replay-order). Second pass of all four is a byte no-op. Blob sha256 a4ff0effc5b80bbd4edea4c9f3855555d622e6939edfb720d08c4603b61ebee9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:07:10 +02:00
Meta Vens
f123cdb735 Merge gear-lines (eureka/aetheria-release-gear-lines, a1e81613)
Code only. The branch's GameData/Aetheria.cc is not taken; the catalog is regenerated by replay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:02:03 +02:00
Meta Vens
c486b06d04 Merge minor-power-factions (eureka/aetheria-release-minor-power-factions, 7d1106a9)
Code only: Aya, Megiddo and Forge as ordinary factions, the Pirates allegiance top-up, ten minor-power products. Also carries the ItemData.ResolveStatField fix: the static stat-field cache is a ConcurrentDictionary (Soul judged ItemData the right owner), because parallel catalog opens raced on it. The branch's GameData/Aetheria.cc is not taken; the catalog is regenerated by replay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 17:01:16 +02:00
Meta Vens
7d1106a907 Stat-field resolution cache is concurrent: parallel catalog opens corrupted the shared Dictionary
Two test classes opening the catalog at once threw 'concurrent update' from
ValidateStatModifiers; the cache is static.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:25:49 +02:00
Meta Vens
cfba303afa Test: gear draw assertion back to Assert.Contains
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:23:48 +02:00
Meta Vens
16eef88455 Test: gear draw failure names the weights
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:22:40 +02:00
Meta Vens
51fc64de31 Tests: Pirates allegiance count is the other factions' count, not 12; gear draw seeds spread by a hash
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:22:01 +02:00
Meta Vens
a1e81613e6 Tests: the weapon and gear command tests share one xunit collection
Run side by side they raced on shared catalog state (concurrent-collection error in the mutation job's baseline at c8deb15b). Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:18:41 +02:00
Meta Vens
c8deb15b38 Tests: null-safe role filter in the gear invariant; scratch roleless design drops its role-naming behaviors
The first full Yggdrasil run at 446c1325 failed these two tests (a design with null Roles; the store refusing Radiator's behaviors once its roles were cleared). Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:14:06 +02:00
Meta Vens
1191aa1423 Test: a minor power's own allegiance names every faction but the Pirates
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:02:14 +02:00
Meta Vens
446c13252f Catalog: product-lines gear apply (22 gear products)
Output of 'product-lines gear apply' on master's catalog, run on Yggdrasil; second apply reports nothing to do. Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:01:52 +02:00
Meta Vens
d91fa1a6e9 Catalog: minor-power-factions apply, pirates-faction apply, product-lines minor-powers apply (alone)
Three factions, 33 allegiance gains, the Pirates topped up to 1.0, ten products;
a second apply of all three writes nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:01:09 +02:00
Meta Vens
f54dada786 Tests: minor powers are ordinary factions, command idempotence and conflict, Pirates top-up, shipped minor-powers rows
These fail until the catalog commit lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:59:01 +02:00
Meta Vens
7e857cd6e5 Fix the Pirates top-up's two string literals (ac0b39f8 does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:58:49 +02:00
Meta Vens
fbd8ab0915 product-lines minor-powers: ten products of Aya, Megiddo and Forge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:54:34 +02:00
Meta Vens
ac0b39f84e minor-power-factions command, MakerProfiles rows, Pirates allegiance top-up (ported from 57083412)
MinorPowerFactionsCommand authors Aya Collective, Megiddo and Orbital Forge as
ordinary factions plus the gains on other factions' Allegiance. pirates-faction on
an existing record now tops up allegiance under its key. Unbuilt here; verified at
the head on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:54:31 +02:00
Meta Vens
3e5e794bcc Tests: gear line rows, two-maker gear invariant, per-line command tests, cargo exemption
Builds: not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:54:23 +02:00
Meta Vens
064d19a1d3 AetherDb: product-lines gear (22 rows), cargo bays exempt from the no-roles refusal
Builds: not yet run (verified at head by Yggdrasil job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:53:28 +02:00
Meta Vens
f66d921fec release map: gear-lines and minor-power-factions (PL10-PL13), replay order
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:50:56 +02:00
Meta Vens
7dddcc4727 Merge eureka/aetheria-gravity-floater-fixtures-wells (floater-fixtures-wells, head d6380ca8)
Origin branch lagged at c631e09f; merged the closed head d6380ca8 from the shared object store (branch hands/ag4-floater-fix, unpushed).

Spec aetheria-gravity:cut_spec:cut-floater-fixtures-wells.r1; report h1; Soul s1 holds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 15:03:43 +02:00
Meta Vens
e1ec1e89a2 Merge eureka/aetheria-release-ships-studio-footprint (ships-studio-footprint, head 13499535)
Spec aetheria-release:cut_spec:cut-ships-studio-footprint.r1; reports h1, h2; Soul s2 holds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 15:03:15 +02:00
Meta Vens
1349953500 Shape.SetLine writes through the indexer so it invalidates the caches; footprint tests pin refusal Position and a wide shape
Builds: yes (Shared-only; verified on Yggdrasil in the report).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:33:41 +02:00
Meta Vens
d6380ca8e0 DrawnPoseWiringVerify: the planet passes within about 8 u of both floaters; the guard names the heights it saw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:28:27 +02:00
Meta Vens
417ac9c76a DrawnPoseWiringVerify: the planet passes within about 20 u of the pickup and mine, with a wider softening, so the field moves over a lead
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:23:17 +02:00
Meta Vens
cc243e7f7c DrawnPoseWiringVerify: bind the prefabs to the wells zone directly, no ZoneRenderer
A renderer loading a zone with a sun and a planet needs the planet prefab, the map and a GPU; the check pins the presenters' Place, so the prefabs are bound as LoadFloatingItem and LoadMine bind them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 14:14:05 +02:00
Meta Vens
b3eb6b0c37 Floater fixtures: planets placed where the field changes under the floaters; probe removed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:56:32 +02:00
Meta Vens
b708d51617 probe (temporary) 2026-10-17 13:54:38 +02:00
Meta Vens
be198593cc Floater fixtures: orbits and planets live in the run store, so the fixtures open one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:53:09 +02:00
Meta Vens
f37949f139 Studio: HardpointFootprintDrawer paints a hardpoint's footprint over its hull's cells; the hull drawer tint reads HullFootprint.Cells
Editor code; not yet compiled (Unity batch compile at the end).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:50:50 +02:00
Meta Vens
d76b27673a HullFootprint: the one footprint cell reading and edit rule (grow, trim, refuse last cell), with tests
Not yet built or run (verify job at the end).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:49:45 +02:00
Meta Vens
7a44e0c00c Shape: one dirty flag invalidates Coordinates, AllCoordinates and CenterOfMass; Resize marks dirty
Resize keeps its fill (new cells on): the hull drawer's width grow relies on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:48:35 +02:00
Meta Vens
71fa9411c6 Belt rocks and their reticle are drawn on the floater layer over the field by DrawAhead
DrawAhead.Chunk/ChunkHeight (ruling asteroids-on-floater-layer); ZoneRenderer and the
chunk reticle both read it; ChunkWorldPosition and the renderer's global are gone.
Fixes the reticle sitting off the rock by |field|. Test: AChunkIsDrawnOnTheFloaterLayerOverTheField.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:48:34 +02:00
Meta Vens
2055e18d3e Delete AsteroidVerticalOffset: setting, asset line, shader global, and the asteroid shader's field read
Rock height leaves the shader; DrawAhead owns it (next commit). Does not build alone:
ZoneRenderer and ActionGameManager still reference the deleted names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:48:29 +02:00
Meta Vens
e4f19df15e Shape caches: behavioural tests (CenterOfMass and AllCoordinates stale after an edit; Resize fill kept)
Builds; ShapeCacheTests.CenterOfMassFollowsACellCleared and ResizeRecountsEveryCoordinateRead fail at this commit by design (fixed in the next).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:48:17 +02:00
Meta Vens
c631e09fe8 Floater fixtures: the grab-point test and the wiring verify run over a moving well
PickupTests builds the zone over a sun and a planet on a rail, asserts the field differs between the ship's point and the item's and between start and end of the run, and checks each grab event at the zone time it was published. DrawnPoseWiringVerify gets a sun and a planet near the pickup and mine, requires the field under each to move with the drawn time, and checks the pickup's y as well as the mine's. Not compiled or run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:47:52 +02:00
Meta Vens
333d95ec04 release map: ships-addon line at 1d4aa626 (footprint split out, underlay waits on question, livery and mesh-mounts holds)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:46:11 +02:00
Meta Vens
0c8b15f6c1 gravity map: B57 asteroid probe (reticle gap, rock size, thinner belts); floater-layer cut line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:41:52 +02:00
Meta Vens
1d4aa626aa RigBrandTests: Belt is built in its own pinned arena, not eight seeds that may hold no belt
Merge fix: the children-within-reach generator leaves 37 of 90 arenas with no belt, so
Belt.Stage threw under seeds 7919*k. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 12:18:26 +02:00
Meta Vens
6fe7f7cecb Merge eureka/aetheria-gravity-children-within-reach (children-within-reach, head cf242106)
Merged into master f937662d. No textual conflicts (auto-merged: ActionGameManager.cs,
Belt.cs, LockOn.cs, RunStartTests.cs, ScenarioTests.cs, AetherDb/Program.cs).
GameData/Aetheria.cc untouched by the merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:52:44 +02:00
Meta Vens
cf242106fa Tests: every turret on a read side clears the base body by its extent and reach
The 0.8 tail-extent mutant survived the stop checks alone: it places turrets inside the
distance, which only a placed turret's own clearance shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:30:03 +02:00
Meta Vens
a54707d1d8 Tests: drop the tail diagnostics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:10:25 +02:00
Meta Vens
c345b303de Tests: tail test leaves out stations whose base family holds a belt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:09:03 +02:00
Meta Vens
f881a3bdfe Tests: tail test reads stations whose turrets do not wrap the ring
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:07:54 +02:00
Meta Vens
7db87cfa88 Tests: the entrance fallback reads its root's extent from the bodies alone; tail diagnostics
The zone's well tree counts the station's own rail in its root's family, so the extent is rebuilt
from the generated bodies. Carries a temporary DIAG line in ATurretTailStopsAtItsBaseBody.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:02:51 +02:00
Meta Vens
c39a73ca12 Tests: belts fill their slots, five placement rules pinned by forced fixtures
BeltsFillTheirSlots (midpoint, slot bound, no zero-width belt, width distribution printed),
ANarrowAuthoredBeltKeepsItsWidth, ASoleRootRingSitsAtThreeEighthsOfItsRadius,
ARingMembersChildrenStayWithinAFifthOfTheChord, ATurretTailStopsAtItsBaseBody and
ATutorialEntranceWithNoCandidateOrbitsItsBodyRootOutsideItsExtent. Not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:00:21 +02:00
Meta Vens
b13aa67efd Place: a belt fills its slot between its neighbours' spacing, the Roche margin and the window
Replaces the symmetric half-width about the chain position (which collapsed a belt at the end of its
slot to a line, finding belts-collapse-to-a-line) with the slot interval: the belt sits at the slot's
midpoint and its half width is min(authored width, slot) / 2 (ruling belt-fills-its-slot). The chain
still places belts as massless points, so no fold count moves. Builds; tests follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:00:04 +02:00
Meta Vens
6214741ab5 Restore LiberationSans SDF - Fallback.asset to its 09a7f189 LFS pointer
Unity re-serialised the generated atlas into the working tree and it was committed
in c727141a; the file is back to the pointer (oid f1eead45, size 536050). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:45:41 +02:00
Meta Vens
f937662d75 Merge eureka/aetheria-ew-ew-belief-allegiance (ew-belief-allegiance, head ac5cbcc5)
Spec aetheria-ew:cut_spec:cut-ew-belief-allegiance.r2; reports h1, h2; Soul s2 holds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 08:44:50 +02:00
Meta Vens
ed39d9460d gravity map: B56 belt fills its slot (r4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:41:39 +02:00
Meta Vens
ac5cbcc51b EW 3 fix: a contact is hostile on the observer's own permission, with tests for trespass through Zone.Update
Entity.IsHostileTo read other.PresencePermitted in its claimed-owner term where the spec and map S2
say the observer's own, so a trespasser never held the owner's patrol hostile. Tests: the trespasser
(player or not) holds the patrol hostile and its guns are not safed, a permitted neutral does not,
a ship tracked in open space turns hostile on entering the Critical area through ticks (pins the
per-tick stance refresh), and a third party does not treat a trespasser as hostile (pins the owner gate).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 08:10:29 +02:00
Meta Vens
cbb4526070 EW 3 tests: a live quiet subject's reveal stays in the book, so the belief ends by age, not by the book dropping
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:32:45 +02:00
Meta Vens
6460eed688 Research: quality combining rule meta (rule families simulated over the catalog), for question quality-combining-rule-meta
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:19:47 +02:00
Meta Vens
5a7ab7944b EW 3 tests: add the Forbid helper the previous commit referenced (8a779b3a does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:10:54 +02:00
Meta Vens
1ddd1bef31 EW 3 tests: reciprocity test comment no longer names the deleted recursive branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:05:45 +02:00
Meta Vens
8a779b3aa8 EW 3 tests: forbid by direct PresencePermitted (Update re-derives the security level); listed-once after a tick
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 07:04:46 +02:00
Meta Vens
49423b61fe EW 3: allegiance is the observer's belief; telemetry with the track, grudges from acts, one stance writer
Cuts WatchForGrudge, PerceivedStanceOf, the recursive IsHostileTo and the inline compare-and-write; adds _telemetry (ReceiveTelemetry at track entry), Provoke (Track paint, committed shot), RefreshStance, BelievesTrespassing. Not yet verified: unbuilt, tests unrun.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:45:51 +02:00
Meta Vens
3034721958 ew map: B2 corrected
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:35:03 +02:00
Meta Vens
afae0c6b97 ew map: cut 3 probes at ae300c6a (B1-B3, S1-S6); model page for allegiance belief at track entry
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:25:48 +02:00
Meta Vens
1f83d0743b Tests: folding takes the lightest family
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:08:02 +02:00
Meta Vens
4d6c307d0c StationPlacementTests: each generated galaxy has its own directory
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:07:09 +02:00
Meta Vens
b305c66c6c Tests: belts keep a spacing from their neighbours; story turrets at 3, 5 and 9; a station never sits on a binary's bodyless node
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:56:58 +02:00
Meta Vens
f5329e50a2 RestoredHullsTests: the entrance throw is reached by a single-root zone (several roots give the station a root to orbit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:55:53 +02:00
Meta Vens
ae300c6a84 release map: maker-only faction r3 at aa12cbac
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:47:51 +02:00
Meta Vens
c727141a2f Scenarios: Belt and Lock On take the seeds that hold their conditions under the new placement
Belt: seed 86 (484 rocks, scanned over seeds 1-90). Lock On: seed 1 (the staged hostile settles below the detection threshold).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:40:34 +02:00
Meta Vens
3ef0ac21eb RunStartTests: the belt race takes the first arena that has a belt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:31:08 +02:00
Meta Vens
2111174adf Stations: a candidate rail clears each massive sibling's extent by the largest station or turret reach
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:27:47 +02:00
Meta Vens
513d0c4393 Place: ring merge decided on the heavy member's final mass; a bodyless node keeps a cusp as the one body it would become; tests follow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:25:26 +02:00
Meta Vens
c3d7d077e6 Tests: compile fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:22:57 +02:00
Meta Vens
ed9f9930dd Place: a sole root's ring also folds when it cannot keep its heavy member outside the Roche margin; the entrance station falls back to the heaviest root of childless roots; tests follow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:21:11 +02:00
Meta Vens
aa12cbac8b Catalog: replay verse-grammar apply on the merged catalog (faction-play-1 adds the follow verb)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:13:31 +02:00
Meta Vens
0dc7e4bae3 Tests: compile fixes (does not isolate a build until this commit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:13:03 +02:00
Meta Vens
2409eed0dc Tests: children within reach, subzone isolation, station and turret clearance
ChildrenWithinReachTests reads the production generator's zones (seeds 1-6)
through the Zone and checks each Place rule; SubzonesAreIsolated prints its
pair and orbit counts. StationPlacementTests: a station's source is a body (the
tutorial root-node fallback excepted), turrets clear their base's extent, no
station or turret sits on an unrelated body over 64 instants. Not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:12:17 +02:00
Meta Vens
e83f9a2ed1 Merge eureka/aetheria-release-minimap-asteroids-setting (cut-cut-minimap-asteroids-setting r1, h1) into master
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:58:22 +02:00
Meta Vens
84337de569 ZoneGenerator.Place owns every generated distance, fold and belt width
PlanetSafetyRadius, ChildDistanceMinimum/Maximum, ExpandSolar's distance series
and the window filters are deleted. Place (ported from replace.py, root window
from rootReach per root-window-floor) lays children inside-out, folds the
lightest family while the outermost overflows, stretches to the window, merges
rings that cannot keep their heavy member outside its Roche margin and sets
belt half widths. Stations pick well-bearing, sibling-clear off-ring bodies;
the tutorial entrance falls back to an orbit round a root node; turrets stop a
side when within the base body's extent. GenerateZone/GenerateArena take
PlanetSettings. Not yet built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:55:57 +02:00
Meta Vens
781607763e WellTree: SubzoneReach is one public static; the strengthless-orbit mean rule is deleted
The nearest-anchor rule (Reach x distance to the nearest other root) moves to
WellTree.SubzoneReach(anchors, root) so the generator spells it once; the
instance method returns max(it, floor). PullAround no longer gives a
strengthless orbit on a ring a period of its own (binaries-orbited-from-afar);
its test goes with it.

Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:55:48 +02:00
Meta Vens
d7f30ed165 Merge eureka/aetheria-release-faction-play-1 (cut-faction-play-1 r3, h6) into master
Catalog GameData/Aetheria.cc regenerated by replaying doctrine-catalog apply on the merged catalog, not taken from either branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:50:24 +02:00
Meta Vens
6179846249 Merge eureka/aetheria-release-product-lines-weapons (cut-product-lines-weapons r5, h4) into master
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:48:14 +02:00
Meta Vens
1bb17feabc OldPlayerSettingsLoad: write the old key 2 as 0.25f
The previous commit changed only the assertion; the hand-written array still
wrote the default 1f, which loads the same with key 2 dropped. Builds; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:40:48 +02:00
Meta Vens
dc0b1e2cfe OldPlayerSettingsLoad: old key 2 carries a non-default value
A default 1f would load the same with key 2 dropped, so the test could not
fail when the old array lost it. Builds; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:37:13 +02:00
Meta Vens
b70372963a Delete the minimap asteroids setting; minimap belts always draw
Ruling minimap-asteroids-setting-deleted. PlayerGraphicsSettings key 1 stays
retired so old saves load; OldPlayerSettingsLoad now writes the old 3-element
array by hand. MapPresenterSmoke asserts a belt draws with the map screen
closed. Not built or tested yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:36:13 +02:00
Meta Vens
4e620671dd gravity map: B55 root-window isolation measurement; pointers to children-within-reach r3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:32:28 +02:00
Meta Vens
0f2fc859de ConsumableAiTests: the following agent leaves combat before it is set to follow
The agent starts in combat; two zone ticks with nothing sensed return it to patrol, as the patrol test does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 04:03:08 +02:00
Meta Vens
199f1b1b94 ConsumableAiTests: the following agent clears the Ship's VisibleEnemies
The previous commit does not build: VisibleEnemies is on the Ship, not the Agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 03:51:43 +02:00
Meta Vens
09a7f18985 Merge eureka/aetheria-gravity-well-law (cut well-law; Soul verdicts s1-s4)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 03:49:59 +02:00
Meta Vens
843acb5341 faction-play-1: pin the vent in FollowState, pins to 10%, drop the dead LockAlarm
Combat.cs loses its unused LockAlarm constant. ConsumableAiTests gains a following agent that vents. FlightTests adds
follow-velocity, pull and compliance-entry cases a tenth either side of their thresholds and a hail member that is
nearest only with z halved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 03:49:37 +02:00
Meta Vens
7444f4a0c9 ProductChoiceTests: the nearer-maker bounds tight enough to fail a doubled distance penalty
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 03:30:50 +02:00
Meta Vens
617e602208 RigBrandTests: Arcs' turret is a fitted hull
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:53:34 +02:00
Meta Vens
d4cf8c8244 RigBrandTests: a ship's cargo bays count as fitted gear
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:51:08 +02:00
Meta Vens
86a498c566 RigBrandTests: a pin names its brand only; the design is the product's own
Not yet run on its own; the previous commit's table named designs by hand and Cargo Bay did not match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:48:47 +02:00
Meta Vens
82362da9d5 LockOnSituation: the warning is measured against the hostile's live bearing at the first lock, limit 0.5 deg
The staged line stopped being the hostile's line once consumable-ai r3 gave it a flanking approach. The message records the drift from the staged line. LockOn.cs's 5-degree staged-match claim is removed. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:47:53 +02:00
Meta Vens
94570ca0be Tests: zone-weighted and zero-weight product draws pinned; every scenario brand pin guarded under eight seeds
ProductChoiceTests adopts Soul's probes: a nearer maker is favored (non-null zone), an allegiance weighs the draw, and an all-zero
weight draws uniformly. RigBrandTests becomes a theory over every scenario whose fits name products: each pinned design must come
out as exactly its brand on every fitted ship under eight stage seeds.

Not yet run: the commit is unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 02:41:44 +02:00
Meta Vens
8f20cd3664 Merge map-presenter (aetheria-release cut map-presenter r1; closing verdicts s1 and s2) 2026-10-17 01:17:41 +02:00
Meta Vens
39c7508e38 Merge boss-gate (aetheria-release cut boss-gate r2; closing verdict s3) 2026-10-17 01:17:38 +02:00
Meta Vens
5a96035563 ConsumableAiTests: the refit waits for the new Minion to reach combat
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:13:28 +02:00
Meta Vens
f11ec4f676 ConsumableAiTests: the refit tick count reaches combat from the new Minion's patrol start
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 01:11:15 +02:00
Meta Vens
4920b2c9c0 MapPresenterSmoke pins icon axes and heading; capture proves deep-well pixels; belt benchmarks at 1000/2250/4000
Smoke asserts each icon's x and z against the sim position (non-symmetric, ships ride at y 50 and -90) and the
yaw from the forward heading with a near-vertical rolled hull whose eulerAngles.y differs. MapPresenterCapture renders the
scene's Map Overlays and Map Tint cameras to pixels. MapBeltPerf measures base (MapBeltPerfBase, verbatim
AsteroidBeltUI) and head as median/IQR of 21 runs. All build.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 01:02:39 +02:00
Meta Vens
6985ece70b ConsumableAiTests: the refitted fixture agent starts on patrol and takes one more tick to reach combat
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:56:20 +02:00
Meta Vens
0e0afda03d Merge eureka/aetheria-release-ship-render-fixes-r3 (cut cut-ship-render-fixes, verdicts s2 and s3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:53:39 +02:00
Meta Vens
6f31375def Flight: a member's friendly override keeps it from following a flightmate's track; consumable-ai fixture orbit built on the zone
The union picture stays the flight's; the per-member override is read where the member chooses its bearing. A first
version dropped the track from the whole picture and silenced a hostile unaffiliated flightmate (SmokeRoundsStepped
AiFusedDiscipline).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:40:59 +02:00
Meta Vens
98337213a4 RigBrandTests: each rig is staged under eight seeds, so a pin is told from a lucky draw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:28:00 +02:00
Meta Vens
ca050c9b05 WellLawTests: the belt fixture lists its outermost asteroid in the middle (10, 87, 43)
An extent read from the first or the last asteroid now fails the belt test (finding s3.belt-fixture-first-read). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:26:47 +02:00
Meta Vens
b08f7d80ae FlightTests: the friendly-override pin builds in both orders; compile fixes for the s4 pins
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:23:01 +02:00
Meta Vens
2bb08a91ee Flight: a track any member made friendly is out of the picture; pins for the s4 findings
The flight builds the picture, so it is where per-member friendly overrides meet; the track is dropped there. New
pins: a tuned doctrine survives doctrine-catalog apply, the follower's velocity match and pull at scale, compliance on
a diagonal, the hail speaker and engaged pick off-axis. Not built or run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:21:43 +02:00
Meta Vens
0e40a66592 Vent on a Track paint in every agent state: Agent.Update owns the vent, CombatState keeps the overdrive
Ruling vent-in-any-state. The vent decision (own Track paint above .5, one of a kind through TryActivateConsumable)
moves out of CombatState into Agent.Update, which every state runs; CombatState's overdrive asks Agent.TrackAlarm so a
venting tick still does not overdrive. ConsumableAiTests: AVentDoesNotNeedAnyEnemyInSight is master's premise again
(empty VisibleEnemies), a patrolling agent has its own test, and the fixture zone has one orbit so an unengaged pilot
patrols it. Not built or run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:21:40 +02:00
Meta Vens
d135c77e0e Merge origin/master into faction-play-1 2026-10-17 00:13:54 +02:00
Meta Vens
66aee3cf0e ProductChoiceTests: an outfitter that reaches no maker gets no product
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:04:35 +02:00
Meta Vens
4694366d98 Map presenter: ShowAsteroidsInMinimap stays (head's belt cost misses 0.1 ms); belt upload via SubUpdates; settings key restored
The setting gates belts on the minimap again, through MapPresenter.BeltsOnMinimap; the map screen always draws them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:54:45 +02:00
Meta Vens
07f0037148 MapBeltPerf: belt cost per frame in CPU ms and managed bytes; script metas
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:41:39 +02:00
Meta Vens
350c40236b MapPresenterSmoke: deep planet, yaw-only tilt, one draw per kind, one belt draw, fade; capability smoke binds an icon
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:40:15 +02:00
Meta Vens
35406653b6 GravityField: the band potential's promise is the float32 bound measured, 1.8e-6; the sweep covers the taus above the seam
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:30:31 +02:00
Meta Vens
281745394b Map presenter: one owner places every map icon in 2D, belts become one instanced draw (not yet compiled)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:26:26 +02:00
Meta Vens
538333a4b4 WellLawTests: pin the Gamma half of the fade start and the zone rim radius; the belt fixture is unsorted; SubzoneReach says what superposed-inside needs
Not yet run: pushed once the filtered suite passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:22:16 +02:00
Meta Vens
75df9a8421 RemovePackage: drop the dot-name clause the trailing-dot rule already covers
'.', '..' and '...' all end in a dot; one rule decides, not two.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:16:05 +02:00
Meta Vens
e57eedea71 RemovePackage test: the missing-name case must not create its directory
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:59:36 +02:00
Meta Vens
9315a0019d FireControlPerWeaponTests: the turret threshold is pinned half a hundredth either side of the price
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:57:44 +02:00
Meta Vens
afc570affd ConsumableAiTests: the refitted agent senses the prey again
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:52:29 +02:00
Meta Vens
b76e212d60 RemovePackage: containment under Mods and RemovedMods, name round-trip, no links; Remove dialog keeps other buttons
Refuses names the filesystem rewrites (dot names, trailing dot or space, device names, stream colon), anything that does not
resolve to a strict child of the mods folder under the same name, and link packages. A fault with no known package names
(all mods), so no Remove button. A removal drops only its own button and the dialog returns to the rest.
Unity compile not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:49:44 +02:00
Meta Vens
0f8bb6d9da Release map: map presenter (owner audit, 2D icons, instanced belts, the asteroid setting's cost)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:48:18 +02:00
Meta Vens
ff34648371 ConsumableAiTests: the refit re-admits the agent as a pilot (Zone.Remove drops the agent on this branch)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:42:46 +02:00
Meta Vens
00956ce329 Tests: a loadout may reference products; the unavailable-product test fails one design; distribution tests spread their seeds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:34:34 +02:00
Meta Vens
1519aa8f44 Tests: consumable-ai fixtures let the flight target the prey (the flight is the only Target writer); standoff range, presence and wire-slot test fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:24:33 +02:00
Meta Vens
94ab2d3f50 ProductChoiceTests: the draw follows the outfitter's preference
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:17:35 +02:00
Meta Vens
4609f148a2 Tests: product choice (outfitter, seed, pin, key shuffle, capture, wrong-design chooser, wire keys); rigs keep brands; key-order test removed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:16:15 +02:00
Meta Vens
7bbaa26675 ScenarioStage: names are designs or products, one Resolve path with the generator's chooser; rigs pin today's brands; Crossing back to 1216
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:10:58 +02:00
Meta Vens
3a081160b4 LoadoutGenerator: ChooseProduct (weighted seeded draw, name-ordered) and ProductWeight; generation shares the weight
Builds with commit 1 only once the callers move (commit 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:10:13 +02:00
Meta Vens
40e2ada37e Loadout: slots and hull may name a product; one Resolve; Capture records the brand; ProductsInKeyOrder deleted
Does not build alone: Materialize's callers move in later commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:10:03 +02:00
Meta Vens
b5c4fd0b8e Release map: PL7-PL9 product choice in loadouts (pins, ChooseProduct owner, key order retired)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:08:19 +02:00
Meta Vens
7518c0f3e8 DoctrineCatalog: fix the nothing-to-author line (previous commit does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:07:49 +02:00
Meta Vens
9376e5fcc0 WellLawTests: the three-subzone fixture puts the big sun off the origin and pins each subzone's reach
The first fixture hid the big sun's weight in the barycentre (it stood at the origin) and tested reach with two roots only, where nearest and farthest coincide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:07:11 +02:00
Meta Vens
46a2296ce8 Tests: rig fixture gives map and collider nodes a mesh; fix two test slips
Bind now refuses a meshless map-icon or hull-collider, so ShipRigTests' GLB
needs the meshes real packages carry. Not yet re-run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:05:53 +02:00
Meta Vens
c30764e33e faction-play-1 fixes: doctrine-catalog apply writes nothing on rerun; tests pin the unseen rule off-origin, the hail speaker in every build order, wire slot 17, exact-name match, scaled standoff, compliance axes, threshold boundaries, follow velocity
Does not build-verified yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:05:02 +02:00
Meta Vens
2ff48d0b45 Merge origin/master (da6fe033) into faction-play-1
Combat.cs: master's lazy optimum-range owner kept, the OptimumRange accessor beside it. FireControlPerWeaponTests: the exponent test runs the first Update before reading the optimum (master derives it there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 22:01:56 +02:00
Meta Vens
794ff00541 PotentialOwnerTests: the two-sun height oracle is held to Gamma x reach, where a well is its Plummer pull whole
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:51:20 +02:00
Meta Vens
d35730dc9d ShipModPlaySmoke: exclusion at compose, ImportFault at preload, removal by RemovePackage
Phase 1 expects the map-icon sibling excluded by Compose; phase 2 installs a
sibling whose GLB lost its BIN chunk and requires ImportFault naming exactly
it; phase 3 removes it and composes again. Editor code; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:50:12 +02:00
Meta Vens
f0ec95e640 RemovePackage test: spell the backslash name as a backslash
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:49:18 +02:00
Meta Vens
65a6ce8705 MainMenu: a surfaced broken mod gets a Remove button that moves it aside
RefuseMods names every faulted or excluded package with one Remove button per
package, all through ShipModCatalog.RemovePackage; the catalog stays as this
boot opened it and the dialog says to restart. ModsPath becomes public.
Unity-only code; not built until the Starfire smoke at the end of the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:48:57 +02:00
Meta Vens
249beaa03f Preload faults Loading with ImportFault instead of skipping a composed hull it cannot build
The skip-and-log is deleted. A composed hull that fails to import is a fault
naming its package, not a silent drop. Unity-only code; not built until the
Starfire smoke at the end of the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:47:54 +02:00
Meta Vens
e04e247820 ShipModCatalog.RemovePackage: the one uninstall moves a mod aside to GameData/RemovedMods
Presence under Mods is the only enablement; removal is a move, never a delete,
and moving a package back reinstalls it. Refuses names that are not a package
directory directly under the mods root. Not yet built or run; verify runs at
the end of the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:47:38 +02:00
Meta Vens
f9ece91638 Boss gate test: the main galaxy places no boss in the shipped catalog, so give it one off the exit
Fixes the previous commit's Exit_open_only_in_the_exit_zone, which asserted bosses the main galaxy does not have.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:39:05 +02:00
Meta Vens
3f29d803eb Bind refuses a mod Assemble would throw on: meshless map-icon and hull-collider, non-positive shield scale
Compose is the one owner of whether a mod hull is available. Bind now reads
the node scale and matrix in ReadNodeIds and refuses what Assemble refuses.
Not yet built or run; the verify job runs at the end of the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:37:51 +02:00
Meta Vens
6c53dac3c5 PotentialOwnerTests: the gradient check allows the height's float32 resolution on flat ground between subzones
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:34:34 +02:00
Meta Vens
65aa61811e Well-law tests follow the subzone law: two suns 600 apart are two subzones, not a superposition
WellsSuperpose is removed (its rule, roots superpose everywhere, is the one multi-root-zone-shape decides); HeightIsThePotentialOverOneK and FlowFieldTests probe inside each well's reach. ZoneWorlds gains Belt and AsteroidSize; fade and ring tolerances are relative to the Plummer pull. Not yet run on dotnet at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:32:30 +02:00
Meta Vens
dca660e448 Boss gate: TryWin is the one way to win; equal-gap tie-break and two exit pins tested
Win() becomes TryWin(), which checks RunGoal.ExitOpen itself; the call site no longer reads it.
Pins: first-of-equal-gaps, exit-zone-only, no ship hull on offer. Not yet built or run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:18:52 +02:00
Meta Vens
250b61be2c Well law fix batch: zone node for several massive roots, belt extent, series from tau 0.4, Unity parity on the multi-root fixture
One zone node at the massive roots' centre of mass owns the only global term (SubzoneReach is the one place the subzone shape is decided: isolated-subzones). WellNode gains Extent and Anchor; a belt orbit's extent is its outermost asteroid. GravityField.SeriesFrom = 0.4 is emitted into the shader template and Gravity.cginc. Tests: the spec's WellLawTests; the old seam test is replaced by TheBandPotentialIsExactInSinglePrecision. GravityFieldParityVerify runs the multi-root fixture (second sun, moon inside the planet's Roche limit, far window): PASS, largest drawn tau 1.228, max error 0.01028 u. The dotnet suite has not been run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:14:58 +02:00
Meta Vens
807533d26b FlightTests: the combat-exit test removes every listing of the engaged track
The grudge lists the track in VisibleEnemies a second time (the hostility refresh adds it again), so a single Remove left it visible.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:58:26 +02:00
Meta Vens
c387b137d1 FlightTests: combat exit diagnostics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:56:05 +02:00
Meta Vens
45ab0b9f23 Aetheria.cc: master's catalog with doctrine-catalog and verse-grammar re-applied
doctrine-catalog apply wrote four doctrines (Pirates included); verse-grammar apply added the follow verb (follow-up catalog-blob-merge-order).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:55:22 +02:00
Meta Vens
4fc225b1d5 VerseGrammarTests: the shipped catalog holds eight starter verbs; combat exit asserts the Target cleared
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:54:47 +02:00
Meta Vens
ae290654aa GameData/Aetheria.cc: product-lines weapons apply onto master's catalog (df154ffb), replayed
Master's blob (oid ed0500b4) with the twenty products and nothing else: applied once, then again with no change
(second apply: nothing to do, bytes identical). Replaces the blob whose five hulls a probe had re-encoded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:54:41 +02:00
Meta Vens
da6fe0334e Merge origin/master into suns-never-green + consumable-ai merge (docs only)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:53:39 +02:00
Meta Vens
ceb1a08edb product-lines apply lands on a catalog with older-schema records; refusal axes pinned; one maker-profile table
ExpectUnchanged compares the file's schema ids with the loaded ones, so master's blob (hulls written before
HullData lost GridOffset) made apply throw and write nothing. The batch now expects only that the keys it authors
are absent and lands onto the file as it is. Tests: older-schema replay, the design and maker match, case-insensitive
name conflict, a row name that is a design's, the dispatch word, and the sold-weapon floor replaced by "only Smoke
designs are unsold". LaunchSuppressorCatalogTests reads Program.MakerProfiles instead of spelling six profiles.

Not built or run yet; the catalog blob is regenerated in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:50:47 +02:00
Meta Vens
c1c8d8d7de Gravity map: B52-B54 multi-root zone node, belt extent, series threshold 0.4; rationale for well-law r3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:48:59 +02:00
Meta Vens
e5d35352ee Merge consumable-ai r3 (cut consumable-ai; verdicts s2, s3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:36:18 +02:00
Meta Vens
2d96c3241f Merge suns-never-green (cut suns-never-green; verdicts s1, s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:36:15 +02:00
Meta Vens
04516c72cf Faction play 1: s1/s2 fix batch (Engaged-first anchor, doctrine pins, follow verb)
Flight anchors a blind member on an Engaged track before a nearer Hailing one and keeps its anchor only while nothing outranks it. Doctrine.cs states the trespass rule as the zone owner's permission. DoctrineCatalog matches the faction by exact name and its comment names the landed Pirates record. VerseGrammarCommand gains the follow verb. Tests pin default and authored standoff, Grace against ComplySpeed, nearest hail, the Identified boundary, off-origin direction and anchor choice and switch, the unseen-member rule across geometry, combat from follow, the doctrine-catalog dry run and the turret's global hit threshold.

Not yet run: this commit's tests have not been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:31:41 +02:00
Meta Vens
86c3a94880 Merge origin/master into faction-play-1
Conflicts: GameData/Aetheria.cc takes master's blob (doctrine-catalog and verse-grammar re-applied in a later commit, follow-up catalog-blob-merge-order); IffAndCombatTests NewShip admits through zone.Admit(ship, piloted); Program.cs keeps master's cases plus doctrine-catalog; FireControlPerWeaponTests keeps master's asserts with the branch's Minion constructor. Master-only compile sites adapted: Minion(ship, doctrine) in FireControlPerWeaponTests, LayoutAimTests, ScannerTests; AgentFires threshold in SolutionTests; Zone.Remove and VerseGrammar in FlightTests.

Not verified to build until the verify run at the end of the pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:18:54 +02:00
Meta Vens
c23390c76e CatalogRoleTests: the mine launcher's renamed brand is found by name among its sellers
Tripwire is a second seller of the Mine Launcher; the test asserted the design had a single product.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:01:52 +02:00
Meta Vens
df154ffbdd Gravity map: B50 pockets probe (drawn extent and basin share, C0/C1/C4), B51 binary period shear and C4 merge counts; rosette-equilibria line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:52:30 +02:00
Meta Vens
e5962d960d Crossing: the Lightning Projector's settled Range follows the product a design's first key gives
The staged fit names designs, and the first available product of the design by key builds it. With the Static Shock line in the catalog that product is NiteLife's, whose settled Range is 948.8 m where Lucent's DragOnBreath gave 1216.4; the waiting Djinni sits at 80% of it. Compiles; CrossingConditions passes with the catalog commit before this one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:30:55 +02:00
Meta Vens
1dd3627500 GameData/Aetheria.cc: apply AetherDb product-lines weapons again, with name-derived record keys
Regenerated from master's catalog (cee8cd6e) in the ygg-verify container; a second apply says nothing to do. Replay the command at merge; do not merge this blob. The five HullData records still on the schema before orbital-layering deleted GridOffset were re-encoded first (no ExpectUnchanged commit lands on a catalog with a stale record schema), so this blob carries those five hulls re-encoded plus the twenty products.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:29:13 +02:00
Meta Vens
1e9a89e401 CombatState: drop the StatsKnown gate; a stale optimum is re-derived at the next agent Update
Agents update before the entities, so a weapon that came online this tick has evaluated by the next Update;
the Weapon.StatsKnown flag and the gate on it were dead machinery and are removed. The add handler no longer
marks stale itself (a new item's Online subscription does). The refit test fits and removes a dominating gun.

Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:28:29 +02:00
Meta Vens
05b262f139 Product lines: records get keys derived from the product name; two catalog tests stop hard-coding the old seller sets
The command's records now land with a key derived from the product name, so a replay at a merge reproduces the same records. CatalogRoleTests.RenamedDesignsKeepTheirKeysAndProducts asserts the renamed products are among a design's sellers, not all of them; RolesBackfillIsAuthored reads maker profiles from Program.MakerProfiles (plus the Pirates) instead of its own copy, which lacked AU. Catalog commit before this one is stale: the next regenerates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:28:00 +02:00
Meta Vens
4930ecd06a Suns: secondary hue stays on the allowed arc with the primary; ramp never crosses the band
The secondary is placed along the allowed arc (reflected at its ends, distance capped at half
the arc) so the RGB blend between the two stops stays outside the band for any Settings band.
Tests sample the production ramp and pin draw uniformity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:14:15 +02:00
Meta Vens
7e92c7da93 ConsumableAiTests: refit the gun the way a docked ship does
Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:08:59 +02:00
Meta Vens
58b78f81de GameData/Aetheria.cc: apply AetherDb product-lines weapons (twenty products)
Output of 'dotnet run --project tools/AetherDb -- product-lines weapons apply' on master's catalog, run in the ygg-verify container; a second apply says nothing to do. Replay the command at merge; do not merge this blob.

The catalog's five HullData records were still on the schema before orbital-layering deleted HullData.GridOffset, so no ExpectUnchanged commit could land on it. This blob also carries those five records re-encoded under today's HullData (plain upsert of the five, nothing else changed in bytes), then the twenty products on top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:08:08 +02:00
Meta Vens
99333cf1a2 ConsumableAiTests: the admitted agent has no patrol task (the test zone has no orbits)
Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:04:58 +02:00
Meta Vens
bf32a82e32 CombatState derives its optimum range once the weapons' stats are known, and re-derives on loadout change
A zone-spawned ship's CombatState sampled in its constructor, before any weapon had evaluated its stats,
so the optimum range read 0 and never moved. It now marks the optimum stale on construction, on any
equipment add/remove and on a weapon's online change, and samples at the next Update once every active
weapon reports StatsKnown. ConsumableAiTests build the agent through Zone.Admit(piloted: true) and read
the optimum without re-sampling; new rows pin the hold scope, hull-heading source, mixed paints, sight
independence and the optimum across two guns and a refit.

Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:03:50 +02:00
Meta Vens
3eb9d4df6c Merge stardust-before-fog: Stardust draws before nebula composite (closes aetheria-gravity verdicts cut-stardust-before-fog.s1 and .s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:01:40 +02:00
Meta Vens
df0f51be5f Merge audio-1: simulation names no sound; dead Wwise path deleted (closes aetheria-release:verdict:cut-audio-1.s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 19:01:36 +02:00
Meta Vens
4fb5cb9466 GravityFieldParityVerify: the family zone moves along its tree; tolerance restated from the run
Batchmode on Starfire, Unity 6000.3.24f1: PASS, max error 0.01077 u (tolerance 0.03), gradient 0.07 degrees. The previous
frames teleported the planetoid away from its planet, which a compact tree rightly does not draw. WellTree.cs.meta added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:51:20 +02:00
Meta Vens
3fc59887d5 Scene verifier measures dust at partial fog and reads Stardust's own event
The under-fog check lays a floor under the dust so the march has a finite ray (pixels with no depth are fogged whole), disables the zone noise, and uses a dim uniform fill: the correct event dims the dust to 0.58 of fog-free, and dust drawn after the composite reads 0.99. The check also fails when the dust is erased (below 0.1) or missing with the fog off. The attach check reads Stardust.DrawEvent by reflection and requires no Stardust buffer at any other CameraEvent.

Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:48:11 +02:00
Meta Vens
6667b4c6d3 Tests for the weapon product lines and the product-lines command
Catalog tests read the shipped records against the command's own table; command tests run it on a scratch catalog (dry run, apply, replay, untouched bytes, partial line, name conflict, tier accepted). AetherDb shows its internals to the test project. These tests fail until the catalog commit that follows; this commit builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:47:30 +02:00
Meta Vens
fa3c2ab4d3 AetherDb: product-lines command, with the weapons table
One command file owns the twenty second-maker weapon products; roles and quality come from Program.MakerProfiles, now internal. A maker already selling the design is not refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:46:12 +02:00
Meta Vens
d267a535d2 Delete NoMakerSellsTwoProductsOfOneDesign (ruling maker-design-tiers-allowed)
Its justification, Brand finding a product by (maker, design), went with lot-product. A maker may sell several products of one design at different performance.

All commits in this pass build unless noted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:46:09 +02:00
Meta Vens
cee8cd6e40 Release map: ship-render-fixes r3 (removing a broken mod), run-seed / mining-yield / product-tiers lines; mining refresh: overflow floats
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:40:32 +02:00
Meta Vens
7eaa431240 WellLawTests: a rosette's members feel their partners projected toward the node; the tau-1 branch seam is held to the float32 floor
Full suite at the previous head: 2003 passed, 1 failed (the seam test, whose 3e-6 was tighter than the closed form's
single-precision floor, 1e-5 measured, 1.5e-5 in the research).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:34:45 +02:00
Meta Vens
9d5620ddac WellLawTests: the term's slope and band, the family laws, reach and support; ZoneWorlds shared by the tree tests
Hand-built zones move from OrbitsFromFieldTests into ZoneWorlds so WellLawTests reuses them. Not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:17:59 +02:00
Meta Vens
1068eca331 Gravity.cginc regenerated from the band template; orbit and fixture tests read the new law
Gravity.cginc is GravityShader.Source() output. OrbitsFromFieldTests spell periods from GravityField.Pull composed as the law
(binary members feel the partner's pull at the chord, the outer body feels c(total mass)). Fixtures whose bodies carried
mass 0 under constant curves (WellFixture, the mining scenes) now carry a mass: the tree conserves mass. DrawnPoseTests'
rails use the Plummer pull. Builds; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:15:05 +02:00
Meta Vens
ebce853aba Stardust draws at BeforeImageEffectsOpaque, before the nebula composite; scene verifier proves dust under fog is attenuated
The nebula is an [ImageEffectOpaque] OnRenderImage; a command buffer at BeforeForwardAlpha runs after its composite, so the
dust landed on top of the fog (B49). BeforeImageEffectsOpaque runs before it on the deferred camera. FlowFieldSceneVerify
now requires one Stardust buffer at the new event and none at BeforeForwardAlpha, and scene-stardust-under-fog compares the
dust's contribution with the cloud renderer off and on in an HDR target, with a fog control.

All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:11:04 +02:00
Meta Vens
131895740d WellTree: float2 alias
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:58:17 +02:00
Meta Vens
eeeb6db290 Well law: the band term, WellTree owns every term; the old law, per-body sums and Gauss ring law deleted
GravityField is now the band term U(eps, inner, outer) (C4 smoothstep fade, closed form and a series for tau > 1).
WellTree is built once per Zone from the orbit tree: node terms, reach, support, the pruned Force/Potential walk and
PullAround (rails). Zone.GetHeight/GetForce/PeriodAround delegate to it; WellReference, _wellOn, _strengths,
Strength() and DrawAhead.Well are gone; GravityLowering and the shader template take the flat term list;
HeightExaggeration halves to 2.0491803.

Does not pass yet: Gravity.cginc is not regenerated and PotentialOwnerTests/OrbitsFromFieldTests still spell the old law.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:56:25 +02:00
Meta Vens
a8586d083f Gravity map: B49 stardust order against the opaque fog pass (camera-event probe on the ARPG camera)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:55:56 +02:00
Meta Vens
86d833b0f6 Release map: audio-1 split (audio-present), products order and PL1-PL6, faction pair at 6b6e7c7c; stale "blocked" lines corrected
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:49:11 +02:00
Meta Vens
5b1bfe6cec ColorMath.RgbToHcv: read green-dominant colours with the right channel order
The else branch swapped y and z, so the hue read back from many colours was
wrong (values above 1). Nothing else consumed it; the sun-hue test reads hues
back from RGB. Builds; first run of SunsNeverGreenTests failed on this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:38:37 +02:00
Meta Vens
2f1f392ecf ConsumableAiTests: stock the hold after the optimum is sampled 2026-10-16 17:30:32 +02:00
Meta Vens
9b1ac48027 ConsumableAiTests: assert the fixture carries what it stored 2026-10-16 17:29:20 +02:00
Meta Vens
f39ce7850e ConsumableAiTests: alias the CultMath vector types the static math import shadows 2026-10-16 17:26:14 +02:00
Meta Vens
c5c9086ece Fauna map: trophic gaps mapped to CultLib cuts; fauna-trophic-habitat waits on expr-trophic-ops
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:23:37 +02:00
Meta Vens
fcf1b46880 AI pilots vent on a Track paint past half and overdrive to close (consumable-ai r3)
Re-land on master of the h1 cut with the s1 fixes: the vent rule reads one Track
paint in the ship's own IncomingPaints, TryActivateConsumable refuses on an
inactive ship, the AI holds while a consumable of the kind is active, and the
top of the lock strength range is pinned. Not yet built or run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:22:51 +02:00
Meta Vens
0f26c4bb35 Suns never take a green hue: draw sun hues from the circle minus a Settings band
Primary hue maps through ColorMath.HueOutsideBand; the secondary takes the
out-of-band side; fog tint and light derive from primary. Band edges are
SunHueExcludedStart/End (75 and 165 degrees by default).

Not yet verified on Yggdrasil at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:20:52 +02:00
Meta Vens
0fa5c56821 Audio 1: delete the unread SoundbanksInfo.json Wwise export and its staging mentions
Header comment, the stray staging fixture (now Stray.json) and the
build-delivery doc no longer name it. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:18:13 +02:00
Meta Vens
2102affb09 Audio 1: the simulation names no sound; delete the dead Wwise path on EquippedItem
Removes EquippedItem's SoundBank, AudioEvents/AudioParameters, every
FireAudioEvent/PlaySound/StopSound/SetAudioParameter overload and Update's
AudioStats loop, the four audio enums, WwiseMetadata and WwiseSoundBinding,
the weapon/reactor/thruster call sites, and the Wwise Sounds counters in
FireControlPerWeaponTests (Announced and Starts keep the refused-round pins).
Catalog keys 21, 22 and 13-15 stay, unread.

Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:18:11 +02:00
Meta Vens
6b6e7c7c26 Release map: consumable-ai r3 body facts CA1-CA7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 16:44:07 +02:00
Meta Vens
533b301e49 Gravity map: B44-B48 (layers, turrets, stardust, ambient edge, law and generator r3); tail-taming line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 07:36:51 +02:00
Meta Vens
4abec829ad Merge gravity well-law research r3 (law and generator co-designed, minimap grading)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 07:36:22 +02:00
Meta Vens
fbe3156556 Research: well law and generator co-designed, graded as nested basins (r3), with minimap renders
Generator rules read from the band law's reach (Roche margin, cusp bound, window ending
before the parent's fade, sibling spacing, capacity folding into the parent), applied as a
re-placement of today's zones; basin metrics for ruling wells-read-as-nested-basins (cusp,
blob, nesting, saddle curvature, dead ground, steep share, lanes) and a numpy port of
IsolinesUI.shader rendering four zones per candidate. Stable series branch for the band
potential when the softening is comparable to the band (tau > 1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 07:32:58 +02:00
Meta Vens
6865af813f Merge remote-tracking branch 'origin/eureka/aetheria-gravity-nebula-tint' into eureka/aetheria-gravity-merge-ag3 2026-10-16 07:21:34 +02:00
Meta Vens
e2d78b984c PopulatedRadiusTests: the belt fixture carries the asteroid curves a zone with a belt reads
The belt fixture's PlanetSettings lacked AsteroidSize, AsteroidHitpoints and AsteroidRespawnTime, so building the zone
threw before the bound was read. Builds; the previous commit's belt test fails without this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 06:25:40 +02:00
Meta Vens
fdecde02d0 Merge eureka/aetheria-gravity-stardust-bounds (closing verdicts cut-stardust-bounds.s1, cut-stardust-bounds.s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 06:25:33 +02:00
Meta Vens
74e51586c2 The ambient quad reaches where Fog Tint's format still holds the gaussian; AmbientEdgeVerify renders into that format
Fog Tint is B10G11R11_UFloatPack32. A quad sized to 1e-5 of the centre drew a plateau near 3.2e-5 from 1.75 to 2.1 P and
then zero: a step in the tail the RFloat verify could not see. AmbientFloor is now 2^-15 absolute and the quad ends where
the brightest channel reaches it (1.78 P), so the one step to dark is the format's last value, at most 1.5 floors. The
verify builds its target from the production render texture's descriptor, asserts the format, holds the profile to the
gaussian within the format's 2^-5 step where it is at least 8 floors, and bounds the rim and the step to dark by 2^-14.
Builds; AmbientEdgeVerify passes on Starfire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 06:24:36 +02:00
Meta Vens
13691ac1fa Zone.PopulatedRadius covers belts; the tests pin the largest body and the belt
A belt's asteroids circle its orbit's parent, so a belt reaches the chain's reach to that orbit plus its Radius
(AsteroidBelt.Radius, the largest asteroid Distance); the chain walk is one function for bodies and belts. The fixture
inserts a smaller body after the outermost so a last-wins bound fails, and a belt beyond the outermost body pins the
belt term. Builds; Unity-side files are in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 06:11:49 +02:00
Meta Vens
1973b6d220 Stardust: draw at BeforeForwardAlpha (deferred cameras never run AfterForwardOpaque); probe checks the event, culling mask 1 and a near control; Main Menu drops the stale GravityCamera
Both target cameras are deferred, so the AfterForwardOpaque buffer never drew. The render half of scene-stardust-uncullable now attaches-checks BeforeForwardAlpha, renders with cullingMask 1 (DrawProcedural is layer 0), and requires a near control (dust 100 below, size 5) to draw before the far probe is read, so a miss at 10000 can only be culling.
Builds: not compiled by this commit alone; verified in the Unity batchmode run reported with the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:46:50 +02:00
Meta Vens
8439e39434 FlowFieldSceneVerify: stardust probe sizes its particles to cover pixels at 10000
At size 5 the material's distance^.33 scaling made every quad sub-pixel, so the probe saw no dust with or without the cull. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:24:33 +02:00
Meta Vens
949fa005d6 Merge cut orbital-layering (closing verdicts cut-orbital-layering.s1, cut-orbital-layering.s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:08:26 +02:00
Meta Vens
f50c4cb6c9 Merge cut turret-placement (closing verdicts cut-turret-placement.s1, cut-turret-placement.s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:08:20 +02:00
Meta Vens
9b05ced11f The ambient tint is a gaussian over the populated radius, not a quad that ends at Pack.Radius
Ambient Fog Light leaves Zone Brushes (root object, same pose) and Sector Tint.mat moves from
PowerBrush to Brushes/Ambient Brush: brightness falls as exp(-x^2 ln(1/_EdgeBrightness)), x in
units of Zone.PopulatedRadius. ZoneRenderer.FitAmbientLight, called by LoadZone, is the one
writer of the quad's size and _Reach (the radius where it is 1e-5 of the centre). AmbientEdgeVerify
renders the real scene object through that call. Builds in Unity 6000.3.24f1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:08:16 +02:00
Meta Vens
042839fe58 Merge cut dead-fog-marcher (closing verdict cut-dead-fog-marcher.s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 05:08:13 +02:00
Meta Vens
71bf2a1bff Stardust: draw by a command buffer on the target camera, never frustum culled
Deletes the bounded Graphics.DrawProcedural, its hand-inflated Bounds, the GravityCamera field (and its scene reference) and the dead OnRenderObject block. The camera replays the buffer at AfterForwardOpaque; it is attached on enable, detached on disable and destroy, and released. Unity compile not yet run for this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:48:41 +02:00
Meta Vens
03e91aede2 FlowFieldSceneVerify: stardust probe renders without the camera's image effects
With them on, the effects wrote their own frame and the probe could not tell dust from noise. Builds; the check fails on the bounded draw (buffer count 0, no dust pixels, run against 5a788833 plus this probe).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:37:27 +02:00
Meta Vens
cbdecfd578 Layering fixes: mine floater layer checked in the wiring verify; contact fixture orbitals carry Station/Turret hull types; grab point rides the floater layer
Unity compile is verified before push; not yet built when committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:24:43 +02:00
Meta Vens
ecb165624d Zone.PopulatedRadius: the extent of the populated area, owned by the zone
The largest over bodies of the root orbit's offset from the origin, every orbit Distance
along the chain, and the body's Roche limit: a static bound on where any body can be,
computed once at construction and independent of Pack.Radius. Presenters read it.
Builds; the Unity side follows in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:13:43 +02:00
Meta Vens
ee18829a04 FlowFieldSceneVerify: scene-stardust-uncullable renders the dust 10000 below the camera
Fails on the bounded Graphics.DrawProcedural (this commit builds; the check fails until the cut lands).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:09:08 +02:00
Meta Vens
7274f6d623 Delete the fog marcher nothing draws
VolumeRender and VolumeRenderCustom shaders, the four Fog Marching
materials, ZoneRenderer's FogMaterial/FogFarFadeFraction and its
_DepthCeiling/_DepthBlend writes, the ARPG scene values, and the
Volumetric.cginc _TintExponent, texFlow and tintGradient (with its
commented-out caller). The live nebula is VolumeCloudRenderer + CloudShader.
Unity compile not yet run on this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:06:01 +02:00
Meta Vens
2bc09f832f StationPlacementTests: the narrative station belongs to a faction, as authored stories do
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:56:52 +02:00
Meta Vens
89a481fd16 Turret placement: turrets clear their inner neighbour by their own reach; tests for the tail, the story site, off-ring and no-turret zones
Each side of a station grows outward from it: a turret sits innerReach + 2 turretReach beyond the body inside it,
so turrets of differing reach clear each other (same arcs as before for one turret hull at k = -1, +1).
StationPlacementTests: shared flank check (no off-ring turret escapes it, 1e-4 relative arc), a narrative
station with five authored turrets and a second, larger turret hull, a zone with no turret hull, and a sweep
that no station or turret reaches another orbital. Not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:54:24 +02:00
Meta Vens
d15052afaf LayerTests: provenance lots for the fixture hulls (a0a85920 fails EachKindRidesItsLayer)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:32:19 +02:00
Meta Vens
a0a85920cd LayerTests: using static CultMath.math (fixes the compile error in be7f2b07; be7f2b07 does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 03:17:42 +02:00
Meta Vens
55c61676ce StationPlacementTests: the station's source orbit may be a bodyless node
The generator picks from every non-rosette planet orbit, empty nodes
included, so the source is the one ring orbit no orbital entity rides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:42:25 +02:00
Meta Vens
be7f2b0787 Layers: one owner puts orbitals above the ship plane and floaters below; per-hull GridOffset is deleted
GameplaySettings carries ShipLayerHeight 3, OrbitalLayerHeight 15, FloaterLayerHeight 0 (authored in Settings.asset).
Entity.LayerHeight (Ship, OrbitalEntity) is the one offset RideHeight adds; DrawAhead.FloaterHeight is the floater
height ItemPickup and MineInstance draw at. HullData.GridOffset (Key 26) and the pickup/mine/prefab GridOffset fields
are gone with every reader. Fixtures (DrawnPose, FireControl*, ImpactFeedback) take heights from the layer owner;
LayerTests pin each kind's layer. FloatingItemsDrawnSmoke follows. ItemPickup/MineInstance.Bind take the settings from
ZoneRenderer. Builds as one commit with its tests; not compile-verified until the cut's head run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:35:07 +02:00
Meta Vens
089c3ecad1 Turret placement: stations at L4/L5 in turns, turrets flank by hull reach
CreateLagrangeOrbit adds one sixth of a turn (was PI / 3 on a turns field).
PlaceTurret spaces turrets by k * (stationReach + 2 * turretReach) arcs,
k = -1, +1, -2, +2 (was t / 2 integer division putting two turrets on the
station, and radians-per-arc arithmetic on turns). Contacts.Radius moves to
HullData.Reach. Not yet verified on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:29:57 +02:00
Meta Vens
624d5420e9 Contacts: hull contact is between ships only; orbitals take no part
Step pairs OfType<Ship>; stations and turrets sit on the orbital layer above the ship plane
(ruling aetheria-gravity:orbitals-above-floaters-below). Tests: a ship flies through a station and a turret;
two ships still bounce beside an orbital. Not yet compile-verified (verified once at the cut's head).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:27:58 +02:00
Meta Vens
5a788833f0 Merge gravity-drawn-pose-at-drawn-time
Operator flew 39ba73d5 on 2026-10-16: no jitter coasting beside bodies. Soul s1-s3; residuals in follow-up drawn-pose-residuals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:09:42 +02:00
Meta Vens
39ba73d57d DrawnPoseWiringVerify.cs.meta
Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 01:06:39 +02:00
Meta Vens
215ba46569 DrawnPoseWiringVerify: batchmode proof that ItemPickup, MineInstance and Projectile draw at Clock.Lead
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:50:44 +02:00
Meta Vens
e5eb87050e Drawn pose: ship indicators and map centre read DrawAhead; Round takes one time; RailAt logs a missing parent
- ActionGameManager: the visible hostile/friendly indicators and MenuMap.Position read DrawAhead.Position at Clock.Lead.
- DrawAhead.Round drops its lead parameter: the target's lead is the drawn time less its zone's step time, derived inside,
  so a caller cannot pass two times that disagree. Projectile and BallisticFlightTests updated; the hit tests derive their
  lead from the drawn time; two assertions that only varied the now-absent lead are removed.
- Zone.RailAt logs "Requested orbit is not part of this zone!" for a missing parent again (DrawnPoseTests.AMissingParentOrbitIsLoggedAtADrawnTime).

Builds: not yet compiled at this commit (verified by the run that follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 00:50:29 +02:00
Meta Vens
eb0c12e459 DrawnPoseTests: compare record keys with Equals (2cb1e833's tests do not compile)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:43:56 +02:00
Meta Vens
2cb1e83353 Presenters read the drawn pose: HUD markers, wells, rounds, ping, shield hit, compass, loot view, guided aim
HUD target, lock, incoming-lock, bearing and sweep markers anchor on DrawAhead.Position / AtBearing at Clock.Lead.
GravityLowering's record fill is DrawAhead.Well (pure, pinned at non-zero lead). Rounds take DrawAhead.Time
instead of float Zone.Time + lead. Sensor ping, shield hit, compass icons, wormhole bearing, loot ViewOrigin and
the guided-projectile aim read the drawn pose. Not built in Unity yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:41:49 +02:00
Meta Vens
6c865b2cc9 Zone: the memo fill takes its position from RailAt, so the chain rule exists once
GetOrbitPosition's step-time fill and RailAt each decided the rail chain (root at
FixedPosition, child at parent plus offset). The fill is now RailAt(id, _time).
DrawnPoseTests builds the sun on an off-centre FixedPosition (the ZoneGenerator
cluster-root shape) and adds a root test at step and drawn time, and an unset-orbit
OrbitalEntity fact for the DrawAhead guard.

All commits build, unverified until the job in the report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:39:06 +02:00
Meta Vens
b71dfc219b Gravity map: B40-B43 conserving compact well law; tail-taming cut line
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:27:12 +02:00
Meta Vens
db31d96f8a Merge gravity well-law research
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:27:08 +02:00
Meta Vens
b2f6122dd2 Research: the conserving compact well law (band terms on the orbit tree), for ruling tame-tails-parent-only-rails
Each node pulls exactly as its body inside its outermost child, exactly as one body
of its family's mass beyond its own support, and nothing beyond its reach; the root
has no reach, so the zone's far field is exactly c(M_zone) however the generator
splits it. C4 on every band edge, closed-form potential (grid = K phi), Plummer core.
Probe against today, a2, c2, b1 and the tapered draft: ratio, funnel, 12-18 u/s,
far field, split invariance, whole-zone depth, and evaluation cost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:22:10 +02:00
Meta Vens
fd00ad90ef GravityLowering: build the well Vector2 from the drawn orbit explicitly
Unity presenter file; not compiled by this pass (no Unity run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:59:41 +02:00
Meta Vens
63124add6b DrawnPoseTests: coasting probe reads world-axis swing; SimClockTests rides the field at the drawn time
The co-moving probe projected a world-fixed offset onto the rotating motion
direction; it now compares the planet and ship in world x and z. SimClockTests'
zero-lead sibling at a lead read the step-time ride height; with moving wells the
drawn ride is the field at T.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:45:10 +02:00
Meta Vens
8bc5ef1837 Merge gravity smooth-wells research
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:44:31 +02:00
Meta Vens
e395b5b091 Research: smooth (C-infinity) gravity wells, seam jumps, conserving halo and split-deepening probe
Eyes pass eyes-ag3-smooth-wells (aetheria-gravity, self-2026-10-15-ag3). Extends
gravity-tail-taming: smoothness class per law, measured A&S K0/K1/E1 seam jumps,
log-ratio, screened Plummer, Lamb-Oseen (with and without halo), Plummer log and
conserving-halo families on the same probe, plus zone far-field against merged mass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:43:03 +02:00
Meta Vens
b57207045d Draw every moving body at the drawn time T = ExactTime + Lead
Planets, belts, wells, loot, mines, stations, the chunk reticle and the flow
clock are evaluated through DrawAhead (Time, Orbit, Height, Position) at one
drawn time; the rail law lives once in Zone.Offset; OrbitPositionAt, GetHeight,
ChunkPose, EvaluateBelt and RideHeight take a time. Fixes the planet jumping
against a co-moving ship at display rates above the step rate.

Not yet built or run (Unity presenter files are verified by compile only on
Starfire).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:26:36 +02:00
Meta Vens
39ebf7f6af Merge gravity tail-taming research
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:22:03 +02:00
Meta Vens
ca37b45687 Research: taming summed gravity tails (screened K0, caps, force switch, disc subtraction, exponent, hyperbolic kernel), for ruling tame-tails-parent-only-rails
Eyes pass eyes-ag3-tail-taming, session self-2026-10-15-ag3. Facts file plus
numpy probe over the orbit-probe bodies: enclosed/parent speed ratio by child
class, mid-zone inward pull, planets round a median sun, HLSL cost per well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:19:49 +02:00
Meta Vens
46af8d4f09 Gravity map: B39 planets drawn at the step; drawn-pose and tail-taming cut lines
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:12:35 +02:00
Meta Vens
c981537904 Research: rosettes as relative equilibria under the 2D log law, for follow-up rosette-generation-r3
Eyes facts for aetheria-gravity: regular and twisted alternating polygon
equilibria (log closed form, Newtonian sources), linear stability
(Muscas-Pasca-Stoica log thresholds reproduced, Klemperer, Thomson),
the soft core's reach, PeriodAround's ring rule against the twisted
equilibrium spin, and rotating-frame stationary points against the drawn
potential. Solver scripts beside the note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:01:13 +02:00
Meta Vens
09ec04a8d5 Merge gravity-orbits-from-field
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:52:57 +02:00
Meta Vens
49e8ea58e1 Merge gravity-fog-precision-and-jitter
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:52:55 +02:00
Meta Vens
55cc7eda41 Merge gravity-grid-lowering
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:52:48 +02:00
Meta Vens
1babed4bf1 Ring law: a strengthless ring member takes its bodied partners' period; the ring window and a bodyless node's closed field are pinned
PeriodAround's ring term is one rule: self feels the mean, over the members whose pull it takes (itself if bodied, else every
bodied ring member), of half the rest of the ring. A station on a binary's ring no longer stands still. The 0.1 u window is a
named constant, pinned just inside and just outside it; a bodyless node's children are pinned never to read the node's parent's well.
Both commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:05:03 +02:00
Meta Vens
4bac2623bf AI aim and turret aim ride Entity.RideHeight; tests pin the hull GridOffset on a slope and at both aim sites
Combat and TurretController spelled GetHeight + GridOffset inline; they call target.RideHeight now. The drawn-ship test authors a hull with GridOffset 2.5 on the well's slope. Two new tests aim at a target hull raised 40 u.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:39:28 +02:00
Meta Vens
fe5d03d04b Menu and test scene patch cameras stop culling the gravity layer; the parity verify checks every scene's patch camera
cloudDensity adds the R32 gravity height to the patch texture, so Main Menu and TestScene patch cameras (mask 5632) counted layer 9 twice. Mask 5120, and GravityFieldParityVerify now asserts each of ARPG, Main Menu and TestScene excludes layer 9 from its Fog Patch Displacement camera.

All commits build as far as C# goes; verify runs after the second commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:39:27 +02:00
Meta Vens
160abd8b44 OrbitsFromFieldTests: the facts of a rail's period under the field
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:11:37 +02:00
Meta Vens
a4977cbe48 Every rail's period is derived from the field it orbits in; OrbitPeriod is deleted
Zone.PeriodAround is the one owner: round a body, the pull its well gives at the rail's distance
(GravityField.Acceleration); round a bodyless node, the ring law (strength of the orbits inside, plus
half of what shares the ring). Orbit.Period and AsteroidBelt.Periods are written once at zone build,
before placement; BeltTargets copies the belt's periods. A parentless orbit has no field and stands at
its phase. Fixtures lose OrbitPeriod and gain wells where their rails must move. Builds; the new
OrbitsFromFieldTests follow in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:11:27 +02:00
Meta Vens
d7f0e8f30f Aetheria gravity map: orbits-from-field mapped (B35-B38: field speeds, bodyless parents, hierarchical premise, readers)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 18:00:22 +02:00
Meta Vens
27fd8687a3 Test that a child is drawn where its parent is drawn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:48:09 +02:00
Meta Vens
3b039d069b The nebula patch reads gravity from the R32 surface height, not a half-float copy
Patch Displacement no longer culls layer 9; cloudDensity adds the surface displacement to the patch-only displacement.
GravityFieldParityVerify wiring checks the camera. Neither commit has been built when this is written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:45:57 +02:00
Meta Vens
105f0270eb A drawn ship rides the field at its drawn xz
DrawAhead moved xz ahead but carried the last step's y, so on a slope the ship's height stepped once per sim tick.
Entity.RideHeight is the one owner of 'an unparented entity sits on the field'; the step and DrawAhead both call it.
A child is drawn where its parent is drawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:45:56 +02:00
Meta Vens
5ec9363ac4 Aetheria gravity map: B32-B34 (slope jitter from stepped ride height, half-float patch gravity copy, fog snapping) and fog-precision-and-jitter in the cut sequence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:41:45 +02:00
Meta Vens
37e0cb113d Aetheria gravity map: B31 core at the Roche limit and K = 4.098 (supersedes core and K numbers in B22, B25, B28)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:24:46 +02:00
Meta Vens
8f491fd3c9 Core radius is the Roche curve; the global exaggeration divides by the core's growth
core-at-roche-and-exaggeration-up: PlanetSettings.CoreRadius and Planet.CoreRadius are
deleted; the well's softened core reads the RocheLimit curve (one curve of mass). The
core < Roche guard cannot fail and is replaced by a Roche-limit-positive-and-finite
check. Settings.asset: CoreRadius removed, HeightExaggeration 10 -> 4.0983607
(10 / (7.32 / 3)). Tests pin the new curves and the peak drawn slope / 2.44x steeper tail.
Not yet built or run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:46:53 +02:00
Meta Vens
0d7fc2ee3a Merge origin/eureka/aetheria-gravity-potential-owner (cc3249b8) into grid-lowering
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:44:10 +02:00
Meta Vens
cc3249b8c9 Crossing sweep: rename the shifted-pass lists (a name clash broke the previous two commits' build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:50:20 +02:00
Meta Vens
aa3af5ecc0 Crossing sweep: the lateral shift moves the pass by at least 3 m (the crosser meets the player's hull below a 40 m start)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:48:05 +02:00
Meta Vens
a033c01c56 Crossing sweep: assert the shifts moved the pass, so a sweep that ignores them fails
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:47:12 +02:00
Meta Vens
ced6600261 Crossing: start window centred at (-128, 45); relative speed and angular rate bounds from the sweep
The crosser is unpiloted and launched at 50 u/s; hull drag slows it to about 25 u/s relative at the bow line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:28:56 +02:00
Meta Vens
61dc8c6d0e Crossing test: InArc takes a planar offset as float3 (WIP, bounds still unfitted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:23:38 +02:00
Meta Vens
bf69f489a9 Crossing: unpiloted crosser coasting at 50 u/s; the start-window sweep (bounds to be fitted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:22:14 +02:00
Meta Vens
9b1b27d2d6 GravityShader: verbatim string, not a raw string literal (Unity's C# 9)
Commit 13c7a087 and the merge a1b54bea do not build: error CS8773, raw string literals need C# 11.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:47:01 +02:00
Meta Vens
a1b54bea7a Merge origin/eureka/aetheria-gravity-potential-owner (1c5326dd) into grid-lowering
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:44:31 +02:00
Meta Vens
13c7a08707 Gravity.cginc is generated: GravityShader.Source() is its one author, a test pins the committed file to it byte for byte
The mirror test compared a normalised reading of two spellings and was beaten twice (a statement before the return, gravityHeight's sum). GravityShader writes the whole file (potential, zero-strength guard, reference term, height sum) from GravityField's constant (TailOffset); GravityShaderTests fails on any difference. GravityShaderMirrorTests deleted. GravityFieldParityVerify opens Main Menu.unity: no ZoneRenderer there, its Fog Surface Displacement camera is the menu's own brush presentation (layers 9 and 10) by spec.

Builds not yet verified on this commit; verified at the final merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:44:11 +02:00
Meta Vens
1c5326dd9d TheCoreIsTheBowlUpToItsEdge: sample 0.996R so a join at 0.995R fails
The mutation table showed a join at 0.995R surviving: no sample lay at or past it. At 0.996R the log form
differs from the bowl by 1.6e-5 c, over the test's tolerance.

Not built or run locally; verified in the Yggdrasil job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 08:17:10 +02:00
Meta Vens
e6d1546b44 Gravity grid-lowering fixes: formula mirror test, verify across moved off-axis bodies and a zero-strength body, map camera wiring, RTS Planet's Gravity Well deleted
GravityShaderMirrorTests compares the expression of GravityField.Potential with gravityPotential in Gravity.cginc.
GravityFieldParityVerify now builds four off-axis bodies (one of mass 0), lowers through three frames with bodies moved
between them, and checks the map screen's gravity camera mask. RTS/Planet.prefab loses the Gravity Well object bound to
the Gravity Field material. Builds: yes (verify passes on Starfire; the new test is unrun until the Yggdrasil job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:59:15 +02:00
Meta Vens
4568e217f3 Merge remote-tracking branch 'origin/eureka/aetheria-gravity-potential-owner' into eureka/aetheria-gravity-grid-lowering 2026-10-15 07:55:31 +02:00
Meta Vens
268065ca67 Merge eureka/aetheria-release-mount-cycle-and-test-hygiene
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:49:00 +02:00
Meta Vens
d7bdbc4a77 GravityLowering: the record comment no longer spells the deleted GravityWell name
Comment only; verified code is 3a5b3b0b. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:29:21 +02:00
Meta Vens
45d19f3a8e PotentialOwnerTests: authored curves read from Settings.asset; zero pinned from just below; the core bowl sampled to 0.99R
TheAuthoredCurvesBuildAtEveryMass loads PlanetSettings from the asset the way RunStartTests does. The unphysical-strength
theory adds -1e-6 and -float.Epsilon and a new test builds zero and negative zero. TheCoreIsTheBowlUpToItsEdge compares
the drop from a lone body's centre with c r^2/2R^2 at 0.5R to 0.99R, tightly enough that a join at 0.95R fails.

Not built or run locally; verified in the Yggdrasil job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:23:26 +02:00
Meta Vens
a54e2f53df Pin the mount aim's resolved reads, the record's isolation and its Deactivate clear; delete two dead guards
Forecast and Fire drop a mount aim whose gate closed (destroyed, unidentified); a record for one Bay never hides another's mount; Deactivate clears the record. Deleted: the located-or-booked guard in RecordSeenDestroyed and the Entity == subject check in ResolvedAim (the record is read only for layout mounts; a Target change already clears the slot). Comments name AimedAt. Not built or run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:14:35 +02:00
Meta Vens
3a5b3b0bab Gravity grid-lowering: the drawn height is one Gravity Field pass over the zone's wells; gravity brushes and brush inputs deleted
Zone.WellReference owns each body's reference zero (GetHeight uses it). Gravity.cginc mirrors GravityField.Potential;
Brushes/Gravity Field draws depth = -h on layer 9 from a StructuredBuffer that GravityLowering.Lower fills from the
zone each frame; GravityLowering.CreateField makes the one quad. GravityFieldParityVerify renders it and compares every
texel with -Zone.GetHeight (max error 0.0059 u), the gradient with GetForce (0.03 degrees) and the wiring.

Deleted: the Gravity Well children of Planet, Gas Giant, Sun and PlanetOutpost prefabs, Wormhole 1's three gravity
children, their overrides in Main Menu and TestScene, five wormhole/wave materials and two brush shaders,
Planet.GravityWellDepth/Radius, BodyData keys 6-7, PlanetSettings.GravityDepth/GravityRadius (and the Settings.asset
keys). Surface Displacement culls layer 9 only. Headless build and tests not yet run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 07:11:25 +02:00
Meta Vens
c4dfd905ff Gravity: the Planet guard refuses an unphysical well; tests pin the Roche rule, per-body multipliers, the core band and Ship's order
A WellStrength that evaluates negative, NaN or infinite now throws at construction (it built an
antimass well with NaN height). New tests: the core-inside-Roche guard judged at every mass on
curves that cross in the generated range; per-body multipliers move neither strength, core nor
Roche limit; potential and force consistency inside the cores' outer bands (0.5 R to R); a
moving Ship feels the field where it has moved to.

Not built or run locally; verified in the Yggdrasil job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:36:02 +02:00
Meta Vens
8013c2deec Crossing and Lock On: restaged for the ruled field
Under the potential-owner field the zone pulls everywhere (about 1.4 u/s^2 even in
its weakest places), so the staged runs bend. Crossing's player sat on the star at the
arena's origin and fell in; its crosser, braked by its pilot, never reached the bow
line from 150 m to port. The crosser now starts 96.5 m to port and 70 m ahead of a
player staged 250 m or more from every body, which keeps the pass at 3.2 s and 40 m
(the test's 3.0-4.2 s and 30-60 m unchanged). Lock On's hostile started on the side
where the zone bends its run by 7 degrees; the lock warning must point within 5 degrees
of where the hostile was staged. It now starts ahead and to port, where the bend is under
one degree and the lock comes at about 14 s. No assertion, limit or gravity is changed.

Not built or run locally; verified in the Yggdrasil job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:36:01 +02:00
Meta Vens
f5caef9fd0 Aetheria gravity map: grid-lowering mapped (B27-B30: GPU readers, precision, one-quad lowering, parity verify)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 06:08:27 +02:00
Meta Vens
dd06f39dbc FloatingBodyTests: the tilt expectation is spelled from force and K, not read back from GetNormal
Two hand mutants of GetNormal's K (ignored; times 3) survived because the test compared the ship's
tilt with the same GetNormal it was testing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:40:10 +02:00
Meta Vens
43536ccf5f Pin that a book entry is not a perception of its item's destruction
Mutant d (record written without the identification gate) survived: the located path is
already gated by LayoutOf. The gate matters for a destroyed item held only by its act.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:10:02 +02:00
Meta Vens
41e90d0e40 GravityField: a well of no strength digs nothing (c = 0, R = 0 gave NaN height)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 05:02:48 +02:00
Meta Vens
22e1bc32cc RecordSeenDestroyed allocates nothing in the common path
Sense runs for every pair of ships every tick: iterate Equipment by index and read
the believed layout only for an item actually perceived destroyed.
SenseAllocatesNothingOnceWarm failed on the previous commit (1257600 bytes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:57:13 +02:00
Meta Vens
fde8062931 Gravity potential-owner tests: fixtures keep the brush-input curves Planet still reads
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:51:20 +02:00
Meta Vens
a554d5ed08 Fix stray line in IsRevealed's comment; drop the seen-destroyed record of a departed subject with no book
The previous commit does not build (a leftover line in FireControl.cs). EndReveals
only runs for subjects the book holds, so a record of a quiet departed ship was held
for the sitting; Sense's prune now ends it too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:44:24 +02:00
Meta Vens
f6c0d24dba One aim slot holds an item or a mount; the cycle covers every located mount
Entity.AimedAt (AimTarget: a revealed item or a believed mount) replaces
TargetItem. Two writers, TrySelectTargetItem (IsRevealed) and TrySelectMount
(in LayoutOf, not seen destroyed); ResolvedAim re-validates both on every read.
AimCycle is SchematicRows' enemy rows minus mounts in the observer's
seen-destroyed record, written only in Sense through PerceivesDestroyed.
SchematicRows drops its covering filter. IsLocated and AimsAtMount are deleted;
PendingShot.AimedMount and Silhouette's HardpointData mount replace the bool.
The cycle key calls Entity.CycleAim; the schematic marks read ResolvedAim.
Entity.ToString names an entity (follow-up entity-formats-safely).

The slot is AimedAt, not Aim: Entity.Aim is the pilot's pointing direction.
Not yet built or run; ActionGameManager and SchematicDisplay are uncompiled
without Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:42:38 +02:00
Meta Vens
6957180450 FloatingItemsDrawnSmoke waits on game time and a real-time budget
Both label loops wait on Time.time against the pickup's own persist and fade
durations plus a second, not 1200 frames; Step's guard is a 300 s real-time
budget, not 3000 frames. Batch frames can be far shorter than a game second,
so a frame count could expire before the label faded (follow-up
floating-items-smoke-label-fade-flake). Not yet run in Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:42:28 +02:00
Meta Vens
021c4cbcbf Gravity: one potential per zone owns acceleration and height
GravityField is the law of one well (logarithmic tail, softened core).
Zone.GetForce and GetHeight sum it over the bodies; GetNormal derives from
the force for ship tilt; Flow and Ship read GetForce. Well strength, core
radius and Roche limit are PlanetSettings curves of mass, height
exaggeration K one global. Deletes GravityAcceleration, GravityReferenceRate,
GravityStrength, the PowerPulse well, GetNormal's finite differences and
BodyData.GravityDepthExponent. Settings.asset carries the calibrated curves.
Tests: PotentialOwnerTests, the moon's moon placement, retired keys over every
BodyData type, a body-derived giant sweep. Not yet built or run (verify job
follows); this commit may not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:36:28 +02:00
Meta Vens
54e2f88702 aetheria-release map: mount cycle at 3f5cef68 (MC1-MC10, rationale, cut sequence)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:32:03 +02:00
Meta Vens
ff63362f45 Aetheria gravity map: potential-owner r3 (Roche curve, core inside it, moon windows B25, grid-lowering stacked B26)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:29:14 +02:00
Meta Vens
3f5cef68e7 Merge eureka/aetheria-release-layout-aim
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 02:30:59 +02:00
Meta Vens
61e66dac35 Layout-aim tests: AddWing picks the guns by design name (the hull is equipment too)
Fixes 3098ff69, whose two Wing tests did not build their fixture. Test-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:52:44 +02:00
Meta Vens
3098ff69a5 Layout-aim tests: lookalike-hull lie, asymmetric two-mount Wing hull, Entity assertions without formatting, docked stance through IsHostileTo
UnderALookalikeLieNoGearIsLocated: claimed and true hulls of one type and size with a reactor mount of equal type, position and shape. AMountAimReadsThePositionAxesInOrder and TwoMountsOfOneTypeAreTwoRows use a Wing hull off the diagonal with two Sensors mounts. Assert.Same and DoesNotContain over Entities become ReferenceEquals asserts. The docked-stance test reads IsHostileTo on a hostile-by-default subject instead of _iffOverrides. Test-only; no production change. Not yet built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:39:37 +02:00
Meta Vens
1b0a67069e Layout-aim fixture: reactor mount off the origin so a mount-cell offset term is observable; schematic keys and below-identify rows pinned
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:31:57 +02:00
Meta Vens
1c041cb67b SchematicRow: assign every field in both constructors (the struct language level has no auto-default)
Fixes the build of the layout-aim sim commit (095efacd).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:19:09 +02:00
Meta Vens
2a69c40bfa Tests: layout-aim behaviour, retarget scan progress, Inspection Scanner role map, Entity-free fixture assertion
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:17:21 +02:00
Meta Vens
eb2dc1e501 Scanner progress reads 0 on another target; Program.RoleMapOf exposes roles-backfill's map
Scanner.Progress is bound to the target the scan was built on, so a retarget with the scanner switched off no longer
draws the old scan on the new target (scan-progress-shown-on-retarget). RoleMapOf is the one accessor HasRoleMap now
delegates to. Not yet built or tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:17:17 +02:00
Meta Vens
095efacd79 Layout-aim: an identified hull shows where its mounts are; a located mount can be aimed at
TrySelectTargetItem and ResolvedTargetItem gate on FireControl.IsLocated (an item seen to act, or one on a mount of the
believed hull's layout) instead of IsRevealed; Combat keeps IsRevealed. Entity.LayoutOf derives the layout from the
Contact profile; SchematicRows appends a mount row per unclaimed hardpoint. A mount aim centres on the mount's cells and
is frozen per shot (PendingShot.AimAtMount). The cycle runs over located items, the schematic renders mount rows and
marks through SchematicRow.Marks. Not yet built or tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:17:14 +02:00
Meta Vens
f8e7abf460 Merge eureka/aetheria-release-scanner-catalog
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 23:50:57 +02:00
Meta Vens
22534aebb7 Aetheria gravity map: potential-owner mapped (B19-B24, constants, funnel and moon-window findings)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 23:48:41 +02:00
Meta Vens
5dd1f6b71f Merge eureka/aetheria-gravity-gravity-subtract
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 23:11:47 +02:00
Meta Vens
2aad0fceca Gravity subtract tests: sweep the giant's well densely; pin gas-giant keys 14-17 as retired
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:09:48 +02:00
Meta Vens
7ae77e41a7 Scenes: drop the Sun prefab-instance overrides that targeted the deleted Gravity Waves object
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:08:18 +02:00
Meta Vens
3b9d7e0770 ZonePlacedAtBuildTests: drop the Wave curves the merged settings no longer have
Builds after the merge of orbits-placed-at-build; the merge commit itself does not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:07:22 +02:00
Meta Vens
570f22083b Merge orbits-placed-at-build into gravity-subtract
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:07:09 +02:00
Meta Vens
3314663826 ClaimTests: a weapon claimed as a non-weapon is a gear row of the claimed class
The enemy schematic now lists every non-weapon claim as a gear row (cut scanner-catalog), so the old "no row" expectation became "one row, the claimed class, no range". Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:37:32 +02:00
Meta Vens
9b28daf7eb Tests: the gear schematic fixture reveals the hull as the claim tests do; drop the formatting probe
The Format probe showed a Reveal formats as "Reveal" (no graph walk), so no ToString and no test is added (follow-up bearing-markers-test-residuals (2)). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:23:47 +02:00
Meta Vens
5659bcfdd0 ClaimTests: SchematicRow.Range is nullable
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:20:25 +02:00
Meta Vens
283d1365c4 Tests: inspection scanner catalog, command, schematic gear rows; scanner/emission/stance residuals
InspectionScannerCatalogTests and InspectionScannerCommandTests (new); AFinishedScanListsTheGearOnTheSchematic; AScanReadsNoHostility pins pace, emit and a target-side sensor; AScanTakesTheSamePathForAnyPilot uses a Minion in CombatState; an emission heard within Range over the lot's alpha (ping and scan); the docked-subject test is a Theory over true and false; a ReveEal formatting probe. Not yet run: may not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:19:14 +02:00
Meta Vens
205098ef93 Zone.Update takes every previous position before placing any orbit
GetOrbitPosition places a parent as a side effect of placing its child, so with a child listed first the parent's previous position was already its new one and its Velocity came out zero. The constructor's unread PreviousPosition write is dropped; the first Update takes it from the placed Position. The velocity test now runs moon-first and planet-first packs over varying dt. Builds not verified yet (verify follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:19:09 +02:00
Meta Vens
dbace27ee7 Catalog: Inspection Scanner design and three products (Inkling, Assay, Full Disclosure)
GameData/Aetheria.cc after `AetherDb inspection-scanner apply` on Yggdrasil (sha256 ed0500b4...): one GearData and three FactionProductData by Finch, AU and Lucent; a second apply wrote nothing. Builds: yes (data only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:13:28 +02:00
Meta Vens
b14d609cae Schematic lists revealed gear; scan progress indicators at both ends
Entity.RevealedGear and SchematicRows' enemy branch (revealed weapons then revealed gear); SchematicRow.Range is float? (null for a non-weapon claim); SchematicDisplay shows ShowGear rows for non-weapon claims and hides the range label when null; SchematicListElement.ShowGear. ActionGameManager: one progress-indicator list (lock weapons hostile-gated, scanners ungated) and the incoming indicator follows Track or Scan paints. Not Unity-compiled yet; Shared tests unaffected by the UI files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:11:37 +02:00
Meta Vens
70b7829bb0 AetherDb: inspection-scanner command (design, three products, role map)
Adds the inspection-scanner [apply] command beside launch-suppressor, in its pattern: dry run, all-or-nothing idempotence, partial refuses, ExpectUnchanged batch, root parameter for tests. One Inspection Scanner design (Tool 1x1, one ScannerData) and three products from Finch, AU and Lucent; ToolRolesByDesign gains the design. The catalog itself lands in the next commit. Builds: not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:11:17 +02:00
Meta Vens
cc398ff2ad aetheria-release map: visibility refresh at a17dab36 (VA1-VA12, scanner-catalog r2 and layout-aim r3 order)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 21:04:37 +02:00
Meta Vens
a17dab3677 Merge eureka/aetheria-release-bearing-markers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:32:03 +02:00
Meta Vens
36d2dd45f2 Gravity subtract tests: pin the well fixture to the bowl it replaced
The five bowl fixtures compare to the zone's own normal, so nothing pinned
the shared well's depth or radius to the bowl (a depth-scaled fixture
mutant survived). TheWellFixtureReproducesTheFormerBowl checks heights
against the bowl's own definition. This commit's test has not run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:30:28 +02:00
Meta Vens
abe0c848be Bearing-marker tests: assertions over entities report booleans, and the docked and inbox clauses are pinned
A failing Assert.DoesNotContain/Contains over a collection of Entities made xunit format the Entity graph and overflow the stack, aborting the host; the five such assertions now assert a bool. Adds a docked-subject stance test and a pending-paint-on-leaving test. Builds: yes (test-only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:55:10 +02:00
Meta Vens
9fb5aad454 EvSettle returns the ship to where it stood
A ship stepped alone drifts under the zone's wells while it idles. Orbits are
now placed at build, so those wells are where the bodies are and the drift is
real; the scenarios (Crossing, FusedRounds) staged geometry the wrong wells
happened to leave undisturbed. Settling is about stats and power, not place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:50:08 +02:00
Meta Vens
55d5566743 Gravity subtract tests: open the fixtures' caches with a run store
OrbitData and BodyData are run-store types; a cache opened with a catalog
only has no home for the well body. The six fixtures that dig a well now
open with a run path. The previous commit does not pass its tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:47:32 +02:00
Meta Vens
68c97166ab Aetheria gravity map: cut-sequence line for the top-speed field (no drag below top speed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:46:05 +02:00
Meta Vens
a8876d7a33 ZonePlacedAtBuildTests: open the catalog and run stores as the other zone fixtures do
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:34:21 +02:00
Meta Vens
7d3fb29ed2 Gravity subtract: delete the zone bowl and the gas-giant and sun ripples
GetHeight sums body wells only. Removes RadialWaves, GasGiant wave fields,
GasGiantData keys 14-17, PlanetSettings Zone*/Wave* fields, the minimap
gravity range, the Boundary brush and Gravity Waves objects from the scene
and both prefabs. The five bowl fixtures become one WellFixture well at the
origin with unchanged expected numbers. Not yet built or tested: this commit
has not been through the Yggdrasil job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:34:20 +02:00
Meta Vens
aefd0c0a92 Zone places every orbit when it is built; delete AddOrbit and CreateOrbit
Orbit.Position and PreviousPosition are set from GetOrbitPosition at the pack's
time in the constructor, so wells, lights and poses are valid before the first
Update. AddOrbit and CreateOrbit had no caller. Tests not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:31:03 +02:00
Meta Vens
1ad00c045a Aetheria gravity map: body facts B13-B18, rationale and cut sequence for the subtraction and placement cuts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:27:00 +02:00
Meta Vens
11b2d7adbc Aetheria gravity target: rulings of 2026-10-14; Ink pillars leave the flatspace law
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:16:26 +02:00
Meta Vens
818eee2781 Memory-window edge test runs with the subject staying and departing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:09:15 +02:00
Meta Vens
10aaa8a6ad Pin the book's edge for a departed subject and the stance of one still in the zone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:02:39 +02:00
Meta Vens
0b86888f79 Aetheria gravity: model page and body facts (map), prior-art research for the eight gravity forks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:19:15 +02:00
Meta Vens
c651938381 Aetheria gravity: target document (honest wells, one potential, height = potential x exaggeration)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:02:37 +02:00
Meta Vens
2ba41373bd Bearing markers read the observer's live stance; a ship out of the zone holds no warnings
The hostility stamp (Reveal.Hostile, Contact.Hostile) is deleted: the observer knows its own
stance live. The real fault was the IFF override being dropped when its subject departs while
the book still remembers it; the override now goes when the book drops the subject (ReleaseStance),
so RememberedHostiles reads IsHostileTo. A ship removed from the zone clears its paint inbox and
incoming warnings at the owner, so the Parent == null gate in ActionGameManager is deleted.
Tests pin both stance directions after the act, the departed override hostile, the exclusive
memory window at the equality, and the empty inbox. Unbuilt until the verify job; Unity side not compiled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:53:58 +02:00
Meta Vens
2ea329e6f1 Remember a hostile's stance with its sighting; pin the lapse, claim and distance rules
RememberedHostiles read the stance the freshest reveal was made under (Reveal.Hostile, surfaced as Contact.Hostile) instead of IsHostileTo now, so a hostile held by the observer's override keeps its marker and the music after it dies or warps, until the bearing lapses. The departure test no longer re-sets the override. New tests: the Detected clause for an in-zone lapsed hostile, position independence for far hostiles on three sides, a within-category lie in ClaimedClasses, and the stale warning of a docked ship. The HUD no longer collects sweeps for a docked ship, and a sweep flash resets the pooled lock indicator's motion.

Untested here: the Unity-side changes (ActionGameManager) have no headless test and no compile has run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:12:44 +02:00
Meta Vens
2b726a998b Pin the claimed-class order: reveals made in reverse name order list by name
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:11:56 +02:00
Meta Vens
0debeab1b3 Bearing-marker tests: restate the stance after a departure, bring the claimer into hearing
A departure drops the observer's IFF override (it lasts the sitting), so the departed-hostile case re-sets it to stand for faction-derived hostility; the gun reveal in the claim fixture needs the target within the Eye's hearing. The previous commit's two new tests fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:08:06 +02:00
Meta Vens
7b12fbe417 Bearing markers for remembered hostile contacts, labelled with their claimed classes, and a sweep flash per ping
Entity.RememberedHostiles and ClaimedClasses derive from the book; music and the new markers share RememberedHostiles. Markers sit on the remembered bearing, never the subject's position; Search warnings are collected per tick into sweep flashes. Unity code is not compiled in this commit's verification (dotnet tests only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:54:43 +02:00
Meta Vens
1ff0e185c5 aetheria-release map: bearing-markers refresh at 3300e16e (body facts BM1-BM10, rationale, cut order)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:50:29 +02:00
Meta Vens
eb5083dd44 Merge eureka/aetheria-fauna-curl-probe (docs only)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:37:13 +02:00
Meta Vens
b285f45c9f Merge eureka/aetheria-fauna-target-r3 (docs only)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 13:37:06 +02:00
Meta Vens
3300e16e25 Rerun range-falloff apply on master's catalog; RangeFalloffTests reads the generic missile rack name
Catalog (GameData/Aetheria.cc, LFS): master's blob 00c59a64 re-saved by `AetherDb range-falloff apply` -> sha256 7c9cf240ab5e64973603fe3fe5cadaddfeb620ecb75b0ffae9cc2d84ad72bc9f.
Dry run: 27 weapon records to rewrite. A second apply left the bytes unchanged. Decoded against master's: 273 keys equal, schemas
equal, exactly 27 weapon records' payload differs, nothing else.
The test fix renames the design literal SRMM72 to Short-Range Missile Rack (generic-design-names table).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 10:15:15 +02:00
Meta Vens
97b7566ee9 Merge origin/master into damage-falloff
Conflicts: FusedRounds scenario brief and fixture comment, SmokeRoundsSteppedTests, and AetherDb's usage line keep both sides, with
DeathCluster renamed Cluster Cannon. GameData/Aetheria.cc is master's blob; range-falloff is rerun on it in the next commit.
This commit's catalog does not carry the falloff stats, so CatalogRole/falloff catalog tests do not pass here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:54:44 +02:00
Meta Vens
aff6086c01 Mines are flat by data: refuse falloff on a mine layer, Lay reads no factor; clamp test
A mine layer carries no EffectiveRange or DamageAtMaxRange (StatValidation.ValidateMineLayerFlat, run wherever the other catalog rules run), so RangeFactor is 1 inside its gate for the mine, the AI and the panel without any reader branching on type; Lay's damage is the weapon's damage again. Adds a test that fails without Deliver's min(reach, MaxRange) clamp. Not built or tested yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:06:20 +02:00
Meta Vens
0c5d1f36d2 Test: a targeted fused round reads the falloff at its planned burst point, not the target's distance now
The fire-reads-fire-range mutant survived the first table: no test separated BurstReach from FireRange for a round Fire delivers.
Both commits build (verified on Yggdrasil, Aetheria.Shared.Tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 07:05:11 +02:00
Meta Vens
b713c42503 Read the range factor where the delivery point is decided; mines and unauthored stats go through the one function
A no-lock fused round reads RangeFactor in CommitBurst at the distance it travelled to the hull it stops on; every round whose point
Solve plans reads it once at Fire (PendingShot.DeliveredAtCommit says which). Lay reads it at its own distance 0. PerformanceStat.Evaluate
no longer interpolates a single-value span, so an unauthored +infinity stat evaluates unequipped. Tests: the round that stops short, the
Fused Rounds hull ahead, a mine layer's authored ranges, the group pick at the target's real distance, unequipped SRMM72/Mine Launcher.
Not yet built (verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 06:49:56 +02:00
Meta Vens
05a445418c Fauna r4: body-Voronoi probe (Skein drawn as a diagram over the bodies, per metric); map B37-B42
Imagination probe of the operator's sketch: the bodies as Voronoi sites, the distance metric varied
(power, additive, multiplicative, equal potential, flow-stretched, Minkowski), the lattice web pulled
toward the edges. Images, logs and scripts in docs/research/2026-10-14-body-voronoi-probe/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 06:46:26 +02:00
Meta Vens
196edced82 Research: curl flow probe, Nebula Span Lab stretch as a flow (fixed axis; contour axis fails as built), labs noise facts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 06:17:42 +02:00
Meta Vens
55e92b9d44 Research: curl flow probe, candidates to replace FlowField's Tri3D (curl of CultMath simplex, fbm, warped, with slope terms)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 06:12:43 +02:00
Meta Vens
4354ef2c36 Fauna target r4: placement is a trophic DAG over CultMath nodes; map r4 and the trophic DAG probe
Applies rulings habitat-trophic-dag and voronoi-primitive and the operator's
correction that CultMath owns shader/C# parity. The target's Placement law
becomes a layered, donor-controlled DAG (environment, the Skein, producers,
grazers, predators and ambushers) with pointwise and stencil operators only,
nodes in CultMath and compositions in Aetheria; invariants trophic-dag-acyclic,
-pointwise, trophic-nodes-in-cultmath and skein-gate-continuous are added. The
map gains r4 body facts B28-B36 (CultMath's node and parity surface, the tape,
the probe), decisions, two questions and the r4 cut sequence. The probe renders
filament candidates and trophic layers on the orbiting B20 zone and measures
popping and turnover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 05:30:34 +02:00
Meta Vens
66d069890a Merge origin/master into inspection-scanner
Behaviors.cs union list keeps sensor-catalog's ListenerData at 50 and
this cut's ScannerData at 51. No old design-name literal on the branch.
Commit builds unverified until the merge verify job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 05:21:37 +02:00
Meta Vens
521cb6b9d5 Planar-distance test: the target stands in a gravity well, so space and plane disagree
Units cannot be lifted by hand (Entity.Update resets Position.y to the zone's height), so the first version of the test never put the target off the plane. The zone's depth now does it, and the Dart claim's Range is set between the two distances.

Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:49:06 +02:00
Meta Vens
47f047865a Research: filament constructions, layered ecology graphs and CPU/GPU dual evaluation, for the trophic DAG
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:47:50 +02:00
Meta Vens
7d2443b511 Fused Rounds: the fragile hull sits inside the DeathCluster's effective range; the smoke round follows the first damage
Falloff made the DeathCluster too slow at the old Fragile position (443 m, past its 308 m effective range). Fragile moves to (80, 240), 253 m on the same bearing, and the scenario test asserts it against the weapon's evaluated EffectiveRange. Inside effective range the kill takes about 2.35 s whatever the distance and a Smoke Proximity round flies 1.75 s, so the round is fired once the hull has lost half its durability; the scenario Brief says the same. Probe: lead 0 landed 1.75 / dead 2.35; lead 1.0 dead 2.35 before the round.

Builds: yes. Not run yet (verified at the final job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:43:16 +02:00
Meta Vens
e3f65c894f Combat measures the gate's planar distance: a test that fails when it measures space
The planar-distance mutant survived the first mutation table; no test put a target off the ground plane.

Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:37:47 +02:00
Meta Vens
7633408fee Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-sensor-catalog-r2 2026-10-14 04:24:44 +02:00
Meta Vens
0a3636a4b1 Scanner tests: a broken scan resumes from what decayed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:24:05 +02:00
Meta Vens
b26fbbaa95 Scanner decays from the zone clock, not tick order; revert the consumable reorder
bdc8f1d0 ran Execute before the always-updated pass in ConsumableItemEffect.Update; that moved StatModifier timing for every consumable (TheOverdriveLocksAndBoosts failed). The scan's decay is now derived from the zone clock since the last held tick (Scanner.Progress, one site), so it is the same on the tick it breaks for an equipment host and a consumable host, and Scanner is no longer an IAlwaysUpdatedBehavior. The pilot-path test attaches a task-less Agent: a patrolling Minion needs zone orbits. bdc8f1d0 does not pass its own suite; this commit is the intended state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:23:13 +02:00
Meta Vens
46858dfa54 GameData/Aetheria.cc: apply AetherDb sensor-stat-set on master's catalog (replay at merge, do not merge the blob)
Output of `dotnet run --project tools/AetherDb -- sensor-stat-set apply` on origin/master be01ee06's catalog
(sha256 9ee82a86...; result sha256 00c59a641efc5f3cce3504bf604a9dd25781c06494b141a47cc9aaf56727525d). A second apply
changed nothing. The dry run printed:

Census: 2 sensor designs, 0 listener designs.
  Compact Sensor [Sensors] roles [emitter, receiver]
      not if i see you first by DME: emitter 0.71, receiver 0.75
  Sensor Array [Sensors] roles [emitter, receiver]
      The Bat by Miss Terri's: emitter 0.45, receiver 0.57
New design: Passive Array [Tool] 1x1, EnergyDraw 10/s, Multiple 2-3 reading receiver; products Murmur by Finch, Wallflower by NiteLife
Intercept factor: 2 designs and 2 products to change, 4 sensor products to add; Passive Array to author.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:22:33 +02:00
Meta Vens
cef4f0a746 AI test authors the live gun's damage, cooldown and ranges; Fused Rounds keeps its original Fragile position
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:06:25 +02:00
Meta Vens
d095d9bd61 AI test: report the live gun's range figures when the optimum is wrong
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:04:17 +02:00
Meta Vens
bdc8f1d048 Scanner tests: the pilot-path test steps both ships together and pins no scan before ScanTime
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:04:11 +02:00
Meta Vens
26d0e66ff5 Scanner fix batch: consumable hosts decay on the same tick; hostility, pilot-path, consumable and wire-key-51 tests
ConsumableItemEffect.Update now runs Execute before the always-updated pass, as EquippedItem.Update does, so a consumable-hosted scanner decays on the tick the scan breaks. Tests: AScanReadsNoHostility (hostile/friendly, honest/lying), AScanTakesTheSamePathForAnyPilot (AI-agent ship and agentless ship), AConsumableScannerDecaysOnTheSameTick, ScannerDataRoundTripsAsUnionKey51. Not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:03:20 +02:00
Meta Vens
742ce88a88 sensor-stat-set: name the Finch Passive Array product Murmur
master's NoDesignTextNamesAProduct fails on the first name, Feather, because the Racing Drive's
functional text begins "Feather-light". The product is renamed; its design text is generic-designs' and untouched.
Builds. The catalog does not yet carry the command's output (next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:02:48 +02:00
Meta Vens
f03811a40f TheAIHoldsAtItsEffectiveRange authors the live gun's Range too
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:00:16 +02:00
Meta Vens
5cbc555e4a TheAIHoldsAtItsEffectiveRange authors the live gun's falloff
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 04:00:06 +02:00
Meta Vens
ac1a5d29ed Fused Rounds: Fragile sits inside the DeathCluster's effective range; the AI test refreshes the gun's stats
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:57:58 +02:00
Meta Vens
ca810b9b1a TheAIHoldsAtItsEffectiveRange samples over the evaluated stats
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:55:29 +02:00
Meta Vens
3ca3fcde7b TheAIHoldsAtItsEffectiveRange lets the Online change land between toggles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:52:32 +02:00
Meta Vens
6c924e79e0 TheAIHoldsAtItsEffectiveRange toggles Enabled, the writable source of Online
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:50:10 +02:00
Meta Vens
005e2fc57b Merge origin/master into sensor-catalog-r2 (code; catalog is master's)
Conflicts: EvasionTermTests keeps the branch's EvLonginusDrive split with master's generic
design names; AetherDb Program.cs keeps both the sensor-stat-set and generic-designs cases and
lists both in the usage line. GameData/Aetheria.cc is taken from origin/master unchanged;
sensor-stat-set apply is rerun on it in the next commit. Tests that read the sensor catalog
(TheCatalogCarriesSensorStats and the roles checks) do not pass at this commit: it builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:34:19 +02:00
Meta Vens
a7f149d61d Merge remote-tracking branch 'origin/master' into eureka/aetheria-fauna-flow-field 2026-10-14 03:25:26 +02:00
Meta Vens
aed269ad94 Fire clamps the delivery range to Range; smoke-rounds keeps the template's falloff ratio; fixtures follow the gate
Not yet verified together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 03:04:45 +02:00
Meta Vens
6025009b24 range-falloff: rewrite only stale records; EffectiveRange joins the Range role; fixture fixes
EffectiveRange takes Range's role in the roles maps; the lock weapon's array
header grows to 37 with the weapon base's new keys; the AI test builds its
gun's effective range in the encounter fixture. Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:44:45 +02:00
Meta Vens
b026ea6eb6 Scanner tests: add the third ship before the scan so no zero-dt tick scans untracked 2026-10-14 02:41:58 +02:00
Meta Vens
4bcf5aa61a wip diag2 2026-10-14 02:36:08 +02:00
Meta Vens
9c5e53e88e wip diag 2026-10-14 02:33:20 +02:00
Meta Vens
417dd6c94a Fauna habitat probe kept as research; option images; lattice verdict (B25g, B25h)
Moves the closed-form habitat probe scripts and the images each habitat
question option names into docs/research/2026-10-14-fauna-habitat-probe/,
points the map there, and adds the option renders under the spec's law and
the probe that shows the convergence lattice is FlowField's own structure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:30:21 +02:00
Meta Vens
b5573e9b28 Scanner tests: the scanner ship carries no sensor, so its AI cannot ping beside the scan
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:27:19 +02:00
Meta Vens
e760333baf Fauna map r3: presence-fade and cycle-sampled pop probes (B25e, B25f)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:22:51 +02:00
Meta Vens
177bf4ba50 AetherDb range-falloff: fix a newline literal that did not compile
The previous commit (5e0ec925) does not build tools/AetherDb.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:21:46 +02:00
Meta Vens
064167bd06 Fauna target r3: placement is a closed form of slope and flow at run time
Applies ruling aetheria-fauna:ruling:fauna-placement-ruled: the target gains a
Placement law section and replaces fauna-placement-seeded with the placement
invariants closed-form, story, nested and no-pop. The map gains r3 body facts
(B24-B27, the closed-form density probe), decisions, the two questions and the
r3 cut sequence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:16:36 +02:00
Meta Vens
5e0ec92509 Damage falloff: effective range and damage at max range replace DamageCurve
WeaponData.RangeFactor is the one function of damage over range: 0 outside
[MinRange, Range], 1 up to EffectiveRange, one lerp to DamageAtMaxRange.
DamageCurve (key 7, retired) and its formula parameters, CurveField's
BezierCurve path, and every fixture curve line are deleted. Fire freezes
damage times the factor at BurstReach; the AI's DPS reads, Combat's optimum
sampling and the properties panel chart read the same function. AetherDb
gains range-falloff (command only; the catalog is re-saved in a later commit).
Cut and wiring land in one commit rather than two; this commit has not been
built yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:16:04 +02:00
Meta Vens
be01ee0600 Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-generic-design-names 2026-10-14 02:12:14 +02:00
Meta Vens
cefbb3dca7 aetheria-release map: damage falloff at fire time (cut-damage-falloff r2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:08:26 +02:00
Meta Vens
86843648a7 Add the inspection scanner: a held scan on a tracked target reveals all its gear
Scanner (ScannerData, Union 51) builds Progress while the ship's Target is tracked within Range, paints the target (PaintMode.Scan), emits at Range / InterceptFactor and decays in IAlwaysUpdatedBehavior.Update when not held. At 1 Entity.RecordInspection records every fitted non-hull non-destroyed item through RecordReveal with channel null and the subject's claim. Reveal.Channel and RecordReveal take SignatureChannel?. Scanner.cs.meta is hand-written with a fresh guid; Unity has not compiled this yet. Builds on the headless test project only if the next verify says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:07:17 +02:00
Meta Vens
d06a2faea9 aetheria-release map: inspection-scanner refresh at b836af48 (r3), shared sites with sensor-catalog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 02:01:45 +02:00
Meta Vens
198d6e28dd Research: fix header line breaks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:57:20 +02:00
Meta Vens
1f8492c328 Research: name the ruling the closed-form placement facts serve; drop a scratch path
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:56:55 +02:00
Meta Vens
52eecd6da1 Research: closed-form, runtime fauna placement prior art, for fauna target r3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:56:32 +02:00
Meta Vens
883d38a136 GameData/Aetheria.cc: generic-designs apply on master's catalog at b836af48 (replayed at merge, blob not merged)
Output of `dotnet run --project tools/AetherDb -- generic-designs apply` on f1642a12 (sha256 of the result
9ee82a860bc41fed142226a6bcc5ee8cb26c54ee1112d3d999feffaf1f2339ca). The touched set (139 design and product lines) is
identical to the apply at dc3abbdd on the old base; EW 1b records are untouched. A second dry run prints "Already applied;
nothing to do." The dry run printed:

design name: "ClearPath" -> "Light Machine Gun"
design "Light Machine Gun" text: "Defend your precious cargo and have fun doing it. Comes with optional sound effects." -> "Light ballistic hose: many small rounds at short range."
design name: "6k Shooter" -> "Slug Rifle"
design "Slug Rifle" text: "The fastest gun in Elysium" -> "Single heavy slugs, fired as fast as the trigger."
design name: "Earp" -> "Long Slug Rifle"
design "Long Slug Rifle" text: "Bringing the Wild West to the New Frontier" -> "A lighter slug rifle with the longest ballistic reach."
design name: "DeathCluster" -> "Cluster Cannon"
design "Cluster Cannon" text: "Because why kill two birds with one stone when you could annihilate them with one hundred?" -> "Medium shotgun: a heavy volley of pellets."
design name: "pretty pretty bang bang" -> "Charged Scattergun"
design "Charged Scattergun" text: "make your last stand/ it's a pretty pretty mess you've got us into/ it's a pretty pretty pretty day to die/ locked and loaded we're going out with a bang" -> "Ballistic shotgun that charges for a heavier volley."
design name: "Spectra" -> "Light Laser"
design "Light Laser" text: "Travelling light, for those travelling light. Take out the competition without slowing down with Spectra." -> "The lightest beam: low damage, quick cycle, long reach."
design name: "FastBlast+-" -> "Cell Blaster"
design "Cell Blaster" text: "Do less damage, faster!" -> "Rapid energy bursts fed by cells that cut its reactor draw."
design name: "ColdFire" -> "Long Laser"
design "Long Laser" text: "Operates by taking advantage of the wave/particle duality in a way that has other scientist tearing their hair out. Fact: Adrasteia's R&D department is the reason Einstein's hair looked like that." -> "Heavy small beam: slow, hard-hitting, long reach."
design name: "CShot RainbowLite Lazer" -> "Heavy Beam Laser"
design "Heavy Beam Laser" text: "Light up the cold, infinite void with more than your smile! Our precision full spectrum lasers are both combat and concert ready." -> "The heaviest beam: nine cells, enormous damage and reach."
design name: "ChargeBlast+-" -> "Charged Blaster"
design "Charged Blaster" text: "A knockout weapon, the arms equivalent of downing 9 shots of Tollgan Swamp liquor." -> "One charged knockout shot."
design name: "ChargeBlast SG" -> "Charged Scatter Blaster"
design "Charged Scatter Blaster" text: "For those days when you really want to spread the pain around." -> "Charged energy shotgun."
design name: "plight" -> "Lightning Projector"
design "Lightning Projector" text: "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)" -> "Charged chain lightning."
design name: "GT 3K" -> "Guided Missile Launcher"
design "Guided Missile Launcher" text: "Smaller, faster, and more determined than ever. The little missile that could!" -> "Fires guided missiles."
design name: "LRMM72" -> "Long-Range Missile Rack"
design "Long-Range Missile Rack" text: "" -> "Large missile rack for long engagements."
design name: "SRMM72" -> "Short-Range Missile Rack"
design "Short-Range Missile Rack" text: "" -> "Extra-large rack of short-range missiles."
design name: "pswarm" -> "Swarm Rocket Pod"
design "Swarm Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Dumbfire rockets in a swarm."
design name: "scorched void policy" -> "Incendiary Rocket Pod"
design "Incendiary Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Incendiary dumbfire rockets."
design name: "Arctica" -> "Adaptive Radiator"
design "Adaptive Radiator" text: "Go blazingly fast, without burning up." -> "Radiator whose output scales widely with conditions."
design name: "Iapyx" -> "Radiator"
design "Radiator" text: "" -> "Standard two-cell radiator."
design name: "Skiron" -> "Long Radiator"
design "Long Radiator" text: "" -> "Four-cell radiator with a large surface."
design name: "OK Disperser" -> "Heat Pump"
design "Heat Pump" text: "Adapted from the patented cooling system Lucent uses in their professional gaming setups. A high quality cooler, built to withstand even the most aggressive of rage quits." -> "Moves heat to where it can be shed."
design name: "cold like my heart" -> "Cryogenic Heat Pump"
design "Cryogenic Heat Pump" text: "nothing can touch me/ i'm an agent of entropy/ heat death in a bottle like a molotov cocktail" -> "Heavy heat pump that drives temperatures far down."
design name: "Core Power" -> "Compact Reactor"
design "Compact Reactor" text: "It gets the job done, but that's all." -> "Small reactor."
design name: "Manhattan" -> "Heavy Reactor"
design "Heavy Reactor" text: "Because might is right and finesse is for fools" -> "Large three-by-three reactor."
design name: "Notorious" -> "High-Yield Reactor"
design "High-Yield Reactor" text: "A reactor for those who want the biggest reaction" -> "Large reactor with a wide output range."
design name: "Vulcan" -> "Ring Reactor"
design "Ring Reactor" text: "High output, high heat. Blaze across the cosmos like the comet you were meant to be." -> "Ring-shaped reactor, four by four."
design name: "MoveOnPro" -> "Muon Fusion Reactor"
design "Muon Fusion Reactor" text: "The only muon catalyst fusion reactor on the market! Always gets a great reaction." -> "Compact fusion reactor that draws a reservoir."
design name: "Core Power Station Reactor" -> "Station Reactor"
design name: "Manhattan Station Reactor" -> "Heavy Station Reactor"
design "Heavy Station Reactor" text: "A reactor sized for a station's core." -> "A heavy reactor sized for a station's core."
design name: "Notorious Station Reactor" -> "High-Yield Station Reactor"
design "High-Yield Station Reactor" text: "A reactor sized for a station's core." -> "A high-yield reactor sized for a station's core."
design name: "Vulcan Station Reactor" -> "Ring Station Reactor"
design "Ring Station Reactor" text: "A reactor sized for a station's core." -> "A ring reactor sized for a station's core."
design name: "MoveOnPro Station Reactor" -> "Muon Fusion Station Reactor"
design "Muon Fusion Station Reactor" text: "A reactor sized for a station's core." -> "A muon fusion reactor sized for a station's core."
design name: "RevvITup 2.0" -> "High-Thrust Drive"
design "High-Thrust Drive" text: "" -> "Large drive: huge thrust, little torque."
design name: "deep space burnout" -> "Burn Drive"
design "Burn Drive" text: "go go go go go/ get the drift/ you'll burn before you stop " -> "Large drive that runs very hot."
design name: "Talaria" -> "Rugged Drive"
design "Rugged Drive" text: "" -> "Two-cell working drive."
design name: "Victoire" -> "Racing Drive"
design "Racing Drive" text: "The most responsive thruster on the market, for the most irresponsible of racing pilots." -> "Feather-light two-cell drive with extreme response."
design name: "The Bat" -> "Sensor Array"
design "Sensor Array" text: "" -> "Two-by-two long-range sensor array."
design name: "not if i see you first" -> "Compact Sensor"
design "Compact Sensor" text: "[TODO]" -> "One-cell sensor."
design name: "PotaT+-" -> "Capacitor"
design "Capacitor" text: "[TODO]" -> "Stores charge for burst draw."
design name: "SafeStuff II" -> "Secure Cargo Bay"
design "Secure Cargo Bay" text: "Your stuff is safe stuffed in the new, bigger SafeStuff" -> "Three-by-three secured hold."
design name: "Store-All Enterprise Edition" -> "Large Cargo Bay"
design "Large Cargo Bay" text: "A large amount of storage" -> "Six-by-six hold."
design name: "Store-All Plus" -> "Cargo Bay"
design "Cargo Bay" text: "Take your cargo wherever your shipgo" -> "Two-by-two hold."
design name: "Store-All Plus Mini" -> "Small Cargo Bay"
design "Small Cargo Bay" text: "Take some of your cargo wherever your shipgo" -> "One-cell hold."
product of "Autocannon" by Zhestokost: "Autocannon" -> "Hammerfall"
product "Hammerfall" text: "" -> "The rounds fall steadily, and they do not stop until the work is done."
design "Autocannon" text: "" -> "Belt-fed cannon: a steady stream of rounds at long reach."
product of "Cockpit 2x2" by Lightsail: "Cockpit 2x2" -> "Wheelhouse"
product "Wheelhouse" text: "" -> "Every Lightsail captain's favourite chair. The view comes standard."
design "Cockpit 2x2" text: "" -> "Two-by-two crew cockpit."
product of "Industrial Thermostatic Heater" by Lightsail: "Industrial Thermostatic Heater" -> "Hearth"
product "Hearth" text: "" -> "A warm hold, a warm crew, and a warm welcome at the cold end of the run."
design "Industrial Thermostatic Heater" text: "" -> "Turns reactor power into heat to keep the hull warm."
product of "Medium Drive" by Lightsail: "Medium Drive" -> "Steady Haul"
product "Steady Haul" text: "" -> "Keeps you going and going and going..."
design "Medium Drive" text: "Keeps you going and going and going..." -> "Mid-sized working drive."
product of "Small Drive" by Lightsail: "Small Drive" -> "Short Hop"
product "Short Hop" text: "" -> "Dock to dock, and not a metre further than the manifest says."
design "Small Drive" text: "" -> "Small working drive."
product of "Turret Control Module" by AU: "Turret Control Module" -> "Watchtower"
product "Watchtower" text: "" -> "Point it at the dark and get back to work. It keeps watch."
design "Turret Control Module" text: "" -> "Control module for a station turret."
product of "Medium Docking Bay" by AU: "Medium Docking Bay" -> "Open Berth"
product "Open Berth" text: "" -> "Room for a friend, a customer or a tug. We don't ask which."
design "Medium Docking Bay" text: "" -> "Docking bay for mid-sized ships."
product of "Mine Launcher" by DME: "Mine Launcher" -> "parting gift"
product "parting gift" text: "Lays a drifting proximity mine that arms after two seconds." -> "we were never here/ but we left you something/ it's waiting where we were"
design "Mine Launcher" text: "" -> "Lays a drifting proximity mine that arms after two seconds."
design "Large Drive" text: "Keeps you going and going and going..." -> "Large working drive."
design "Tractor Beam" text: "Trap your enemies in gravity wells. Haul thousands of tons of hay through space!" -> "Holds a target in a gravity well and hauls it in."
design "Smoke Proximity" text: "A Spectra that bursts by proximity, blast 8. For scenarios; no one builds it." -> "A Light Laser that bursts by proximity, blast 8. For scenarios; no one builds it."
design "Smoke Delayed" text: "A Spectra that bursts after two cells of metal, blast 4. For scenarios; no one builds it." -> "A Light Laser that bursts after two cells of metal, blast 4. For scenarios; no one builds it."
design "Smoke Refused" text: "A Spectra whose blast is wider than its reach, so it never fires. For scenarios; no one builds it." -> "A Light Laser whose blast is wider than its reach, so it never fires. For scenarios; no one builds it."
design "Smoke Refused Charge" text: "A ChargeBlast SG whose blast is wider than its reach, so it never charges. For scenarios; no one builds it." -> "A Charged Scatter Blaster whose blast is wider than its reach, so it never charges. For scenarios; no one builds it."
product "Victoire" text: "" -> "The most responsive thruster on the market, for the most irresponsible of racing pilots."
product "DragOnBreath" text: "The subsidiary plight's own description already namechecks: DragOnBreath, a Lucent Media property." -> "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)"
product "Steadfast" text: "Rated for continuous operation. "Continuous" does not imply "uninterrupted." (new text)" -> "It gets the job done, but that's all. Rated for continuous operation. "Continuous" does not imply "uninterrupted.""
product "Steadfast Station" text: "" -> "Rated for continuous operation at station scale. The fine print scales too."
product "Manhattan Station" text: "" -> "A fortress needs a furnace. This is the furnace."
product "Notorious Station" text: "" -> "The biggest reaction in the system, and everyone docked here will hear about it."
product "Vulcan Station" text: "" -> "Keeps the lights on and the forges hot."
product "MoveOnPro Station" text: "" -> "The club never closes. Neither does the reactor."
product "LRMM72" text: "" -> "Engages targets at up to seventy-two kilometres!* *In a vacuum, against a cooperative target."
product "SRMM72" text: "" -> "seventy-two reasons/ to keep your distance/ all of them leaving at once"
product "Iapyx" text: "" -> "Two cells of honest fin. Bolt it on and forget it's there."
product "Skiron" text: "" -> "When the job runs hot, run a bigger fin."
product "Talaria" text: "" -> "Takes a knock, keeps pushing. Built for crews who work for a living."
product "RevvITup 2.0" text: "" -> "Floor it. The bass drops when you do."
product "PotaT+-" text: "[TODO]" -> "Holds the charge until the drop, then lets it all go at once."
product "not if i see you first" text: "[TODO]" -> "eyes in the dark/ you were seen before you looked/ say goodnight"
product "Space Tractor" text: "It's a tractor. In space." -> "It's a tractor. In space. Trap your enemies in gravity wells. Haul thousands of tons of hay through space!"
product "Panopticon" authoring note stripped: "Sees everything, judges nothing. Well, mostly nothing. (new text)" -> "Sees everything, judges nothing. Well, mostly nothing."
product "ClapBack" authoring note stripped: "Your target won't clock it until the killcam. (new text)" -> "Your target won't clock it until the killcam."
product "Panopticon Prime" authoring note stripped: "The upgrade nobody at Finch will admit they needed until they had it. (new text)" -> "The upgrade nobody at Finch will admit they needed until they had it."
product "LockOn Pro" authoring note stripped: "Same promise, sharper lock. (new text)" -> "Same promise, sharper lock."
product "ClapBack Ultra" authoring note stripped: "Now with main-character energy built in. (new text)" -> "Now with main-character energy built in."
product "LockOn" authoring note stripped: "Keeps the lights on your target. (new text)" -> "Keeps the lights on your target."
product "True North" authoring note stripped: "Gets your cargo there. Getting you there is your problem. (new text)" -> "Gets your cargo there. Getting you there is your problem."

Dry run. Pass "apply" to write 89 records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:53:49 +02:00
Meta Vens
36cc37419c Sweep old design-name literals landed on master since the base (Lock On, EW 1b)
LockOn.cs hardpoint rows (Talaria, Core Power, GT 3K, FastBlast+-, Iapyx, not if i see you first, PotaT+-,
Store-All Plus) and LaunchSuppressorCatalogTests' SensorName take the generic names. Product-name literals in
CatalogRoleTests and GenericDesignsCommandTests stay: they are brands, not designs. Does not pass the scenario
tests until the catalog commit renames the designs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:51:55 +02:00
Meta Vens
a8394f3f92 Merge origin/master into generic-design-names
Conflicts: AetherDb usage line (kept master's list plus generic-designs [apply]), Program.cs class tail (kept the
launch-suppressor catalog and GenericDesigns both), GameData/Aetheria.cc taken from origin/master (f1642a12; the
generic-designs apply rerun follows in its own commit). The old-name sweep of the newly landed code follows separately.
This commit does not pass the generic-name tests: the catalog is master's, not yet renamed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 01:49:18 +02:00
Meta Vens
5f5a1e4d48 FlowFieldTests: the unfolded-law oracle skips the field's degenerate origin
The first version compared at the origin, where the field is a zero cross product and the double oracle is NaN; the test failed on a correct tree. This commit builds and passes; the previous one's FoldedScrollIsTheUnfoldedLawAtAnyAge fails.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 23:43:23 +02:00
Meta Vens
068adf0d95 Tests: the lot-derived alpha test equips its lot before the ship deploys
The first commit's test equipped the sensor after Add admitted the ship, and TryEquip refuses on a deployed ship; the lot built through ItemManager now rides Make into the mount. b63cdf5d does not pass that test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:32:50 +02:00
Meta Vens
b836af4850 Merge origin/master into loot-3 (second) 2026-10-13 23:30:23 +02:00
Meta Vens
819bd79424 FlowFieldSceneVerify: the flow as ARPG.unity runs it; parity check on a ramp height and the noise clock
FlowFieldSceneVerify opens ARPG.unity before anything touches the project's types, drives VolumeSampling and Stardust
Start/Update with a zone attached, and asserts no exception or logged error, FLOW_GLOBAL and FLOW_SLOPE enabled,
_FlowAmplitude non-zero, the stardust buffer changing with the flow and freezing with a paused zone, the noise clock,
and CloudShader pass 0 carrying the FLOW_* keywords. FlowFieldParityVerify now binds a ramp height so FLOW_SLOPE and its
pragma matter, and checks the noise follows _NebulaNoiseTime. The mutation harness runs both checks, with six new mutants.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 23:25:45 +02:00
Meta Vens
b155003689 Flow: keywords created on first use, strict [0,1) phases, nebula noise on the flow clock, fold-law and cycle tests
VolumeSampling created its flow keywords in static field initializers, which a scene runs inside a MonoBehaviour
construction where Unity refuses GlobalKeyword.Create; they are now created lazily from LowerFlow. FlowField.Scroll and
Cycle return phases strictly below 1. The nebula noise reads _NebulaNoiseTime (zone time) instead of _Time.y. New
FlowFieldTests pin the per-octave fold to the unfolded law across wraps, the cycle at days of zone time, and the phase edge.
The Unity checks for these are in the next commit; this one builds, its parity check does not yet read the noise clock.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 23:25:44 +02:00
Meta Vens
b63cdf5d2b Tests: a Sensor reads its intercept factor from its lot's emission-discipline; the Longinus broadside ceiling has its own fitted factor
ASensorReadsItsInterceptFactorFromItsLotsEmissionDiscipline equips a catalog-style sensor from a lot filled at .5, .2 and .8 and reads Sensor.InterceptFactor (1, .6168, 1.5534). The Longinus half of ReachIsWhatTheShipCanDo takes LonginusBroadsideFactor (1.27, from reach 12.74 over measured 10.40) in place of the Djinni's. Builds not verified until the verify job; no catalog change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:15:35 +02:00
Meta Vens
78ccb81f72 Merge origin/master into loot-3
No conflicts; GameData/Aetheria.cc taken from master (loot-3 authors no catalog).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 23:13:22 +02:00
Meta Vens
dc3abbddce GameData/Aetheria.cc: generic-designs apply on the base catalog through an ExpectUnchanged batch (sha256 34cbfacc50de6ba7945fe47c1e699d3125c7c3ba445675a8b8bfebfe58c057ba)
Produced by a Yggdrasil job (dotnet run AetherDb -- generic-designs apply at 7d1fa5ce) on the catalog at the base (1746e8bd, sha256 1a2cb55b63f77a113dea0571716994ef8311d5da572a4fc41cbd3a7d2561fb68). 89 records written; the other 169 are byte-identical to the base. Of the 89, 85 differ from the base only in Name/Description; four (Compact Sensor, Sensor Array, Long-Range Missile Rack, Guided Missile Launcher) are authored records and still re-encode their Behaviors through the typed object. A second run answers 'Already applied; nothing to do.' Dry-run text:

design name: "ClearPath" -> "Light Machine Gun"
design "Light Machine Gun" text: "Defend your precious cargo and have fun doing it. Comes with optional sound effects." -> "Light ballistic hose: many small rounds at short range."
design name: "6k Shooter" -> "Slug Rifle"
design "Slug Rifle" text: "The fastest gun in Elysium" -> "Single heavy slugs, fired as fast as the trigger."
design name: "Earp" -> "Long Slug Rifle"
design "Long Slug Rifle" text: "Bringing the Wild West to the New Frontier" -> "A lighter slug rifle with the longest ballistic reach."
design name: "DeathCluster" -> "Cluster Cannon"
design "Cluster Cannon" text: "Because why kill two birds with one stone when you could annihilate them with one hundred?" -> "Medium shotgun: a heavy volley of pellets."
design name: "pretty pretty bang bang" -> "Charged Scattergun"
design "Charged Scattergun" text: "make your last stand/ it's a pretty pretty mess you've got us into/ it's a pretty pretty pretty day to die/ locked and loaded we're going out with a bang" -> "Ballistic shotgun that charges for a heavier volley."
design name: "Spectra" -> "Light Laser"
design "Light Laser" text: "Travelling light, for those travelling light. Take out the competition without slowing down with Spectra." -> "The lightest beam: low damage, quick cycle, long reach."
design name: "FastBlast+-" -> "Cell Blaster"
design "Cell Blaster" text: "Do less damage, faster!" -> "Rapid energy bursts fed by cells that cut its reactor draw."
design name: "ColdFire" -> "Long Laser"
design "Long Laser" text: "Operates by taking advantage of the wave/particle duality in a way that has other scientist tearing their hair out. Fact: Adrasteia's R&D department is the reason Einstein's hair looked like that." -> "Heavy small beam: slow, hard-hitting, long reach."
design name: "CShot RainbowLite Lazer" -> "Heavy Beam Laser"
design "Heavy Beam Laser" text: "Light up the cold, infinite void with more than your smile! Our precision full spectrum lasers are both combat and concert ready." -> "The heaviest beam: nine cells, enormous damage and reach."
design name: "ChargeBlast+-" -> "Charged Blaster"
design "Charged Blaster" text: "A knockout weapon, the arms equivalent of downing 9 shots of Tollgan Swamp liquor." -> "One charged knockout shot."
design name: "ChargeBlast SG" -> "Charged Scatter Blaster"
design "Charged Scatter Blaster" text: "For those days when you really want to spread the pain around." -> "Charged energy shotgun."
design name: "plight" -> "Lightning Projector"
design "Lightning Projector" text: "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)" -> "Charged chain lightning."
design name: "GT 3K" -> "Guided Missile Launcher"
design "Guided Missile Launcher" text: "Smaller, faster, and more determined than ever. The little missile that could!" -> "Fires guided missiles."
design name: "LRMM72" -> "Long-Range Missile Rack"
design "Long-Range Missile Rack" text: "" -> "Large missile rack for long engagements."
design name: "SRMM72" -> "Short-Range Missile Rack"
design "Short-Range Missile Rack" text: "" -> "Extra-large rack of short-range missiles."
design name: "pswarm" -> "Swarm Rocket Pod"
design "Swarm Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Dumbfire rockets in a swarm."
design name: "scorched void policy" -> "Incendiary Rocket Pod"
design "Incendiary Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Incendiary dumbfire rockets."
design name: "Arctica" -> "Adaptive Radiator"
design "Adaptive Radiator" text: "Go blazingly fast, without burning up." -> "Radiator whose output scales widely with conditions."
design name: "Iapyx" -> "Radiator"
design "Radiator" text: "" -> "Standard two-cell radiator."
design name: "Skiron" -> "Long Radiator"
design "Long Radiator" text: "" -> "Four-cell radiator with a large surface."
design name: "OK Disperser" -> "Heat Pump"
design "Heat Pump" text: "Adapted from the patented cooling system Lucent uses in their professional gaming setups. A high quality cooler, built to withstand even the most aggressive of rage quits." -> "Moves heat to where it can be shed."
design name: "cold like my heart" -> "Cryogenic Heat Pump"
design "Cryogenic Heat Pump" text: "nothing can touch me/ i'm an agent of entropy/ heat death in a bottle like a molotov cocktail" -> "Heavy heat pump that drives temperatures far down."
design name: "Core Power" -> "Compact Reactor"
design "Compact Reactor" text: "It gets the job done, but that's all." -> "Small reactor."
design name: "Manhattan" -> "Heavy Reactor"
design "Heavy Reactor" text: "Because might is right and finesse is for fools" -> "Large three-by-three reactor."
design name: "Notorious" -> "High-Yield Reactor"
design "High-Yield Reactor" text: "A reactor for those who want the biggest reaction" -> "Large reactor with a wide output range."
design name: "Vulcan" -> "Ring Reactor"
design "Ring Reactor" text: "High output, high heat. Blaze across the cosmos like the comet you were meant to be." -> "Ring-shaped reactor, four by four."
design name: "MoveOnPro" -> "Muon Fusion Reactor"
design "Muon Fusion Reactor" text: "The only muon catalyst fusion reactor on the market! Always gets a great reaction." -> "Compact fusion reactor that draws a reservoir."
design name: "Core Power Station Reactor" -> "Station Reactor"
design name: "Manhattan Station Reactor" -> "Heavy Station Reactor"
design "Heavy Station Reactor" text: "A reactor sized for a station's core." -> "A heavy reactor sized for a station's core."
design name: "Notorious Station Reactor" -> "High-Yield Station Reactor"
design "High-Yield Station Reactor" text: "A reactor sized for a station's core." -> "A high-yield reactor sized for a station's core."
design name: "Vulcan Station Reactor" -> "Ring Station Reactor"
design "Ring Station Reactor" text: "A reactor sized for a station's core." -> "A ring reactor sized for a station's core."
design name: "MoveOnPro Station Reactor" -> "Muon Fusion Station Reactor"
design "Muon Fusion Station Reactor" text: "A reactor sized for a station's core." -> "A muon fusion reactor sized for a station's core."
design name: "RevvITup 2.0" -> "High-Thrust Drive"
design "High-Thrust Drive" text: "" -> "Large drive: huge thrust, little torque."
design name: "deep space burnout" -> "Burn Drive"
design "Burn Drive" text: "go go go go go/ get the drift/ you'll burn before you stop " -> "Large drive that runs very hot."
design name: "Talaria" -> "Rugged Drive"
design "Rugged Drive" text: "" -> "Two-cell working drive."
design name: "Victoire" -> "Racing Drive"
design "Racing Drive" text: "The most responsive thruster on the market, for the most irresponsible of racing pilots." -> "Feather-light two-cell drive with extreme response."
design name: "The Bat" -> "Sensor Array"
design "Sensor Array" text: "" -> "Two-by-two long-range sensor array."
design name: "not if i see you first" -> "Compact Sensor"
design "Compact Sensor" text: "[TODO]" -> "One-cell sensor."
design name: "PotaT+-" -> "Capacitor"
design "Capacitor" text: "[TODO]" -> "Stores charge for burst draw."
design name: "SafeStuff II" -> "Secure Cargo Bay"
design "Secure Cargo Bay" text: "Your stuff is safe stuffed in the new, bigger SafeStuff" -> "Three-by-three secured hold."
design name: "Store-All Enterprise Edition" -> "Large Cargo Bay"
design "Large Cargo Bay" text: "A large amount of storage" -> "Six-by-six hold."
design name: "Store-All Plus" -> "Cargo Bay"
design "Cargo Bay" text: "Take your cargo wherever your shipgo" -> "Two-by-two hold."
design name: "Store-All Plus Mini" -> "Small Cargo Bay"
design "Small Cargo Bay" text: "Take some of your cargo wherever your shipgo" -> "One-cell hold."
product of "Autocannon" by Zhestokost: "Autocannon" -> "Hammerfall"
product "Hammerfall" text: "" -> "The rounds fall steadily, and they do not stop until the work is done."
design "Autocannon" text: "" -> "Belt-fed cannon: a steady stream of rounds at long reach."
product of "Cockpit 2x2" by Lightsail: "Cockpit 2x2" -> "Wheelhouse"
product "Wheelhouse" text: "" -> "Every Lightsail captain's favourite chair. The view comes standard."
design "Cockpit 2x2" text: "" -> "Two-by-two crew cockpit."
product of "Industrial Thermostatic Heater" by Lightsail: "Industrial Thermostatic Heater" -> "Hearth"
product "Hearth" text: "" -> "A warm hold, a warm crew, and a warm welcome at the cold end of the run."
design "Industrial Thermostatic Heater" text: "" -> "Turns reactor power into heat to keep the hull warm."
product of "Medium Drive" by Lightsail: "Medium Drive" -> "Steady Haul"
product "Steady Haul" text: "" -> "Keeps you going and going and going..."
design "Medium Drive" text: "Keeps you going and going and going..." -> "Mid-sized working drive."
product of "Small Drive" by Lightsail: "Small Drive" -> "Short Hop"
product "Short Hop" text: "" -> "Dock to dock, and not a metre further than the manifest says."
design "Small Drive" text: "" -> "Small working drive."
product of "Turret Control Module" by AU: "Turret Control Module" -> "Watchtower"
product "Watchtower" text: "" -> "Point it at the dark and get back to work. It keeps watch."
design "Turret Control Module" text: "" -> "Control module for a station turret."
product of "Medium Docking Bay" by AU: "Medium Docking Bay" -> "Open Berth"
product "Open Berth" text: "" -> "Room for a friend, a customer or a tug. We don't ask which."
design "Medium Docking Bay" text: "" -> "Docking bay for mid-sized ships."
product of "Mine Launcher" by DME: "Mine Launcher" -> "parting gift"
product "parting gift" text: "Lays a drifting proximity mine that arms after two seconds." -> "we were never here/ but we left you something/ it's waiting where we were"
design "Mine Launcher" text: "" -> "Lays a drifting proximity mine that arms after two seconds."
design "Large Drive" text: "Keeps you going and going and going..." -> "Large working drive."
design "Tractor Beam" text: "Trap your enemies in gravity wells. Haul thousands of tons of hay through space!" -> "Holds a target in a gravity well and hauls it in."
design "Smoke Proximity" text: "A Spectra that bursts by proximity, blast 8. For scenarios; no one builds it." -> "A Light Laser that bursts by proximity, blast 8. For scenarios; no one builds it."
design "Smoke Delayed" text: "A Spectra that bursts after two cells of metal, blast 4. For scenarios; no one builds it." -> "A Light Laser that bursts after two cells of metal, blast 4. For scenarios; no one builds it."
design "Smoke Refused" text: "A Spectra whose blast is wider than its reach, so it never fires. For scenarios; no one builds it." -> "A Light Laser whose blast is wider than its reach, so it never fires. For scenarios; no one builds it."
design "Smoke Refused Charge" text: "A ChargeBlast SG whose blast is wider than its reach, so it never charges. For scenarios; no one builds it." -> "A Charged Scatter Blaster whose blast is wider than its reach, so it never charges. For scenarios; no one builds it."
product "Victoire" text: "" -> "The most responsive thruster on the market, for the most irresponsible of racing pilots."
product "DragOnBreath" text: "The subsidiary plight's own description already namechecks: DragOnBreath, a Lucent Media property." -> "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)"
product "Steadfast" text: "Rated for continuous operation. "Continuous" does not imply "uninterrupted." (new text)" -> "It gets the job done, but that's all. Rated for continuous operation. "Continuous" does not imply "uninterrupted.""
product "Steadfast Station" text: "" -> "Rated for continuous operation at station scale. The fine print scales too."
product "Manhattan Station" text: "" -> "A fortress needs a furnace. This is the furnace."
product "Notorious Station" text: "" -> "The biggest reaction in the system, and everyone docked here will hear about it."
product "Vulcan Station" text: "" -> "Keeps the lights on and the forges hot."
product "MoveOnPro Station" text: "" -> "The club never closes. Neither does the reactor."
product "LRMM72" text: "" -> "Engages targets at up to seventy-two kilometres!* *In a vacuum, against a cooperative target."
product "SRMM72" text: "" -> "seventy-two reasons/ to keep your distance/ all of them leaving at once"
product "Iapyx" text: "" -> "Two cells of honest fin. Bolt it on and forget it's there."
product "Skiron" text: "" -> "When the job runs hot, run a bigger fin."
product "Talaria" text: "" -> "Takes a knock, keeps pushing. Built for crews who work for a living."
product "RevvITup 2.0" text: "" -> "Floor it. The bass drops when you do."
product "PotaT+-" text: "[TODO]" -> "Holds the charge until the drop, then lets it all go at once."
product "not if i see you first" text: "[TODO]" -> "eyes in the dark/ you were seen before you looked/ say goodnight"
product "Space Tractor" text: "It's a tractor. In space." -> "It's a tractor. In space. Trap your enemies in gravity wells. Haul thousands of tons of hay through space!"
product "Panopticon" authoring note stripped: "Sees everything, judges nothing. Well, mostly nothing. (new text)" -> "Sees everything, judges nothing. Well, mostly nothing."
product "ClapBack" authoring note stripped: "Your target won't clock it until the killcam. (new text)" -> "Your target won't clock it until the killcam."
product "Panopticon Prime" authoring note stripped: "The upgrade nobody at Finch will admit they needed until they had it. (new text)" -> "The upgrade nobody at Finch will admit they needed until they had it."
product "LockOn Pro" authoring note stripped: "Same promise, sharper lock. (new text)" -> "Same promise, sharper lock."
product "ClapBack Ultra" authoring note stripped: "Now with main-character energy built in. (new text)" -> "Now with main-character energy built in."
product "LockOn" authoring note stripped: "Keeps the lights on your target. (new text)" -> "Keeps the lights on your target."
product "True North" authoring note stripped: "Gets your cargo there. Getting you there is your problem. (new text)" -> "Gets your cargo there. Getting you there is your problem."

Dry run. Pass "apply" to write 89 records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:56:49 +02:00
Meta Vens
5c2c11bfd0 Merge origin/master into ew-claims-in-the-book
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:53:15 +02:00
Meta Vens
7d1fa5ce60 AetherDb: ExpectUnchanged belongs to generic-designs' batch, not roles-migrate's
The previous sweep commit put the ExpectUnchanged batch in RolesMigrate's commit (first match of the anchor) and left GenericDesigns on a plain commit. RolesMigrate is restored to its base text; GenericDesigns now lands its batch onto the file as it is. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:52:24 +02:00
Meta Vens
ae8d11e3ac GenericDesignsCommandTests: import the MessagePack snapshot serializer the payload-widening helper uses
Fixes the compile break at 205c9f52 and 4d127c82 (the missing using). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:39:21 +02:00
Meta Vens
4d127c8246 GameData/Aetheria.cc: generic-designs apply again, on the base catalog, landing only its own records (sha256 c22457d1de3c36214f1fa3d115527f8145bd687387d14252cfce1558471253d7)
Produced by a Yggdrasil job (dotnet run AetherDb -- generic-designs apply) on the catalog at the base (1746e8bd, sha256 1a2cb55b63f77a113dea0571716994ef8311d5da572a4fc41cbd3a7d2561fb68). The batch carries ExpectUnchanged: 89 records written, every other record byte-identical to the base. A second run answers 'Already applied; nothing to do.' Dry-run text:

design name: "ClearPath" -> "Light Machine Gun"
design "Light Machine Gun" text: "Defend your precious cargo and have fun doing it. Comes with optional sound effects." -> "Light ballistic hose: many small rounds at short range."
design name: "6k Shooter" -> "Slug Rifle"
design "Slug Rifle" text: "The fastest gun in Elysium" -> "Single heavy slugs, fired as fast as the trigger."
design name: "Earp" -> "Long Slug Rifle"
design "Long Slug Rifle" text: "Bringing the Wild West to the New Frontier" -> "A lighter slug rifle with the longest ballistic reach."
design name: "DeathCluster" -> "Cluster Cannon"
design "Cluster Cannon" text: "Because why kill two birds with one stone when you could annihilate them with one hundred?" -> "Medium shotgun: a heavy volley of pellets."
design name: "pretty pretty bang bang" -> "Charged Scattergun"
design "Charged Scattergun" text: "make your last stand/ it's a pretty pretty mess you've got us into/ it's a pretty pretty pretty day to die/ locked and loaded we're going out with a bang" -> "Ballistic shotgun that charges for a heavier volley."
design name: "Spectra" -> "Light Laser"
design "Light Laser" text: "Travelling light, for those travelling light. Take out the competition without slowing down with Spectra." -> "The lightest beam: low damage, quick cycle, long reach."
design name: "FastBlast+-" -> "Cell Blaster"
design "Cell Blaster" text: "Do less damage, faster!" -> "Rapid energy bursts fed by cells that cut its reactor draw."
design name: "ColdFire" -> "Long Laser"
design "Long Laser" text: "Operates by taking advantage of the wave/particle duality in a way that has other scientist tearing their hair out. Fact: Adrasteia's R&D department is the reason Einstein's hair looked like that." -> "Heavy small beam: slow, hard-hitting, long reach."
design name: "CShot RainbowLite Lazer" -> "Heavy Beam Laser"
design "Heavy Beam Laser" text: "Light up the cold, infinite void with more than your smile! Our precision full spectrum lasers are both combat and concert ready." -> "The heaviest beam: nine cells, enormous damage and reach."
design name: "ChargeBlast+-" -> "Charged Blaster"
design "Charged Blaster" text: "A knockout weapon, the arms equivalent of downing 9 shots of Tollgan Swamp liquor." -> "One charged knockout shot."
design name: "ChargeBlast SG" -> "Charged Scatter Blaster"
design "Charged Scatter Blaster" text: "For those days when you really want to spread the pain around." -> "Charged energy shotgun."
design name: "plight" -> "Lightning Projector"
design "Lightning Projector" text: "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)" -> "Charged chain lightning."
design name: "GT 3K" -> "Guided Missile Launcher"
design "Guided Missile Launcher" text: "Smaller, faster, and more determined than ever. The little missile that could!" -> "Fires guided missiles."
design name: "LRMM72" -> "Long-Range Missile Rack"
design "Long-Range Missile Rack" text: "" -> "Large missile rack for long engagements."
design name: "SRMM72" -> "Short-Range Missile Rack"
design "Short-Range Missile Rack" text: "" -> "Extra-large rack of short-range missiles."
design name: "pswarm" -> "Swarm Rocket Pod"
design "Swarm Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Dumbfire rockets in a swarm."
design name: "scorched void policy" -> "Incendiary Rocket Pod"
design "Incendiary Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Incendiary dumbfire rockets."
design name: "Arctica" -> "Adaptive Radiator"
design "Adaptive Radiator" text: "Go blazingly fast, without burning up." -> "Radiator whose output scales widely with conditions."
design name: "Iapyx" -> "Radiator"
design "Radiator" text: "" -> "Standard two-cell radiator."
design name: "Skiron" -> "Long Radiator"
design "Long Radiator" text: "" -> "Four-cell radiator with a large surface."
design name: "OK Disperser" -> "Heat Pump"
design "Heat Pump" text: "Adapted from the patented cooling system Lucent uses in their professional gaming setups. A high quality cooler, built to withstand even the most aggressive of rage quits." -> "Moves heat to where it can be shed."
design name: "cold like my heart" -> "Cryogenic Heat Pump"
design "Cryogenic Heat Pump" text: "nothing can touch me/ i'm an agent of entropy/ heat death in a bottle like a molotov cocktail" -> "Heavy heat pump that drives temperatures far down."
design name: "Core Power" -> "Compact Reactor"
design "Compact Reactor" text: "It gets the job done, but that's all." -> "Small reactor."
design name: "Manhattan" -> "Heavy Reactor"
design "Heavy Reactor" text: "Because might is right and finesse is for fools" -> "Large three-by-three reactor."
design name: "Notorious" -> "High-Yield Reactor"
design "High-Yield Reactor" text: "A reactor for those who want the biggest reaction" -> "Large reactor with a wide output range."
design name: "Vulcan" -> "Ring Reactor"
design "Ring Reactor" text: "High output, high heat. Blaze across the cosmos like the comet you were meant to be." -> "Ring-shaped reactor, four by four."
design name: "MoveOnPro" -> "Muon Fusion Reactor"
design "Muon Fusion Reactor" text: "The only muon catalyst fusion reactor on the market! Always gets a great reaction." -> "Compact fusion reactor that draws a reservoir."
design name: "Core Power Station Reactor" -> "Station Reactor"
design name: "Manhattan Station Reactor" -> "Heavy Station Reactor"
design "Heavy Station Reactor" text: "A reactor sized for a station's core." -> "A heavy reactor sized for a station's core."
design name: "Notorious Station Reactor" -> "High-Yield Station Reactor"
design "High-Yield Station Reactor" text: "A reactor sized for a station's core." -> "A high-yield reactor sized for a station's core."
design name: "Vulcan Station Reactor" -> "Ring Station Reactor"
design "Ring Station Reactor" text: "A reactor sized for a station's core." -> "A ring reactor sized for a station's core."
design name: "MoveOnPro Station Reactor" -> "Muon Fusion Station Reactor"
design "Muon Fusion Station Reactor" text: "A reactor sized for a station's core." -> "A muon fusion reactor sized for a station's core."
design name: "RevvITup 2.0" -> "High-Thrust Drive"
design "High-Thrust Drive" text: "" -> "Large drive: huge thrust, little torque."
design name: "deep space burnout" -> "Burn Drive"
design "Burn Drive" text: "go go go go go/ get the drift/ you'll burn before you stop " -> "Large drive that runs very hot."
design name: "Talaria" -> "Rugged Drive"
design "Rugged Drive" text: "" -> "Two-cell working drive."
design name: "Victoire" -> "Racing Drive"
design "Racing Drive" text: "The most responsive thruster on the market, for the most irresponsible of racing pilots." -> "Feather-light two-cell drive with extreme response."
design name: "The Bat" -> "Sensor Array"
design "Sensor Array" text: "" -> "Two-by-two long-range sensor array."
design name: "not if i see you first" -> "Compact Sensor"
design "Compact Sensor" text: "[TODO]" -> "One-cell sensor."
design name: "PotaT+-" -> "Capacitor"
design "Capacitor" text: "[TODO]" -> "Stores charge for burst draw."
design name: "SafeStuff II" -> "Secure Cargo Bay"
design "Secure Cargo Bay" text: "Your stuff is safe stuffed in the new, bigger SafeStuff" -> "Three-by-three secured hold."
design name: "Store-All Enterprise Edition" -> "Large Cargo Bay"
design "Large Cargo Bay" text: "A large amount of storage" -> "Six-by-six hold."
design name: "Store-All Plus" -> "Cargo Bay"
design "Cargo Bay" text: "Take your cargo wherever your shipgo" -> "Two-by-two hold."
design name: "Store-All Plus Mini" -> "Small Cargo Bay"
design "Small Cargo Bay" text: "Take some of your cargo wherever your shipgo" -> "One-cell hold."
product of "Autocannon" by Zhestokost: "Autocannon" -> "Hammerfall"
product "Hammerfall" text: "" -> "The rounds fall steadily, and they do not stop until the work is done."
design "Autocannon" text: "" -> "Belt-fed cannon: a steady stream of rounds at long reach."
product of "Cockpit 2x2" by Lightsail: "Cockpit 2x2" -> "Wheelhouse"
product "Wheelhouse" text: "" -> "Every Lightsail captain's favourite chair. The view comes standard."
design "Cockpit 2x2" text: "" -> "Two-by-two crew cockpit."
product of "Industrial Thermostatic Heater" by Lightsail: "Industrial Thermostatic Heater" -> "Hearth"
product "Hearth" text: "" -> "A warm hold, a warm crew, and a warm welcome at the cold end of the run."
design "Industrial Thermostatic Heater" text: "" -> "Turns reactor power into heat to keep the hull warm."
product of "Medium Drive" by Lightsail: "Medium Drive" -> "Steady Haul"
product "Steady Haul" text: "" -> "Keeps you going and going and going..."
design "Medium Drive" text: "Keeps you going and going and going..." -> "Mid-sized working drive."
product of "Small Drive" by Lightsail: "Small Drive" -> "Short Hop"
product "Short Hop" text: "" -> "Dock to dock, and not a metre further than the manifest says."
design "Small Drive" text: "" -> "Small working drive."
product of "Turret Control Module" by AU: "Turret Control Module" -> "Watchtower"
product "Watchtower" text: "" -> "Point it at the dark and get back to work. It keeps watch."
design "Turret Control Module" text: "" -> "Control module for a station turret."
product of "Medium Docking Bay" by AU: "Medium Docking Bay" -> "Open Berth"
product "Open Berth" text: "" -> "Room for a friend, a customer or a tug. We don't ask which."
design "Medium Docking Bay" text: "" -> "Docking bay for mid-sized ships."
product of "Mine Launcher" by DME: "Mine Launcher" -> "parting gift"
product "parting gift" text: "Lays a drifting proximity mine that arms after two seconds." -> "we were never here/ but we left you something/ it's waiting where we were"
design "Mine Launcher" text: "" -> "Lays a drifting proximity mine that arms after two seconds."
design "Large Drive" text: "Keeps you going and going and going..." -> "Large working drive."
design "Tractor Beam" text: "Trap your enemies in gravity wells. Haul thousands of tons of hay through space!" -> "Holds a target in a gravity well and hauls it in."
design "Smoke Proximity" text: "A Spectra that bursts by proximity, blast 8. For scenarios; no one builds it." -> "A Light Laser that bursts by proximity, blast 8. For scenarios; no one builds it."
design "Smoke Delayed" text: "A Spectra that bursts after two cells of metal, blast 4. For scenarios; no one builds it." -> "A Light Laser that bursts after two cells of metal, blast 4. For scenarios; no one builds it."
design "Smoke Refused" text: "A Spectra whose blast is wider than its reach, so it never fires. For scenarios; no one builds it." -> "A Light Laser whose blast is wider than its reach, so it never fires. For scenarios; no one builds it."
design "Smoke Refused Charge" text: "A ChargeBlast SG whose blast is wider than its reach, so it never charges. For scenarios; no one builds it." -> "A Charged Scatter Blaster whose blast is wider than its reach, so it never charges. For scenarios; no one builds it."
product "Victoire" text: "" -> "The most responsive thruster on the market, for the most irresponsible of racing pilots."
product "DragOnBreath" text: "The subsidiary plight's own description already namechecks: DragOnBreath, a Lucent Media property." -> "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)"
product "Steadfast" text: "Rated for continuous operation. "Continuous" does not imply "uninterrupted." (new text)" -> "It gets the job done, but that's all. Rated for continuous operation. "Continuous" does not imply "uninterrupted.""
product "Steadfast Station" text: "" -> "Rated for continuous operation at station scale. The fine print scales too."
product "Manhattan Station" text: "" -> "A fortress needs a furnace. This is the furnace."
product "Notorious Station" text: "" -> "The biggest reaction in the system, and everyone docked here will hear about it."
product "Vulcan Station" text: "" -> "Keeps the lights on and the forges hot."
product "MoveOnPro Station" text: "" -> "The club never closes. Neither does the reactor."
product "LRMM72" text: "" -> "Engages targets at up to seventy-two kilometres!* *In a vacuum, against a cooperative target."
product "SRMM72" text: "" -> "seventy-two reasons/ to keep your distance/ all of them leaving at once"
product "Iapyx" text: "" -> "Two cells of honest fin. Bolt it on and forget it's there."
product "Skiron" text: "" -> "When the job runs hot, run a bigger fin."
product "Talaria" text: "" -> "Takes a knock, keeps pushing. Built for crews who work for a living."
product "RevvITup 2.0" text: "" -> "Floor it. The bass drops when you do."
product "PotaT+-" text: "[TODO]" -> "Holds the charge until the drop, then lets it all go at once."
product "not if i see you first" text: "[TODO]" -> "eyes in the dark/ you were seen before you looked/ say goodnight"
product "Space Tractor" text: "It's a tractor. In space." -> "It's a tractor. In space. Trap your enemies in gravity wells. Haul thousands of tons of hay through space!"
product "Panopticon" authoring note stripped: "Sees everything, judges nothing. Well, mostly nothing. (new text)" -> "Sees everything, judges nothing. Well, mostly nothing."
product "ClapBack" authoring note stripped: "Your target won't clock it until the killcam. (new text)" -> "Your target won't clock it until the killcam."
product "Panopticon Prime" authoring note stripped: "The upgrade nobody at Finch will admit they needed until they had it. (new text)" -> "The upgrade nobody at Finch will admit they needed until they had it."
product "LockOn Pro" authoring note stripped: "Same promise, sharper lock. (new text)" -> "Same promise, sharper lock."
product "ClapBack Ultra" authoring note stripped: "Now with main-character energy built in. (new text)" -> "Now with main-character energy built in."
product "LockOn" authoring note stripped: "Keeps the lights on your target. (new text)" -> "Keeps the lights on your target."
product "True North" authoring note stripped: "Gets your cargo there. Getting you there is your problem. (new text)" -> "Gets your cargo there. Getting you there is your problem."

Dry run. Pass "apply" to write 89 records.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:35:47 +02:00
Meta Vens
c1eee662f9 Loot 3 fix1: the stand-in pose check derives its progress from the rule, not from FieldTester
The pull-progress input came from FieldTester.PullProgress, so a mutant of that function agreed with itself. The smoke now spells the pull start from Extend and Envelop independently.
Builds; both smokes green; Unity mutant u-f killed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:34:50 +02:00
Meta Vens
205c9f5205 Briefs, comments and tests name current gear; generic-designs lands only its own records and rewrites the last flavour and brand design texts
Scenario Briefs (Crossing, Duel, FusedRounds, LauncherAngles, StarvedReactor, WeaponFeel), scenario and test comments and test locals say the design names (Lightning Projector, Light Laser, Cell Blaster, Guided Missile Launcher, Swarm Rocket Pod, Muon Fusion Reactor, Cluster Cannon, Charged Scatter Blaster, Rugged Drive, Racing Drive) instead of the retired brand names; Crossing.PlightRange is ProjectorRange.

generic-designs: the batch carries ExpectUnchanged so every record it does not author keeps its bytes (the plain commit re-encoded four records, dropping SensorData key 7). DesignTexts rewrites Large Drive, Tractor Beam, Smoke Proximity, Smoke Delayed, Smoke Refused and Smoke Refused Charge as tech-node text; the Tractor Beam's old line moves to its product Space Tractor. smoke-rounds' authored text names Light Laser and Charged Scatter Blaster to match.

Tests: NoScenarioBriefNamesRetiredGear, TheCapacitorDesignCarriesItsRoleMap, NoDesignTextNamesAProduct, and a command test that widens every payload and checks apply changes only the three records it authors and restores the rewritten texts.

Not built or run at this commit; GameData/Aetheria.cc is regenerated in the next commit, so NoDesignTextNamesAProduct and the command test fail here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:34:08 +02:00
Meta Vens
64fd701920 Merge origin/master into ew-hide-launch-catalog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:34:03 +02:00
Meta Vens
a345bd3dcb Loot 3 fix1: the loot-3 findings' fixtures, and the held-pose curve has one owner
PickupTests: TheBeamTakesFromWhicheverBayCanStore is a theory over which bay is full.
CapabilityPresentationSmoke: tracked ship's hull hit is drawn; a beam above the held point stays on the ground plane; a grab at the beam keeps its aim; the other entity's grab reaches its own bound beam and not this one.
FloatingItemsDrawnSmoke: a held item's label comes up; the test scene's stand-in pose equals the zone's held pose.
Zone.HeldPull is the one smoothstep of the held pose; FieldDriver's tendril and FieldTester's stand-in call it (FieldTester.PulledPosition, PullProgress), deleting the two copies.
All commits build (Unity compile and both smokes green).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:25:49 +02:00
Meta Vens
2cd92fe15d Tests: a consumable listener's Multiple below 1 is not clamped up
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:57:12 +02:00
Meta Vens
5309b7365e Tests: the Djinni's reach is bounded by its measured motion times the fitted ship's own factor
Replaces the allocated*1.2 ceiling, which scaled with Reach; a reach inflated 1.1x or 3x now fails on the Djinni half too. Fixes the stale comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:56:17 +02:00
Meta Vens
9ae8cd277e EW 2 fix: wear the fixture gun to 95% range, above the fuse arming distance
A gun worn to half its range falls under the fuse's arming distance and FireControl refuses it, so the fixture never fired. At 95% the gun fires and its live range (38) still differs from its rated 40.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:56:09 +02:00
Meta Vens
281b911e6a Catalog: sensor-stat-set re-applied to the base catalog so the Passive Array description is tech-node text
Regenerated from e99cfbed's catalog by the tool (apply twice, second writes nothing); the seven new records carry fresh guids.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:55:20 +02:00
Meta Vens
49ef136d1c GameData/Aetheria.cc: apply AetherDb launch-suppressor again, landing only its own records (replay the command at merge, do not merge the blob)
Output of `dotnet run --project tools/AetherDb -- launch-suppressor apply` at 18fa8a5e on the catalog at fa6108de (sha256 of the base 1a2cb55b63f77a113dea0571716994ef8311d5da572a4fc41cbd3a7d2561fb68, of the result f1642a12c3f7b1184a159985944f128704bd489151f8fb9077a057b9c0fa7347). Decoded against the base: 258 -> 266 records, header equal, 8 added, no base record changed (the previous blob re-encoded four). The dry run printed:

    /src/Assets/Scripts/ServerShared/Behaviors/LockWeapon.cs(49,25): warning CS0067: The event 'LockWeapon.OnLocked' is never used [/src/Aetheria.Shared/Aetheria.Shared.csproj]
    /src/Assets/Scripts/ServerShared/Behaviors/LockWeapon.cs(51,25): warning CS0067: The event 'LockWeapon.OnLockLost' is never used [/src/Aetheria.Shared/Aetheria.Shared.csproj]
    /src/Assets/Scripts/ServerShared/Behaviors/LockWeapon.cs(50,25): warning CS0067: The event 'LockWeapon.OnBeginLocking' is never used [/src/Aetheria.Shared/Aetheria.Shared.csproj]
    New designs:
      Launch Suppressor  1x1 Tool  mass 60  price 40000  durability 50  roles [baffles, heat sink]
          Factor 0.08-0.03 (baffles)
          HeatPerUnit 1.4-0.8 (heat sink)
          RatedTemperature 310-330 (heat sink)
          "Baffles and a heat sink remove nearly all of a weapon's launch flash, hiding the shot from its target. The removed light is dissipated as heat in the device's own cell; above its rated temperature it passes the full flash."
      Launch Baffle      1x1 Tool  mass 60  price 25000  durability 50  roles [baffles, heat sink]
          Factor 0.4-0.2 (baffles)
          HeatPerUnit 0.8-0.5 (heat sink)
          RatedTemperature 310-330 (heat sink)
          "Baffles dim a weapon's launch flash to a fraction and a heat sink absorbs the difference. The target still sees the shot; distant observers do not. The sink sustains the effect through a long fight."

    New products:
      Launch Suppressor -> "Velvet Rope" by NiteLife, every role mean 0.55 dev 0.12: Keeps the flash on the inside. Nobody sees who you let out.
      Launch Suppressor -> "Hush" by Finch, every role mean 0.65 dev 0.2: Small, quiet, and the first shot is a secret. The second, probably.
      Launch Suppressor -> "lights out" by DME, every role mean 0.55 dev 0.2: no flash/ no name/ nobody saw a thing
      Launch Suppressor -> "Plausible Deniability" by R&D, every role mean 0.6 dev 0.15: Hides 100% of launches!* *Launches defined as the ones nobody saw.
      Launch Baffle -> "Low Profile" by Lightsail, every role mean 0.55 dev 0.1: Quiet on the manifest, quiet on the scope. A hauler nobody notices is a hauler that gets paid.
      Launch Baffle -> "Fast Pass Dim" by Alakrita, every role mean 0.6 dev 0.14: Takes the glare off every launch and keeps the schedule. Anyone close enough to mind was already your problem.

    Dry run. Pass "apply" to author 2 designs and 6 products.

The full Aetheria.Shared.Tests suite passed on this catalog (1714 passed, 0 failed) at 18fa8a5e.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:55:10 +02:00
Meta Vens
13dae2beb6 FlowFieldParityVerify: tolerance 1.5e-4, 5x the measured 2.9e-5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:52:13 +02:00
Meta Vens
b903912e8c FlowFieldParityVerify: bind a flat gravity height for the keyword-gated flow()
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:51:22 +02:00
Meta Vens
1c9c70a3ec FlowParity.compute: declare the flow keywords the way Stardust.compute does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:50:27 +02:00
Meta Vens
9d23d4fe8d FlowFieldParityVerify: fix the split literal (0a3180d3 does not compile in Unity)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:49:16 +02:00
Meta Vens
ab0ab9f1af Tests: listener stacking, alpha derivation and the Djinni reach ceiling pinned (first cut, constants to be measured)
Does not carry the regenerated catalog; the Djinni factors are provisional until measured.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:44:08 +02:00
Meta Vens
824e0f6a95 AetherDb: the Passive Array design description is tech-node text (designs-are-tech-nodes); flavour stays on its products
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:44:05 +02:00
Meta Vens
0a3180d386 Flow: register the flow keywords, one zone-time value for Zone.Flow and the scroll, presenter phases from zone time, folded scroll, tighter parity
- VolumeSampling registers FLOW_GLOBAL / FLOW_SLOPE with GlobalKeyword.Create (the constructor only looks up).
- FlowField.Scroll folds each Tri3D octave's phase modulo 1 in double (float2, [0,1)); Zone.Flow evaluates at Zone.FlowScroll.
- FlowField.Cycle: the nebula's flow cycle and Stardust's particle lifetime phase come from zone time (_FlowCycle, phase uniform), not _Time.y / Time.time.
- FlowFieldParityVerify reaches the keyword-gated flow(), fails on logged errors, tolerance 3e-4; mutants updated.

Not built or run when committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:43:41 +02:00
Meta Vens
18fa8a5e1d launch-suppressor: apply lands only its own records; tests pin late hiding, the rating line, linear suppression and a named observer sensor
Command: the batch carries ExpectUnchanged, so CultCache lands it onto the file as it is. A plain commit re-encoded every record through today's types (two sensors lost a retired key-7 payload and gained a trailing nil, LRMM72 and GT 3K gained a trailing nil); this one leaves every record it did not author byte-identical. A conflicting writer now fails the apply instead of being overwritten.

Tests: the mild baffle stores exactly flash x Factor and pays exactly its predicted heat for the first 30 launches of a 300 flash or 8 of a 1000 flash, then is either hidden or bright; the rating is pinned to half a kelvin either side at three heat-sink qualities; suppression and heat are checked at six flash strengths; the observer fits the named sensor 'not if i see you first'; the command test widens every payload and checks apply leaves all other records byte-identical.

This commit's GameData/Aetheria.cc pointer is the previous apply's output; the regenerated catalog follows in its own commit. Not built or run at this commit yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:37:41 +02:00
Meta Vens
01ccb32b89 EW 2 fix: the worn-gun fixture reads its live range after the gun has ticked in the test's own path
The previous commit ticked before firing and the gun never lit; the wear is attached, the gun fires, then the live range is asserted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:37:23 +02:00
Meta Vens
0eb7a2734e Merge origin/master into scenarios-lock-on-r3 2026-10-13 21:36:00 +02:00
Meta Vens
b6146022e7 EW 2 fix: claims fixtures see live state; hull claim guard both ways; charged multiplier once; stale gear sorts last
- Enemy and own schematic rows, and the rebuild key's Item half, are pinned by fixtures whose live range differs from the rated range and whose guns share a claimed design.
- Entity.Claim refuses a hull class on a non-hull item as it refuses a non-hull class on the hull.
- ChargedWeapon live reads (DamagePerSecond, RangeDamagePerSecond) start from the uncharged damage so the charge multiplier is applied once and a nominal weapon reads its rated figure at every charge.
- RevealedWeapons orders reveals of gear the subject no longer carries after all fitted gear, then by lot.

Builds and tests unverified at this commit; verification follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:19:53 +02:00
Meta Vens
53a13675d5 Flow parity: FlowParity.compute, FlowFieldParityVerify (Unity batchmode, GPU) and its mutation harness
The probe steps a Zone, lowers its flow through VolumeSampling.LowerFlow, dispatches the HLSL
globalFlow and slopeFlow, and compares with FlowField (max error 1.0e-4 of amplitude, tolerance
1e-3). All commits build; the Unity side was verified from this tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:49:22 +02:00
Meta Vens
9b5eaa45d6 GenericDesignsCommandTests: restore of brand design text and a product-text row, and a held brand refused
Not built yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:36:15 +02:00
Meta Vens
c648416b59 Lock On test: drop the monotonic-Strength assertion, which the sim does not promise
The lock's Strength rises from its first paint to its last; it is not monotonic. Builds: yes (test-only change after 038628e9, which built and failed this assertion).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:35:22 +02:00
Meta Vens
743d62ae7e Tests for generic-designs: brands on every product, no authoring notes, renamed designs keep keys, the command's refusals and idempotence
The command's authoring-note suffix is a public constant so the catalog test reads the one literal.
Not built yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:32:21 +02:00
Meta Vens
f7cf3257d0 Sweep: every old design-name literal in C# becomes its generic name; product texts ship without the authoring notes
Scenarios, tests, AetherDb templates and name-keyed maps now resolve designs by the generic names (231 literals in 30 files);
TargetingCatalog's product texts lose the authoring note, Steadfast carries its r3 text, DragOnBreath plight's old design text.
Not built yet; tests that depend on the generic-designs command and new tests follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:29:10 +02:00
Meta Vens
3f7bd145bb GameData/Aetheria.cc: apply AetherDb launch-suppressor (replay the command at merge, do not merge the blob)
Output of `dotnet run --project tools/AetherDb -- launch-suppressor apply` on the catalog at fa6108de (sha256 of the base 1a2cb55b63f77a113dea0571716994ef8311d5da572a4fc41cbd3a7d2561fb68, of the result 3c2f3649762d35f66f3f220dbd4aa289d1711f05f8b7195a4cc3e5cc43085fa8). The dry run printed:

    New designs:
      Launch Suppressor  1x1 Tool  mass 60  price 40000  durability 50  roles [baffles, heat sink]
          Factor 0.08-0.03 (baffles)
          HeatPerUnit 1.4-0.8 (heat sink)
          RatedTemperature 310-330 (heat sink)
          "Baffles and a heat sink remove nearly all of a weapon's launch flash, hiding the shot from its target. The removed light is dissipated as heat in the device's own cell; above its rated temperature it passes the full flash."
      Launch Baffle      1x1 Tool  mass 60  price 25000  durability 50  roles [baffles, heat sink]
          Factor 0.4-0.2 (baffles)
          HeatPerUnit 0.8-0.5 (heat sink)
          RatedTemperature 310-330 (heat sink)
          "Baffles dim a weapon's launch flash to a fraction and a heat sink absorbs the difference. The target still sees the shot; distant observers do not. The sink sustains the effect through a long fight."
    New products:
      Launch Suppressor -> "Velvet Rope" by NiteLife, every role mean 0.55 dev 0.12: Keeps the flash on the inside. Nobody sees who you let out.
      Launch Suppressor -> "Hush" by Finch, every role mean 0.65 dev 0.2: Small, quiet, and the first shot is a secret. The second, probably.
      Launch Suppressor -> "lights out" by DME, every role mean 0.55 dev 0.2: no flash/ no name/ nobody saw a thing
      Launch Suppressor -> "Plausible Deniability" by R&D, every role mean 0.6 dev 0.15: Hides 100% of launches!* *Launches defined as the ones nobody saw.
      Launch Baffle -> "Low Profile" by Lightsail, every role mean 0.55 dev 0.1: Quiet on the manifest, quiet on the scope. A hauler nobody notices is a hauler that gets paid.
      Launch Baffle -> "Fast Pass Dim" by Alakrita, every role mean 0.6 dev 0.14: Takes the glare off every launch and keeps the schedule. Anyone close enough to mind was already your problem.
    Dry run. Pass "apply" to author 2 designs and 6 products.

Builds and passes the full suite (1687 passed, 0 failed) at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:28:02 +02:00
Meta Vens
37acc6bbc3 GameData/Aetheria.cc: generic-designs apply (sha256 c9adaa7a1334983d685e0730bdae0b245bd703337a4c02f13a79d5ccbcac06bf)
Produced by a KEEP-style Yggdrasil job (dotnet run AetherDb -- generic-designs apply) on the
catalog at 0ee04f20. A second apply answers "Already applied; nothing to do." Dry-run text:

design name: "ClearPath" -> "Light Machine Gun"
design "Light Machine Gun" text: "Defend your precious cargo and have fun doing it. Comes with optional sound effects." -> "Light ballistic hose: many small rounds at short range."
design name: "6k Shooter" -> "Slug Rifle"
design "Slug Rifle" text: "The fastest gun in Elysium" -> "Single heavy slugs, fired as fast as the trigger."
design name: "Earp" -> "Long Slug Rifle"
design "Long Slug Rifle" text: "Bringing the Wild West to the New Frontier" -> "A lighter slug rifle with the longest ballistic reach."
design name: "DeathCluster" -> "Cluster Cannon"
design "Cluster Cannon" text: "Because why kill two birds with one stone when you could annihilate them with one hundred?" -> "Medium shotgun: a heavy volley of pellets."
design name: "pretty pretty bang bang" -> "Charged Scattergun"
design "Charged Scattergun" text: "make your last stand/ it's a pretty pretty mess you've got us into/ it's a pretty pretty pretty day to die/ locked and loaded we're going out with a bang" -> "Ballistic shotgun that charges for a heavier volley."
design name: "Spectra" -> "Light Laser"
design "Light Laser" text: "Travelling light, for those travelling light. Take out the competition without slowing down with Spectra." -> "The lightest beam: low damage, quick cycle, long reach."
design name: "FastBlast+-" -> "Cell Blaster"
design "Cell Blaster" text: "Do less damage, faster!" -> "Rapid energy bursts fed by cells that cut its reactor draw."
design name: "ColdFire" -> "Long Laser"
design "Long Laser" text: "Operates by taking advantage of the wave/particle duality in a way that has other scientist tearing their hair out. Fact: Adrasteia's R&D department is the reason Einstein's hair looked like that." -> "Heavy small beam: slow, hard-hitting, long reach."
design name: "CShot RainbowLite Lazer" -> "Heavy Beam Laser"
design "Heavy Beam Laser" text: "Light up the cold, infinite void with more than your smile! Our precision full spectrum lasers are both combat and concert ready." -> "The heaviest beam: nine cells, enormous damage and reach."
design name: "ChargeBlast+-" -> "Charged Blaster"
design "Charged Blaster" text: "A knockout weapon, the arms equivalent of downing 9 shots of Tollgan Swamp liquor." -> "One charged knockout shot."
design name: "ChargeBlast SG" -> "Charged Scatter Blaster"
design "Charged Scatter Blaster" text: "For those days when you really want to spread the pain around." -> "Charged energy shotgun."
design name: "plight" -> "Lightning Projector"
design "Lightning Projector" text: "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)" -> "Charged chain lightning."
design name: "GT 3K" -> "Guided Missile Launcher"
design "Guided Missile Launcher" text: "Smaller, faster, and more determined than ever. The little missile that could!" -> "Fires guided missiles."
design name: "LRMM72" -> "Long-Range Missile Rack"
design "Long-Range Missile Rack" text: "" -> "Large missile rack for long engagements."
design name: "SRMM72" -> "Short-Range Missile Rack"
design "Short-Range Missile Rack" text: "" -> "Extra-large rack of short-range missiles."
design name: "pswarm" -> "Swarm Rocket Pod"
design "Swarm Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Dumbfire rockets in a swarm."
design name: "scorched void policy" -> "Incendiary Rocket Pod"
design "Incendiary Rocket Pod" text: "let's set the stars on fire/ there's nothing left on earth to burn/ we're just killing time while we're filling space/ and catacombs in turn" -> "Incendiary dumbfire rockets."
design name: "Arctica" -> "Adaptive Radiator"
design "Adaptive Radiator" text: "Go blazingly fast, without burning up." -> "Radiator whose output scales widely with conditions."
design name: "Iapyx" -> "Radiator"
design "Radiator" text: "" -> "Standard two-cell radiator."
design name: "Skiron" -> "Long Radiator"
design "Long Radiator" text: "" -> "Four-cell radiator with a large surface."
design name: "OK Disperser" -> "Heat Pump"
design "Heat Pump" text: "Adapted from the patented cooling system Lucent uses in their professional gaming setups. A high quality cooler, built to withstand even the most aggressive of rage quits." -> "Moves heat to where it can be shed."
design name: "cold like my heart" -> "Cryogenic Heat Pump"
design "Cryogenic Heat Pump" text: "nothing can touch me/ i'm an agent of entropy/ heat death in a bottle like a molotov cocktail" -> "Heavy heat pump that drives temperatures far down."
design name: "Core Power" -> "Compact Reactor"
design "Compact Reactor" text: "It gets the job done, but that's all." -> "Small reactor."
design name: "Manhattan" -> "Heavy Reactor"
design "Heavy Reactor" text: "Because might is right and finesse is for fools" -> "Large three-by-three reactor."
design name: "Notorious" -> "High-Yield Reactor"
design "High-Yield Reactor" text: "A reactor for those who want the biggest reaction" -> "Large reactor with a wide output range."
design name: "Vulcan" -> "Ring Reactor"
design "Ring Reactor" text: "High output, high heat. Blaze across the cosmos like the comet you were meant to be." -> "Ring-shaped reactor, four by four."
design name: "MoveOnPro" -> "Muon Fusion Reactor"
design "Muon Fusion Reactor" text: "The only muon catalyst fusion reactor on the market! Always gets a great reaction." -> "Compact fusion reactor that draws a reservoir."
design name: "Core Power Station Reactor" -> "Station Reactor"
design name: "Manhattan Station Reactor" -> "Heavy Station Reactor"
design "Heavy Station Reactor" text: "A reactor sized for a station's core." -> "A heavy reactor sized for a station's core."
design name: "Notorious Station Reactor" -> "High-Yield Station Reactor"
design "High-Yield Station Reactor" text: "A reactor sized for a station's core." -> "A high-yield reactor sized for a station's core."
design name: "Vulcan Station Reactor" -> "Ring Station Reactor"
design "Ring Station Reactor" text: "A reactor sized for a station's core." -> "A ring reactor sized for a station's core."
design name: "MoveOnPro Station Reactor" -> "Muon Fusion Station Reactor"
design "Muon Fusion Station Reactor" text: "A reactor sized for a station's core." -> "A muon fusion reactor sized for a station's core."
design name: "RevvITup 2.0" -> "High-Thrust Drive"
design "High-Thrust Drive" text: "" -> "Large drive: huge thrust, little torque."
design name: "deep space burnout" -> "Burn Drive"
design "Burn Drive" text: "go go go go go/ get the drift/ you'll burn before you stop " -> "Large drive that runs very hot."
design name: "Talaria" -> "Rugged Drive"
design "Rugged Drive" text: "" -> "Two-cell working drive."
design name: "Victoire" -> "Racing Drive"
design "Racing Drive" text: "The most responsive thruster on the market, for the most irresponsible of racing pilots." -> "Feather-light two-cell drive with extreme response."
design name: "The Bat" -> "Sensor Array"
design "Sensor Array" text: "" -> "Two-by-two long-range sensor array."
design name: "not if i see you first" -> "Compact Sensor"
design "Compact Sensor" text: "[TODO]" -> "One-cell sensor."
design name: "PotaT+-" -> "Capacitor"
design "Capacitor" text: "[TODO]" -> "Stores charge for burst draw."
design name: "SafeStuff II" -> "Secure Cargo Bay"
design "Secure Cargo Bay" text: "Your stuff is safe stuffed in the new, bigger SafeStuff" -> "Three-by-three secured hold."
design name: "Store-All Enterprise Edition" -> "Large Cargo Bay"
design "Large Cargo Bay" text: "A large amount of storage" -> "Six-by-six hold."
design name: "Store-All Plus" -> "Cargo Bay"
design "Cargo Bay" text: "Take your cargo wherever your shipgo" -> "Two-by-two hold."
design name: "Store-All Plus Mini" -> "Small Cargo Bay"
design "Small Cargo Bay" text: "Take some of your cargo wherever your shipgo" -> "One-cell hold."
product of "Autocannon" by Zhestokost: "Autocannon" -> "Hammerfall"
product "Hammerfall" text: "" -> "The rounds fall steadily, and they do not stop until the work is done."
design "Autocannon" text: "" -> "Belt-fed cannon: a steady stream of rounds at long reach."
product of "Cockpit 2x2" by Lightsail: "Cockpit 2x2" -> "Wheelhouse"
product "Wheelhouse" text: "" -> "Every Lightsail captain's favourite chair. The view comes standard."
design "Cockpit 2x2" text: "" -> "Two-by-two crew cockpit."
product of "Industrial Thermostatic Heater" by Lightsail: "Industrial Thermostatic Heater" -> "Hearth"
product "Hearth" text: "" -> "A warm hold, a warm crew, and a warm welcome at the cold end of the run."
design "Industrial Thermostatic Heater" text: "" -> "Turns reactor power into heat to keep the hull warm."
product of "Medium Drive" by Lightsail: "Medium Drive" -> "Steady Haul"
product "Steady Haul" text: "" -> "Keeps you going and going and going..."
design "Medium Drive" text: "Keeps you going and going and going..." -> "Mid-sized working drive."
product of "Small Drive" by Lightsail: "Small Drive" -> "Short Hop"
product "Short Hop" text: "" -> "Dock to dock, and not a metre further than the manifest says."
design "Small Drive" text: "" -> "Small working drive."
product of "Turret Control Module" by AU: "Turret Control Module" -> "Watchtower"
product "Watchtower" text: "" -> "Point it at the dark and get back to work. It keeps watch."
design "Turret Control Module" text: "" -> "Control module for a station turret."
product of "Medium Docking Bay" by AU: "Medium Docking Bay" -> "Open Berth"
product "Open Berth" text: "" -> "Room for a friend, a customer or a tug. We don't ask which."
design "Medium Docking Bay" text: "" -> "Docking bay for mid-sized ships."
product of "Mine Launcher" by DME: "Mine Launcher" -> "parting gift"
product "parting gift" text: "Lays a drifting proximity mine that arms after two seconds." -> "we were never here/ but we left you something/ it's waiting where we were"
design "Mine Launcher" text: "" -> "Lays a drifting proximity mine that arms after two seconds."
product "Victoire" text: "" -> "The most responsive thruster on the market, for the most irresponsible of racing pilots."
product "DragOnBreath" text: "The subsidiary plight's own description already namechecks: DragOnBreath, a Lucent Media property." -> "Chain lightning has your enemies chain smoking while you enjoy a relaxing DragOnBreath vapepop, now available in 17! flavours (manufactured by DragOnBreath, a subsidary of Lucent Media)"
product "Steadfast" text: "Rated for continuous operation. "Continuous" does not imply "uninterrupted." (new text)" -> "It gets the job done, but that's all. Rated for continuous operation. "Continuous" does not imply "uninterrupted.""
product "Steadfast Station" text: "" -> "Rated for continuous operation at station scale. The fine print scales too."
product "Manhattan Station" text: "" -> "A fortress needs a furnace. This is the furnace."
product "Notorious Station" text: "" -> "The biggest reaction in the system, and everyone docked here will hear about it."
product "Vulcan Station" text: "" -> "Keeps the lights on and the forges hot."
product "MoveOnPro Station" text: "" -> "The club never closes. Neither does the reactor."
product "LRMM72" text: "" -> "Engages targets at up to seventy-two kilometres!* *In a vacuum, against a cooperative target."
product "SRMM72" text: "" -> "seventy-two reasons/ to keep your distance/ all of them leaving at once"
product "Iapyx" text: "" -> "Two cells of honest fin. Bolt it on and forget it's there."
product "Skiron" text: "" -> "When the job runs hot, run a bigger fin."
product "Talaria" text: "" -> "Takes a knock, keeps pushing. Built for crews who work for a living."
product "RevvITup 2.0" text: "" -> "Floor it. The bass drops when you do."
product "PotaT+-" text: "[TODO]" -> "Holds the charge until the drop, then lets it all go at once."
product "not if i see you first" text: "[TODO]" -> "eyes in the dark/ you were seen before you looked/ say goodnight"
product "Panopticon" authoring note stripped: "Sees everything, judges nothing. Well, mostly nothing. (new text)" -> "Sees everything, judges nothing. Well, mostly nothing."
product "ClapBack" authoring note stripped: "Your target won't clock it until the killcam. (new text)" -> "Your target won't clock it until the killcam."
product "Panopticon Prime" authoring note stripped: "The upgrade nobody at Finch will admit they needed until they had it. (new text)" -> "The upgrade nobody at Finch will admit they needed until they had it."
product "LockOn Pro" authoring note stripped: "Same promise, sharper lock. (new text)" -> "Same promise, sharper lock."
product "ClapBack Ultra" authoring note stripped: "Now with main-character energy built in. (new text)" -> "Now with main-character energy built in."
product "LockOn" authoring note stripped: "Keeps the lights on your target. (new text)" -> "Keeps the lights on your target."
product "True North" authoring note stripped: "Gets your cargo there. Getting you there is your problem. (new text)" -> "Gets your cargo there. Getting you there is your problem."

Dry run. Pass "apply" to write 82 records.

This commit builds (a data file); tests that name old design literals fail until the sweep commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:27:26 +02:00
Meta Vens
c87809cf7b FlowFieldTests: assert the flow moved and scaled on probes where the field is nonzero (the origin is a zero of the field)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:26:29 +02:00
Meta Vens
4aeeea0ff7 AetherDb generic-designs: track changed records in a list (ReferenceEqualityComparer is not in this target)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:21:38 +02:00
Meta Vens
90294e0fef EW 2 fix: the enemy schematic's rows, claimed class and range label are derived in ServerShared
Entity.SchematicRows(subject) owns which weapon rows a schematic shows, each row's item and
claimed design, and its range (own ship: live; any other: the claimed design's rated range).
SchematicDisplay renders SchematicRow and decides nothing. Headless tests cover default-to-truth,
a weapon claimed as another weapon, a weapon claimed as a non-weapon, own rows, and the rebuild key.

Builds on the Shared side not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:21:15 +02:00
Meta Vens
c17b70a862 AetherDb generic-designs [apply]: 43 designs take generic tech-tree names, eight same-named products take brands
Adds the command, its rename/brand/product-text tables, and the ToolRolesByDesign
Capacitor key. The catalog and the old-name literal sweep follow in later commits;
this commit has not been built yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:14:41 +02:00
Meta Vens
038628e914 Lock On: observe "beyond its sight" in the sim's own sensing, pin the hostile's facing, stage off axis, read the lock's Strength
The Update(0) checks could not fail and the 40..200 tick window was tuning. The test now asks the hostile's
PassiveInfo for the player's signature against the detection threshold after the first real tick, asserts the
hostile has no track then, pins the facing, and asserts the Track paint's Strength rises. The hostile is staged at
(1500, 3700) facing the player. The unsound comment about the player's sight is corrected.

Builds: not yet verified (verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:13:02 +02:00
Meta Vens
947b86f7f3 Tests: the fitted Djinni's reach ceiling is its allocated reach
The fitted Djinni's measured motion sits further below its reach than the generated one did (nose-on 1.69), so the
fixed 1.6 ceiling over measured motion was the old ship's number. The ceiling is the allocated reach with 20% to
spare, as the Longinus's is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:11:33 +02:00
Meta Vens
de6dbce70f AetherDb launch-suppressor: two Tool designs (Launch Suppressor, Launch Baffle) and six products, with catalog and command tests
The catalog tests need the applied catalog; this commit does not pass them until the next commit lands the apply output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:10:21 +02:00
Meta Vens
f9eaee7c10 FlowField: alias float2/float3 (math.float3 method shadows the type; e8ec8e90 does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:08:10 +02:00
Meta Vens
0d291a8a42 Tests: the flight fleet's Longinus is its drive train, not the Duel's loadout
The Longinus the reach test measures is fitted with the drive train the generated one carries
(EvLonginusDrive, which EvLonginus now extends); the Duel's guns and stores added mass the
reach ceilings were not measured with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:07:08 +02:00
Meta Vens
e8ec8e903c Flow field: FlowField owns the global flow, Zone.Flow evaluates it at zone time, VolumeSampling.LowerFlow lowers it
FlowField (ServerShared) is the flow law; Zone.Flow/FlowScroll read PlanetSettings.Flow at zone
time. The Flow block moves from DefaultEnvironment to PlanetSettings (ZoneEnvironment key 1 is
retired), VolumeSampling's frame-clock scroll accumulator and the Stardust leftover field are
deleted, and slopeFlow returns 0 for a zero gradient. Unity parity probe follows in the next
commit; this commit has not been built in Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:06:35 +02:00
Meta Vens
0ee04f2081 Map: weapon damage over range (range falloff is never applied; census of authored curves; options)
Body facts R1-R3 for ruling range-ramps-not-curve: no hit path scales damage by
range, DamageCurve feeds only AI estimates and a UI chart, and 26 of 27 shipped
weapons carry one copied default curve. Options with cost, a recommendation to
delete the curve, and cut-sequence lines damage-curve-delete,
sensor-bearing-shape and consumable-effectiveness.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:04:16 +02:00
Meta Vens
0a4a2cf56a Tests: reuse the existing EvDjinni fit instead of a second one
The previous commit added a duplicate EvDjinni and did not build (CS0111).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:03:44 +02:00
Meta Vens
a35dc97790 Merge remote-tracking branch 'origin/master' into HEAD 2026-10-13 20:02:58 +02:00
Meta Vens
b753dbe337 Tests: the two flight tests fit their ships by name; a consumable-hosted Listener test
ReachIsWhatTheShipCanDo and TheThrustersReadLiveThrust built their ships with the
generator, whose draw follows the run's item stream and so the catalog's census; the
applied sensor catalog shifted it. They now fit the Djinni (a Talaria on each thruster
hardpoint, reactor, cockpit) and the Longinus (EvLonginus) by name. AConsumableListenerHearsAtItsMultiple
pins Entity.HearingMultiple over an active consumable's Listener.

Not yet verified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:02:32 +02:00
Meta Vens
b0fc86c774 Release map: generic-design-names refresh at 1746e8bd (GN1-GN8, brands and flavour under kitchen-sink-content); catalog-breadth lines follow catalog-breadth-now
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:00:14 +02:00
Meta Vens
fa6108de7d EW map: 1b r2 (two suppressor designs) and probes K9-K11 (sensor reach, suppressor endurance, opening volley)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 20:00:04 +02:00
Meta Vens
adb632fe3d Hull-claim test: signature strong enough to survive the one-tick exponential decay
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:58:56 +02:00
Meta Vens
1e219e96e3 Fauna r2: target content r2 (attacks, harvest, flow owner, Sol, seeded placement, kitchen-sink classes), map r2 (B15-B23, decisions, r2 cut sequence), placement prior art and probe
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:55:24 +02:00
Meta Vens
a782c7d5d2 EW 2 fixes: one hull claim slot, explicit tie order, one burst divisor, fixtures that see range and live state
- Entity: delete _hullClaim; the hull's claim is the EquippedHull entry of _itemClaims, so ClaimOf(EquippedHull)
  and ClaimedHull read one slot (hull-claim-split). Claim(HullData) writes it; a non-hull claim of the hull throws.
- RevealedWeapons orders by the subject's equipment order, not dictionary slot order (tie-order-unpinned).
- InstantWeaponData.PerRound is the one burst divisor for UpdateStats and the rated read (burst-divisor-twice).
- Tests: falling-curve, Range-span, MinRange>0 fixtures and a charged weapon in the rated tests (rated-figure-range-blind);
  Combat ranks claims at the target's distance, ignores a worn target gun's live figure (live-state-unpinned),
  and takes ties in equipment order.

Not yet run; may not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:55:18 +02:00
Meta Vens
1746e8bdc8 Research: orbit probe (rails vs gravity terrain, slope-squared and potential readings, implied density)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:38:05 +02:00
Meta Vens
ab42214329 EW map: cut 1b probes at 0898725f (K1-K8); ew-hide-launch-catalog mapped as cut-ew-hide-launch-catalog.r1; H7 corrected (union key 49)
The 1b line leaves the cut sequence. The spec is blocked on question ew-suppressor-strength
(what the suppressor hides from: its target or only distant observers), recommended
hides-from-the-target. Probes ran on Yggdrasil from a scratch commit never pushed to origin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:36:40 +02:00
Meta Vens
ad7613eb83 Catalog: sensor-stat-set applied (alpha on both sensor designs, four sensor products, Passive Array)
GameData/Aetheria.cc regenerated by `AetherDb sensor-stat-set apply` on master's catalog
(sha256 6f79cf44...); a second apply writes nothing. Binary: never hand-merge, rerun on
master's catalog if another catalog cut lands first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:17:08 +02:00
Meta Vens
bce2cd0154 sensor-stat-set: Lucent and Finch products for the two sensor designs; catalog test
The catalog sold only two sensor designs (DME and Miss Terri's), so brand flavour had
nothing to vary: the command adds one Lucent and one Finch product per design. Adds
TheCatalogCarriesSensorStats. Catalog not yet regenerated; not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:15:19 +02:00
Meta Vens
05b17ba43a Scenarios: Lock On (seed 113), a piloted hostile that closes from out of sight and locks the player
The hostile starts 4000 m ahead with no track of the player; stepped headlessly it
sees the player at tick 81 and paints a Track lock at tick 83. LockOnSituation pins
the staging, the absence of a paint at Update(0), and the lock's bearing and timing.
LockOn.cs.meta is provisional until the Unity compile on Starfire writes its own.
Builds: yes (not yet run; verification follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:13:59 +02:00
Meta Vens
45f98c74eb Listener gear (ListenerData, union 50), float HearingMultiple, and AetherDb sensor-stat-set
Entity.HearingMultiple is now the largest of 1 (any active sensor) and each active
listener's Multiple. sensor-stat-set authors every sensor design's InterceptFactor
as a quality-ranged emission-discipline stat plus the Passive Array and its
products. Not yet built or run; the catalog is not yet regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:10:15 +02:00
Meta Vens
f9705d328b Merge remote-tracking branch 'origin/master' into eureka/aetheria-fauna-map 2026-10-13 19:05:37 +02:00
Meta Vens
7f0b8e4cbd Fauna: target r0 and map for proposed campaign aetheria-fauna; prior art kept
Imagination pass (imagination-aeth-fauna, self-2026-10-13-ag2). Target: fauna are
simulated props seen through the one gain rule, each class with a legible motion
law (ruling disguise-held-by-flying). Map: body facts B1-B14 with a cost probe on
Yggdrasil, nine draft questions, first cut fauna-krill-swarms as a draft spec,
later cuts one line each. Docs only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 19:03:11 +02:00
Meta Vens
e99cfbed37 Release map: visibility refresh at 0898725f (scenarios-lock-on r3, sensor-catalog r2; concurrency vs ew-claims)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:59:38 +02:00
Meta Vens
48b42992ee Loot 3 group A: the grab is presented, not simulated
IGrabPresenter.Grab(GrabEvent) only; the binder's Transform and velocity resolvers go. TractorBeam
presents a running grab (aims at Started's TargetPosition, emits at Power, dark otherwise). FieldDriver
draws its tendril from GrabEvents alone with a real-time phase clock over each event's PhaseDuration and
writes no transform and destroys nothing; its grab times move to FieldTester, now the scene's stand-in sim
that owns its pickup's timeline and pose. ItemPickup keeps its label lit while held. ImpactPresenterSmoke
becomes CapabilityPresentationSmoke with a grab section; its two untracked-ship expectations follow
DrawsAt since contact-hud. Builds (Unity 6000.3.24f1 batchmode: smoke ok, scene opens, no missing script).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:43:15 +02:00
Meta Vens
24ab95af8d Loot 3 group B fix: compare FloatingBodyId with Equals (the type has no ==)
8b2eef7b did not build (CS0019 at PickupTests.cs:419); this commit builds the test project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:23:40 +02:00
Meta Vens
ad71eabbaa WeaponData.RatedRange is not a MessagePack member
The previous commit's public RatedRange property had no Key, so MessagePack refused to build the formatter for every weapon design and the catalog failed to load (869 tests red). Marked [IgnoreMember]. The previous commit (76aeeabf) compiles but does not run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:19:53 +02:00
Meta Vens
8b2eef7b51 Loot 3 group B: PickupTests two-bay fixture and TheBeamTakesFromWhicheverBayCanStore
Spawn takes bays (default 1) and equips that many crates before Zone.Admit. The new test fills the
first bay and expects the beam to claim and land the ore in the second, pinning ruling
beam-skips-unstorable-items over bays (Select's Any over bays). Builds; test not yet run on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:18:23 +02:00
Meta Vens
76aeeabfca EW 2: claims ride the act into the book; schematic and AI classify from them
Signature, ActiveEmission and Reveal carry Claimed (the class the ship's EW claims for the item, the true item's data by default); Entity gains the claim slots and one write port; Contact gains Profile, derived from the ship's claimed hull once Identified; Entity.RevealedWeapons is the one classifying read for weapons. Combat and the enemy schematic read it; their reads of the target's live gear are cut. Weapons rate by their claimed design (ew-claim-weapon-measure-ruled, rated-design): WeaponData.RatedRangeDamagePerSecond runs the same per-kind formula as the live weapon. Aim, damage and physics keep the truth.

Not yet compiled or run at this commit; the Unity-only SchematicDisplay is unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:17:14 +02:00
Meta Vens
0898725f62 Release map: L11 loot-3 probes at cb14a816 (FieldDriver on no ship, beam aim from HeldFrom, multi-bay fixture order); loot-3 leaves the cut sequence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 18:11:46 +02:00
Meta Vens
cb14a816f8 EW map: cut 2 probes at 0681d6f2 (C1-C10), Contact.Profile derived until the judge, claim slots
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:14:14 +02:00
Meta Vens
0681d6f29b Merge fix: the contact-hud test removes through Zone.Remove (Zone.Entities is read-only on master)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:48:39 +02:00
Meta Vens
16466b148a Merge cut contact-hud (Soul verdicts cut-contact-hud.s1, .s2) 2026-10-13 08:48:13 +02:00
Meta Vens
a89d30376d Fix merge build: contact reveal tests remove through Zone.Remove; PickupTests settings drop the retired TargetArmorInfoThreshold
The merge commit before this does not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:31:27 +02:00
Meta Vens
fbe05c7992 Merge cuts loot-1-present and loot-2 (Soul verdicts cut-loot-1-present.s1, cut-loot-2.s2)
Conflicts: Behaviors.cs keeps Union(48, PickupData) and Union(49, LaunchSuppressorData);
Zone.cs keeps the departure record on _entities with master's Visibility (emissions-heard);
ContactRevealTests.cs keeps master's removal of the emission-departure test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:27:47 +02:00
Meta Vens
0bff723029 contact-hud: the shield ripple draws only where DrawsAt places the ship
Fixes finding shield-ripple-draws-on-untracked. ShieldManager already reaches
ActionGameManager (Clock), so DrawsAt stays the one owner. Unity code; compile
verified separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:00:28 +02:00
Meta Vens
a1d1db963f contact-hud: RevealedSubjectsListsTheBook holds two subjects at once, then one departs
Fixes finding revealed-subjects-multi-subject-unpinned.

All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:00:26 +02:00
Meta Vens
4fba95e56f Pickup: one beam region for selection and the pre-pull cancel; selection skips what no bay can store; test gaps and the phase rule pinned
beam-corner-claim-loop: InBeam is the one region predicate; Select claims from it and the pre-pull cancel holds the item only while it stays in it (an item at 74 along, 20 off is collected, not claimed and dropped every other tick).
full-hold-regrab-pins-and-blocks: Select skips an item no cargo bay can store whole, asked of the bay's own TryFindSpace (the test TryStore opens with), per ruling beam-skips-unstorable-items; a hold that fills mid-grab still cancels at the end.
pickup-test-gaps: smoothstep pose, spin-down while the gear is inactive, Remove freeing only the removed holder's items.
phase-ticks-not-rate-invariant: the claim is corrected in the tests; each phase fires on the first tick at or after its boundary, pinned at 1/60, 1/600 and an uneven dt cycle.

Builds; not yet run (the verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:43:42 +02:00
Meta Vens
ecc6f3d67d contact-hud: the new tests assert counts, not collections of entities
A failing Assert on a collection of Entity prints the whole entity graph and aborted the test host, so two hand
mutants read as a crash rather than a named failing test. Builds (test-only change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:35:52 +02:00
Meta Vens
8f184a8f69 contact-hud: NothingReadsSelection reads the paint inbox on every tick
A warning lives one tick, so the end-state read could not see a paint selection wrote; a hand mutant that paints
on SetTarget survived. Builds (test-only change).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:30:48 +02:00
Meta Vens
4708a71a67 contact-hud: the HUD reads the player's own ContactOf and book; TargetedBy and the spotted blink go
Selection is nothing the selected ship can sense: TargetedBy, TargetedByCount, their subscriptions and the music
read of them are deleted. Indicator fills, the target panel, the compass, music and the enemy schematic rows now
read CurrentEntity's ContactOf / RevealsOf / RevealedSubjects (new, the book's keys); the schematic rows are built
by one builder from the book and rebuilt when the revealed set changes. Impact hull effect and projectile hit
effects at another ship's position draw only through ActionGameManager.DrawsAt (the player's own ship or a Tracked
contact). Builds untested in Unity at this commit; tests NothingReadsSelection and RevealedSubjectsListsTheBook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:13:55 +02:00
Meta Vens
8e3dd3129d PickupTests: assert on booleans, never on an Entity (a failing Assert.Same prints the whole entity graph and crashes the test host)
Found by the mutation table: two mutants read 'Test Run Aborted' instead of naming the failing test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:07:03 +02:00
Meta Vens
60b5876cd9 PickupTests: bounded waits (a broken rule fails instead of hanging the run); a stray item is never even attempted
Found by the mutation table: a mutant that never claims hung the test host, and a mutant that doubled the
range survived because the observation landed between two attempts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 07:01:35 +02:00
Meta Vens
6292d82615 Merge cut ew-hide-launch (Soul verdicts cut-ew-hide-launch.s1, .s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:49:53 +02:00
Meta Vens
83b1b62a92 ConsumableSupplyTests: re-pin the generators' residual Random with the tractor beam's draw
The old pin (d4a27def) is exactly what this tree leaves with EquipPickup's call removed (run: passes), so the
new values differ from it only by the one product draw each generated ship makes for its beam.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:30:32 +02:00
Meta Vens
bc082c09a0 PickupGenerationTests: count fitted beams, not a station's stock
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:27:46 +02:00
Meta Vens
87642a9b4d Tests: the consumable rig's hull has an interior cell for the beam; the Longinus reach ceiling follows the new sample
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:27:15 +02:00
Meta Vens
774d2476ff LaunchSuppressorTests: pin the factor clamp (above 1, below 0) and the exactly-rated-temperature boundary with a step either side
Tests only; production unchanged. Fixture gear SuppressorBright (Factor 3) and SuppressorNegative (Factor -1).
Maps Soul findings clamp-unpinned and rated-boundary-unpinned. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:12:18 +02:00
Meta Vens
4a41aec68f Retire AetherDb pickup-catalog: applied in the previous commit, a one-shot
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:06:12 +02:00
Meta Vens
727c525c7a Catalog: the Tractor Beam is priced (25000); fixtures that generate ships sell a tractor beam
AetherDb pickup-catalog apply on the previous catalog (5efc5225...): result 1a2cb55b... (12730143 bytes), the
Tractor Beam's price 0 -> 25000; a second dry run printed "already authored", dangling reports zero. The ship
generator now requires a sold tractor beam, so the five synthetic catalogs that generate ships (LoadoutTests,
RunSaveTests, FireControlCut6cTests, TargetingSystemTests, ConsumableSupplyTests) each sell one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:06:09 +02:00
Meta Vens
ea66153d58 AetherDb pickup-catalog: two string literals broken by newlines; the previous commit did not build
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:03:24 +02:00
Meta Vens
f26beec14e AetherDb pickup-catalog: also price the Tractor Beam (25000); it was the one gear with price 0, so generation could not offer it
Found by the full suite on the previous catalog: every generated ship threw 'no compatible tractor beam'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 06:03:06 +02:00
Meta Vens
aae779c653 Revert "Retire AetherDb pickup-catalog: applied in the previous commit, a one-shot"
This reverts commit 72872c9817.
2026-10-13 06:02:47 +02:00
Meta Vens
359aba2c5d PickupTests: each grab phase is published on the tick its boundary is crossed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:54:08 +02:00
Meta Vens
720fbd6431 PickupTests: gear off, range before the pull, the loser's next item, a held item's pose
Pins the cancel rules (inactive gear, out of range before the pull and not after it), TryHold refusing a held
item, the next-item selection, and the held pose as a function of progress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:50:46 +02:00
Meta Vens
72872c9817 Retire AetherDb pickup-catalog: applied in the previous commit, a one-shot
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:41:15 +02:00
Meta Vens
73c44a5ed3 Catalog: the Tractor Beam is Tool gear whose one behaviour is Pickup (AetherDb pickup-catalog apply)
Applied on Yggdrasil from the base catalog (sha256 ce5c8be5...), result 5efc5225... (12730141 bytes); a second
dry run printed "already authored" and dangling reports zero. Builds; PickupGenerationTests needs this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:41:04 +02:00
Meta Vens
09884c2116 LaunchSuppressorTests: read the control flash on its own tick, before decay erases it
7e0b950d builds; its reveal test failed on a KeyNotFound for the control gun after later ticks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:30:27 +02:00
Meta Vens
2f718f7753 AetherDb pickup-catalog: fix two string literals broken by a newline; the previous commit did not build
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:20:59 +02:00
Meta Vens
68430771f3 Every generated ship carries a tractor beam; AetherDb pickup-catalog turns the Tractor Beam into Pickup gear (group B, code)
GenerateShipLoadout equips one gear whose behaviours include PickupData after the shared outfitting
(stations and turrets get none). The pickup-catalog command (retired in the next commit after apply) edits
the existing Tractor Beam. PickupTests: two fixes found by group A's run (equip is refused once a ship is
deployed, and the freeing tick takes one step). PickupGenerationTests needs the applied catalog and is
red until the catalog commit; the catalog itself is not in this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:18:15 +02:00
Meta Vens
7e0b950d63 LaunchSuppressorTests: activate the beam through its ConstantWeapon type
15b12cb9 does not build: Behavior has no Activate; this commit fixes the one compile error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:14:51 +02:00
Meta Vens
15b12cb95b Launch suppressor: scale the ship's own launch flash inside SetSignature, paying heat to its own cell
LaunchSuppressorData (union key 49; key 48 is held by cut loot-2 on eureka/aetheria-release-loot-2)
and LaunchSuppressor: Entity.SetSignature folds each light signature through the equipped
suppressors in equipment order. Only LaunchFlash is scaled, only while the item is Active and at
or below its rated temperature; each pays (removed x HeatPerUnit) through Behavior.AddHeat.
Fixture gear and LaunchSuppressorTests added. Not yet built or run (verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:11:55 +02:00
Meta Vens
5b19c1e853 EW map: body facts for ew-hide-launch, suppression derived by pull, cut 1b
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:03:27 +02:00
Meta Vens
e7a35135fe PickupData: gear only (CreateInstance for a consumable throws); the previous commit did not build
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:02:07 +02:00
Meta Vens
5aa989abbf Pickup is a capability: PickupData/Pickup run a timed grab through Zone's hold API and TryPickUp (group A, sim)
GrabEvent carries a FloatingBodyId; Zone gains TryHold/SetHeldProgress/Free and places a held item instead of
integrating it; Entity.TractorPower is derived from Pickup.Power and TractorCommand is the pilot's input
(ActionGameManager writes it undamped, the Time.deltaTime ramp is deleted). Binder and FieldTester change the
delegate type only. PickupTests and a save round-trip pin for the player's zone index.

Group A builds; no beam is on any generated ship until group B.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:00:22 +02:00
Meta Vens
1779ca9775 EW target r2: fold the eight rulings, noise jamming in as a crude loud tier (ew-jammer), present-model-stays amended
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:57:29 +02:00
Meta Vens
0894aab1bd Map: L10 loot-2 r3 probes at e24d942b; loot-2 leaves the cut sequence
Imagination imagination-aeth-loot-2's map edit, ported from the operator's
checkout (where it was written against aac2cf91) onto master. loot-2 r3 is
mapped on loot-1-present and alone restores pickup in play.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:51:19 +02:00
Meta Vens
20cd1d7cf5 Merge cut reveals-replace-tiers (Soul verdicts cut-reveals-replace-tiers.s1, .s2): restore the merged tree
The previous push (07854ed5) came from `git pull --rebase`, which linearized the merge and dropped the
adaptation of master's ContactTests and LootTests to the deleted TargetArmorInfoThreshold, so master did not
compile its tests. This commit joins the reveals branch history and sets the tree to the verified merge
(c7edbf0b: Yggdrasil full suite 1624 passed, 0 failed) plus master's two docs-only commits since.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:16:15 +02:00
Meta Vens
07854ed5ad ImpactFeedbackTests: the marker fixture records the reveal that makes it aimable
Master's feedback tests aimed at a marker the shooter's book never held; the reveals
rule (book holds the item, fitted, not destroyed) refuses that. Same fixture step the
FireControlCut12 tests use (RecordReveal via LaunchFlash).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:15:38 +02:00
Meta Vens
54bc2eecf4 Visibility 5: a fired gun is aimable and its same-design twin is not; fix stale reveal-ranking comment
Builds: yes (verified by the follow-up job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:15:37 +02:00
Meta Vens
8076f0ad7e Visibility 5: TheAIAimsOnlyAtWhatItSaw also pins that Combat clears a destroyed gun
The first form let the Combat-side IsRevealed check be removed unseen,
because TrySelectTargetItem refuses an unrevealed pick anyway. A destroyed gun
left in the raw aim field distinguishes Combat's own choice. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:15:36 +02:00
Meta Vens
eebf6f375a Visibility 5: an item can be aimed at when the observer's book holds it and it is still fitted and whole
IsRevealed is now the observer's book (Entity.HasReveal) plus the live filter
(still on its ship, not IsDestroyed). The tier ladder and
GameplaySettings.TargetArmorInfoThreshold are deleted, with the 19 fixture
initializers and the Settings.asset line. Fixtures that aim at an item record
its reveal through RecordReveal; Aetheria.Shared exposes internals to
Aetheria.Shared.Tests for that. Unbuilt and untested at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:15:35 +02:00
Meta Vens
2715b2e155 EW target: envelope shaping as claims judged by each observer, model page, probes, cut sequence
Target document for the proposed aetheria-ew campaign (rulings ew-is-envelope-shaping,
ew-owns-ambiguity-and-decoys). No cut specified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 03:56:26 +02:00
Meta Vens
e89d38e97a Research: electronic warfare prior art (Body, lore, games, real-world vocabulary)
Eyes facts file for the EW campaign mapping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 03:40:25 +02:00
Meta Vens
3c628f54f2 Merge cut emissions-heard (Soul verdict cut-emissions-heard.s1)
Conflict: ContactRevealTests Locker fixture. Kept the branch's Locker(name, interceptFactor) helper and added master's five munition parts to it (as master's Locker carries them since missile-stats).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 03:20:22 +02:00
Meta Vens
a58aea6375 Visibility 5: a fired gun is aimable and its same-design twin is not; fix stale reveal-ranking comment
Builds: yes (verified by the follow-up job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:54:35 +02:00
Meta Vens
e24d942b9d Smoke and wiring script: no GridObject or FloatingItemLifetime spelling outside the sim
Builds: Unity batchmode compile green (smoke run unity-smoke5 compiled and passed at this commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:37:58 +02:00
Meta Vens
c7c7e58508 Unity draws Zone.FloatingItems and nothing else; the Unity loot roll, collision pickup, tractor pull and GridObject are gone
ZoneRenderer draws one ItemPickup per FloatingItem (load, ObserveAdd, ObserveRemove, ClearZone); ItemPickup.Bind places it
from the sim body and spins it for show. EntityInstance's drop loops, ShieldManager's pickup branch (the whole
OnCollisionEnter, which did nothing else), ZoneRenderer.DropItem/DestroyLoot/_loot, TractorBeam's pull, and
GameSettings' three loot fields are deleted; WireFloatingItems stripped GridObject from the five pickup prefabs and
reassigned ZoneRenderer's four pickup fields in ARPG.unity; FloatingItemsDrawnSmoke (play session, batchmode) pins the
lowering. GridObject and TimedDestroy were deleted in fa911f2d, so fa911f2d and 2565e2c5 do not build in Unity.
Assets/Resources/Settings.asset keeps three stale serialized GameSettings fields Unity ignores (LFS object, not rewritten).

Builds: Unity batchmode compile green at this commit; dotnet green at 2565e2c5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:36:47 +02:00
Meta Vens
6177ded511 Merge cut ships-addon-bake (Soul verdict cut-ships-addon-bake.s3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:33:01 +02:00
Meta Vens
f866db1e1c Visibility 5: TheAIAimsOnlyAtWhatItSaw also pins that Combat clears a destroyed gun
The first form let the Combat-side IsRevealed check be removed unseen,
because TrySelectTargetItem refuses an unrevealed pick anyway. A destroyed gun
left in the raw aim field distinguishes Combat's own choice. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:22:48 +02:00
Meta Vens
2565e2c5d7 Retire the test that mirrored Unity's loot handler; route FireControlCut8Tests joins through Admit
Builds: with fa911f2d this is the tests project at the head of the Zone encapsulation; fa911f2d alone does not build
(FireControlCut8Tests still called the removed Entities.Add).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:17:26 +02:00
Meta Vens
61e9fe792c Visibility 4b: paint tests use deaf observers; the sensor record is one slot longer; the key test serializes JSON from a bare launcher
Three tests failed at 8be15c6a: TheBeamWidthIsKey12OfUnion5 read a 13-slot sensor record (14 now, key 13 added);
TheInterceptFactorKeys serialized a float4 guidance curve to JSON; ASearchPaintFromAPingerThatHasLeftCreatesNoReveal
heard the ping while its pinger stood in the zone. The paint tests (revealed-unseen, search-paint reveal, departed
pinger and departed locker) now observe with no active sensor so the reveal they pin is the paint's alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:15:46 +02:00
Meta Vens
fa911f2d85 Zone.Entities read-only outside Zone: Admit and Remove are the only membership writers
Entities is a MemberView with no mutating member; Admit installs the death watch with the
membership and refuses a member already present, Remove takes it away with the membership.
The Reset and duplicate-Add bypass paths of the death watch cannot be spelled any more.
Tests move to Admit/Remove; Admit also activates, so the explicit Activate calls that followed
a raw Add are dropped. Unity call sites route through Zone.Remove.

Builds: unverified at this commit (verified in the job at the head).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:13:43 +02:00
Meta Vens
75d97af1ef MunitionPartsTests: ShipSums reads per-channel light from VisibilitySources, SignatureOn being retired
The merged tree needs this: loot-1 added the SignatureOn reader after the cut's base.
Does not build without it; builds with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:05:46 +02:00
Meta Vens
8c8669b669 Merge cut ping-signature-retired (Soul verdicts cut-ping-signature-retired.s1, .s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:05:22 +02:00
Meta Vens
b89e5751cb Visibility 5: an item can be aimed at when the observer's book holds it and it is still fitted and whole
IsRevealed is now the observer's book (Entity.HasReveal) plus the live filter
(still on its ship, not IsDestroyed). The tier ladder and
GameplaySettings.TargetArmorInfoThreshold are deleted, with the 19 fixture
initializers and the Settings.asset line. Fixtures that aim at an item record
its reveal through RecordReveal; Aetheria.Shared exposes internals to
Aetheria.Shared.Tests for that. Unbuilt and untested at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:01:20 +02:00
Meta Vens
8be15c6ac1 Visibility 4b: pin the departure's item-less hull light, the Emission guard's item-less and zero-strength forms, and that the ping test's ping started
Follow-up ping-signature-test-gaps (departure-hull-light-unpinned, guard-null-item-unpinned,
ping-test-never-asserts-it-fired). Tests only; unverified until the suite runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:57:28 +02:00
Meta Vens
80a27648ad Visibility 4b: the departure comment names the whole Visibility, not a non-Emission signature
Follow-up ping-signature-test-gaps (stale-non-emission-comment). Comment only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:57:26 +02:00
Meta Vens
9de7756006 Visibility 4b: a ping or a lock paint is an emission heard within its range over its intercept factor
Entity.Emit posts an ActiveEmission (item, range / InterceptFactor) from Sensor's sweep and LockWeapon's
Track paint; Sense hears every other ship's emissions within HearRange x HearingMultiple x obscuration
through RecordReveal, bearing only, feeding no track. SensorData key 13 and LockWeaponData key 34 carry
InterceptFactor (absent reads 1). Unverified at this commit: the headless suite has not run yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:56:50 +02:00
Meta Vens
bc88f43a19 Bake From Source: one pair under its own names even beside orphans, linked mesh data refused, one error-text site in the operator
Orphan images holding the pair's names are freed at the commit instead of forcing .001; a bake never repoints a slot Source shares through mesh data; the operator's execute is the only place a bake error becomes report text (Refusal marks the module's own fixed text, everything else goes to the console); the copied-material count is asserted. Builds (Blender add-on, no compile step).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:47:23 +02:00
Meta Vens
38c2fcf6e4 Merge cut loot-1 (Soul verdict cut-loot-1.s4) 2026-10-13 01:44:56 +02:00
Meta Vens
4435ab16c9 Adapt vector-rows ShipRigTests to ShipAuthoringStore.Read's product element
Master's Read returns (Hull, Visual, Products); the branch's row-roundtrip
test deconstructed two. Mechanical; builds on the merged tree (the merge
commit before this does not build the test project).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 01:27:08 +02:00
Meta Vens
27094e8859 Merge cut vector-rows-record (Soul verdict cut-vector-rows-record.s3)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 01:21:40 +02:00
Meta Vens
4cea604b85 Bake From Source: the bake never rewrites what Source owns, bakes onto UV0, keeps one pair under its own names, reports Blender errors as fixed text
Shared material (shared-material-source-rewritten): a target slot holding a material a Source mesh uses is given a copy before the bake; a replaced image is removed only when unused.
UV0 (bake-follows-active-uv-not-uv0): every target's active UV layer is held at 0 for the bake and put back.
Relief (normal-tolerance-accepts-near-flat): smoke_bake bounds the normal's median tilt at 3 degrees (copy of Source 0.32, hull 16.59).
Pair names (pair-names-suffixed): a name held by an image the bake would not free refuses with fixed text.
Fixed text (refusal-passes-plain-runtimeerror-text): any foreign exception inside the bake becomes BakeFailed with the console pointer.
All builds; smoke_bake.py passes on Blender 5.2.2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:10:34 +02:00
Meta Vens
fc5afd385f Map: hardpoint lines read schematic and model as separate spaces
Ruling schematic-and-model-are-separate-spaces: no model dimension from schematic
cells; sockets fix shape and proportion with scale per mount; radiator panels read
a region marked on the model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:09:54 +02:00
Meta Vens
b6e0283f5a Merge origin/master into feedback-present merge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:03:24 +02:00
Meta Vens
fdf642f7da Add ThrottleLock.cs.meta, generated by Unity; no asset references its GUID
Follow-up aetheria-release:throttlelock-meta-missing left open. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:03:17 +02:00
Meta Vens
55904bed77 Map: hardpoint cut lines held for the operator walkthrough
Ruling hardpoint-work-held-for-walkthrough: mounts are named and hardpoint data
addresses them by name; the add-on-reads-cells premise is withdrawn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:01:30 +02:00
Meta Vens
3b65985a0b Map: cut-sequence lines for hardpoint sockets, adapters, gear models, radiator geonodes and floating greebles
Rulings hardpoints-and-floating-greebles, hardpoint-sizes-are-footprint-palette,
radiator-panels-molded-by-geonodes and caliber-is-presentation (2026-10-13).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:46:32 +02:00
Meta Vens
07852e6313 smoke_bake: pin the link restore, the offender selection, Blender's text staying out of the report, and the preference-to-bake relation
Found by hand mutants that survived: a failed bake restored a Base Color link only when a prior non-image link
existed (the smoke now has one), the offenders were already the selection, the bake's RuntimeError text was not
checked, and the cage/ray windows allowed a constant offset. All commits build; no C# touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:45:59 +02:00
Meta Vens
d1f8302d54 Merge cut feedback-present (Soul verdict cut-feedback-present.s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:44:56 +02:00
Meta Vens
f2bf0c0410 Zone: a death watch exists only for a non-member and is disposed by Remove and Clear; tests for duplicate Add, Clear and the pickup room boundary
WatchDeath returns when the entity already holds a watch, so a duplicate
Entities.Add neither throws nor leaves a second live subscription;
Entities.Clear (ObserveReset) disposes every watch. Adds
AMemberAddedTwiceStillDropsEachItemOnce, AClearedZoneDropsNothingWhenAFormerMemberDies
(finding duplicate-add-leaks-second-watch) and
APickUpOfExactlyTheRoomLeftFitsAndOneMoreChangesNothing (finding
pickup-room-arithmetic-unpinned, from Soul's boundary probe). Unverified
until the Yggdrasil job; no commit here is known not to build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:43:12 +02:00
Meta Vens
39713df097 smoke_bake: fixture gaps found by the hand mutants: commit-step rollback, bare-mesh rollback, linked Metallic, bake preferences
The Source gets a linked Metallic and a Transmission Weight of 1, the bake is forced to fail at the
wiring and replace steps and with meshes that have no material, and the cage extrusion and max ray
distance preferences must move the normal map. All commits build; no C# touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:40:20 +02:00
Meta Vens
55429376bc Research: hardpoint size systems (Aetheria Body facts and prior art)
Eyes facts file for the hardpoint size-system fork.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:39:36 +02:00
Meta Vens
91bae0dd83 Bake From Source: Cycles Selected-to-Active from Source onto her UV0, one albedo and normal pair per ship
Adds aetheria.bake_from_source: bakes the Source meshes onto the selected render meshes as
'<ship id>.albedo' (sRGB) and '<ship id>.normal' (Non-Color), packed, wired into every material
(a shared '<ship id>.hull' material for a mesh with none). One routine serves both maps and every
target. The Source's Metallic and Transmission Weight are neutralised for the bake (the glTF importer
sets Metallic 1.0, which bakes black); engine, samples, device, selection and Source are restored in
a finally, and a failure removes everything made and puts every changed link back. Three bake
preferences, a panel button, the tripo-hull.glb LFS fixture and smoke_bake.py (4 passes).
_refuse_loose_meshes now shares the select-offenders refusal with the bake.
All commits build; no C# touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:38:26 +02:00
Meta Vens
addaa7c308 ShipRigTests: nesting is refused for a driven immediate parent or middle ancestor under an undriven root
Builds (tests only). Closes the surviving a11 mutant of the previous table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:35:12 +02:00
Meta Vens
642a61ebbf Visibility 4a: the ping test ticks once so Ping() fires; a departure counts light on every channel
The ping test never pinged (a sensor's cooldown opens on its first tick), so a restored ping bump survived. ADepartureCountsLightOnEveryChannel pins the departure to the subject's whole Visibility. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:27:22 +02:00
Meta Vens
836279e35f ShipRigTests: the bind tests ride the thruster on a pod joint of its own, apart from the gun's arm
Builds (tests only). The previous commit unset the gun's joint, which bind then refused against the model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:21:54 +02:00
Meta Vens
cf981a2cf3 ShipRigTests: the bind tests ride a thruster on the arm without nesting the gun, and every shipped hull that names a rig passes the judge
Builds (tests only; production unchanged since 27ecd1f9).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:05:45 +02:00
Meta Vens
c000d5ca74 Aetheria.cc: smoke-rounds replayed on master's catalog (AetherDb smoke-rounds apply, Smoke Proximity and Smoke Delayed at energy 4)
Master's catalog (2e2d927a, with missile-stats) plus the five smoke weapons the command authors; not a hand merge of the two branches' binaries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:04:15 +02:00
Meta Vens
018a62be81 Merge cut scenarios-smoke-rounds (Soul verdict cut-scenarios-smoke-rounds.s2)
Catalog taken from master (2e2d927a); the branch's catalog change is replayed by the next commit. Scenarios.cs: both lists unioned.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:32:51 +02:00
Meta Vens
941a934ab6 ShipRigTests: nesting is refused, every shared-driving kind falls out of one rule, and the gun conflict is pinned at other sizes
Replaces the tests that pinned nested acceptance with refusal tests plus disjoint controls; gun arcs 10..360 against rows
of 1..5 thrusters; 360.01 and 360.5 against the thruster cap; a plan test that a thruster row adds no gun rig.
Findings nested-actuators-accepted and gun-conflict-pinned-at-fixture-sizes. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:31:16 +02:00
Meta Vens
27ecd1f9c0 RigChains owns what drives a joint; the judge refuses two actuators on a joint and a reach through a driven joint
RigChains.Actuates/Drives/Actuator are the one definition of actuator kinds; ValidateRig, BindRig and ShipModPlan consume
it, and the hand-derived gun-versus-row check and the chain stop are deleted. A nested actuator is now refused, as ruling
one-joint-one-actuator says. Findings nested-actuators-accepted and actuator-kinds-spelled-in-four-places.
Builds; the tests of the previous batch that pinned nesting are red until the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:31:14 +02:00
Meta Vens
aa851cfc72 ContactRevealTests: the Locker launcher fixture carries the five munition parts missile-stats requires
Mechanical merge adaptation: contact-reveals landed on master after missile-stats' base, and its fixture built a LauncherData without the
munition parts ValidateMunitionParts now demands (63 failures at Upsert). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:14:26 +02:00
Meta Vens
9afa5700a9 Wire ImpactFeedback into ARPG.unity (WireImpactFeedback output)
Adds the Impact Feedback object (TinyExplosion, the weapons' own hit effect, as the pooled hull effect) and a
CinemachineImpulseListener on the follow camera. Additions only (188 lines, 0 removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:10:07 +02:00
Meta Vens
97d94ecfae Present landed impacts: shield ripple, hull reaction and camera kick through one ImpactPresenter
ImpactPresenter (bound on every EntityInstance by SetEntity through the one CapabilityPresentationBinder) renders
feedback-1's absorbs: Feedback.Cue decides intensity and shake, DrawAhead.Carried the drawn point; a hull absorb
spawns ImpactFeedback's pooled effect under the instance, and a cue with shake raises a Cinemachine impulse.
ShieldManager ripples on a Shield-layer absorb. MainMenu gains a Screen Shake slider that persists on Back.
Editor: WireImpactFeedback (scene wiring, scene diff in the next commit) and ImpactPresenterSmoke.
Unity batchmode compile 0 error CS; ImpactPresenterSmoke exit 0. The scene is not yet wired in this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:10:04 +02:00
Meta Vens
dfa85be635 Visibility 4a: ping-light expectations in paint-mode test; ping test needs no lit-hull assertion
Builds; test run follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:10:01 +02:00
Meta Vens
789fe9fcdc Turn the shooter to the heading the direct-absorb test fires along
The mount fires inside an arc about the shooter's facing; the first version fired backwards and found no hit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:09:13 +02:00
Meta Vens
446f84458c Pin the feedback-1 cue path's remaining mutants (follow-up feedback-1-test-gaps)
A direct absorb's heading and damage type are the shot's, on both layers (non-Kinetic weapon, both heading
components negative); a blast absorb carries the blast's damage type and the target's height on both layers;
DrawAhead.Impact sits at the hull's height. Tests only; every commit builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:57:56 +02:00
Meta Vens
3535660cc5 Merge cut package-product (Soul verdict cut-package-product.s4) 2026-10-12 20:54:40 +02:00
Meta Vens
a19e3ba647 Merge cut missile-stats (Soul verdict cut-missile-stats.s2) 2026-10-12 20:54:30 +02:00
Meta Vens
82d4881ca2 Zone: the death watch is added, not overwritten, so a second one for a member cannot exist
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:53:15 +02:00
Meta Vens
d8b7f33d90 Visibility 4a: retire the ping's light signature; Emission is never light
SetSignature refuses Emission; Sensor.PingVisibility (key 7) is retired and
Ping() writes no signature; Sense's Emission skip, the departure subtraction
and SignatureOn are deleted. Tests: SetSignatureRefusesEmission,
APingNoLongerBrightensThePinger; fixtures drop PingVisibility.

Not yet built or tested at this commit (verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:51:46 +02:00
Meta Vens
cc9403ce58 Loot-1 fix batch: whole-or-nothing commodity store, and tests for the Soul s1/s2 findings
EquippedCargoBay.TryStore(SimpleCommodity) now returns false before touching anything when
TryFindSpace says the whole quantity does not fit (its documented contract: true only when ALL
is stored), so Zone.TryPickUp keeps "first accepting bay, otherwise nothing changes" with no
rollback in Zone. Tests: refused pickup of a stackable item changes nothing; a stack plus free
cell stores whole; first accepting bay; headings cover the circle; the loot stream is not the
mine stream; dock/undock and jump drop once and only in the zone the ship is in.
Untested on this commit: not yet built (verify job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:51:45 +02:00
Meta Vens
8120419ecd Merge origin/master into the loot branch (Self's direction)
One conflict, Zone.cs death subscription against contact-reveals' _departures insert: kept both.
The resolution already routes the death subscription through WatchDeath/UnwatchDeath (next
commit's fix target is the same line, so this commit resolves it in that shape).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:49:42 +02:00
Meta Vens
16ed52d890 Merge cut feedback-1 (Soul verdict cut-feedback-1.s3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:30:02 +02:00
Meta Vens
9f85978f22 Merge cut scenarios-belt (Soul verdict cut-scenarios-belt.s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:29:59 +02:00
Meta Vens
f85a0b0e17 Merge cut sim-contact (Soul verdict cut-sim-contact.s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:29:56 +02:00
Meta Vens
7be5454742 AI discipline test flies half a minute: a hostile moved to 7000 m must fail it
The two-minute run let a hostile placed ten times farther still arrive; the hostile closes in about 15 s from 700 m (about 50 m/s),
so thirty seconds separates the arena's geometry from a mutant of it. Both controls fire within a second.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:23:52 +02:00
Meta Vens
08f19e6c6c Map: cut-sequence lines for mining-index-tree, mining-belt-cells, sim-speed-scale
Their specs were withdrawn under map-only-what-runs once their deferred
findings moved to follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:05:11 +02:00
Meta Vens
734804b6d7 Aetheria release map: cut sequence of the 51 cuts withdrawn under map-only-what-runs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:00:40 +02:00
Meta Vens
6087fd967e zero-byte test asserts cultcache-py's own refusal, so a restored add-on size==0 branch fails it
The test compares type and message with SingleFileMessagePackBackingStore.pull_all on the same
file; the add-on's shape refusal (also a ValueError) no longer passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:00:35 +02:00
Meta Vens
96bbaa6320 validate shares Read's post-load composition; products, key, price rules pinned beyond the first product
ShipAuthoringStore.ValidateLoaded is the one composition of hull Validate and ValidateProducts;
Read and the draft branch of ship-authoring validate both call it (ValidateProducts is private).
Tests: a draft with an unnamed hull is refused; blank product name and key collision with the
offending product not first (both makers in turn); a negative hull price refused.
Builds untested here; the verify job runs at the end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:00:18 +02:00
Meta Vens
2e92db41d1 Vector rows fix: one joint, one actuator; the judge owns every thruster arc's range; row rules tested at other sizes
- finding joint-moved-by-two-actuators (ruling one-joint-one-actuator): RigChains.Driven names every actuator's joint (weapon-mount and
  thruster-emitter anchors), so YawReach's chain stops at a thruster row's joint as it does at a gun's; Validate refuses a gun and a
  thruster row on one joint. The test that pinned the mixed joint as accepted is replaced.
- finding row-of-one-arc-uncapped: Validate refuses any Thruster hardpoint with FiringArc above 360, row or not; the named-row check keeps only
  the above-0 rule.
- finding row-rules-pinned-at-fixture-sizes: tests at row sizes 3 to 5, arcs 10 to 360, hair-width arc gaps, every non-thruster type, case-distinct rows.

All three findings land in this one commit (the edits share hunks in ShipAuthoring.cs and ShipRigTests.cs). Not yet built here; verified on Yggdrasil after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:58:22 +02:00
Meta Vens
557edc5017 Tests: the ship-sum separation settles the ship and sums thruster thrust, so a munition thruster joining the ship's thrusters shows
Builds. The previous commit's test survived the hand mutant munition-thruster-joins-ship-thrusters because the ship was never stepped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:57:24 +02:00
Meta Vens
aac3e9f260 Stepped smoke-rounds tests with controls; the catalog regenerated with the lighter Smoke Proximity and Smoke Delayed
The two fused rounds draw 4 energy a shot, so the Smoke Test Hull's one reactor carries the Fused Rounds fit and the rounds fire
(sha256 b60cefa2). New tests: every weapon aboard fires in the stepped Fused Rounds arena with the DeathCluster as the control,
the round's flight is seconds and bursts on the first hull, the DeathCluster kills the fragile hull before the round lands (A.3),
the AI holds fire against its two controls, New Game lists the three arenas, and the command's replay writes the shipped records.
Not run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:53:12 +02:00
Meta Vens
b0de7c746b AetherDb smoke-rounds: Smoke Proximity and Smoke Delayed draw 4 energy a shot
A stepped Fused Rounds arena showed no round fired from any weapon aboard, the DeathCluster included: the Smoke Test Hull's one
2x2 reactor (Core Power, charge 100) cannot carry two Spectra clones at 20-40 energy a shot, overloads, reaches 445 K within a
second and goes offline. The catalog is regenerated in the next commit; this commit's command no longer matches the committed
catalog, so SmokeRoundsCommandTests/stepped tests are not meaningful at this commit alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:50:13 +02:00
Meta Vens
b53d071ef6 Merge cut ships-addon-guards (Soul verdict cut-ships-addon-guards.s2) 2026-10-12 19:44:33 +02:00
Meta Vens
1f1d0bfa35 Tests: the gate holds each of the five parts, catalog load and Upsert run it, consumables are refused, and the ship-sum separation is read on a ship with drives and a sensor
Builds (unverified until the next ygg run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:31:53 +02:00
Meta Vens
b33f39447e Validate: a consumable is held to the munition-part gate too (any other design carries none)
Builds. The tests that pin it follow in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:31:52 +02:00
Meta Vens
88dfd1da30 ImpactFeedbackTests: pin shield-layer absorb fields, blast order, impact height and cue saturation edges
Test-only; builds. Ports Soul's feedback-1 s2 probes as behavioural tests that
observe where each rule is decided (the published AbsorbEvent, the handler's
view of hull and shield, Feedback.Cue, DrawAhead.Carried). The blast shield
Magnitude is read against an unshielded twin's totalShare so a scale mutant
fails. Covers findings shield-layer-fields-unpinned, blast-order-unpinned,
height-fixtures-at-zero and cue-saturation-edges-unpinned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:31:29 +02:00
Meta Vens
6130eb7d04 LootTests: a station is active once built, so the pickup taker's second bay is equipped before Activate
Station() activates the entity and TryEquip refuses while active; the second Crate at (2,2) failed for that reason, not a hull rule. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:30:30 +02:00
Meta Vens
fdcd5298b1 ContactTests: add the 3000-mass Mid hull the unequal-mass tests use
The previous commit's ContactTests did not build a Mid hull, so ten tests failed on the missing hull (full run at
806641ae: 1481 passed, 10 failed). The commit builds; those ten tests are red until this one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:44:39 +02:00
Meta Vens
806641ae62 Ship contact is a restitution impulse along the normal while closing; e is GameplaySettings.ContactRestitution (.5)
Ruling ship-bounce-restitution-setting: j = -(1+e)(v_rel.n)/(1/m1+1/m2), applied only while closing. The old
exchange formula (PostCollisionVelocity) is deleted. ContactTests now pin momentum, frame shift, restitution,
no impulse while separating, slow closing, tangent of both bodies, inactive hulls, the contact point radius
and the three-body pile. Not yet built or run; verification follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:28:29 +02:00
Meta Vens
cf149c4280 ValidateJudgesProductsOnADraftAndInspectListsThem: drafts have no model, so validate takes the records-only path the finding names
The first version left the package's GLB in place, so validate judged records and model through ReadPackage and the test failed in the mutation baseline. Test-only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:03:48 +02:00
Meta Vens
042a13f979 smoke_package: a tall image whose width rounds up pins rounding of the first axis (200x513 -> 100x256, not 99)
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:03:13 +02:00
Meta Vens
aa2bf0d41f Guards fix: cultcache-py version is read from the imported module; texture cap boundary, rounding, orientation, group and failure cases pinned
Findings of verdict cut-ships-addon-guards.s1: guard-not-import (the version now comes from the checkout the imported
cultcache_py lives in, one owner, no pyproject-beside-a-path), prefix-compare-survives (0.3.0.1, 0.3.0rc1, 0.3.00
refused), cap-boundary-unpinned and group-restore-unpinned (smoke_package texture_boundary_cases: at the cap, one over,
height-long, non-square rounding, file/packed/node-group images, failed export restores). A copy whose scale raises is
removed. All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:59:24 +02:00
Meta Vens
68519f9fb9 Merge cut emoji-sequences (Soul verdict cut-emoji-sequences.s3)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 06:39:40 +02:00
Meta Vens
faa05eec83 Merge cut vapour-cloud-presenter (Soul verdict cut-vapour-cloud-presenter.s2)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 06:39:33 +02:00
Meta Vens
ae3740a050 Fix s2 findings: product validate/inspect/key-collision/price-1 tests; ship_cc.read drops the zero-byte compensator
ship_cc.read lets cultcache-py refuse a zero-byte file (CultLib pins that); the test expects the refusal. New behavioural tests: ValidateJudgesProductsOnADraftAndInspectListsThem (through ShipAuthoringCommands.Run), AProductKeyAlreadyInTheCatalogExcludesThePackage, and price 1 in ASoldPackageHullNeedsAPrice. Tests only plus the add-on deletion; all commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:38:09 +02:00
Meta Vens
febda87ec5 ContactTests: the docked-hull visitor is the heavy hull, which keeps closing after its first exchange
With equal masses the first exchange stops the visitor and a second contact with the docked hull cannot show.
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:33:28 +02:00
Meta Vens
8d7b90111a ContactTests: the docked-hull test closes a third ship on the carrier, so excluding the docked hull is observable
A docked hull shares its carrier's velocity, so the pair alone never closes; a visitor does expose a second contact.
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:32:58 +02:00
Meta Vens
b00fc7e581 Emoji font rebuilt in python:3.13-slim on Yggdrasil with the 15 FE0F-less twins (reproduced: second run equals the lock); lock records fe0f_less_twins=15
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:27:25 +02:00
Meta Vens
7565458b4d ContactTests: the distant pair starts beyond the discs' reach after the tick's own movement
The pair moved 0.1 each before the contact step and so closed inside the 14.14 bound; start them 15 apart.
Builds; the first commit's only red test was this one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:05:48 +02:00
Meta Vens
d8150a504f Release map: visibility refresh at efee2a2a (body facts VR1-VR15, cut order, model page amendments)
Imagination imagination-aeth-refresh-visibility, session self-2026-10-11-ag2. The model page
amendments are stated in this section; folding them into the Visibility rework rows is owed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 06:04:38 +02:00
Meta Vens
6eebec78f9 ImpactFeedbackTests: direct-hit tests aim at an off-centre marker item so the production lateral draw lands the cell off centre
Moving the target after Fire never changed the cell: the lateral is drawn in the hull's frame about the aimed point. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:49:43 +02:00
Meta Vens
7392bc8fe1 Ship contact is a simulation rule: Zone steps Contacts, Unity physics writes no Entity
Contacts.Step exchanges normal velocity between touching hull discs (PostCollisionVelocity moved verbatim
from ShieldManager) and publishes Zone.Contacted; ShieldManager presents it; HullCollider.OnCollisionEnter
and ShieldManager's ship-on-ship branch are deleted. Not yet built or tested (verification follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:46:32 +02:00
Meta Vens
873ee6eae4 Guards tests: version drift of any size is refused; the texture fixture's aspect is not a power-of-two ratio
The untested-cultcache test now refuses 0.4.0, 0.3.1 and 0.3 as well as 9.9.9 (a major-only comparison survived).
smoke_package's hull map is 4096x1000, so the scaled size (2048x500, 512x125) is not what a clamp of both sides or of
the other axis would give. Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:41:08 +02:00
Meta Vens
efee2a2adc Merge origin/master into merge/contact-reveals
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:40:05 +02:00
Meta Vens
4acf05da46 smoke_mounts: the mirror matrix on wide grids, 14 and 15 cells across
Passes 7 and 8 run mirror_matrix on ships whose grids are 14 (even) and 15 (odd) wide; the expected twin cells are
grid_w - a - w computed in the matrix itself. Pass 6 (5 wide) now runs through the same matrix_pass function. This is
the commit that adds the cases for follow-up mirror-wide-grid-test. Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:38:42 +02:00
Meta Vens
5545c850a2 Add-on: Max texture preference; ship.glb exports larger material images scaled
_export_glb points each Image Texture node of the exported objects' materials whose image is longer than the Max texture
preference (default 2048) at a scaled copy (longest side at the cap, aspect kept) and restores the originals and removes
the copies in its finally block, so the .blend's images are never modified. smoke_package.py reads the GLB's PNG
headers: a 4096x1024 map exports at 2048x512 and at 512x128 under a 512 cap, a 256x256 map exports as it is, the .blend
images keep their size and no copy is left in bpy.data.images. Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:37:50 +02:00
Meta Vens
ca19deab68 LootTests: the pickup taker is an unstocked two-bay station, as the StationServices fixture builds one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:33:27 +02:00
Meta Vens
4f9ada5a6f ship_cc: refuse a cultcache-py that is not the tested version
_libraries reads [project].version from the pyproject.toml beside the cultcache-py source before importing it and raises
ValueError naming the version found and the packages path when it differs from TESTED_CULTCACHE_PY (0.3.0) or the file is
missing. Builds: yes. test_refuses_a_file_with_no_record fails as before (cultcache-py unpack error on a 0-byte file).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:31:46 +02:00
Meta Vens
31d19eae64 Merge eureka/aetheria-release-contact-reveals: reveals end on perception (cut-contact-reveals.r2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:18:17 +02:00
Meta Vens
22dba843a5 AShipHullWithoutATopSpeedIsRefused: the hull carries an unrelated behavior, so a rule that counts any behavior fails
Survivor of the top-speed-any-behavior-counts hand mutant: the cleared fixture hull held no behavior at all. Test-only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:03:02 +02:00
Meta Vens
ee479eba7a test_fe0f_twins: the function test no longer depends on the font already holding twins
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:57:33 +02:00
Meta Vens
8fc19aed94 Emoji font build: add FE0F-less twins of the 15 ligature records TMP cannot match (ruling fe0f-less-ligatures-in-font-build); Eyes' TMP diagnosis; headless GSUB test
The committed font is not rebuilt yet, so test_fe0f_twins.py's first test is red against it; the font lands next. Builds nothing in Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:57:04 +02:00
Meta Vens
c34f72e3d5 LootTests: the station's bay goes in first, as the StationServices fixture does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:55:37 +02:00
Meta Vens
3da1622478 Vapour presenter: draw the sim's OpacityAt directly, not divided by the cloud's raw Opacity
OpacityAt is already saturated to 0..1 by the sim, so a 0.3 vent reads thinner than a full
cloud and nothing above full draws thinner. Builds (Unity compile run after).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:53:18 +02:00
Meta Vens
43b8db6bcd LootTests: the pickup test uses a two-bay station and a non-stacking item
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:52:27 +02:00
Meta Vens
aebf12e195 Emoji routes: Emoji.asset named in TMP's emoji fallback list as well as the global list (ruling emoji-fallback-route); EmojiCheck asserts both routes and prints the font serving each piece of a failing sequence
Keycaps and the other body-font-based sequences now collapse: 25 failures become 13. The 13 FE0F+ZWJ sequences still show three pieces. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:50:31 +02:00
Meta Vens
26cdd578c1 Merge eureka/aetheria-release-ships-addon-mounts (cut-ships-addon-mounts.s2)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:44:13 +02:00
Meta Vens
a486a7cae2 ProductAndPriceCommands reads the reopened cache's own product handle; ship_cc.read treats a zero-byte file as holding no records
The test asked a second cache for the handle of an object loaded by the first (identity lookup, no handle); it now asks the reopened cache for its product. cultcache-py raises an Unpack error on a zero-byte file, so ship_cc.read names the empty file through its own shape refusal. Both commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:38:53 +02:00
Meta Vens
7d2276a708 LootTests: fixture fixes (zone radius for the well, six pieces of gear, a hitting shot, second bay by cell)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:37:38 +02:00
Meta Vens
e1a5c6a1b0 Emoji sequences: liga in the 142 serialized TMP texts (43 prefabs, 2 scenes) and in TMP Settings, written by EmojiFont.EnableLigatures
Every prefab and scene was re-serialized by Unity 6, so each file also carries the editor's own migrations (m_RootOrder, m_ConstrainProportionsScale, m_enableWordWrapping to m_TextWrappingMode, name quoting). Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:37:07 +02:00
Meta Vens
6d2d52c529 EmojiFont, EmojiCheck: OTL_FeatureTag lives in UnityEngine.TextCore; kerning read from the serialized m_enableKerning
Compiles (Unity 6000.3.24f1 batchmode). Fixes the previous commit, which did not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:36:52 +02:00
Meta Vens
4c893b2a45 ImpactFeedbackTests: the target steps aside after Fire so direct hits land off the hull's centre
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:33:28 +02:00
Meta Vens
96b255541c Mirror Mount reflects the footprint's cells about the centre line, derived once from the footprint
hull_grid.mirror_position gives the twin Position as grid_w - a - w, so an even-width footprint mirrors to its true
reflection and the cell lookup's tie rule no longer decides a mirror; the twin's object stands in the cell that Position
puts it in, so Package derives the same Position back. test_hull_grid pins the reflection on odd and even grids and
rows of 4 or more cells; smoke_mounts runs footprint widths 1 to 4 at every cell of an even and an odd grid, the
boundary tie, the armour and arc copy, the muzzle's local X, the centre-line threshold, the grid edge and the parent
check, and keeps a mirrored pair of two-cell footprints through Package and the validator. Every commit builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:33:26 +02:00
Meta Vens
5a72c6f5c8 LootTests: the ledger holds lots for every minted ship (previous commit's tests failed on it)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:32:16 +02:00
Meta Vens
a249f86cef Tests: the lock fixtures carry munition parts; the migration and item-read tests read the stat the way the engine does
LockWarningTests builds launcher designs, which the new gate (ValidateMunitionParts) refuses without parts. The golden test
selects the role's Quality term among the stat's heat and durability terms, and the item-read test settles the ship at the
item's optimal temperature so only role quality moves the stat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:30:09 +02:00
Meta Vens
bd78401967 Emoji sequences: EnableLigatures writes liga into every serialized TMP text and TMP Settings; EmojiCheck renders every fully-qualified sequence as one visible character
Adds tools/emoji/emoji-sequences.txt (2760 fully-qualified multi-code-point sequences from the pinned emoji-test.txt), written by fetch_emoji_font.py and recorded in the lock. Not compiled yet (first Unity pass follows); the asset changes land in a later commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:22:40 +02:00
Meta Vens
d24135a075 Catalog: re-saved through AetherDb after the launcher fields were retired
The five munition designs are written by the post-cut schema, so keys 29-31 and 24-26 are gone from the file. The catalog loads
through AetherDb (census) and every munition design carries its five parts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:03:31 +02:00
Meta Vens
56129b43d5 Package derives no mounts for a ship with no Ship Root, and refuses a framed one whose layout is not loaded
smoke_package's hand-tagged ship has a weapon-mount object, no Ship Root and no loaded
buffer; the first mounts commit refused it. A ship with no frame has no grid to derive
from, so Package leaves its rows alone as before. A framed ship with a mount and an
unloaded buffer is refused with 'Load Layout first'. All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:03:12 +02:00
Meta Vens
0985989744 Retire the launcher flight fields; the presenter reads the munition parts; the migrate command goes
Thrust, DodgeFrequency and MissileVelocity are gone from LauncherData (keys 29-31) and GuidedWeaponData (keys 24-26), keys
reserved. GuidedProjectileManager flies the round from MunitionParts.Of: Acceleration, MaxSpeed and EvasionFrequency,
evaluated through the item. munition-parts-migrate is deleted with the fields it read.

The shipped catalog still carries the dead keys in this commit; the next commit re-saves it. The Unity assembly was not compiled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:02:32 +02:00
Meta Vens
445bdb66f2 FireControlCut124Tests: the shipped catalog is fuse-neutral for the weapons a product sells; the product-less smoke weapons are the fused designs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:00:55 +02:00
Meta Vens
fa4467e9a3 Loot 1 (simulation): Zone owns floating items, rolls death drops on SimulationDice, expires them and commits pickups
Zone.Release is the one adder, StepFloatingItems and TryPickUp the only removers; DropLoot runs from the one
death subscription before the entity leaves the zone. Three C# default settings. Unity's drop path is untouched
(loot-1-present deletes it). Not yet built or run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 04:00:08 +02:00
Meta Vens
34ea8bfa15 Catalog: the five launcher designs carry their munition parts (munition-parts-migrate apply)
GT 3K, LRMM72, SRMM72, pswarm, scorched void policy. Acceleration, Lateral and MaxSpeed copy Thrust and MissileVelocity with
their thruster role; EvasionFrequency is DodgeFrequency; the rest are authored flat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:59:48 +02:00
Meta Vens
3c1e1e7421 Munition parts: five gear-part behaviours carry a missile type's stats; completeness gate; one-shot migrate command
MunitionHullData, MunitionThrusterData, MunitionSeekerData, MunitionControlData (with Cognition) and MunitionFuelData
(Behaviors union 43-47), read through MunitionParts.Of. StatValidation.ValidateMunitionParts refuses a launcher design
without exactly one of each and any other design carrying one, at catalog load and Upsert. AetherDb gains
munition-parts-migrate; LauncherRoles names the part's thruster stats by type and field (Range and Visibility also name
the seeker's and plume's flat stats, which RolesBackfill must not range).

Does not pass tests on its own: the shipped catalog is migrated in the next commit, and until then it fails the new gate at load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:59:39 +02:00
Meta Vens
de7e4a0261 ImpactFeedbackTests: direct, shield, blast, mine and ordering absorbs; Cue, ScreenShake, Carried
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:58:37 +02:00
Meta Vens
8adda0b3de FireControl publishes every landed impact on the receiver's Capabilities; Feedback.Cue and DrawAhead.Carried
AbsorbEvent gains AbsorbLayer. Entity.Capabilities, four publish sites in ApplyDirectHit and Detonate (each before the damage it reports), Feedback.Cue, DrawAhead.Carried (Impact delegates), PlayerGraphicsSettings.ScreenShake. Not yet built or tested; tests follow in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:58:34 +02:00
Meta Vens
1052a445fb ShipRigTests: the muzzle-on-a-joint refusal now says a thruster emitter may ride one too
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:58:26 +02:00
Meta Vens
cc77c4b5f5 ship_cc carries product envelopes through every push; PRODUCT_SCHEMA pinned; authoring doc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:54:31 +02:00
Meta Vens
943c492bb8 Packages carry their products: ship.cc homes FactionProductData at mod-product:<id>:<maker key>
ShipAuthoringStore.Load/Read return (Hull, Visual, Products); Open homes the third kind;
WriteProduct/DeleteProduct are the only product writers; ValidateProducts and the ship
top-speed rule; compose checks makers, keys and product names; ship-authoring product and
price commands. Unbuilt until the verify job (Python, pin test and docs follow in the next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:54:30 +02:00
Meta Vens
d50f54bf53 Release map: refresh 2026-10-12, feedback and loot (body facts RF1-RF9, the sim/present splits)
Imagination imagination-aeth-refresh-feedback-loot, session self-2026-10-11-ag2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:51:46 +02:00
Meta Vens
730a4e5a52 Release map: missile-stats r3 (stat groups as gear-part behaviours) and its body facts MS1-MS9
Replaces "The missile's stats" paragraph and appends the refresh's premise
check, body facts, rationale and downstream notes (Imagination
imagination-aeth-refresh-missile-stats, session self-2026-10-11-ag2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:48:57 +02:00
Meta Vens
a89d885c6b smoke_mounts: an asymmetric footprint shows Mirror Mount turning it
All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:47:44 +02:00
Meta Vens
1660a68a8a Fog Patch prefab carries VapourCloudInstance at the origin and unit scale; ZoneRenderer.CloudPrefab assigned in ARPG
Wired through the Editor in batchmode (component, root pose reset, field assignment); the scene diff is the one
CloudPrefab line, the Editor's unrelated field churn reverted. Builds (Unity compile 0 error CS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:46:24 +02:00
Meta Vens
42227f3435 Blender add-on weapon mounts: Add Weapon, Add Muzzle, Mirror Mount, Remove Mount; Package derives mounted Position and yaw
hull_grid gains mounted_position, facing_yaw, mirror_rotation and mirror_footprint. The
mount helpers edit the layout buffer and create a tagged weapon-mount object with its row
as a pair; Package derives each mounted row's Position from its object and each mount's yaw
from its row's Rotation, then saves the buffer through _save_layout. The panel gets a
Mounts box and greys a mounted row's x and y. smoke_mounts.py pins the gunboat flank,
derive and remove paths. All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:45:12 +02:00
Meta Vens
b614260607 Release map: package-product r4 body facts (refresh against b6262467)
Imagination imagination-aeth-refresh-package-product, session self-2026-10-11-ag2:
ShipAuthoringStore registers no product type, the product writer, sequencing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:44:38 +02:00
Meta Vens
0388e39913 SmokeRoundsScenarioTests: the direct weapon's kill check counts a burst's rounds (Damage is per round, ammo per burst)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:43:41 +02:00
Meta Vens
5a5fde07c8 ShipValidationTests: the row cases use ItemRotation.None; the previous commit did not compile
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:41:09 +02:00
Meta Vens
5d5bdc25f8 SmokeRoundsScenarioTests: the kill check names its numbers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:40:03 +02:00
Meta Vens
e9d59cff72 BeltConditions: let the ship settle for a second before reading what its sensors see
A weapon's reach and a sensor's gain are zero until the ship's stats settle, so at the first instant no rock is in reach.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:39:59 +02:00
Meta Vens
b1f4a2aa08 Vectored rows recorded: HardpointData.Row, ThrusterData.Slew, the judge's row rules
Thruster hardpoints state a gimbal arc in FiringArc and join a row by Row (key 7);
the thruster design carries its slew (key 6). The judge refuses a Row on a
non-thruster, rows whose members disagree on Rotation or FiringArc, and a fixed
thruster, a mixed or split row, or a joint too short for the arc on a joint. Bind
treats a thruster emitter's joint as it treats a gun mount's. Not yet verified:
this commit has not been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:38:29 +02:00
Meta Vens
8128bce6ba Belt scenario: an arena on seed 24, whose entrance zone carries a 615-rock belt, the player parked 100 m outside its ring
Spec cut-scenarios-belt.r1. Scenarios/Belt.cs stages the Longinus at the ring's edge nearest the origin facing along it; BeltConditions in
BeltScenarioTests.cs pins it. Built and tested through ygg-verify in the next commit's verification.
2026-10-12 03:38:06 +02:00
Meta Vens
f44dadc5cf Fused Rounds, Refused Rounds and AI Fused Discipline arenas, and the five smoke weapons they carry
The catalog gains Smoke Proximity, Smoke Delayed, Smoke Refused, Smoke Refused Beam and Smoke Refused Charge (AetherDb smoke-rounds apply), none with a product. Seeds 108, 109 and 110 stage the demo's cast with the Smoke Test Hull; SmokeRoundsScenarioTests pins their conditions and that no smoke weapon is offered. Design and arenas land together so the census never sees an uncarried design. Not yet run: the verification job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:36:57 +02:00
Meta Vens
db5fc667c9 AetherDb smoke-rounds: fix two newline escapes the previous commit wrote as literal line breaks
The previous commit (93d5a0c6) does not build: two string literals in SmokeRoundsCatalog carry a raw line break. This commit builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:34:54 +02:00
Meta Vens
f1c36b4ccb Vapour clouds are drawn as fog banks: one ZoneRenderer subscription, VapourCloudInstance presenter, DrawAhead for a free body
ZoneRenderer loads and subscribes Zone.Clouds like mines and destroys a bank on removal; VapourCloudInstance
places a Fog Patch brush at DrawAhead.Position(cloud.Body, Lead) and thins its _Depth with OpacityAt. The prefab
and scene wiring follow in the next commit; this one compiles but CloudPrefab is unassigned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:34:50 +02:00
Meta Vens
93d5a0c69c AetherDb smoke-rounds: the five product-less smoke weapons, dry run unless apply
Smoke Proximity, Smoke Delayed and Smoke Refused are Spectra clones with the operator's fuse values; Smoke Refused Beam is a constant weapon and Smoke Refused Charge a charged one cloned from ChargeBlast SG, each fused with a Range below its BlastRadius. No products. SmokeRoundsCommandTests covers dry run, apply and the no-op second apply.

The catalog and the arenas that carry the designs follow in the next commit. This commit builds; its command test needs no catalog change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:33:22 +02:00
Meta Vens
0af394bd4b Exact-gate departure test: the observer sits where its info per unit light is a power of two (previous commit's test does not pass)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:03:43 +02:00
Meta Vens
ddbd120af0 Pin the departure gate's strictness with a light exactly at the threshold
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 03:02:54 +02:00
Meta Vens
53ff5f7c01 Unreachability test: the departing ship leaves by the warp path, so its own subscriptions to the observer are not the question
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:23:33 +02:00
Meta Vens
f815406e9e Qualify ReferenceEqualityComparer (a3 commit does not build: ambiguous name)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:22:42 +02:00
Meta Vens
a23a76b608 Step-kill test lights the ship at its death; the unreachability test walks the observer's fields
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:22:12 +02:00
Meta Vens
c212ec0232 Reveal book: no scratch holds a departed entity, a destroyed lit gun is refused at the gate, one IsDestroyed rule, departure and allocation pins
Not verified yet at this commit (build and tests run next).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 02:20:46 +02:00
Meta Vens
b6262467f0 Merge cut-scenarios-smoke (verdict cut-scenarios-smoke.s2)
Scenarios.cs Tests list: kept WeaponFeel, Pursuit and Crossing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:28:05 +02:00
Meta Vens
336cf3a684 Merge cut-scenarios-crossing (verdict cut-scenarios-crossing.s3)
Scenarios.cs Tests list: kept Pursuit and Crossing both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:27:47 +02:00
Meta Vens
9131cce3b9 Merge cut-scenarios-pursuit (verdict cut-scenarios-pursuit.s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 23:27:39 +02:00
Meta Vens
396c02b08f Perceived item destruction ends the reveal in the observer's Sense; moving-subject bearing pinned
Restores the Identified item-end pass and its tests (AnIdentifiedObserverSeesGearDestroyed, the flashing-gun tick case,
the Identified part of SenseAllocatesNothingOnceWarm) that 49ace47f held for this batch, and extends
AnActIsRevealedOnItsOwnTickWhateverTheListOrder to a moving subject (two velocities, both observer orders).
Builds: all commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:58:10 +02:00
Meta Vens
4658fa7af6 RunStartTests: the offered-gear checks read the hulls a product sells
GenerationOffersExactlyTheSoldGearSomeHullCanFit compares against LoadoutGenerator.SoldHulls; GearNoHullCanFitIsOfferedOnlyOnceAHullTakesIt
gives its scratch hull a product, since a hull no product sells is no home. The previous commit (2a943370) left both red (found by the
full run); this one is the head. Commit 2a943370 does not pass the full suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:51:07 +02:00
Meta Vens
2a943370ab Smoke Test Hull fixes: the home rule reads sold hulls only; command and flank geometry pinned; turret off the starboard line
LoadoutGenerator.SoldHulls is the one definition of the hulls HasHome considers (a hull some product sells); AvailableProducts and the
tests read it, so the product-less test hull gives no gear a home. TheSoldHardpointGearWithNoHomeToday describes production again.
SmokeHullCommandTests pins each added hardpoint's firing arc, armour and shape; ArcsFlanks asserts the flank hulls abeam from the
player's facing within 5 degrees; Arcs' Turret moves to (600,300). Not yet built or run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:35:25 +02:00
Meta Vens
49ace47f34 Leave perceived item destruction to batch B: drop the Identified item pass and its tests from this cut
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:06:24 +02:00
Meta Vens
d03b85ea34 ContactRevealTests: departure fixtures put the ship's other light out and show exactly the authored signature
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:05:16 +02:00
Meta Vens
22296ae4eb ContactRevealTests: settle the last flash before the departure signature; identified-observer tick fixture
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:04:34 +02:00
Meta Vens
b6c2a2368b Reveal book: one gate, one removal counterpart; departure ends reveals on perception; departed subjects age out
RecordReveal gates on zone membership and EndReveals is the only way out; the observer's Zone.Entities handler no longer wipes the book and PublishInbox no longer decides membership. Zone records each removal as a one-tick Departure that each observer's Sense judges under the light-act gate; a departed subject's entries are pruned once older than BearingMemory. Unverified build at this commit (first test run follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:03:20 +02:00
Meta Vens
8d38409d60 Crossing: Brief says coasting pass; pin idle pass, crosser x speed, rest default
Builds (test and Brief text only; not yet run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:48:39 +02:00
Meta Vens
2a62d90b3f Release map: the Reveal row ends a reveal only on what the observer perceives
Amends the model page to Defaulted ruling reveal-ends-on-perception (Soul
findings cut-contact-reveals.s2.perceived-destruction-never-ends-reveal and
unseen-departure-clears-contact): zone departure no longer empties books.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:47:15 +02:00
Meta Vens
5c294ef994 GameData/Aetheria.cc: smoke-hull apply on the 2x2-flank hull (replaces the previous commit's catalog)
Output of `AetherDb smoke-hull apply` on this tree's base catalog, run on Yggdrasil: one HullData,
Smoke Test Hull, 17 hardpoints, no product.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:36:21 +02:00
Meta Vens
043a73eb0a Smoke Test Hull: 2x2 side mounts on a two-cell margin; test classes read sold hulls only
The 1x1 Ballistic side mount tripped IsFilledByAgreesWithACellOracle (Shape.FitsWithin never places a
design whose only cell is not its origin, so Takes and the oracle disagree on a 1x1 hardpoint); the
side mounts are 2x2 now, which needs two columns of margin on each side, so every Longinus cell and
hardpoint moves right by two. The two catalog-wide tests that listed every hull now list sold hulls.
This commit does not pass the suite: GameData/Aetheria.cc still holds the previous hull until the
next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:32:50 +02:00
Meta Vens
6b0f15d76a GameData/Aetheria.cc: smoke-hull apply (Smoke Test Hull, no product)
The catalog is the output of `AetherDb smoke-hull apply` on this tree's catalog, run on Yggdrasil.
It adds one HullData, 17 hardpoints (the Longinus's 13 and four new ones), and nothing else.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:16:48 +02:00
Meta Vens
fed0e61d11 smoke-hull: fix the dry-run and apply message literals and the lambda names that shadowed the hull
e8442328 does not build (newline inside two string literals); this one does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:11:26 +02:00
Meta Vens
e8442328df Smoke Test Hull command, Weapon Feel and Arcs on the test hull (catalog not yet applied)
AetherDb smoke-hull [apply] adds a product-less Longinus copy with a 2x2 Energy and a 2x2 Ballistic
hardpoint past the bow and a 1x1 side mount on each flank. Weapon Feel (seed 107) stages it with
ChargeBlast SG, Autocannon and FastBlast+-; Arcs flies it with a mount on each flank and a Port and
Starboard hull. This commit does not build a passing suite: the scenarios name the hull and
GameData/Aetheria.cc does not hold it until the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:04:09 +02:00
Meta Vens
34ec64356e Release map: the Reveal row keeps a reveal of gear destroyed out of sight; only the aiming read filters on live gear
Amends the model page to Defaulted ruling contact-reads-book-aim-reads-live
(Soul finding cut-contact-reveals.s1.unseen-destruction-leaks-into-contact).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:54:39 +02:00
Meta Vens
c86f28e93f MiningCut3Tests: ChunkInfo equals the bits recorded at base 12dfcef5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:34:59 +02:00
Meta Vens
b3c003dc3e Contact reads only the observer's book; a stale paint never recreates a reveal; Sense runs after every update; tests for the unpinned rules
- RevealsOf returns the book and nothing the subject's gear or Durability says (ruling contact-reads-book-aim-reads-live); FireControl.IsRevealed stays the live aiming read.
- PublishInbox records a paint's reveal only for an emitter still in the zone.
- Sense moves from Entity.Update to a Zone.Update phase after all entities have updated, so reveals do not depend on list order.
- ChunkInfo calls PassiveInfo(position, brightness) in the original multiplication order (PassiveInfoPerSignature becomes PassiveInfo with the signature argument).
- Tests: unseen destruction, ghost paint, Search paint reveal, no self-sense, quiet tracked ship levels, list-order independence.

Not built or run locally; verified on Yggdrasil after the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:34:58 +02:00
Meta Vens
4897d8d157 Crossing test: the crosser is placed moving across the bow, and FastBlast+- mounts forward
Not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:13:13 +02:00
Meta Vens
4f12d581cb Crossing: the crosser starts to port at 50 m/s and the test observes the pass over simulated time; fit and hull pinned
Not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:57:16 +02:00
Meta Vens
dc34562fdb ScenarioStage.Place: a placed ship can start moving (velocity), the one staging capability a crossing needs
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 19:50:13 +02:00
Meta Vens
7ab267c314 Crossing scenario and Djinni Shakedown targets, with their staging tests
Crossing (seed 112, demo cast): the Arcs Longinus fit with plight and FastBlast+- under the Fire Control Array, a piloted
hostile Djinni crossing the bow inside 400 m, an unpiloted neutral one at 80% of plight's Range. Djinni Shakedown gains
bare Longinus targets Ahead (inside the generated Djinni's ballistic mount arc) and Abeam (outside it). CrossingConditions
and DjinniShakedownTargets read what each arena staged. Not yet verified on a full-suite run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:52:35 +02:00
Meta Vens
9ccc846c1a Pursuit scenario: Cargo stages consumables; a hostile on your tail, a Mine Launcher fitted, vents and overdrives in the hold
ScenarioStage.Cargo resolves one name across equippable and consumable
designs; a consumable is built from its first available product in key
order. Pursuit (seed 111, demo cast) lists last in Scenarios.Tests.
All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:41:48 +02:00
Meta Vens
b32729de22 ContactRevealTests: an Emission entry is not light; the freshest reveal gives the bearing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:41:21 +02:00
Meta Vens
b888b20c33 Release map: scenarios for operator checks (check-to-scenario table, six cuts)
Body facts SC1-SC16, the table of every operator check against the
scenario that stages it, and the cut order for scenarios-smoke r4,
smoke-rounds, pursuit, crossing, belt and lock-on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:31:17 +02:00
Meta Vens
dcc6f0a7d2 ContactRevealTests: a null-item signature from a non-hull source reveals nothing
Unverified; the running verify job predates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:31:13 +02:00
Meta Vens
e0758fdf1c ContactRevealTests: reveals by act, by paint, contact levels, lifetime and Sense allocation
Does not build or pass yet unverified: first verify run follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:26:00 +02:00
Meta Vens
6894c2093e Entity records reveals and derives Contact; ChunkInfo reads PassiveInfoPerSignature
The observer's Entity owns a reveal book keyed (subject, item). Sense records a
light act when its strength times PassiveInfoPerSignature clears the detection
threshold; PublishInbox records an emitter whose paint arrived. ReceivePaint takes
the emitter and its item. ContactOf derives Detected, Tracked, Classified and
Identified from track, reveals, the zone clock and GameplaySettings.BearingMemory.
ChunkInfo's arithmetic moves into PassiveInfoPerSignature; ActiveSensors fills one
buffer instead of allocating per call.

Not yet built or tested: verify follows with the tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 18:25:57 +02:00
Meta Vens
12dfcef563 Merge eureka/aetheria-release-paint-modes: paint modes, swept ping set and ping returns
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 17:39:31 +02:00
Meta Vens
d2709d550e Sensor: one reset of the swept set; a ping belongs to its zone; PaintModeTests pin the ending step and the return inbox
The idle _reached.Clear() at the end of Execute is deleted: Ping() is the one per-ping reset
(ASecondPingCrossesTheSameShipAgain). A sweeping tick drops reached subjects that left the zone,
and a ping ends when its pinger is in another zone than it began in. New tests: the ending step's
band, every return credited, an inactive ally posted none, Deactivate clearing the inbox, a ping
ending on a zone change, and a leave-and-return subject crossed again.

Not yet verified: no verify job has run on this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 16:42:16 +02:00
Meta Vens
0b917630ad PaintModeTests: a second ping crosses the same ship again
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:26:45 +02:00
Meta Vens
34a9e72ce1 PaintModeTests: the cloud fixture lives long enough that its fade does not move the zero cases, and the finished ping is read at its last radius
Opacity falls linearly over the cloud's lifetime and the receive leg takes a square root, so a thousand-second cloud turned an opaque leg's 3e-4 into a .004 credit. The finished ping's radius is 300 within float rounding, not above it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:25:08 +02:00
Meta Vens
86323768e0 PaintModeTests: a cloud-thinned echo reads as nothing within the cloud's own fade, not exactly zero
The cloud fades linearly over its lifetime, so an opaque cloud's two legs read 3e-5 a few ticks in. The zero cases compare within a tolerance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:23:28 +02:00
Meta Vens
dd896528cc Sensor: the pinger's swept set decides each crossing once; allies credit a published ping return inside the bistatic oval
Deletes the stateless interval crossing (_previousRadius, PreviousRadius, Crossing) and the allied-pinger scan over
other ships' Sensors. The pinging Sensor remembers the subjects its wavefront has reached (_reached), in the beam
or not, and a subject's first sweeping tick inside the radius is its one crossing. On it the pinger paints, credits
itself and posts a PingReturn to each ally; Entity publishes returns with paints (PublishPaints is now
PublishInbox) and the ally's own sensors credit them for one tick at the geometric mean range, inside
Rt x Rr < PingRange^2, through the geometric mean of both legs' obscuration (ruling ally-echo-bistatic-oval).
This commit builds and replaces the sensor the previous commit's tests were written against.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:22:29 +02:00
Meta Vens
e1827c9db0 PaintModeTests: the swept-set and bistatic-echo rules, written against the c1d5487b sensor
Eight new tests (moving subjects, list order, stopped illuminator, bistatic oval, cloud legs, drift behind the
front, late arrival, BeamWidth key 12 and its JSON name) and the ally credit of AnAllyHearsTheReturnSilently
restated as bistatic (.21213). This commit builds; the moving-subject, list-order, stopped-illuminator, oval, cloud
and ally-echo tests are expected to fail against the Sensor of c1d5487b, which the next commit replaces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:22:08 +02:00
Meta Vens
1f6ba67d5f Release map and prior art: one owner per ping crossing, bistatic ally credit
Map R2/R3 rewritten after Soul failed paint-modes h1: the pinging sensor
keeps a per-ping reached set and posts PingReturn to allies through the
zone inbox; ally credit gated by the bistatic oval (R_t * R_r < range^2).
Research section 7: bistatic radar, cooperative engagement, game gaps.
Serves cut_spec paint-modes r3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:17:33 +02:00
Meta Vens
c1d5487b72 PaintModeTests: a pinging ship is not a subject of its own ping, observed through its ally
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:24:57 +02:00
Meta Vens
8c5825ed94 PaintModeTests: concurrent sweeps credit once per crossing; factionless ships are not allies
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:09:32 +02:00
Meta Vens
5731fcee94 PaintModeTests: the hull radiates nothing, so visibility is the fixture's own constant
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:07:47 +02:00
Meta Vens
9dc4ae092f Sensing.cs: using CultMath for PaintWarning's float2 (the previous commit does not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:06:24 +02:00
Meta Vens
c47ced9cfd Paints carry search or track; a ping sweep warns every ship it crosses in its beam; allies hear the return silently
LockWarning becomes PaintWarning with a PaintMode (Search for a ping sweep, Track for a lock);
Entity.IncomingLocks becomes IncomingPaints. Sensor replaces the _pingedEntities set with a stateless
crossing rule over the previous and current wavefront radius, limited to a new BeamWidth stat (key 12,
absent reads 360), and credits allied pings from the receiving sensor's own sensitivity and distance.
The HUD lock indicator follows Track paints only. Folds in the radiator sampling-instant pin.

Unverified at this commit (first build still to run).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 14:05:16 +02:00
Meta Vens
a47f967d13 Merge eureka/aetheria-release-signature-channels
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 13:43:49 +02:00
Meta Vens
f30c3550ab SignatureTests: the one-view check fails by assertion, not by a test-host abort (Assert.Same formatted the entity graph)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:24:52 +02:00
Meta Vens
4059e53351 SignatureTests: decay channels named per writer, radiator strength at a nonzero exponent and two temperatures, the view is not a Dictionary
Findings decay-channel-baseline-vacuous (expected DrivePlume, Emission, LaunchFlash per source, not a post-tick
baseline), radiator-temperature-factor-unpinned (T^2 x multiplier x emissivity at two temperatures) and
one-writer-castable (the exposed view is not a Dictionary, is the same object each read, refuses writes).
Not built locally; verified on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:06:27 +02:00
Meta Vens
c76584ee21 Entity.VisibilitySources: a ReadOnlyDictionary created once over the private field, so a cast back to Dictionary fails
Finding one-writer-castable. Test commit follows; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 13:06:04 +02:00
Meta Vens
fb0c18b4fd SignatureTests: decay test uses sources nothing rewrites (the item-swap mutant survived the first fixture)
Mutant decay-item-from-last-entry survived dc244686: the gun was the last-inserted entry, so
Values.Last().Item was its own, and every other entry was rewritten by its Execute after the
decay loop. The fixture now stops the drive and pings once, so the gun, the drive and the ping
are touched by decay alone and their three items differ. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 12:05:18 +02:00
Meta Vens
dc24468609 SignatureTests: pin decay items, key 3 and ordinals, radiator and ping strength, channels at two strengths
Decay with a gun, a drive and two Visibility gears checks every entry keeps its own item.
Key 3 of union 22 by golden bytes, the old three-slot record reads Thermal, the five ordinals,
json "channel", and a reopened catalog file. The radiator's strength is HeatRadiationMultiplier
x Emissivity at exponent 0; the ping's is its authored PingVisibility at two values. Gun,
beam and thruster channels hold at a strong and a sub-threshold strength.
Not yet built or run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:37:08 +02:00
Meta Vens
6f2dea3849 Entity.VisibilitySources is a read-only view: SetSignature and the decay loop are the only writers
The dictionary is private; the public member is an IReadOnlyDictionary over it, so a write
around SetSignature is a compile error, not a grep. Readers (Thruster, tests) use only the
read members. Builds; the test project at this commit still compiles (no reader writes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 11:37:07 +02:00
Meta Vens
78c6c78e60 SignatureTests: light every channel in the sum fixture (a mutant dropping Reflection from the sum survived on a zero)
Builds and passes are verified at the previous commit; this commit changes the test only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:59:05 +02:00
Meta Vens
28250600f1 Merge eureka/aetheria-release-cultmath-0-4-1-pin: CultMath 0.4.1, the allocator's answer no longer depends on its warm start
Soul held (aetheria-release:verdict:cut-cultmath-0-4-1-pin.s1); master
moved only in docs since the branch point, so the branch's verify stands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:46:34 +02:00
Meta Vens
2cb3ded00f Release map and prior art: quiet gear identifiable, hull layout from class
Map: hull layout and aim point (V15, V16), model rows for layout, located
item and the scan, rules R8-R11, and cuts layout-aim and inspection-scanner,
for ruling quiet-gear-identifiable-hull-layout-known. Research section 6:
game scanners and identification of non-emitting equipment, serving
questions scanner-reveals-its-user and scanner-held-or-pulse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:18:24 +02:00
Meta Vens
1d14edea3a Signatures: every light signature names its channel and item through Entity.SetSignature
VisibilitySources holds Signature (channel, strength, item); the eight direct writes
go through the one writer; Visibility stays the sum; SignatureOn(channel) splits it.
VisibilityData gains Key(3) Channel. No number changes. Not yet built or tested at this
commit (verification follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:13:24 +02:00
Meta Vens
e0b123a98d Release map: the visibility rework (signature channels, paint modes, reveal record, emissions heard)
Body facts, model page, authority map, rules, rationale and cut order for
ruling visibility-per-capability-reveal folded with sensor-stat-set; seven
cuts pinned at 93b7ff8d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:59:17 +02:00
Meta Vens
1b5499cf78 ThrustAllocatorTests: System.Random (CultMath.Random is ambiguous); fixes the build of the previous commit
c7dcf178 does not build (CS0104); this commit does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:46:54 +02:00
Meta Vens
c7dcf178f3 ThrustAllocator: cold and warm starts agree on the hull that stopped early
The finding's fixture (Synthetic(8, 7005), the seeded random walk through its
eighth intent) compares a warm allocator with a fresh one at every step. Fails
on the 0.4.0 pin, passes on 0.4.1. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:44:04 +02:00
Meta Vens
b4d5cee48e CultMath pin to 0.4.1 (BoundedLeastSquares stopping fix and Validate)
CultMathRevision, the manifest tag and the lock hash move together to
cultmath-unity-v0.4.1 (9c1b06cd). CultLibRevision is unchanged. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 08:44:02 +02:00
Meta Vens
93b7ff8da0 Merge eureka/aetheria-release-envelope-from-columns: the evasion envelope is the box extremes of the thrusters' columns at live thrust
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 04:46:26 +02:00
Meta Vens
ab80aa8f73 Envelope: pin each side as the sum of its thrusters; drop the unused ManoeuvreEnvelope operator +; document Column(Thrust) against the allocator's Column(NominalThrust)
Builds not verified yet at this commit; verification follows on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 04:08:09 +02:00
Meta Vens
e386e1c437 Merge eureka/aetheria-release-lock-warning: a painted ship owns a typed incoming-lock warning
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 03:53:33 +02:00
Meta Vens
7437b13a5b TheEnvelopeIsWhatTheGrantAllows: let the grant settle one tick
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:21:05 +02:00
Meta Vens
844e363cbf Envelope tests under a partial and a nil power grant: live thrust and the unpowered gate are pinned (two Stryker-style hand mutants survived without them)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:19:06 +02:00
Meta Vens
02ca78f1e1 ReachIsWhatTheShipCanDo: the Longinus's reach is bounded above by the allocated reach (1.3 nose-on, 1.2 broadside), not open
Finding cut-thrust-allocator.s3.longinus-envelope-unbounded. The allocated reach carries the envelope's turn terms, which now include the
drives' yaw, so the measured broadside lower bound moves from .9 to .85 of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:26:43 +02:00
Meta Vens
3056171c41 TheEnvelopeCountsTheMains: yaw is rad/s, fixture threshold .1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:23:07 +02:00
Meta Vens
db3103a026 Envelope from columns: Ship.RecalculateEnvelope sums the thruster columns' box extremes; Thruster.Manoeuvre and TorqueFloor deleted
Unverified at this commit (first build still to run); ceiling test not yet restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:14:31 +02:00
Meta Vens
efaa8f5b54 LockWarningTests: pin the full-lock strength through the launcher's own Execute (a zone tick resolves the shot a full lock fires) 2026-10-10 23:45:21 +02:00
Meta Vens
230aeccdd3 Merge thrust-allocator-wire: Ship.Update hands intent and live columns to ThrustAllocator
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	tests/Aetheria.Shared.Tests/RestoredHullsTests.cs
2026-10-10 23:44:54 +02:00
Meta Vens
a403b44ab5 LockWarningTests: a full lock fires and spends the launcher's lock; read the emitter's own Lock only below it 2026-10-10 23:43:03 +02:00
Meta Vens
cbf31c2719 Research: launcher lock, launch signatures and graded contact knowledge
Eyes pass for the operator's lock and visibility rethink: how Aetheria
represents visibility today, LOBL/LOAL and loitering munitions, warning
receivers, provocation, graded contacts in games, and the novella passages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:42:18 +02:00
Meta Vens
3022741745 LockWarningTests: author the launcher as LauncherData (the catalog round-trips it); last commit's tests did not run 2026-10-10 23:41:54 +02:00
Meta Vens
1c5c602054 Lock warning fix 1: publish paints in a zone phase, one lock-indicator curve, strength and progress-term pins
- Zone.Update publishes every entity's paints before any entity updates (Entity.PublishPaints), so a broken lock clears on the same tick whatever the entity order.
- ActionGameManager.ApplyLockProgress is the one lock-indicator curve, called by the outgoing and the incoming indicator.
- LockWarningTests drive the real LockWeapon through Zone.Update; pins on strength across 0.15..1.0, the direction and sensor progress terms, and both entity orders.

Not yet run: this commit's tests have not been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:29:27 +02:00
Meta Vens
6a8ecb9b8d Merge ships-addon-package-frame: Package recentres on the centre of mass and generates map icon, shield, tractor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:09:30 +02:00
Meta Vens
429c651a2a Package: sweep only what it generated (aetheria.generated), pin bounds centre, Source-only and collider-in-Generated
Stale sweep identified generated anchors by collection membership and role, so an author's hull-collider in
Generated was deleted. Generated anchors now carry aetheria.generated; the sweep removes only those. New smoke
pass package_asymmetric_pass: an L-shaped render hull pins tractor X and shield centre to the bounds centre,
a Source-only ship pins that generation never reads the Source fallback, and a collider placed in Generated
survives Package. All commits build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:55:18 +02:00
Meta Vens
91fe002596 ThrottleLock comment describes the floor; test pins the wormhole gate on the allocator
Builds: not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:19:37 +02:00
Meta Vens
5a92b74e52 smoke_frame: pin the shield floor, the no-outline refusal before any change, and the collider check ahead of the verdict
Hand mutants (floor dropped; recentre before generation) survived the first Package pass; both now fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:24:02 +02:00
Meta Vens
8d9acf269d Package recentres on the grid's centre of mass and generates map icon, shield, tractor; no collider
AetherDb ship-authoring centre prints Shape.CenterOfMass; Package asks it and moves Ship Root so that point sits
at the world origin, after regenerating the unowned map icon, shield and tractor from the render meshes (Keep
leaves one alone). Package never makes a hull collider (ruling package-frame-defer-collider). smoke_package's
bound-collection rollback cases now rebind to a different path so a rollback that restores keys but not values fails.

C# not yet built when committed; the Blender smokes and Python unit tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:02:22 +02:00
Meta Vens
92b82e9aa5 Ships add-on: all-or-nothing bind, pin the cross-drive fallback
_bind_collection restores every aetheria.* key if the ID-property store
refuses a value, so a bad ship id or pending leaves the collection as it
was. smoke_package.py gains default-run cases: relpath raising ValueError
(the cross-drive signal) must store the absolute path and finish; a refused
id or pending must leave bound and unbound collections unchanged.
All commits build (Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:38:17 +02:00
Meta Vens
e1788e19c1 Tests: the Longinus's reach bound is derived from the allocator's own push, not a widened constant; stale mixer comments and unused using UniRx removed
Builds; not yet run (the run follows).
2026-10-10 20:32:18 +02:00
Meta Vens
5a6e81db75 wip reach probe 2026-10-10 20:23:27 +02:00
Meta Vens
54ac0fcfa7 Merge eureka/aetheria-release-ships-addon-frame-r4: ships authoring tool and add-on frame
# Conflicts:
#	tests/Aetheria.Shared.Tests/ShipSchemaPinTests.cs
2026-10-10 19:54:03 +02:00
Meta Vens
90f1775cb9 LockWarningTests: a paint waiting in the inbox does not outlive a deactivation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:49:56 +02:00
Meta Vens
66641b46de ThrustAllocatorTests: throttles stay in bounds and floors hold wherever the solve ends
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:47:53 +02:00
Meta Vens
6fff037ac7 LockWarningTests: find the launcher gear by its weapon behaviour
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:46:48 +02:00
Meta Vens
9f779d42c0 ThrottleLockTests: the twin comparison reads to the solver's precision (1e-4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:42:37 +02:00
Meta Vens
033d37eda0 LockWarningTests: build the launcher as the existing lock fixtures do (a plain gear, the LockWeapon beside it)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:41:04 +02:00
Meta Vens
9ff6e4ba42 Tests: the floor's stick-independence at the allocator; throttle-lock twin diagnostics
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:39:42 +02:00
Meta Vens
3400268681 Tests: forward floor under the lock, thermal death tick, nominal columns under total brownout
Not yet run; this commit may not pass. Co-Authored-By below.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:26:51 +02:00
Meta Vens
534e402fdf Throttle lock is a forward floor on the solve; allocation moves after the performance update
The lock stops being an intent rewrite in Ship.Update: ThrustAllocator.Allocate takes forwardFloor, which ignores the
stick, asks full forward and holds every column with y > 0 at full (ruling overdrive-forward-floor). Ship allocates in
Entity's new UpdateThrottles phase, after every item's UpdatePerformance and before the power bus and Execute, so
liveness and thrust are the ones Execute acts on (finding liveness-read-before-performance).
Tests follow in the next commits; the test project still compiles, new behaviour is untested here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:26:49 +02:00
Meta Vens
e5cfc0d676 Lock warning: a painted ship owns a typed incoming-lock warning carrying the lock's strength
LockWeapon.Execute paints its target with its own Lock (the one value the outgoing indicator also reads);
Entity publishes the one-tick inbox as IncomingLocks; the HUD shows one incoming indicator on the strongest
warning with the outgoing indicator's curves. Unity HUD code not compiled here; tests not yet run at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:25:22 +02:00
Meta Vens
caa424f424 BrownoutTests: a throttle under the old .01 gate still asks for its power
Hand mutant powerrequest-gate-01 survived: the gate's only reach is the energy asked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:08:04 +02:00
Meta Vens
0caf1fa525 ConsumablesFirstSetCommandTests: the landed designs carry the thermal pins and linear Quality terms (the shipped-catalog pins cannot see the command)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:53:25 +02:00
Meta Vens
b517642cd5 ConsumablesFirstSetTests: conductivity measured at 1; the thermal pins hold
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:53:07 +02:00
Meta Vens
3cb721e130 ConsumablesFirstSetTests: specific heat measured at 1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:52:13 +02:00
Meta Vens
e2d421621d ConsumablesFirstSetTests: pin the quality exponent and thermal constants; command test: dry run writes nothing, re-run is a no-op
The two Lows from Soul s1 (follow-up catalog-merge-replay-order). The thermal constants are placeholders
(-1) in this commit: it builds and fails by design, the next commit pins the measured values.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:49:27 +02:00
Meta Vens
d26b465e9a consumables-first-set command: public with a root argument, as the other catalog commands (tests drive it on a scratch catalog)
Settings are read from the opened db's root, not the working directory. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:49:26 +02:00
Meta Vens
cd5b7faad0 GameData/Aetheria.cc: consumables-first-set apply replayed on the merged tree
Master's catalog blob (f5645e0a, grammar global and seven verbs), then `consumables-first-set apply`.
Dry run on that tree, verbatim:

Vent radius Min 33.03 (Djinni 14x17 cells at 2 units: half diagonal 22.02, x1.5), Max 49.55
New designs:
  Thruster Overdrive   1x1  mass 10  price 18000  stackable False  duration 6  roles [propellant, regulator]
      ThrottleLockData
      Multiplier ThrusterData.Thrust 3-4.5 (propellant)
      Multiplier VelocityLimitData.TopSpeed 2-3 (propellant)
      Multiplier ThrusterData.Heat 5-3 (regulator)
      Multiplier ThrusterData.Visibility 5-3 (regulator)
      "Opens every drive wide and holds it there. The ship is thrown forward on a bright, hot plume while the pilot keeps the wheel."
  Coolant Vent         1x1  mass 15  price 12000  stackable False  duration 15  roles [nozzle, coolant]
      VapourDump radius 33.03-49.55 (nozzle), opacity 0.9-0.98 (nozzle), lifetime 14-20 (coolant)
      Multiplier RadiatorData.Emissivity 0.3-0.5 (coolant)
      "Dumps the coolant loop into space as a spreading bank of vapour. Sensors lose whoever is inside it, and the radiators pay for the loss."

New products:
  Thruster Overdrive -> "send it" by DME, every role mean 0.55 dev 0.2: no brakes/ no regrets/ one good burn
  Thruster Overdrive -> "Updraft" by Finch, every role mean 0.65 dev 0.2: Light as a feather and, for six seconds, about as fast as one in a gale.
  Coolant Vent -> "Smoke Machine" by NiteLife, every role mean 0.55 dev 0.12: Fills the room. Nobody can say who came in with you.
  Coolant Vent -> "Morning Fog" by Lightsail, every role mean 0.55 dev 0.1: Rolls in thick, lifts slowly, and leaves the bills with the other fellow.

Dry run. Pass "apply" to author 2 designs and 4 products.

A second run answers "already authored; nothing to do". This commit builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:48:38 +02:00
Meta Vens
4d1635b472 Merge origin/master (verse-grammar) into eureka/aetheria-release-consumables-first-set
GameData/Aetheria.cc is master's blob, not this branch's; the consumables-first-set
apply is replayed in the next commit. The AetherDb command list takes both new
commands. This merge commit does not build until the apply and test seeding follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:47:01 +02:00
Meta Vens
5a2f44db94 ThrottleLockTests: a full stick is the hull's whole forward thrust
Hand mutant move-clamped (forward intent capped at .9) survived the .5 bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:43:52 +02:00
Meta Vens
35af29304e ConsumableSupplyTests: seed the VerseGrammar global (master's new test used TestCatalogGlobal, which verse-grammar retired)
Mechanical merge fix. The merge commit before this does not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:34:06 +02:00
Meta Vens
c4578cbd1f Merge origin/master into ghostlight-verse/verse-grammar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:32:31 +02:00
Meta Vens
859ecad83a verse-grammar apply: the grammar update builds a new record instead of editing the cached one; replace test compares fields
The command mutated the cache's own VerseGrammar before the batch upsert, so the upsert was redundant and two Soul
mutants (update branch dropped; Same ignoring description or render path) survived: the replace test judged the result
with the same Same() the command uses. The test now reads the fields. Unrun until the full job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:39:44 +02:00
Meta Vens
6666f81385 Tests: the tiny-imbalance flight runs six seconds; the stick's length and no stick are pinned
The Longinus the fixture builds has no heatsinks: its drives overheat and shut down at
about seven seconds (measured: drift -0.006 deg to tick 360, then the thermal shutdown),
so the 600-tick flight of the spec reads the shutdown, not the allocator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:29:18 +02:00
Meta Vens
7378c8f1a8 ThrustAllocationTests: fix the diagnostic string (does not build the previous commit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:27:35 +02:00
Meta Vens
158aeecf70 ThrustAllocationTests: probe the tiny-imbalance drift (temporary diagnostics)
Does not claim green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:26:50 +02:00
Meta Vens
95a1395235 ThrustAllocationTests: heat the degraded drive stepwise; report the drift
The commit does not claim a green run; both tests were red in the previous run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:25:38 +02:00
Meta Vens
ab450e72d3 Tests follow the allocator: warm-up, free thruster power, heat-detuned drives
The allocator reads Item.Active every tick, so fixtures that fire a thruster on their
first update warm its performance first; flight fixtures take the thrusters' energy draw
to zero so a brownout does not scale the turn; the Duel drives are mismatched after they
heat apart, and degraded by heat (the Large Drive has no durability term); the
consumer sits at (2,1), the Skiff's interior centre column. ReachIsWhatTheShipCanDo's
Longinus ceiling is 1.3 (measured 1.195 nose-on, 1.249 broadside).

Previous test commits do not build or pass; this one is unverified until the full run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:24:05 +02:00
Meta Vens
cf6503bf4e Merge origin/master into consumable-supply 2026-10-10 14:05:56 +02:00
Meta Vens
c5e8e45e61 VerseGrammarTests: Author keeps its own grammar parameter (6c1b448c renamed it too; the test project did not compile)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:05:04 +02:00
Meta Vens
6c1b448c0e VerseGrammarTests: RootWith parameter does not shadow the loop variable (972848cb did not compile the test project)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:03:57 +02:00
Meta Vens
972848cb5f VerseGrammar: Open refuses a role named actor and two verbs with one name; edge and command-update pins
ValidateAll (one owner, called by AetheriaStores.Open) refuses duplicate verb names; Validate refuses the reserved role
name actor. Tests pin the name-class edges (a z 0 9 _), a null role element, the starter verb replaced when only its
description or render path differs, the grammar global updated in place, and the fixture's second allegiance and zero-role
speak. The test's scoped registry is TestCatalog.Registry(). Builds; unverified until the full run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:02:10 +02:00
Meta Vens
88fb919099 GameData/Aetheria.cc: verse-grammar apply replayed on the merged tree (master's catalog, then grammar revision 1 and the seven starter verbs)
Catalog sha256 193a4d25... (origin/master) -> f5645e0a... Output of 'dotnet run --project tools/AetherDb -- verse-grammar' (the dry run, before this apply), CultLib git-45c2f40:

    Grammar: new, revision 1.
      Verbs a Ghostlight-simulated Aetheria world may use: ship actions the game films in-engine, and speech rendered as Aetheria conversation.

    Starter verbs (7):
      mine(site: Place, ore: Cargo)  [ShipAction]  new
        The actor works an ore body at a place and takes the ore into its hold.
      haul(cargo: Cargo, destination: Place)  [ShipAction]  new
        The actor carries cargo to a destination place.
      tow(target: Faction)  [ShipAction]  new
        The actor tows a station or hull belonging to the target faction.
      defend(protected: Faction, at: Place)  [ShipAction]  new
        The actor guards a protected faction's ships and holdings at a place.
      attack(target: Faction)  [ShipAction]  new
        The actor attacks the target faction's ships and holdings.
      explore(region: Place)  [ShipAction]  new
        The actor surveys a region and charts what is there.
      speak()  [Conversation]  new
        The actor says something to whoever is in earshot. Shown as Aetheria dialogue: face to face when docked, by radio with the speaker's portrait over their ship when undocked.

    Dry run. Pass "apply" to land the grammar global and 7 verb(s).

A second dry run printed 'Nothing to do.' Data only; does not itself pass the suite until the validation commit's tests are in (builds: yes, the code is unchanged by this commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:02:02 +02:00
Meta Vens
3f5eb6b5c3 Merge origin/master into ghostlight-verse/verse-grammar
Takes master's catalog pointer (GameData/Aetheria.cc) and its TestCatalog.Registry fixture path;
VerseGrammar is the global scratch catalogs author (TestCatalogGlobal stays deleted: the shipped
registry now has a real global, so a test-only second one would have to be authored beside it).
StatResolverTests, TestCatalogTests and AetheriaStoresTests author VerseGrammar.

Does not pass the suite: the catalog is master's and holds no grammar until the verse-grammar apply commit follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:00:03 +02:00
Meta Vens
f8f4f65299 Merge origin/master into eureka/aetheria-release-mods-in-tree 2026-10-10 13:57:37 +02:00
Meta Vens
ffda2a8a76 Tests: add the missing usings (UniRx, System.Linq)
Fixes the compile errors of the previous commit; that commit does not build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:47:58 +02:00
Meta Vens
df61900db8 Rewrite the tests that read the mixer; add the ship-level allocator tests
EvasionTerm: the aggregate reads go; SteeringTests: ATurnIsThatFractionOfTheHullsTurn;
Brownout/ConditionRatio seat the lone thruster on the centre column; ThrottleLockTests
compare a locked ship to an unlocked twin through the same ticks; ThrustAllocationTests
(Duel flight, lost/degraded/repaired drives, dead thrusters, full turn, arena-stepped
flight); ThrustAllocatorTests.AMicroIntentIsServed.

Not yet verified green at this commit; the test project builds only against the
deleted aggregates' removal in the previous commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:44:22 +02:00
Meta Vens
c349de9c31 Delete the thrust mixer, buckets, aggregates, trim and pruning; wire ThrustAllocator into Ship.Update
Ship.Update hands the intent (the throttle lock's one line) and every thruster's live
Column(NominalThrust) to one ThrustAllocator and writes each Axis from its throttle.
Thruster gains NominalThrust and Column; the .01 throttle gates become > 0.

Does not build the test project: EvasionTermTests still read the deleted aggregates
(next commit rewrites them). Not compiled in Unity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:40:06 +02:00
Meta Vens
618e53336f Delete TurnTime and IAnalogBehavior
TurnTime has no caller; IAnalogBehavior's only implementer is Thruster. Pure
deletes, no behaviour change. Not compiled in Unity (the operator's); the
Shared tests build at the end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:39:23 +02:00
Meta Vens
55e607db35 Release map: allocator wiring refresh (TW1-TW6) and the lock warning (LW1-LW8)
Imagination passes (session self-2026-10-10-ag): the Duel oscillation was a
probe artifact (orbits unplaced before the zone's first tick); wiring and
envelope specs refreshed at 08d064c8; the ship-owned incoming-lock warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:37:37 +02:00
Meta Vens
2be1f8efa2 Merge origin/master into eureka/aetheria-release-mods-in-tree
AetheriaStores.Open keeps both: the registry parameter and the missing-catalog refusal.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 13:35:39 +02:00
Meta Vens
1f8af424bf Merge origin/master into eureka/aetheria-release-link-rig-record
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 13:14:43 +02:00
Meta Vens
e058843a34 Add-on frame fix 2: New Ship drafts the hull it leaves; Save, New Ship and undo-past-Save are pinned
New Ship places each mesh by the matrix an object can hold (_held: location, rotation, scale), so a sheared parent no
longer makes the drafted cells differ from the cells Rasterise reads from the hull left behind. smoke_frame pins a failed
Save of a saved ship (write failure and stale revision) leaving its ship.cc, New Ship refusing a vertical wall before
anything changes (twice), the sheared-parent equality, and Ctrl+Z past a first Save: the refusals name the way forward
(Bind Ship Collection, Load Layout) and the route works. All commits build.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 12:56:58 +02:00
Meta Vens
577da4f75b Merge origin/master into eureka/aetheria-release-link-rig-record
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:31:49 +02:00
Meta Vens
02d9a5219e New Ship: the placement is the objects' matrix, so the cells are the hull the author sees
New Ship baked rotation and scale into the mesh data after checking the cells on the evaluated mesh, so a Mirror
modifier acted in a changed frame (a half hull, length 10, got 3x5 cells). The meshes now keep their data and carry the
placement as their own matrix; the cells and grid_origin are the ones computed before the bind and are placed by the one
_place_grid writer, which Rasterise shares; no call that can refuse follows the bind. The single-user refusal, which
protected the baking, is deleted. One _triangles_xy reads the evaluated meshes for both New Ship and Rasterise.
smoke_frame: a Mirror half hull gets the cells of the hand-mirrored solid, and the drafted cells equal Rasterise's of the
hull left behind. Every commit builds (Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:26:42 +02:00
Meta Vens
9b78940766 smoke_frame: pin the eight refusal guards the smoke left unpinned
Package refuses loose meshes and a pending ship; Package reads the .cc rows cut to the seven known members and only
compares a buffer that belongs to the bound ship; Flip Nose turns the hull back when its Rasterise fails; New Ship
refuses meshes in child collections; the Grid is not drawn from a buffer short of cells; Rasterise refuses a ship with
no Ship Root. Eight hand mutants, all caught. Every commit builds (Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:23:51 +02:00
Meta Vens
08d064c8dc Merge origin/master into eureka/aetheria-release-thrust-allocator-core 2026-10-10 12:23:02 +02:00
Meta Vens
47cc0c28db Add-on: an unparented Source mesh is loose; Package reports no library text
One frame predicate: _loose_meshes no longer exempts Source, so a mesh Rasterise reads is a mesh Flip Nose turns (it
turns Ship Root's descendants) or the operator refuses and selects it. Package: the glTF exporter's RuntimeError is
printed to the console and reported as fixed text; the validator's verdict goes to the console and the panel reports
accepted or refused with the anchor count only (no ship ID, no anchor ID). smoke_frame and smoke_package pin each, five
hand mutants caught. Every commit builds (Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:20:41 +02:00
Meta Vens
0906eb53e7 smoke_frame: pin the guards that protect an author's files and the UNDO flags
Pass 7: a pending Save over an existing ship.cc is refused and leaves it; a failed Save keeps the files that were in
the ship folder; New Ship takes no hardpoints from the ship before it; a buffer that belongs to another ship is neither
saved nor rasterised. Pass 8: operators called with undo=True push a native step in background Blender only when they
carry UNDO, so Rasterise, Flip Nose and New Ship undo as one step and Save does not. Nine hand mutants, all caught.
Closes no finding; every commit builds (Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 12:16:41 +02:00
Meta Vens
863d6c8fad ConsumableSupplyTests: 1500 station seeds, a ship hull with three interior cells, units reach the maximum on each station hull
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:30:46 +02:00
Meta Vens
a00054aa7e LoadoutGenerator: a station stocks its consumable before the gear
Sixteen gear picks drawn with replacement fill a shipped station hold, so a station whose roll hit
usually stored nothing (29 of 400 held one against the ruled quarter). The consumable step now runs
before the gear fill; with no consumable on offer it still draws nothing, so generation is unchanged.
Ships keep their step after OutfitEntity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:09:59 +02:00
Meta Vens
1a81d07e3a ConsumableSupplyTests: shipped hulls, tight holds, two hulls per kind, 3000 ship seeds
Station and ship rates are measured per hull on two station hulls and two ship hulls with holds that
sixteen gear picks fill, on a station whose first bay refuses, and on the shipped catalog's own hulls.
The ship band is 3000 seeds so chances of .12, .15 and .05 fall outside it. These tests fail on the
generator as it stands (consumable stocked after the gear); the next commit fixes the generator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 11:02:27 +02:00
Meta Vens
2be6ed9de7 ShipSchemaPinTests: test each allowed character mid-ID, where a trailing dot cannot refuse it
Builds: yes. The previous commit's pin test failed on '.' (a dot last is refused by its own rule).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:21:35 +02:00
Meta Vens
b772b13d43 VerseGrammarValidation: canonical names by character class, not Regex
The Regex form could not be mutated on the verification path (the mutant runner collapsed its backslashes), and a
character loop with named length constants states the same rule without the dependency. Adds refusals for a capital
inside a name, a hyphen, and a direct empty-name case. Builds (not yet run when committed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:21:11 +02:00
Meta Vens
aab6654cc1 smoke_frame: a Grid placed for another size is removed after a resize
Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:52:51 +02:00
Meta Vens
caa418d6cd smoke_frame: a refused create and a nested render mesh; test_ship_cc: refusals name no input
Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:50:52 +02:00
Meta Vens
5beb693c00 Add-on: the .cc written only by Save; New Ship, Rasterise and Flip Nose edit the undoable buffer
One chooser (_ship_collection) and one predicate (_is_ship). _save_layout is the only
replace_layout caller and creates a pending ship's file, removing what it made on failure.
Rasterise writes the layout buffer and aetheria.grid_origin = [x, y, width, height]; Flip Nose
and Package refuse meshes outside Ship Root. New Ship checks first and writes nothing to disk.
Operator reports are fixed text; AetherDb output goes to the system console. smoke_frame covers
undo, hardpoints, Save, cleanup, loose meshes and an empty Game folder preference.

Builds: yes (needs the previous commit's ship_cc).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:49:40 +02:00
Meta Vens
0b5cad8903 ship_cc: layout_revision and valid_ship_id as pure functions, fixed-text errors; pins and tests for the authoring-tool Low findings
layout_revision(shape, hardpoints) is the revision rule replace_layout and Package share.
SHIP_ID_CHARS and RESERVED_SHIP_IDS mirror ShipAuthoringStore.RequireShipId; ShipSchemaPinTests
sweeps every character and every candidate stem against the C# rule. ship_cc errors no longer
carry the path, mount id, anchor id or object name. C# tests: create judges the ID not the
display name, FindRoot answers the working directory itself, short trailing-dot IDs.

Builds: yes (C# test edits and Python only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:49:39 +02:00
Meta Vens
f7f6c0b98e Merge origin/master into eureka/aetheria-release-player-build
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 09:32:12 +02:00
Meta Vens
144b2f5b95 ThrustAllocator tests: System.Random, not CultMath.Random, in the large-hull fixture
The previous commit (8bfce189) does not build: CS0104 ambiguous Random in ThrustAllocatorTests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:27:59 +02:00
Meta Vens
8bfce1899e ThrustAllocator: zero intent returns exact zeros before the solve; the 1e-9 output flush is deleted (zero-intent-warm-nonzero, zero-intent-at-the-cap)
Nothing asked, nothing fired is a fact about the intent: when all three clamped intents are exactly zero Allocate returns the zeroed buffer before the solve, so a warm solve that stops at the iteration cap can no longer fire thrusters. The output flush is gone. The warm start is left at the last solved point. Tests: the two 40-thruster hulls Soul found, and a small intent still answered at any column scale. Builds untested locally; verified on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:08:55 +02:00
Meta Vens
70ee3d3730 ConsumablesFirstSetTests: a drive that has burned six seconds glows brighter than a cold one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:30:15 +02:00
Meta Vens
7a195d2384 Pin the rig's slot 5 carry-through: C# slot numbers and Python replace_visual/replace_lines round trips
Tests only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:29:12 +02:00
Meta Vens
638856afc1 ShipValidationTests: a NaN Min and a NaN Max are each refused as not finite
Tests only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:29:11 +02:00
Meta Vens
191f1fec04 ShipRigTests: pin asymmetric reach, tagged non-joint nodes in Bind, and hull-order Rigs
Off-centre joint limits (20..50, -10..50, -50..0) so Max-Min is distinguishable from |Min|+|Max| and 2*max/2*Max; Bind walking past tagged
nodes that are not joints; Rigs and the lead mount follow hull order where it differs from name order. Tests only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:29:09 +02:00
Meta Vens
9ae5fbb350 AetheriaStoresTests: MissingCatalogGlobalIsLoud copies the fixture catalog and removes its global
Flushing an empty cache writes no file, so the previous fixture still hit the new missing-file refusal.
Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:10:12 +02:00
Meta Vens
eff21e0513 ConsumableSupplyTests: spell the ruling's chances and units out instead of reading the constants
A mutant that changed a constant moved the test's expectation with it and survived (station chance 1,
ship chance 0 and 1, station units 3).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:02:48 +02:00
Meta Vens
8fab3052e1 ThrustAllocator: solver residue below 1e-9 is zero; zero intent after a call is exact zeros (zero-intent-warm-nonzero)
After a good call the warm start left 1e-34..1e-44 throttles on a zero-intent call. Throttles at or below ThrottleResidue return 0 on the one general path; TA-R3's warm start is kept. The test NothingAskedAfterACallFiresNothing arrived in the previous commit (22cb76e8), which therefore fails that test; this commit makes it pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:56 +02:00
Meta Vens
22cb76e85b ThrustAllocator tests: the drive's leak pins the sign of TA-R2's cost row (cost-row-sign-unpinned)
A cost row pulling the errors the other way lowers the pre-onset drive throttle by about 20 percent (1.30e-4 to 1.06e-4 at turn .5); the bounds sit 8 percent under the measured value.

Commit builds: yes (tests/Aetheria.Shared.Tests not yet run on this commit; the full run is the closing job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:43 +02:00
Meta Vens
87e9bfd06b ThrustAllocator tests: a full turn against a full reverse keeps its whole yaw (error-bound-unpinned)
The turn leaves a forward error of 2, the top of TA-R2's error box; a bound of 1 or 1.5 gives yaw back.

Commit builds: yes (tests/Aetheria.Shared.Tests not yet run on this commit; the full run is the closing job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:39 +02:00
Meta Vens
aa5e45a2ff ThrustAllocator tests: IterationLimit keeps the solver's iterate (iteration-limit-untested)
128 torque-free forward thrusters from a cold start reach the 100-iteration cap through the public surface; the call must keep the iterate it reached, not zero it.

Commit builds: yes (tests/Aetheria.Shared.Tests not yet run on this commit; the full run is the closing job).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:36 +02:00
Meta Vens
b3b81007d5 BuildThrustedShip fills extra hardpoint types before activation; the vent test fits a radiator through it
A ship cannot be equipped once active, so the radiator has to be fitted inside the one builder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:13 +02:00
Meta Vens
293747c5f9 ConsumableSupplyTests: pin the generator's Random after generation to the pre-consumable tree
The gated-versus-plain comparison alone cannot see an unconditional draw (both catalogs draw).
Values measured on origin/master d4a27def with the same fixture. The roll-before-availability
mutant survived the full suite without this pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:57:32 +02:00
Meta Vens
86fb594031 Release map: vectored thruster rows (probes V1-V8, model rows, cut order)
Imagination pass (session self-2026-10-10-ag): the row gimbal is sim data,
one shared-throttle actuator per row in the allocator's single solve;
specs vector-rows-record r2 and vector-rows-allocator r1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:37:49 +02:00
Meta Vens
1047698568 Missing ship.cc fails the fixture, not the game's compose
The game treats a directory without ship.cc as not a package (TheBootCatalogIsTheShippedOneUntilAModIsInstalled), so da4d8c6c's
Compose exclusion broke that test. Reverts the Compose and ResolveCatalog change and moves the check to the one place that
holds the first-party tree to a stricter rule: TestCatalog.Resolve throws, naming each directory under GameData/Mods that
holds no ship.cc (missing-ship-cc-skipped). The GLB case change and the registry parameters stand.

Builds; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:35:08 +02:00
Meta Vens
1521c68a79 AetheriaStores.Open: a missing catalog throws FileNotFoundException
The test assembly registers a catalog [CultGlobal], so the global check already threw on a missing
file there and AStoreRefusesAMissingCatalog passed against the old Open (run at fe9da2e: 12 passed).
The refusal is now a FileNotFoundException naming the path, and the test pins that type, which the
global check never throws. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:28:04 +02:00
Meta Vens
387404c6ea AetheriaStoresTests: MissingCatalogGlobalIsLoud opens an existing empty catalog
The test relied on a read-only open of a nonexistent file yielding an empty catalog, which
AetheriaStores.Open now refuses; the fixture writes the empty catalog first. Builds; the suite is green with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:27:31 +02:00
Meta Vens
fb030ca9c3 smoke_package: a folder holding only a ModTools tool is not a game folder
Pass 4 gains the case that kills the mutant dropping the Aetheria.cc check on the Game folder preference. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:27:04 +02:00
Meta Vens
c98ad8f56a Add-on: _aetherdb joins its output lines with a newline escape, not a raw newline
The previous commit's _aetherdb did not parse (unterminated string literal), so 63d16e81 and 6971ff70 cannot import the add-on; this one can.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:25:05 +02:00
Meta Vens
0b721d691f Tests: the VerseGrammar global replaces TestCatalogGlobal as the catalog global fixtures author
TestCatalogGlobal existed only to give the test host one [CultGlobal] routed to the catalog. VerseGrammar is the
game's first, so the test-only type is deleted and every fixture authors a VerseGrammar instead (63 call sites; the
missing-global tests assert on aetheria.verse_grammar). Stale comments about the test type are rewritten.
Builds (not yet run when committed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:18:00 +02:00
Meta Vens
e5a57dab9f AetheriaBuild: qualify UnityEditor.PlayerSettings (the game has a global PlayerSettings); Unity .meta files
The previous commit did not compile in Unity (CS0117 on PlayerSettings.bundleVersion); this one does,
and a batchmode run of AetheriaBuild.Build succeeded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:17:13 +02:00
Meta Vens
6971ff70a7 ShipValidationTests: every Windows device name, alone and before a dot
Builds; the id-refusal cases pin prn and aux, which the first set left unchecked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:11:55 +02:00
Meta Vens
b997b80f81 AetheriaBuild.Build: one player entry point; AetheriaStores.Open refuses a missing catalog
AetheriaBuild (Assets/Editor) sets the version, builds Addressables, builds the
Win64 player, stages GameData through PlayerStaging, publishes AetherDb to
ModTools and removes the Burst debug folder; any failure exits 1 naming the step.
PlayerStaging is Unity-free and linked into Aetheria.Shared.Tests. A read-only
AetheriaStores.Open of a nonexistent catalog throws.

Builds on the headless side; the Unity .meta files and the batchmode run follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:55:32 +02:00
Meta Vens
63d16e81f3 AetherDb for ship authors: rooted at a game folder, found in ModTools; ship-ID rule in create
FindRoot keys on GameData/Aetheria.cc. ShipAuthoringStore.RequireShipId is the one ID rule
(Validate and create), refusing Windows device names and a trailing dot, naming no value.
The add-on's one preference is Game folder; _aetheria_repo, the repo preference and the
dotnet-run invocation are deleted. Smokes take SMOKE_GAME_FOLDER. Not yet built or tested
at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:53:03 +02:00
Meta Vens
fe9da2e0af Test AStoreRefusesAMissingCatalog (red: AetheriaStores.Open does not yet refuse)
Builds; the new test fails against the current Open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:52:06 +02:00
Meta Vens
d6100b18ca Route every real-catalog test reader through TestCatalog
Deletes the direct GameData/Aetheria.cc opens (FireControlCut124Tests x3, FireControlCut7Tests, MiningCut3Tests x2,
RestoredHullsTests x11) in favour of TestCatalog.Repo, and the eight copies of the shipped-assembly registry in favour of
TestCatalog.Registry() (real-catalog-readers-bypass). Pirates and Roles command tests keep copying the shipped catalog (they
rewrite a copy through AetherDb) and take only the registry.

Builds; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:50:26 +02:00
Meta Vens
da4d8c6c96 Fixture boots the game's catalog under one scoped registry; missing ship.cc is an exclusion; GLB extension is lowercase only
AetheriaStores.Open, ShipModCatalog.Compose and ResolveCatalog take an optional registry (the game passes none and keeps the
process-wide one). TestCatalog.Registry() is the shipped assembly's registry, so the test assembly's TestCatalogGlobal is no
longer a catalog global the real catalog must hold (fixture-fails-on-real-package). TestCatalog.ForRepo(root) is the one
binding Repo uses, pinned by a test over a real catalog plus a package (repo-wiring-unpinned). A package directory without
ship.cc is excluded with a reason, in Compose and so in ResolveCatalog's pre-check (missing-ship-cc-skipped). The loader takes
only a lowercase .glb, matching the case-sensitive LFS rule (lfs-glb-case).

All commits build; not yet run (verification job follows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:50:18 +02:00
Meta Vens
7f64e0d733 Merge origin/master into ships-addon-frame-r4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:50:14 +02:00
Meta Vens
30d027195b Research: prior art on thrust allocation with vectored thrusters
Serves follow-ups vectored-thruster-rows and gimballed-thrusters: virtual
actuators, nonlinear and cascaded allocation, rate and gimbal limits as
per-tick bounds, the zero-thrust singularity, games, shared-angle rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:50:05 +02:00
Meta Vens
ff1f5e9ebd Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-mods-in-tree 2026-10-10 06:46:41 +02:00
Meta Vens
02145a105c VerseGrammarTests: fixed record keys go through a batch (previous commit did not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:43:22 +02:00
Meta Vens
d577c64d8f ConsumablesFirstSetTests: fit the first radiator pairing that the hull takes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:37:38 +02:00
Meta Vens
93b03bb0f5 verse-grammar: drop the TaskType guard the one-verb-per-TaskType test already covers
Builds (deletion of a guard statement only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:37:21 +02:00
Meta Vens
2efd882965 GameData/Aetheria.cc: verse-grammar apply (grammar revision 1 and the seven starter verbs)
Output of 'dotnet run --project tools/AetherDb -- verse-grammar' (the dry run, before this apply), CultLib git-45c2f40:

    Grammar: new, revision 1.
      Verbs a Ghostlight-simulated Aetheria world may use: ship actions the game films in-engine, and speech rendered as Aetheria conversation.

    Starter verbs (7):
      mine(site: Place, ore: Cargo)  [ShipAction]  new
        The actor works an ore body at a place and takes the ore into its hold.
      haul(cargo: Cargo, destination: Place)  [ShipAction]  new
        The actor carries cargo to a destination place.
      tow(target: Faction)  [ShipAction]  new
        The actor tows a station or hull belonging to the target faction.
      defend(protected: Faction, at: Place)  [ShipAction]  new
        The actor guards a protected faction's ships and holdings at a place.
      attack(target: Faction)  [ShipAction]  new
        The actor attacks the target faction's ships and holdings.
      explore(region: Place)  [ShipAction]  new
        The actor surveys a region and charts what is there.
      speak()  [Conversation]  new
        The actor says something to whoever is in earshot. Shown as Aetheria dialogue: face to face when docked, by radio with the speaker's portrait over their ship when undocked.

    Dry run. Pass "apply" to land the grammar global and 7 verb(s).

Then 'verse-grammar apply' on that catalog (sha256 193a4d25... -> b5b3db48...), and a second run printed no changes.
Run on Yggdrasil; the catalog copied back and committed here. Builds: this commit changes data only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:36:01 +02:00
Meta Vens
b45c6cab35 ConsumablesFirstSetTests: the Djinni has four radiator hardpoints; fit the first
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:35:44 +02:00
Meta Vens
d382d4e062 VerseGrammarTests: the fixture writer is deterministic in content, not bytes
CultCache mints a random record key and a wall-clock storedAt per write, so two writes never match byte for byte.
The writer now fixes every record key and the test compares what a reader consumes (schema, key, content) across two
writes. Builds; the shipped-catalog test still fails at this commit because the catalog lands in the next one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:35:44 +02:00
Meta Vens
c321e84702 ConsumablesFirstSetTests: call the validator by its real owner (CultRecordRefs.Validate)
The previous commit, 51b8ecf7, does not build (AetheriaStores.Validate does not exist); this one does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:27:36 +02:00
Meta Vens
30c008d7a8 Merge origin/master into eureka/aetheria-release-modifier-stacking 2026-10-10 06:26:08 +02:00
Meta Vens
987849edd0 VerseGrammar: escape the regex end anchor (previous commit did not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:25:47 +02:00
Meta Vens
7a882b626b GameData/Aetheria.cc: apply AetherDb consumables-first-set (replay the command at merge, do not merge the blob)
Output of `dotnet run --project tools/AetherDb -- consumables-first-set apply` on the catalog at e71540be (sha256 of the
result 7e56a2ba4f9a8146ca785c326fd42228d011ffb5ac3e7e6a999e0e4e3f5cd0e2). The dry run printed:

-rw-r--r--  1 root          root          12718840 Oct 10 04:22 Aetheria.cc
-rw-r--r--  1 root          root              1603 Oct 10 04:22 apply.txt
-rw-r--r--  1 root          root              1612 Oct 10 04:22 dryrun.txt
Vent radius Min 33.03 (Djinni 14x17 cells at 2 units: half diagonal 22.02, x1.5), Max 49.55
New designs:
  Thruster Overdrive   1x1  mass 10  price 18000  stackable False  duration 6  roles [propellant, regulator]
      ThrottleLockData
      Multiplier ThrusterData.Thrust 3-4.5 (propellant)
      Multiplier VelocityLimitData.TopSpeed 2-3 (propellant)
      Multiplier ThrusterData.Heat 5-3 (regulator)
      Multiplier ThrusterData.Visibility 5-3 (regulator)
      "Opens every drive wide and holds it there. The ship is thrown forward on a bright, hot plume while the pilot keeps the wheel."
  Coolant Vent         1x1  mass 15  price 12000  stackable False  duration 15  roles [nozzle, coolant]
      VapourDump radius 33.03-49.55 (nozzle), opacity 0.9-0.98 (nozzle), lifetime 14-20 (coolant)
      Multiplier RadiatorData.Emissivity 0.3-0.5 (coolant)
      "Dumps the coolant loop into space as a spreading bank of vapour. Sensors lose whoever is inside it, and the radiators pay for the loss."

New products:
  Thruster Overdrive -> "send it" by DME, every role mean 0.55 dev 0.2: no brakes/ no regrets/ one good burn
  Thruster Overdrive -> "Updraft" by Finch, every role mean 0.65 dev 0.2: Light as a feather and, for six seconds, about as fast as one in a gale.
  Coolant Vent -> "Smoke Machine" by NiteLife, every role mean 0.55 dev 0.12: Fills the room. Nobody can say who came in with you.
  Coolant Vent -> "Morning Fog" by Lightsail, every role mean 0.55 dev 0.1: Rolls in thick, lifts slowly, and leaves the bills with the other fellow.

Dry run. Pass "apply" to author 2 designs and 4 products.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:24:01 +02:00
Meta Vens
51b8ecf7fa ConsumablesFirstSetTests: the catalog's two consumables, the overdrive's lock and boost, the vent's cloud
Run against the shipped catalog once the next commit lands; this commit alone fails them (it builds).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:23:57 +02:00
Meta Vens
623072c711 Verse grammar: VerseGrammar and VerseVerb catalog documents, validation, the verse-grammar AetherDb command, tests
Adds the aetheria.verse_grammar global and aetheria.verse_verb documents (one render path per verb, typed
participant roles), VerseGrammarValidation run by AetheriaStores.Open over every verb, the AetherDb
'verse-grammar [apply]' command (starter set: one ship-action verb per TaskType plus speak; question
verse-social-verbs default speak-only), and VerseGrammarTests with a deterministic fixture writer.

The shipped catalog does not carry the grammar yet: it lands in the next commit, so
The_shipped_catalog_holds_revision_one_and_the_seven_starter_verbs fails at this commit. Not yet built when committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:23:01 +02:00
Meta Vens
815526eeb8 AetherDb consumables-first-set: Thruster Overdrive and Coolant Vent with two products each
Dry-run by default, validated and committed in one batch like pd-gear. Overdrive (1x1, mass 10, price 18000, duration 6,
ThrottleLock then Thrust 3-4.5 and TopSpeed 2-3 on propellant, Heat and Visibility 5-3 on regulator); Coolant Vent
(1x1, mass 15, price 12000, duration 15, VapourDump radius from the Djinni diagonal x1.5, opacity .90-.98, lifetime
14-20, then Emissivity .3-.5). Builds; the catalog is not yet applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:15:53 +02:00
Meta Vens
e8d42df258 ConsumableSupplyTests: ship hull with two interior cells (cargo bay and capacitor)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:56:45 +02:00
Meta Vens
e71540be5b Merge origin/master into eureka/aetheria-release-vapour-cloud
Behaviors.cs union list: keep Union(41, ThrottleLockData) from master and
Union(42, VapourDumpData) from this cut; no key renumbered. All commits build
as a merge result only after the verify job.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 05:51:04 +02:00
Meta Vens
87528dbda4 ConsumableSupplyTests: a station roll can also stock a single unit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:47:37 +02:00
Meta Vens
a5aac29055 ConsumableSupplyTests: roomy holds (gear stock draws 16 with replacement), drop the probe, pin the station maximum
Commit 54d200ec before this is a diagnostic probe (builds, test deliberately red).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:47:11 +02:00
Meta Vens
54d200ec60 probe
x
2026-10-10 05:37:21 +02:00
Meta Vens
562de34c4e ShipRigTests: the Max-180 boundary joint needs one degree of reach for its 1 degree arc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:36:32 +02:00
Meta Vens
c2e46a4637 ConsumableSupplyTests: count consumables in docking-bay holds too (a station's first bay is its dock)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:34:47 +02:00
Meta Vens
7b73e51346 Consumable supply: scarce stock at stations and on ships through the one availability rule
LoadoutGenerator.AvailableProducts and RandomProducts now range over CraftedItemData; only
equippable gear needs a hull home. StockConsumables is the last step of GenerateShipLoadout and
GenerateStationLoadout: it draws nothing when no consumable is on offer. Unbuilt/untested at
this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:32:50 +02:00
Meta Vens
77e441df31 StatResolver tests: keep the boost gear online with the entity's override so the modifiers execute
The first commit's gear modifiers never executed (test gear has no heat response, so it read offline). Builds; the first commit's new tests fail without this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:32:45 +02:00
Meta Vens
11a7843c61 StatResolver tests: boosts on one stat multiply, constants add, gear and consumable share the rule
Pins ruling boost-stacking-multiply through the production path (gear and consumable StatModifierData on a ship, read via EquippedItem.Evaluate): TwoScalesOnOneStatMultiply, AConsumableBoostMultipliesWithGear, TwoConstantsOnOneStatAdd. Tests only; no production change. Not yet run; the commit is unverified.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:30:38 +02:00
Meta Vens
b623d519f7 ThrottleLock tests: pin the exact tick the lock ends, as a function of Duration
Replaces TheLockHoldsThroughMostOfItsDurationAndEndsAfter with a theory over Duration 1 and 2 at 0.25 s ticks. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:26:51 +02:00
Meta Vens
1be1023558 Merge origin/master into throttle-lock 2026-10-10 05:26:11 +02:00
Meta Vens
9e516d06d9 Rig in the visual record: ShipAuthoring.Joints, ShipAnchor.Joint, reach check, Bind and ShipModPlan.Rigs
Deletes the articulation anchor role. Adds ShipJoint (key 5 Joints), ShipAnchor.Joint (key 5),
the judge's joint-shape, mount-on-joint and yaw-reach checks over RigChains, Bind's GLB checks
(ReadNodeIds returns the nearest tagged ancestor), and ShipModPlan.Rigs. Presentation only:
arc stays HardpointData.FiringArc and traverse WeaponData.Tracking (ruling mount-arc-gun-traverse).
Not yet built or run when committed; the verification commit follows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:23:02 +02:00
Meta Vens
d4a27def37 Merge origin/master into eureka/aetheria-release-consumable-host
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:12:57 +02:00
Meta Vens
8755da5ecb Release map: articulated mounts re-mapped to the hardpoint-arc ruling
Imagination r2 re-map (session self-2026-10-10-ag): the sim already carries
per-hardpoint arc and weapon traverse; links are rig only. Target doc moves
articulated weapon mounts into scope under ruling mount-arc-gun-traverse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:12:27 +02:00
Meta Vens
c22456b52c Merge origin/master into eureka/aetheria-release-consumable-host
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 04:59:19 +02:00
Meta Vens
1fc98bdcde ThrustAllocator: write the error coefficients every call; no Array.Clear on A
Every entry of A is now assigned each call or never written, so the clear was a second
owner of the same state (hand mutants a-never-cleared and a-cleared-by-division survived
it as equivalent).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:31:49 +02:00
Meta Vens
c770e11bfa ThrustAllocator: tests for a one-thruster first call and for stale rows; drop the b clear
Stryker survivors 12390 (initial _columns +1 skips the first resize at n = 1) and
12399/12400 (A not cleared between same-count calls) get tests. Array.Clear on b was an
equivalent mutant: rows 0-6 are assigned every call and the ridge rows are never written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 03:23:50 +02:00
Meta Vens
acea1aa73e Merge remote-tracking branch 'origin/master' into eureka/aetheria-release-ballistic-flight 2026-10-10 02:00:50 +02:00
Meta Vens
ce0023f1f8 Research: prior art on hull decals, panel lines and wear layering
Eyes pass before the hull shader fork: DECALmachine 2.17 export paths,
forward-renderer decal practice, parallax for panel lines, layered wear
on the built-in pipeline, and this project's rendering constraints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:50:14 +02:00
Meta Vens
1d031bd273 ThrustAllocator tests: a bad column zeroes the caller's buffer after a good call
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:31:58 +02:00
Meta Vens
f78fc421ef ThrustAllocator tests: the drive's pre-onset throttle bound is 3e-4, measured 1.6e-4 at most
Removes the scratch probe. The spec pinned 1e-4; the optimum leaks 1.2e-4 (Duel) and
1.6e-4 (halved Talaria) from the first touch of Turn. Builds; ran 18 tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:31:14 +02:00
Meta Vens
828d90ce32 scratch probe (removed next commit); not a build deliverable
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:30:18 +02:00
Meta Vens
e355747dae ThrustAllocator: one bounded least-squares solve, yaw first, translation error paid linearly
Rules TA-R1 to TA-R4 of cut-thrust-allocator-core.r2, tests on synthetic columns
(Duel, damaged Duel, symmetric hull). First draft; not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:29:05 +02:00
Meta Vens
5792354c61 Merge self/pbr-materials: 12 tileable CC0 PBR materials for Blender and Unity
ambientCG 2K sets under Assets/Materials/PBR (GlowFade .mat per material,
packed metallic/smoothness), and Asset Sources/PBR Materials.blend as a
UV-mapped Blender asset library linking the same textures. Sources and
licence in Assets/Materials/PBR/SOURCES.md. Unity import unverified until
the project is opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:28:24 +02:00
Meta Vens
80842ba2fc Carbon_Fibre: dielectric, metallic 0 (drop unused Metalness map)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:27:53 +02:00
Meta Vens
492a8333fb Blender asset library: PBR Materials.blend (catalog Aetheria/PBR)
12 asset-marked materials, UV mapping with a scalar Tiling node, images
linked by relative path to Assets/Materials/PBR, previews generated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:26:22 +02:00
Meta Vens
840dfe6460 PBR materials: 12 ambientCG CC0 sets for Unity (GlowFade) under Assets/Materials/PBR
2K-JPG Color/Roughness/NormalGL (+Metalness, AO where the set has them),
generated MetallicSmoothness.png (R metallic, A 1-roughness), texture and
material .meta files, SOURCES.md. Unity side not opened yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:26:21 +02:00
Meta Vens
9f6d8659af Pin CultMath 0.4.0 (BoundedLeastSquares KKT tolerance; snoise tie rule is Breaking)
CultMathRevision 252e226c (cultmath-unity-v0.4.0), manifest tag and lock entry.
Generated content that samples noise may move; fixtures follow in later commits.
Builds as a pin; the suite may fail on re-rolled content until then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:15:18 +02:00
Meta Vens
d519d99b1e Consumable host: an effect lives exactly its Duration, not Duration plus one tick
Expiry fires when the remaining duration reaches zero (<= 0), so behaviours execute on
Duration/dt ticks and not one more. AConsumableRunsForExactlyItsDurationInTicks pins it
with 0.25 s ticks. Builds; verified in the next run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:48:02 +02:00
Meta Vens
a74065dbee ThrottleLockTests: pin stick length, counter-clockwise turn, non-lock consumables and the lock-end boundary
Four tests for Soul's survivors lock-intent-length, lock-ignores-ccw-turn, lock-any-consumable and
lock-ends-at-half-duration. Tests only; not yet run on Yggdrasil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:46:33 +02:00
Meta Vens
afe44b09d3 ConsumableTests: the overlap test attaches both modifiers before the first expires
The first draft activated the second effect so late it was not yet attached when the
first detached, so the shared-entry guard mutants survived it. Builds; tests green
status is in the next verification run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:38:26 +02:00
Meta Vens
6b36835953 Ballistic flight r3: name CultMath.float2x2.Rotate in full (the math.float2x2 method shadows the type)
The previous commit (2dcb7b20) does not build: DrawAhead.cs CS0119.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:29:32 +02:00
Meta Vens
2dcb7b2078 Ballistic flight r3: DrawAhead draws a round from the sim's facts, a hit ends at its impact cell; FireControl draws nothing
FireControl.RoundEnd and RoundAt leave FireControl (RoundEnd to DrawAhead verbatim, RoundAt as DrawAhead's private Line);
DrawAhead.Round takes the published outcome, steers a hit or burst from its frozen line at the commit tick onto its
end (burst point, else the impact cell on the target's drawn pose), and RoundStop is deleted. Projectile caches the
last published ShotOutcome and calls DrawAhead only. BallisticFlightTests move to the new signatures; the frozen-line
moving-target test is replaced by impact-cell, steer and no-drawing-function tests. Unverified: not yet built or run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:27:22 +02:00
Meta Vens
87ec736f04 Map: articulated mounts (body facts AM1-AM11, model-page rows, authority map, rationale)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:25:28 +02:00
Meta Vens
29c5f7aba1 Consumable host: one initialiser for gear and running effects; tests pin overlap, lifetime, per-design cooldown, refit
Entity.Activate re-initialises the running consumable effects through the same
InitializeBehaviors that initialises gear and ActivateConsumable, so a consumable
active across deactivate/refit/activate retargets to the new items.
ConsumableTests gains the stackable overlap/multiply, shared-entry detach,
expiry-boundary, per-design cooldown and refit facts. StatResolverTests' expiry
test builds its consumable through ItemManager.CreateInstance.
Not yet built or run; verification follows in a later commit message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:24:54 +02:00
Meta Vens
ce4bb199a7 Map: ballistic flight is presentation (r3 probes and rationale)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:23:24 +02:00
Meta Vens
d98818ea0c BallisticFlightTests: a receding proximity target puts the burst point off the arrival line
The contact-burst fixture cannot tell RoundStop's burst point from the line at
arrival (CommitBurst puts both at the same distance), so a stop that ignored the
burst point survived. A targeted proximity round at a target receding faster
than the round closes bursts at the pulled-back range point while arriving at
the fired-at distance; this test pins the stop to the sim's burst point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:56:51 +02:00
Meta Vens
ba2b4a7377 Projectile draws through DrawAhead and computes no position, time or range
Deletes At, the end formula (Unity restating the range) and Resolve's own stop
arithmetic. Launch binds ShotCommitted (refresh the record, learn the outcome)
and ShotResolved; Draw is DrawAhead.Round plus RoundOver; a hit or burst stops at
DrawAhead.RoundStop. Projectile names no flight quantity.

Builds headless (Projectile is not in the test project); the Unity compile is
run separately at the final head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:35:46 +02:00
Meta Vens
f9483181f2 BallisticFlightTests: the moving target crosses at 10, below the round's speed, so an intercept exists
Spec r2 said 30 against a round speed of 20: no first-order intercept exists
there (the target outruns the round sideways), so the round did not lead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:35:37 +02:00
Meta Vens
a9f1196472 BallisticFlightTests: using UniRx for the Subscribe lambda
Builds headless; Unity still on the old Projectile at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:33:51 +02:00
Meta Vens
85e57aef78 BallisticFlightTests: using System for the Subscribe lambda; DrawAhead comment names no frame clock
Builds headless; Unity still on the old Projectile at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:32:08 +02:00
Meta Vens
60aacfdc35 FireControl.RoundEnd states a round's end; DrawAhead draws rounds as pure statics
RoundEnd(shot, known) is the one statement of when a ballistic round's drawn
flight ends: arrival for a hit, burst or unpublished outcome, the frozen range
(never short of arrival) for a miss. RoundAt takes the known outcome and clamps
at RoundEnd. DrawAhead gains Round, RoundStop, RoundOver (pure, no state) so the
blend, stop and done rules are headless-testable. Seven new tests (ten cases).

Unity build: Projectile.cs still calls the old RoundAt, so this commit does not
compile in Unity (the headless test project does not include Projectile). The
next commit moves Projectile onto the statics.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:31:12 +02:00
Meta Vens
6d83597b77 Map: ballistic-flight r2 body facts and why a round's end is one sim statement
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 22:27:59 +02:00
Meta Vens
950b0e3ddc VapourCloud: drop the zero-lifetime guard saturate already covers
The mutation table let the guard's removal survive: with saturate's NaN rule
(max(0, NaN) = 0) a zero-lifetime cloud has no opacity without it, and
ACloudWithNoLifetimeObscuresNothing still pins that behaviour. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:17:35 +02:00
Meta Vens
e56f9c8be5 BallisticFlightTests: move the shooter after Fire so a live-origin RoundAt fails
The origin-from-live-shooter hand mutant survived against a stationary shooter. Builds: yes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:56:01 +02:00
Meta Vens
8c549719c0 ThrottleLockTests: strafe pairs placed for opposing torque
Pairs mirrored across the ship's width had equal torque and the compensation still cancelled one; the previous commit's AnUnlockedShipFollowsIntent was red. Mirror across its length instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:54:20 +02:00
Meta Vens
015e6d86bd ThrottleLockTests: strafe thrusters in mirrored pairs
A lone off-axis strafe thruster cancels its own torque in Ship.Update, so its axis read 0 unlocked; pairs leave the strafe axis plain. The previous commit's AnUnlockedShipFollowsIntent was red for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:51:30 +02:00
Meta Vens
84f9cd39e5 VapourCloudTests: settled ratio to two places
The settled ratio carries the seed's last residue (.4007 against .4); two
places still separates .4 from the squared .16. Test-only; builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:40:48 +02:00
Meta Vens
42c403dc32 VapourCloudTests: settled-state ratios, drag-aware drift, capture at vent
Fixes the fixtures the first verify run falsified: the sensor's start-up seed
made one-tick ratios meaningless (compare settled infos and the settled ping
extra), launch drag moves a cloud less than its velocity, and the vent's own
velocity is read when the cloud is added, not after it has drifted. Test-only;
builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:39:24 +02:00
Meta Vens
2b03d90812 RoundAt clamps at the weapon's frozen Range (PendingShot.MaxRange), not FireRange
FireRange is the distance to the engaged target and 0 for a round with none, so a no-lock burst round and a
round that misses never flew. MaxRange = weapon.Range is frozen at Fire beside Speed. Unity compile not yet run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:35:37 +02:00
Meta Vens
0c29ea1768 ThrottleLockTests: place thrusters on interior hull cells
The first commit's tests failed in setup (border cells are not interior); it builds, its three new tests were red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:32:00 +02:00
Meta Vens
f79cf8b7a7 ConsumableTests: a hold with room for two consumables
The 1x1 interior fixture could not store the second consumable the
non-stackable test needs. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:29:27 +02:00
Meta Vens
2640faa9a6 VapourCloudTests: drift, ping, wire shape and authored stats
Pins the cloud's drift and fade-from-vent-time, the ping branch of Gain, the
dump's authored radius/opacity/lifetime and its union 42 keys 1-3. Test-only;
builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:24:06 +02:00
Meta Vens
0fb5ac1dfc Sensor.Gain takes the obscuration of its sight line
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>
2026-10-09 20:22:16 +02:00
Meta Vens
6dcf33d11c Vapour clouds: Zone owns them, a VapourDump behaviour vents one (union 42)
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>
2026-10-09 20:22:00 +02:00
Meta Vens
aa9288d9de Projectile is drawn on FireControl.RoundAt and integrates nothing
Deletes the Time.deltaTime gravity/drag/position integration and the range-distance kill from Projectile and the
UnityEngine.Random jitter, barrel direction and inherited velocity from ProjectileManager. A round holds a copy of
its PendingShot and draws at RoundAt(Zone.Time + Clock.Lead) with a barrel offset decaying over BlendTime; ShotResolved
ends a hit or burst at the outcome's BurstPoint, a miss flies to the FireRange clamp. Unity compile not yet run at
this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:19:23 +02:00
Meta Vens
aaab561f98 Consumable host: initialise at activation, dispose at expiry, instantiate consumables
ActivateConsumable runs Initialize on the effect's behaviours; expiry disposes
them before Resolver.Forget, so a consumable's modifiers exist exactly while
its effect is active. ItemManager.CreateInstance returns a ConsumableItem for a
consumable design. StatResolver.DetachModifier drops an entry left with
nothing attached, so ModifierEntryCount returns to baseline. LoadoutTests'
hand-built ConsumableItem goes through CreateInstance. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:19:22 +02:00
Meta Vens
0e89dd1673 FireControl.RoundAt: the one statement of where a fired round is at a sim time
PendingShot freezes the weapon's Velocity as Speed at Fire; RoundAt(shot, time) reads the frozen origin,
direction, speed and fire time, clamped to the FireRange point. Step, Commit and Apply do not call it.
BallisticFlightTests pin the line against the shooter position, aim and authored velocity.
Builds: yes. Presenters still fly their own rounds at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:19:22 +02:00
Meta Vens
c6bca1a522 ThrottleLock behaviour: an active consumable forces full forward intent, read once in Ship.Update
ThrottleLockData (union 41) marks the lock; Entity.ThrottleLocked is derived from the
active effects; Ship.Update reads one `move` in place of MovementDirection. Turn is
untouched (ruling overdrive-keep-steering). Not yet verified by a build when committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:17:47 +02:00
Meta Vens
739eee4a8e Consumable host: tests first (red at the base; they build, three fail)
Adds AConsumableModifierBoostsUntilExpiry, ABoughtConsumableActivates and
ANonStackableConsumableRefusesASecondActivation. This commit builds; its tests
fail until the host cut lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:17:36 +02:00
Meta Vens
1b2e9c1258 Map: allocator translation cost is linear (core r2 probes, tolerance, chosen constants)
Imagination pass, aetheria-release, session self-2026-10-09-morning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:37:59 +02:00
Meta Vens
a04ab767b9 Merge eureka/aetheria-release-cultmath-0-3-pin: CultMath 0.3.0 (BoundedLeastSquares), the pin guard fires on Linux, fixtures stop depending on the re-rolled galaxy
Soul s1-s2 hold (aetheria-release:verdict:cut-cultmath-0-3-pin.s2). The generated galaxy re-rolls with the noise kernel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:24:28 +02:00
Meta Vens
a3ea1d7ba1 Tests: scan's miss path fails then returns default (Assert.Fail is void)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:40:42 +02:00
Meta Vens
549c1b0253 Tests: the two no-Lagrange zone tests share one scan; restore NotSame, use Assert.Fail
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>
2026-10-09 15:39:05 +02:00
Meta Vens
aac2cf91e4 Map: spec refresh 2026-10-09 (scarce consumables, fog-bank presenter, multiply, tiered boosters, shipped AetherDb, player build)
Body facts RF1-RF8, model rows, booster and consumable tables, and rationale for the
revisions admitted under follow-up rulings-2026-10-09-spec-refresh. Sweeps the stacking
and hoarding lines the 2026-10-09 rulings made stale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 15:28:29 +02:00
Meta Vens
ab396c786a Tests: the evasion volleys fire enough shots to resolve the price gap
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>
2026-10-09 14:57:48 +02:00
Meta Vens
c724001467 Tests: the evasion range's target is a written-out Djinni fit
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>
2026-10-09 14:54:44 +02:00
Meta Vens
0ccf02746d Tests: restored-hull station tests pick their zone by the property they test
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>
2026-10-09 14:54:43 +02:00
Meta Vens
a59f1fa977 Tests: TutorialSeed1 follows the galaxy CultMath 0.3.0 rolls
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>
2026-10-09 14:54:42 +02:00
Meta Vens
97dd38dfb8 Pin CultMath 0.3.0 and make the pin guard fire on Linux
Directory.Build.props, Packages/manifest.json and the lock move to
cultmath-unity-v0.3.0 (614fd445) together. VerifyCultLibRevision matched the
CultMath ProjectReference by a backslash-spelled identity and was skipped on
Linux; it now matches by project file name. Does not pass tests: generated
content re-rolls with the new noise kernel, fixtures follow in later commits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:02:36 +02:00
Meta Vens
439d488ac8 Map: flight control allocates thrust (body facts, authority map, rationale); locomotion-cut.md superseded for Cuts 2-3
Imagination pass, aetheria-release, session self-2026-10-09-morning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:42:38 +02:00
Meta Vens
80d2c7f305 Tests: TurnRateIsTheActuatorsTurn idles the drives before it checks a Direction write
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>
2026-10-09 03:35:13 +02:00
Meta Vens
0c944a5a51 Catalog: replay roles-backfill apply on master's catalog
AetherDb roles-backfill apply on master's blob 32a2e401: 12 designs and 6 products authored; a second apply is a no-op.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 03:23:55 +02:00
Meta Vens
e915f95244 Merge eureka/aetheria-release-roles-backfill: roles backfill command and its tests (catalog blob stays master's; regenerated on the next commit)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 03:21:01 +02:00
Meta Vens
f28d4b4b12 Merge eureka/aetheria-release-sim-speed: one SimClock steps the zone, presenters draw ahead by Lead
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>
2026-10-09 02:29:37 +02:00
Meta Vens
450e371f74 Tests: the exponent pin reads the shipped designs through the catalog opener
AetherDb.Open refuses a catalog without the test global record the scoped copies lack.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 02:14:54 +02:00
Meta Vens
a91bd1f7cf Tests: the replay resets the drives to unnamed terms, not stripped ones, as they shipped
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>
2026-10-09 02:13:15 +02:00
Meta Vens
ba382a6d5c Merge eureka/aetheria-release-modifier-subtypes: modifiers reach a behaviour type and its subtypes 2026-10-09 02:12:41 +02:00
Meta Vens
651f5cdc4f Tests: CB-R1 counts every Quality term on a non-flat stat and rejects a role named on a flat one
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>
2026-10-09 01:59:26 +02:00
Meta Vens
9744d3969f Roles backfill: the exponent precedent is read before any target changes; the replay sees exponents and a one-of-two-roles seller
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>
2026-10-09 01:59:25 +02:00
Meta Vens
d7ee26d389 Tests: the replay reads the shipped designs and resets through the scoped registry before the catalog gains the sibling record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 00:36:45 +02:00
Meta Vens
2843358430 Tests: a names-only replay, so apply still lands designs when no seller changes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 00:24:58 +02:00
Meta Vens
94f4a9872c Roles backfill: separate the null and map checks (definite assignment survives mutation)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 00:11:04 +02:00
Meta Vens
e97968e271 Roles backfill: read each stat with as, so Stryker can mutate the command
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-09 00:02:46 +02:00
Meta Vens
80b51d63ea Catalog: roles-backfill apply re-run (6 designs name their unnamed Quality terms)
Produced by `AetherDb roles-backfill apply` on Yggdrasil over the previous catalog blob (3d531aff). Dry run:

  DeathCluster  (Weapon/Ballistic)  roles [barrel, feed mechanism]
      AutoWeaponData.Count            12 -> 12..15  feed mechanism ^1
  Flak Gun  (Weapon/Ballistic)  roles [barrel, feed mechanism]
      AutoWeaponData.Count            6 -> 6..8  feed mechanism ^1
  GT 3K  (Weapon/Launcher)  roles [guidance system, thruster, warhead]
      LauncherData.MinRange         500 -> 500..50  guidance system ^1.75
  plight  (Weapon/Energy)  roles [focusing array, power coupling]
      ChargedWeaponData.DamageSpread     1 -> 1..3.3  focusing array ^1.25
  MoveOnPro  (Reactor)  roles [core, regulator]
      StatModifierData.Modifier         1.1 -> 1.1..1.25  core ^1
  MoveOnPro Station Reactor  (Reactor)  roles [core, regulator]
      StatModifierData.Modifier         1.1 -> 1.1..1.25  core ^1

6 design(s) and 0 product(s) to author.
Dry run. Pass "apply" to land them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 23:50:35 +02:00
Meta Vens
c5ce2b6409 Tests: the replay leaves Small Drive's sellers as they shipped
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 23:50:14 +02:00
Meta Vens
d2f4061769 Tests: fix the broken join string in the catalog roles test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 23:48:23 +02:00
Meta Vens
6218f9fdc1 Roles backfill: Count and MinRange take a role but are never ranged; fix a broken string in the catalog test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 23:47:54 +02:00
Meta Vens
2e1c2c439b Tests: CB-R1 enforced whole, backfill replay on a scratch catalog, envelope and operability read the catalog
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>
2026-10-08 23:46:28 +02:00
Meta Vens
6a1eb68ddb Roles backfill: one role map per design, the six unnamed non-flat stats named, RolesBackfill takes a root
RoleMapFor answers for the Mine Launcher (MineLayerRoles) so roles-migrate and roles-backfill no longer
disagree on it; BackfillMapFor is deleted. Count, MinRange, DamageSpread and the reactor Modifier join their
kind maps, and the backfill points a varying stat's unnamed Quality term at its role without touching its
range. DeathCluster, Flak Gun, GT 3K, plight and both MoveOnPros join the backfill set (CB-R1 forces them).
RolesBackfill(apply, root) mirrors PiratesFaction so tests can replay it on a scratch catalog.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 23:46:26 +02:00
Meta Vens
257a8a4795 Sim speed fix: scripted poses are not drawn ahead; a step cannot reset its clock; DrawAhead.Time deleted
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>
2026-10-08 23:39:30 +02:00
Meta Vens
56f7162923 Merge emoji-font into master 2026-10-08 23:37:09 +02:00
Meta Vens
a7f801c4b9 Subtype modifier tests: deactivate the ship before equipping the guns
TryEquip refuses on a deployed ship.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:54:11 +02:00
Meta Vens
544807bb85 PiratesRecordTests: a Pirates rebrand unit titles and brands as its own product through the merged lot-product code
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:50:12 +02:00
Meta Vens
162e60889d Merge lot-product: a lot records its product 2026-10-08 22:49:08 +02:00
Meta Vens
37f40dfdd7 Emoji routing: the global fallback is the only route; the check observes it
EmojiFont.Build leaves TMP's emoji fallback list empty. EmojiCheck fails when that list is non-empty,
when the global fallback lacks Emoji.asset, or when a glyph is served by a font other than Emoji.asset
or the body font; reads the Pirates product names from the shipped catalog; renders the
emoji-test.txt corpus and reports what Twemoji lacks; counts only used atlas pages (TMP doubles the
array capacity, so trailing slots are null by design).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:45:51 +02:00
Meta Vens
8d2b18bb17 Emoji corpus from Unicode's emoji-test.txt; lock records interpreter and container
1400 single code points (the 2 and 3 digit ones included), Twemoji lacks none; font sha256
unchanged (reproduced in python:3.13-slim on Yggdrasil).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:45:48 +02:00
Meta Vens
8e73b54271 README: Twemoji CC BY 4.0 attribution
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:45:46 +02:00
Meta Vens
303f73e19f Tests: the Longinus envelope's flank sides are each Talaria's own thrust
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>
2026-10-08 22:39:21 +02:00
Meta Vens
f3550b67a4 Tests: roles-backfill fallout (Tractor Beam has no stat, Longinus fitted by name)
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>
2026-10-08 22:26:34 +02:00
Meta Vens
b5ff1ae260 Map: ships add-on frame r5, authoring without the repo
Probes B1-B9, the owner answer (published AetherDb), the r5 authority map
and rationale from the imagination-addon-frame pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:25:34 +02:00
Meta Vens
017da88334 Catalog: roles-backfill apply (6 designs, 6 products)
Output of `AetherDb roles-backfill apply` on origin/master 325ef4bc's catalog, run on
Yggdrasil at 54999a64. Dry run: Autocannon, LRMM72, SRMM72, Mine Launcher, Large Drive
and Small Drive gain roles and quality ranges; Autocannon (Zhestokost, Pirates),
LRMM72 (R&D), SRMM72 (DME), Mine Launcher (DME) and True North (Lightsail) author their
ProductRoles. A replay prints "already authored". At merge, take master's catalog and
rerun `AetherDb roles-backfill apply`.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:11:52 +02:00
Meta Vens
54999a642b Roles backfill: AetherDb command and catalog role tests (CB-R1)
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>
2026-10-08 22:09:18 +02:00
Meta Vens
e7375d54a1 Map: consumables (host fix, supply, throttle lock, vapour cloud)
Body facts CC1-CC12, rules CS-R1..CS-R4 and rationale from the
imagination-consumables pass; specs and questions are in the mind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:06:21 +02:00
Meta Vens
851476bc23 Emoji font script: pin Unicode emoji-test.txt, refuse outside the pinned container
The corpus now derives from emoji-test.txt (sha256 pinned), keeps single code points of any digit
count, and lists the emoji Twemoji lacks. The script runs only on linux, Python 3.13, image
python:3.13-slim and records those in the lock; identical pins with a different font exit 1 and
leave the committed font and lock untouched.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:05:09 +02:00
Meta Vens
99f0005c8a Merge origin/master (325ef4bc, pirates-record) into the emoji-font branch
Mechanical merge; this cut changes no catalog.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 22:03:04 +02:00
Meta Vens
7ee40255ca Modifiers reach a behaviour type and its subtypes: TargetsOf matches assignable types
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>
2026-10-08 22:01:47 +02:00
Meta Vens
e389e3972c Map: catalog breadth (weapon matrix, roles backfill, stat-boosting gear)
Body facts CB1-CB12, rules CB-R1..CB-R5 and rationale from the
imagination-catalog-breadth pass; specs and questions are in the mind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:57:21 +02:00
Meta Vens
325ef4bc1a Catalog: replay pirates-faction apply on master's catalog
Master's catalog (LFS 5ecf375f: PD gear, Mine Launcher, retirements) differs from this
branch's base, so the branch's blob was not taken. AetherDb pirates-faction apply was rerun
on master's catalog (merged tool, Yggdrasil container): the Pirates faction and eight
emoji-named products authored; catalog 5ecf375f -> 32a2e401 (12712398 bytes); a second run
reports the faction already exists and the blob is byte-identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 21:41:45 +02:00
Meta Vens
2c065937ee Merge origin/eureka/aetheria-release-pirates-record (8e51016f) into master
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>
2026-10-08 21:37:22 +02:00
Meta Vens
cff4e0ffa7 Sim speed: the exact-step frame stays under the hitch clamp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:01:27 +02:00
Meta Vens
090b6d18dc Sim speed: tests for the survivors Stryker found (thruster turn, tilted draw, exact step)
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>
2026-10-08 21:00:16 +02:00
Meta Vens
a8f71d463b Catalog: replay pd-gear apply on master's catalog
Master's catalog (LFS adba0389: Mine Launcher present, LonginusX and Traction retired)
differs from this branch's base, so the branch's catalog was not picked. AetherDb
pd-gear apply was rerun on master's catalog (merged tool): 3 designs and 11 products
authored, a second run reports it already authored, dangling reports 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:56:56 +02:00
Meta Vens
d17fe3a410 Merge origin/master (13a6b4f5, gear-without-presence and retire-longinusx) into eureka/aetheria-release-pd-gear
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
2026-10-08 19:51:53 +02:00
Meta Vens
07dcb580c3 test_hull_grid: pin point-in-triangle sides, sample positions, bound samples, single triangles and messages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:48:32 +02:00
Meta Vens
a9ce0bbc42 test_hull_grid: load hull_grid under its repo-rooted dotted name so mutmut can attribute kills
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:43:15 +02:00
Meta Vens
8e51016f23 PiratesFactionCommandTests: flush the name-file removal; tolerate a null empty role list
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 19:39:54 +02:00
Meta Vens
13a6b4f5b8 Catalog: replay retire-longinusx apply on master's catalog
Master's catalog (LFS 9e75d9a4, carrying the Mine Launcher and the gear-without-presence
merge base) differed from this branch's base, so the branch's catalog was not picked.
AetherDb retire-longinusx apply was rerun on master's catalog (tool as of 8038b46a plus
origin/master): the dry run listed the same four records (HullData LonginusX, GearData
Traction, their two FactionProductData), a second apply is refused, dangling reports 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:38:33 +02:00
Meta Vens
a308a7d8ea Add-on: New Ship, Flip Nose, Rasterise Hull and a Grid object; Source and Generated never exported
New Ship creates the ship .cc, binds through the one shared binding, moves the meshes into Source
under a Ship Root, turns them nose to -Y and sizes them. Rasterise is the only writer of
aetheria.grid_origin; Load, Save and Rasterise redraw the Grid.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:35:47 +02:00
Meta Vens
922928ebe7 Ship grid: hull_grid.py holds the cell arithmetic and the silhouette rasteriser, importable without Blender
cell_centre and cell_at map a cell to and from the Ship Root frame through a stored grid_origin;
rasterise turns top-down triangles into column-major cells (4x4 samples, half occupies, 32 cells
per axis at most).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:35:46 +02:00
Meta Vens
1c549325f9 Generate the Twemoji colour font, build Emoji.asset and route TMP's emoji fallback to it
Assets/Fonts/Emoji/Twemoji.ttf is fetch_emoji_font.py's output for jdecked/twemoji
v17.0.3 (nanoemoji 0.16.0, glyf_colr_0), reproduced bit-identically by two
independent runs on Yggdrasil; the lock pins source and font sha256. EmojiFont.Build
wrote Emoji.asset (dynamic, COLOR, multi-atlas) and TMP Settings' emoji fallback list,
global fallback entry and empty default sprite asset. EmojiCheck.Run: 1425 single
code points and the eight Pirates names render with no missing code point. CC BY 4.0
attribution ships in Assets/Fonts/Emoji/LICENSE.txt. Builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:34:49 +02:00
Meta Vens
38f7d73823 Sim speed: Entity.TurnRate's comment names no presenter
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 19:16:10 +02:00
Meta Vens
b385c65194 PiratesFactionCommandTests: pin the faction's fields, the eight products' designs, descriptions and roles, and the missing name file
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 19:15:37 +02:00
Meta Vens
ec081b9b6d Brand: ItemData.Get already refuses an unset ref; drop the duplicate IsSet guard
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>
2026-10-08 19:04:09 +02:00
Meta Vens
284231f4c1 Merge origin/master (2403a5f3, gear-without-presence) into eureka/aetheria-release-retire-longinusx
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
2026-10-08 18:59:38 +02:00
Meta Vens
8cb53049aa PiratesFactionCommandTests: strip the copy through a shipped-assembly registry, then seed the test global AetherDb.Open demands
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 18:53:18 +02:00
Meta Vens
b3d1e92904 FlightTests: the patrolling fixture starts far from its circuit point
At distance 0 MoveToOrbit hands back to patrol every tick and the patrol
state's unconditional transition wins over the combat interrupt, so no
combat transition was ever reachable in the fixture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:52:43 +02:00
Meta Vens
4e1b4882d4 Add the emoji font pipeline: pinned Twemoji fetch, font builder, rendering check
tools/emoji/fetch_emoji_font.py builds Assets/Fonts/Emoji/Twemoji.ttf from the
pinned jdecked/twemoji release with nanoemoji (glyf_colr_0); EmojiFont.Build is
the one writer of Emoji.asset and TMP Settings' emoji routing; EmojiCheck.Run
renders every single-code-point emoji and the Pirates names through TMP. The
generated font, lock and asset land in the next commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:43:39 +02:00
Meta Vens
4d64966d04 Sim speed: the drawn turn goes the way the step turned; the history test fires both ships
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>
2026-10-08 18:41:29 +02:00
Meta Vens
cc83f5adda Packages in the tree: LFS rules for GameData/Mods, and the test fixture boots the catalog the game boots
The fixture resolves GameData/Mods through ShipModCatalog.ResolveCatalog once per test process and throws on any
excluded package, so a broken first-party package fails the suite. With no GameData/Mods it is the shipped catalog,
unchanged. Builds and tests not yet run on this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:35:50 +02:00
Meta Vens
2403a5f393 Merge origin/master (594d3477) into eureka/aetheria-release-gear-without-presence
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>
2026-10-08 18:33:40 +02:00
Meta Vens
a2ad79a68e FlightTests: combat transitions are looked for across the patrol sub-states' own hand-overs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:33:31 +02:00
Meta Vens
c1b83e84e5 FlightTests: the combat transition tests give the pilot a track it sees
Entity clears a target its pilot does not see; the earlier commit set one
without perception, so the pilot never entered combat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:31:32 +02:00
Meta Vens
0a57e417bd Catalog: pirates-faction apply lands the Pirates and eight emoji-named products
Operator approved the dry run as shown (ruling pirates-record-apply). Dry run output:

New faction "Pirates": influence 3, names "pleiades", allegiance 1.0 to 12 factions.
  colours: primary (0.42, 0.40, 0.37) primer grey, secondary (1.00, 0.45, 0.05) hazard orange
  A loose coalition of crews and hidden docks moving people and goods outside official control. No command, no common law: possession has a maintenance schedule.

New products (8):
  🫳🔫  [U+1FAF3 U+1F52B]
    design WeaponItemData "Autocannon" (made by Zhestokost), roles []
    "Serial number filed off. Still shoots."
  🪦🤠  [U+1FAA6 U+1F920]
    design WeaponItemData "Earp" (made by AU), roles [barrel, feed mechanism]
    "The previous owner had no further use for it."
  🧾🚫  [U+1F9FE U+1F6AB]
    design WeaponItemData "FastBlast+-" (made by NiteLife), roles [focusing array, power coupling]
    "Warranty void where prohibited, which is everywhere."
  🎨🙈  [U+1F3A8 U+1F648]
    design WeaponItemData "6k Shooter" (made by Zhestokost), roles [barrel, feed mechanism]
    "The logo underneath is somebody else's problem."
  🔥  [U+1F525]
    design WeaponItemData "scorched void policy" (made by DME), roles [guidance system, thruster, warhead]
    "Turns out we did start the fire after all."
  👀🎯  [U+1F440 U+1F3AF]
    design GearData "Targeting Computer" (made by Finch, Lucent, NiteLife), roles [processor, array]
    "Somebody else's eyes. They still work."
  🔑🏃💨  [U+1F511 U+1F3C3 U+1F4A8]
    design GearData "Small Drive" (made by Lightsail), roles [injector, nozzle]
    "Hotwired. Do not ask about the ignition."
  📦🤫  [U+1F4E6 U+1F92B]
    design CargoBayData "Store-All Plus" (made by Lightsail), roles []
    "Contents not as declared."

Dry run. Pass "apply" to land the Pirates faction and 8 products.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 18:29:23 +02:00
Meta Vens
c4bd6e153e Sim speed: one SimClock steps the zone; presenters draw ahead by Lead
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>
2026-10-08 18:26:02 +02:00
Meta Vens
59bc0e556c Delete the EmojiOne sample sprite asset, its sheet and attribution
Sixteen faces nothing references but TMP Settings (E3); EmojiOne art is not
openly licensed. TMP Settings still names the asset until EmojiFont.Build
rewrites its emoji routing, so this commit leaves a dangling reference and the
next commits land the font that replaces it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:21:50 +02:00
Meta Vens
78755fd176 pirates-faction: callable on a root, prints its colours; tests pin dry run, idempotence, conflict and missing design
Not yet built when committed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 18:16:10 +02:00
Meta Vens
1fea9cd2e1 FlightTests: pin the executor's combat and root transitions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:13:50 +02:00
Meta Vens
f91f658ad2 Flight: a member that cannot see the engaged track steers on its bearing
The member kept Target to its own sensors but fell back to patrol while a
flightmate fought; it now follows the engaged track as it followed the
hailed one (ruling shared-track-bearing-only: a bearing, never targeting data).

Builds: not yet verified at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 18:13:48 +02:00
Meta Vens
594d347704 Merge origin/master (8a98aef5 sim-mines presenter) into eureka/aetheria-release-controls-mount-aim 2026-10-08 18:00:34 +02:00
Meta Vens
8a98aef5c1 Merge origin/master (ace81719 product-titles) into eureka/aetheria-release-sim-mines 2026-10-08 17:02:10 +02:00
Meta Vens
3d081f0d3b RunSaveTests: the product round-trip uses the fixture's one faction
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>
2026-10-08 16:58:55 +02:00
Meta Vens
978632bc26 A lot records its product: Lot.Product owns an item's brand, Brand reads it
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>
2026-10-08 16:45:56 +02:00
Meta Vens
675e22d735 Operability test: assert performance above the online threshold, not above zero
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>
2026-10-08 16:33:31 +02:00
Meta Vens
96e96319c8 Merge origin/master (bd46f942 boss-gate, 1476cfd0 map docs) into eureka/aetheria-release-sim-mines 2026-10-08 16:31:36 +02:00
Meta Vens
e95116b670 Tests: removal order, per-faction flights, zone tick, exponent margin
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 16:30:34 +02:00
Meta Vens
ace8171929 Merge origin/master into eureka/aetheria-release-product-titles 2026-10-08 16:27:49 +02:00
Meta Vens
7217112873 FlightTests: a patrolling pilot never falls back to the root state
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 16:21:37 +02:00
Meta Vens
290b34331a Minion: a task change leaves its own state only; the walk no longer crosses into the other task's states
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 16:20:33 +02:00
Meta Vens
c3c6d12db8 FlightTests: boundary, selection, trespass, standoff and task-change pins
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 16:12:53 +02:00
Meta Vens
32b14b966b Pin ManufacturerPreference: neutral without galaxy or faction, zero outside allegiance, table-bound distance
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>
2026-10-08 16:12:48 +02:00
Meta Vens
2c7c20607f Tests: pin the PD designs' authored stats, the no-maker-name rule, and TrackingRate through the catalog design
PdGearStatsAreAuthored reads the shipped catalog and pins every authored value of the three designs against the spec
derivation (ammo draw, velocity, visibility, range, pellet count, heat, descriptions and the rest). PdDesignsCarryNoMakerName
enumerates the makers from the catalog and rejects any in a PD design's name or description. PdGunHoldsASpeedDemon now sets
the catalog design's authored Tracking on the fixture weapon and asks FireControl.TrackingRate, instead of recomputing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 16:01:01 +02:00
Meta Vens
847e5eabf2 SolutionTests: compare the subject by reference so a failing assert does not format the entity graph
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:54:43 +02:00
Meta Vens
1476cfd0e0 Map: catalog growth, generic designs and branded products
Folds the catalog-growth addendum and the emoji-pirates product facts into a
new section: probes CG1-CG12 and LP1-LP9, the maker profile, PD product,
generic-name and weapon product-line tables, the model page rows (Title is
the one owner of an item's title; DisplayName is not a thing) and rationale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:42:12 +02:00
Meta Vens
c8376c354e Map: munition evasion core, mount term and autofire seams
Folds the munitions-autofire addendum into Missiles and point defense:
probes MA1-12, the munition Track and autofire-subject model page row
changes, and the rationale for the evasion core, the split cuts and the
close-crosser divert test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:40:53 +02:00
Meta Vens
573aae7e90 ItemTitleTests: Upsert already returns the faction ref (previous commit did not build)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:39:51 +02:00
Meta Vens
0e39a7f058 Map: faction-play re-anchor on 4d664b53 and the prelude retirement
Folds the faction-prelude addendum: faction-play probes BS1-3 and FP1-14
under Faction play, prelude probes PR1-11 and their rationale under Demo
scope, and the changed model page rows in both sections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:39:50 +02:00
Meta Vens
4a38634e53 Map: full emoji body facts and model page rows
Folds the emoji section of the emoji-pirates addendum into Demo scope:
TextMesh Pro probes E1-E10, the font-asset rationale and rejected
alternatives, and the emoji and product model page rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:38:58 +02:00
Meta Vens
658e25054b Map: demo hulls, the Pirates record and the derived boss hull
Folds the demo-hulls and emoji-pirates (Pirates record r2, several package
products per hull) addenda into Demo scope: body facts H1-H11, the Pirates
record and product tables, the boss-hull rationale and the model page rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:38:15 +02:00
Meta Vens
7e400543b7 Fix the new pins: an unfused layer lays nothing, so the mine-layer exemption is pinned at the gate; decoy lot in the ledger
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:31:50 +02:00
Meta Vens
7c211cee3c ItemTitleTests: pin the maker-without-product and crafted-commodity arms of Title
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:30:49 +02:00
Meta Vens
8761b3707f Loot scan label and FIRE CONTROL overlay read Title, not the design name
Every item-title display site now routes through ItemManager.Title. The grep
for design-name reads under Assets/Scripts outside ServerShared leaves only
log lines, exception text, console parsing and the Type row.
Does not build-verified yet; the Unity compile runs at the end of the batch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:30:48 +02:00
Meta Vens
24fb38496f Catalog: the Mine Launcher's heat envelope in kelvin (173.15..473.15, optimum 249.65, plateau 36)
Authored by AetherDb mine-launcher apply from the 532be3a5 catalog; the new blob is 9e75d9a4 (LFS).
Fixes the zero performance at a hull's starting 280 K; ShippedWeaponOperabilityTests is green from here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:24:38 +02:00
Meta Vens
b38589a1b4 Pin the mine-layer gate exemption and Solve's target argument (Soul s1 findings)
AMineLayerLaysWithTheAimOutsideItsArc: an unfused mine layer passes ArcPermitsFire and lays with the aim outside
its arc. SolveFliesToTheTargetItIsGiven: Solve flies to the decoy it is passed, not the designated target.
ATargetOutOfArcGivesNoSolution also asserts the subject of a designated target out of arc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:21:20 +02:00
Meta Vens
9e86bcd43d AetherDb mine-launcher: escape the newline in the two messages (baf90d34 did not compile)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:10:37 +02:00
Meta Vens
baf90d34c9 Mine Launcher heat in kelvin; every shipped weapon must perform at a hull's starting temperature
AetherDb mine-launcher now corrects an already authored launcher to 173.15..473.15 K (optimum 249.65, plateau 36,
the sibling weapon's) and authors new ones the same way. Entity.StartingCellTemperature names the 280 the hull
cells start at, and ShippedWeaponOperabilityTests reads it against the shipped catalog. The catalog blob follows
in the next commit, so the test is red at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:04:16 +02:00
Meta Vens
7262429a60 Delete WireMines: the run-once editor tool named the .sbsar material guids (clean-break-from-substance)
It served its single run; Mine.prefab and the scene wiring are committed and reference plain materials only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:04:14 +02:00
Meta Vens
e16288bfcf Pirates record: the demo tests read the shipped faction; tests pin its eight emoji-named products
Deletes the AddPirates stand-in and its 21 calls. DemoTerminus_missing_cast_refused removes the shipped record from its scratch
copy first. LoadoutGenerator.HasHome is public so the catalog test asks production's own home rule. These tests are red on
a catalog without the Pirates: the catalog commit (pirates-faction apply) follows separately.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:50:48 +02:00
Meta Vens
1f83235919 Tests: compare record keys with Equals (the previous commit does not build)
CultRecordKey has no == operator. 13d26df2 fails to compile for that reason.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:49:58 +02:00
Meta Vens
13d26df2d5 Tests: PdGearIsAuthored, PdGunsHaveHomes, PdGunHoldsASpeedDemon
Pins the authored PD designs (hardpoint, shape, Tracking 40/40/20, at least three
products each, no maker twice, none by Miss Terri's), that Djinni and Longinus
hardpoints take them, and that the PD gun follows a 150 m/s crosser at 200 m
where ClearPath does not. Built and run in the next job.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:45:25 +02:00
Meta Vens
bb175f2bc4 Catalog: pd-gear apply output, 3 designs and 11 products
Applied with: AetherDb pd-gear apply (dry-run text below), on Yggdrasil against a copy of the base catalog.

New designs:
  Point Defense Gun    Ballistic 1x1  mass 40  price 80000  durability 60  modifiers RapidFire
      damage 1.5-4  count 1-1  range 300-550  cooldown 0.06-0.025  spread 1-0.3  velocity 1100-1600
      energy 0.4-0.2  heat 40-15  visibility 400-150  ammo Ammo  magazine 250  reload 3  tracking 40  roles [barrel, feed mechanism]
      "Close-in defence gun: a hose of light rounds."
  Point Defense Laser  Energy    1x1  mass 30  price 110000  durability 30  modifiers None
      damage 5-12  count 1-1  range 400-750  cooldown 0.2-0.1  spread 0.05-0  velocity 0-0
      energy 6-10  heat 300-150  visibility 300-100  ammo none  magazine 1  reload 1  tracking 40  roles [focusing array, power coupling]
      "Close-in defence beam: quick, light, instant."
  Flak Gun             Ballistic 1x2  mass 120  price 180000  durability 80  modifiers Cluster
      damage 30-70  count 6-8  range 350-800  cooldown 0.6-0.35  spread 4-2  velocity 900-1300
      energy 1-0.5  heat 300-150  visibility 800-300  ammo Ammo  magazine 40  reload 4  tracking 20  roles [barrel, feed mechanism]
      "Small flak gun: a short-range pellet volley."

New products:
  Point Defense Gun -> "Waykeeper" by Lightsail, every role mean 0.55 dev 0.1: Freight first, questions later. Keeps a hauler's paint unscratched through a full salvo.
  Point Defense Gun -> "Rampart" by Zhestokost, every role mean 0.5 dev 0.08: A column does not dodge. It does not need to.
  Point Defense Gun -> "Swatter" by AU, every role mean 0.5 dev 0.12: Keeps the rocks and the rockets off your back while you work.
  Point Defense Gun -> "Catch-All" by R&D, every role mean 0.6 dev 0.15: Guaranteed to stop the missile!* *Missile defined as whatever it stops.
  Point Defense Laser -> "Glare" by Lucent, every role mean 0.6 dev 0.15: Every missile gets its moment in the spotlight. A short one.
  Point Defense Laser -> "Nightlight" by NiteLife, every role mean 0.55 dev 0.12: Lights out for anything with a warhead. Shares the bus with your blasters, so mind the meter.
  Point Defense Laser -> "Wren" by Finch, every role mean 0.65 dev 0.2: Small, quiet and quicker than it looks, most days.
  Point Defense Laser -> "Gnat" by Alakrita, every role mean 0.6 dev 0.14: Weighs less than your conscience and keeps the fast pass fast.
  Flak Gun -> "MFer" by Zhestokost, every role mean 0.5 dev 0.08: Our shrapnel turns your enemies into scrapnel.
  Flak Gun -> "Hailstorm" by AU, every role mean 0.5 dev 0.12: A wall of steel for crews who would rather not count missiles.
  Flak Gun -> "sky full of teeth" by DME, every role mean 0.55 dev 0.2: light it up/ shake it loose/ nothing gets through tonight

Dry run. Pass "apply" to author 3 designs and 11 products.

Replay after apply: Point-defence gear is already authored; nothing to do.

Tests (EvasionTrackingTests): PdGearIsAuthored, PdGunsHaveHomes, PdGunHoldsASpeedDemon. Not yet run when committed; the next job reports them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:45:09 +02:00
Meta Vens
7330058991 AetherDb: pirates-faction command authors the Pirates and eight emoji-named rebrands
Dry run unless given 'apply'. Not yet built when committed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:40:08 +02:00
Meta Vens
7e3c872f0f AetherDb: pd-gear command authors three generic PD designs and eleven branded products
Dry run prints every record; apply commits (the field-kinds pattern). Designs are
deep copies of ClearPath, Spectra and DeathCluster with only the cut-spec stats
overridden; branding lives in the eleven products. Catalog not yet applied in
this commit. Not yet compiled when committed; the next commit's job builds it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:38:45 +02:00
Meta Vens
c8c544f489 PatrolOrbitsState: compare the task by reference
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:35:00 +02:00
Meta Vens
7f700d3c78 Items are titled by their product: ItemManager.Title, read by every title site
Title derives the brand's product name and falls back to the design name.
The trade list, buy dialog and properties title read it; the product name
line leaves the properties body. Build not yet verified at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:34:47 +02:00
Meta Vens
7e121f282d Mine prefab and scene wiring: WireMines built Mine.prefab and assigned ZoneRenderer.MinePrefab
Unity 6000.3.24f1 batchmode; the three Substance materials fell back to the project's plain materials (Car Paint
Red, Car Paint Magenta, Steel) because .sbsar imports nothing in this Unity. Font-asset churn reverted.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:34:37 +02:00
Meta Vens
080dbed07d Catalog: doctrine-catalog apply (Zhestokost, Lucent Media, Aeronautics Unlimited)
Ran on Yggdrasil against the base catalog; the Pirates have no Faction record
(follow-up pirates-catalog-record), so their doctrine is not written. Miss
Terri's untouched.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:32:15 +02:00
Meta Vens
488c57050a Catalog: the Mine Launcher with a shape, a damage curve and a product that sells it
Supersedes the catalog blob of b60c695a (item without shape, curve or product, which broke six tests). The blob
is the file the verify job authored from the master catalog and ran 968 tests against.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:30:05 +02:00
Meta Vens
9978d28763 PatrolOrbitsState: arrival advances the circuit only while the pilot is still on its task
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:29:47 +02:00
Meta Vens
9e5c8de7d5 Top-speed test comment: drop the retired hull's name so the negative grep for it stays empty
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:27:37 +02:00
Meta Vens
4d29e0b33e WireMines: Substance materials fall back to the project's plain materials of the same finish
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:26:26 +02:00
Meta Vens
90462179b8 SteeringTests: Agent takes its RoleDoctrine
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:21:04 +02:00
Meta Vens
3b41267bee Mine Launcher: the 2021 damage curve; a mine layer is mountless in EveryCatalogGunTracks; script metas
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:20:13 +02:00
Meta Vens
8f42265de3 Faction play 1: typed doctrine on Faction and one flight per faction per zone
FactionDoctrine/RoleDoctrine (Faction key 17), Flight as the only writer of
members' Target and Task, hail/grace/compliance, FollowTask/FollowState,
agent removal on Entities removal, doctrine-catalog command, FlightTests.
Not yet built or run; verification follows in later commits.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:18:41 +02:00
Meta Vens
1937ea04fe ARPG scene: the RPM Display object and SchematicDisplay's stale drive references are gone
The RPM Display subtree (55 serialized objects) and the seven removed SchematicDisplay
fields in both instances (AetherDriveUi, the three RPM labels and fills). Removed by a
scripted edit of the scene YAML, not an editor re-save, to keep the diff to the
subtraction; Unity 6000.3.24f1 batchmode then opened the scene and compiled the project
with no error CS and no missing reference on either SchematicDisplay.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:15:49 +02:00
Meta Vens
5e0c0d44f8 Scenario fits: the Fire Control Array lies turned on interior cells (1,6)-(1,7)
Tools need interior hull cells (the shrunk shape); (0,4) is an edge cell. The 2x1 array
turned clockwise takes the free interior column beside the cockpit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:14:43 +02:00
Meta Vens
400db21399 MiningCut3Tests: pin a chunk's bearing as pose minus the shooter's position (Stryker survivor FireControl.cs:142)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:13:49 +02:00
Meta Vens
04d2947a80 Gear without presence: IsAvailable reaches by allegiance alone
Presence in the galaxy no longer gates gear (ruling gear-without-presence).
Delete the IsPrelude exception, Galaxy.ContainsFaction with its cache, and
the AetherDb loadout exclude-sellers mode that existed to exercise the
presence gate. An absent maker weighs as one jump beyond the farthest zone
the generator's zone reaches. Not yet verified; may not build.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:10:58 +02:00
Meta Vens
bd46f942bf Boss-gate tests: RunSave.Capture gained a credits parameter on master
Adapted the two boss-gate/demo-galaxy Capture call sites to pass 0 credits,
the value master's other tests pass when credits are not under test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:09:22 +02:00
Meta Vens
8b2147a5f7 Mine Launcher: a shape and a product that sells it; the blast-neutrality test exempts a mine layer; WireMines takes a Substance material by its path
The first catalog commit left the item shapeless and unsold; this commit's mine-launcher command fixes both. The
catalog blob committed before this one is superseded by the next commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:09:03 +02:00
Meta Vens
328f9513d7 Delete the transient retire-longinusx command now that the catalog has landed
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:04:52 +02:00
Meta Vens
2cfdc72853 Delete the aether drive: behaviour, union 12, hardpoint type, aggregates, settings, presenters, prefab
AetherDriveData and AetherDrive, Union(12) (now a retired-do-not-reuse comment, as 26 is),
HardpointType.AetherDrive (last member, nothing shifts), Ship's drive sets, aggregates and
Axis write, the five request-field rows, GameplaySettings Aether multipliers, ShipInstance's
drive particles, SchematicDisplay's RPM display and AetherDriveUi, the undock refusal's drive
clause, the drive prefab and material, and AetherDb's drive roles and brownout row. The
design is kept at parked/aether-drive.
Adds EveryShippedShipHullHasATopSpeed. ARPG.unity still holds stale serialized references to
the removed SchematicDisplay fields and the RPM Display object; the next commit removes them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 14:04:28 +02:00
Meta Vens
e3a457793b Merge eureka/aetheria-release-boss-gate (with eureka/aetheria-release-demo-galaxy) into master
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 14:03:32 +02:00
Meta Vens
4656857420 Catalog: HullData LonginusX, GearData Traction and their two FactionProductData are gone
Produced by AetherDb retire-longinusx apply on this branch's base catalog (63250cf2 in
the LFS store); dry run listed exactly the four records, a second apply is refused,
and AetherDb dangling reports 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:59:45 +02:00
Meta Vens
2226190d7a Scenario fits: the Fire Control Array sits on free Longinus cells (0,4)
The first relaying put it at (1,6), where its 2x1 footprint met the cockpit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:59:36 +02:00
Meta Vens
8038b46aec retire-longinusx: a record names the retiring ones only by a whole string, not by a substring
The first dry run was refused by NameFile USA, whose name list holds longer strings
containing the words. A reference is a string equal to the id or the name.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:57:31 +02:00
Meta Vens
7109ce9e57 retire-longinusx command: import its serializer namespace; keep the Python enum names equal to the enum until the enum member goes
The previous commit did not compile AetherDb (missing using) and dropped the
Python name while HardpointType.AetherDrive still existed, which ShipSchemaPinTests
pins. Both repaired; the name leaves with the enum member.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:55:55 +02:00
Meta Vens
ee24728d11 FireControlCut5Tests: a target ahead that is not designated is no solution; the second half fires on the free aim
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:52:30 +02:00
Meta Vens
b60c695a61 Catalog: the Mine Launcher item (one MineLayerData), authored by AetherDb mine-launcher apply
Dangling refs 0. Numbers are the 2021 record's; see the cut report's deviations.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:51:23 +02:00
Meta Vens
fb00f6687d Mines presented: MineInstance draws each Zone.Mines body; Mine Launcher catalog command; WireMines builds the prefab
MineInstance reads a Mine and draws it (latest sim body at the grid height, spin, real-time pulse by arming and
trigger); ZoneRenderer makes one per Zone.Mines add and plays the blast on remove; EntityInstance gives a mine
layer no effect manager. AetherDb mine-launcher authors the item; the catalog, prefab and scene wiring follow in
later commits, so this one does not build a playable mine (no MinePrefab yet).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:49:23 +02:00
Meta Vens
f53f45fdf1 AetherDb retire-longinusx: the one-shot that deletes the hull, the drive and their products
Dry run unless "apply". Refuses unless exactly the four records are present,
refuses when any other record's bytes name one of their ids or the names
LonginusX or Traction, and finds nothing on a second apply. Deleted again once
the catalog lands.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:47:23 +02:00
Meta Vens
bf17314765 Move every LonginusX consumer to the Longinus: scenarios, tests, tools, the starting hull
Duel, Arcs, Launcher Angles and Starved Reactor fit and place the Longinus
(thrusters, Core Power or MoveOnPro at (2,4), radiators relaid); the modes start
a Longinus (Settings.asset StartingHullName; the Aether multipliers leave it).
The drive's tests, its Steering Axis probe and its Brownout fixtures go with their
subject; ship_cc.py and the live-game checklist drop the drive and the hull.
The drive itself and the catalog records are deleted in the following commits.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:44:48 +02:00
Meta Vens
538b11b4ea Drop Broadside (no catalog hull has side-rotated gun hardpoints); fix Cut5 arc fixtures for solutions
Question aetheria-release❓broadside-hull-source is raised on the spec. The Cut5 arc tests now
aim astern so only a solution can fire the gun (the aim used to be zero, which is free fire).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:37:15 +02:00
Meta Vens
e103b90aea Fire on solutions: FireControl.Solution is each gun's one solution; the trigger fires on it without the aim
Bears is extracted from PFire; ArcPermitsFire passes on a fused gun, a solution, or a free aim in arc.
Solve flies along Solution's direction. ArticulationPoint loses its yaw clamp and follows a per-group
aim point placed from the group's solution. Arcs gets its new brief; Broadside is new.
Unverified: first commit of the cut, not yet built.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:25:53 +02:00
Meta Vens
4d664b537f EvasionTermTests: LookDirection became Aim and Ship.Turn is the only facing command
The merge brought tests that set Ship.LookDirection and relied on Ship.Update turning toward it. Master's helm split removed both. EvFace sets Aim and asks Steering.Toward for Turn each tick, the same law the old steering pass applied; the two multi-step loops now face per tick.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 22:33:16 +02:00
Meta Vens
179ab92abc Merge evasion-term: evasion is changes of vector plus a per-gun mount term; authored tracking rates in the catalog; the aether drive leaves the envelope
Soul gate closed at verdict cut-evasion-term.s5 (head 473a4bcc); remaining Low
test gaps are deferred to a follow-up. Merged under operator ruling
aetheria-release:ruling:completed-cuts-merge. Carries the migrated
GameData/Aetheria.cc (LFS sha256 63250cf2...7ae25); master did not change the
catalog.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 22:29:51 +02:00
Meta Vens
71894d1db1 Merge sim-mines: mines are free-floating sim bodies with hostile trigger and no leash
Soul gate closed at verdict cut-sim-mines.s2 (head 06efde6f; branch already contained master, so the merged tree is the verified head). Merged under aetheria-release:ruling:completed-cuts-merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:54:33 +02:00
Meta Vens
06efde6f51 MineTests: pin the layer's identity, the faction frozen at lay, and the blast disc as the trigger disc
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 21:17:41 +02:00
Meta Vens
231cb732e2 Merge origin/master (controls-helm) into sim-mines
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:36:32 +02:00
Meta Vens
0f568a018a Zone mine step: no empty-set fast path, one trigger scan; MineTests pin the turn with an oblique mount
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:17:47 +02:00
Meta Vens
df53360aa3 FloatingBodyTests: set Ship.Aim where the fixture set LookDirection
The helm split removed LookDirection. The ship-gravity test asserts only Velocity
after Update, so it needs no facing; Aim keeps the value the fixture carried
(Direction already defaults to the same +z facing).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:11:08 +02:00
Meta Vens
3fcdc20c00 Merge controls-helm: Ship.Turn is the only facing command; the helm split and face-the-aim
Soul gate closed at verdict cut-controls-helm.s3 (head b644fceb). Merged
under operator ruling aetheria-release:ruling:completed-cuts-merge.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:08:31 +02:00
Meta Vens
cbe975d9a9 MineTests: every delay is inclusive at its exact step
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:05:57 +02:00
Meta Vens
44cc356a05 MineTests: the launch angle is the mine's own dice; a mine layer ignores blast against range
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 20:05:34 +02:00
Meta Vens
473a4bcccd Evasion fix batch C: drop the unruled catalog thresholds, pin the jink price and the torque trim membership, give an unlimited gun on zero gear one meaning
- Delete ABigGunHitsABigShipAtRange and TheCatalogMeetsTheRuledOutcomes (rulings cshot-rainbowlite-rate, evasion-angular-velocity-r2).
- TheJinkIsForgivenPerShipInThePrice: HitProbability of two guns of different rates carries PDeviation(Evasion, Tracking(shooter)).
- TrackingRate: an unlimited gun is +infinity whatever the gear reads, not inf * 0 = NaN.
- EveryAggregateAndTheCompensationReadLiveThrust: trim membership read from the thrusters' torques, not Ship's private list.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:59:29 +02:00
Meta Vens
c100ba986f MineTests: a shield regenerates over the run, and a faction is not a catalog record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:55:19 +02:00
Meta Vens
23aa848315 Mines in the sim: a mine layer lays a free-floating mine body in Zone
MineLayerData (union 40) lays through InstantWeapon -> FireControl.Fire -> Lay;
Zone.Mines steps each mine as a KinematicBody after the entity loop, arms it,
triggers it on a hostile hull its blast disc touches (FireControl.Touches, the
coverage Detonate uses) and detonates it through FireControl.Detonate at the
fuse delay or lifetime. Hostile trigger, faction-blind blast, no owner leash.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:47:21 +02:00
Meta Vens
9f8b3f4536 Merge floating-bodies: the floating body loot and mines share, one gravity law in Zone
Soul gate closed at verdict cut-floating-bodies.s3, head 6299627b, under
operator ruling aetheria-release:ruling:completed-cuts-merge.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:19:27 +02:00
Meta Vens
a6484c2599 EvasionTermTests: the range fixture's guns follow anything, so the evasion tests price evasion and not the catalog's mount rates
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:18:28 +02:00
Meta Vens
b644fceb24 Turn bound has one owner, the actuators; pin the turn rate and the 90 degree boundary
Ship.Update no longer clamps Turn: Thruster.Axis saturates and AetherDrive.Axis
clamps, which is where the bound is enforced. TurnIsClampedToOne becomes
TheActuatorsBoundATurnBeyondOne and asserts the actuator bounds directly. The turn
rate is pinned against a value computed from each thruster's Torque, Thrust,
TorqueMultiplier and the hull's Mass; the behind-the-hull rule is probed at 85 and
95 degrees.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:11:34 +02:00
Meta Vens
cdaef1a098 EvasionTrackingTests: EveryCatalogGunTracks, TheCatalogMeetsTheRuledOutcomes, PlightHasItsRuledShape
Data checks over the migrated catalog; no value is restated and nothing derives a rate from Shape.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 18:57:54 +02:00
Meta Vens
846f836aac AetherDb: delete evasion-catalog now that the migrated catalog is the table's only copy
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 18:54:17 +02:00
Meta Vens
3d77f2e038 Catalog: every weapon's Tracking and plight's 1x2 Shape, by evasion-catalog apply
Rates are the authored table (ruling weapon-tracking-authored); launchers and guided weapons stay +infinity. plight takes Spectra's one-by-two Shape (ruling plight-shape).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 18:53:07 +02:00
Meta Vens
1d85e1d4da AetherDb: evasion-catalog, the literal per-weapon tracking table and plight's 1x2 Shape
One-shot, dry run unless apply, refuses a second apply. Deleted in its own commit after the catalog lands.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 18:52:47 +02:00
Meta Vens
6299627b72 FloatingBodyTests: pin Ship.Update's gravity line through a real ship in a real well
Ship at +x in an empty zone with a slope: velocity after Update(delta) equals the
3035230b ship law scaled by delta * 60, at 1/60 and 1/30. Fails on `-=` and on a
changed delta factor.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 18:49:20 +02:00
Meta Vens
db19ecfeb7 EvasionTrackingTests: the entity overload's offset is checked with the shooter away from the origin
Stryker survivor at FireControl.cs:211 (target.Position + source.Position) was invisible while the shooter sat at 0.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:43:21 +02:00
Meta Vens
4dea45bb19 FloatingBodyTests: the legacy drift table is keyed by the normal's length, not its square
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:43:08 +02:00
Meta Vens
6c15a33315 Tests: pin For's double mix against the single-xor collapse and Commit's | 1u seed bit
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:32:55 +02:00
Meta Vens
d62d44cb99 One gravity law in Zone: ships and floating bodies read Zone.GravityAcceleration
The law ships felt (normalize(f) * strength * (1/(1-|f|^2) - 1), gated at |f|^2 .001) is
now Zone.GravityAcceleration, per second via a 60 Hz reference rate; Ship.Update applies it
times delta, so ships push as before at 60 fps. Zone.GetForce's separate law is gone and
delegates to it. Floating-body drift at 60 fps now matches the legacy GridObject magnitude.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:32:53 +02:00
Meta Vens
97adf07aec TurnIsClampedToOne: say that the consumers clamp too
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:17:49 +02:00
Meta Vens
7d80af6dfe EvasionTrackingTests: both guns on the one shooter, at the origin at rest
A ship's targeting gear carries its own item quality, so Tracking(shooter) differs between two ships fitted alike:
the gun-times-ship comparison needs two designs on one ship. The gunner now carries FastBlast+- and ColdFire, and
the mount fixture puts it back at the origin so the sweep is the geometry the test states.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 17:02:52 +02:00
Meta Vens
2b7cf309d2 EvasionTermTests: EvLonginus carries the Targeting Computer at the generated Longinus's cell; the stop-jinking probe reads at a half-period of 0.5 s
Tool gear fits only interior hull cells and the Fire Control Array has no free one on a Longinus. The jink that
stops at t=3 s has been quiet longer than the 0.75 s window by t=4 s, so the Djinni reads 0 there: the jink is the
0.5 s half-period that was already used in the speed-demon rows.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:55:54 +02:00
Meta Vens
e5232ad9d3 EvasionTrackingTests: take the targeting gear offline through its durability, as the gear tests do
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:45:54 +02:00
Meta Vens
8e20617f5f AetherDrive: restore the Execute signature the drop commit deleted with Manoeuvre
e360ceeb removed one line too many (public override bool Execute), so the drop commit and its two successors do not
build. The file is now exactly the base minus the 24 lines of Manoeuvre.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:45:10 +02:00
Meta Vens
286a610b17 EvasionTrackingTests: the mount term's rules, with EvCross taking a velocity
AngularVelocityIsTransverseOverRange, TheMountHitsHalfAtItsRate, TrackingRateIsGunTimesShip,
LightAndHeavyGunsSplitOnAFastCloseCrosser, ABigGunHitsABigShipAtRange, TheJinkIsStillForgivenPerShip,
AShotFreezesItsMount, AnUnauthoredWeaponHasNoMountLimit. Rates are set on the loaded designs in code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:43:32 +02:00
Meta Vens
b6487afd95 FireControl: the mount factor, AngularVelocity, TrackingRate and PMount, in the price, the freeze, Inspect and the HUD
PMount(AngularVelocity(source, target), TrackingRate(weapon, source)) multiplies HitProbability after the pFire gate;
Fire freezes it into PendingShot.PFire; Inspect and the debug HUD show omega, rate and the factor. TrackingRate is the
one product of the gun's rate and the ship's gear (ruling tracking-per-gun). Tracking(Entity) in metres still alone
forgives the changes of vector (ruling jink-per-ship).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:40:00 +02:00
Meta Vens
8cd71ed6da WeaponData.Tracking and Weapon.Tracking: the gun's mount rate in degrees per second
Key 33 (first free across WeaponData and its subclasses), default positive infinity: an unauthored gun has a mount
that follows anything. The resolver's NaN fallback to Min yields +infinity for the degenerate lerp.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:39:59 +02:00
Meta Vens
e360ceeb27 Evasion r6: drop the aether drive from the envelope; the gemini fixtures fly thruster hulls
Ruling retire-longinusx. AetherDrive.Manoeuvre and the drive line in Ship.RecalculateEnvelope go: the envelope
sums thrusters only. TheDrivesReportReadsItsStateAndTheShipsSpeed, the EvGemini fixture and the drive-only asserts
are deleted. Sideways jinks and the shooters' target move to the generated Djinni; the gun platforms (FastBlast+-,
ColdFire) are EvLonginus, the Duel's guns on a Longinus. TheThreeShipsOrder becomes TheShipsOrder.

Not built or run on its own: verified together with the mount term at the head.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:39:45 +02:00
Meta Vens
6833f5aa7f TurnIsClampedToOne: compare against the starting heading, not the hull's own
The reference-turn assertion measured the angle between the hull and itself.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:35:00 +02:00
Meta Vens
b0d7ccb4f8 Pin the agent steering writes and the helm rules Soul found unpinned
Holding heading after a state stops piloting (SteeringTests, and a Minion that
loses its target), Combat leading a moving target, MoveTo's Aim and Turn in the
low-delta regime, the behind-the-hull threshold, the Turn clamp, and the hold
branch clearing a stale MovementDirection.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:23:56 +02:00
Meta Vens
636ffc92bd Agent.Update writes Turn every tick, so a state that does not pilot holds the hull
Turn is a rate. Combat wrote it each tick and nothing wrote it after the Minion
returned to its root state, so the hull kept the last rate and spun without end.
The pilot tick now writes zero before the state runs; a piloting state overwrites
it with its demand. One writer per tick, no reset in Ship.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:23:55 +02:00
Meta Vens
593958ec2d EvasionTermTests: one-way ships are probed at 160 degrees, not the knife-edge at 180 where the two turn directions tie
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:21:41 +02:00
Meta Vens
ee5f5cbb49 EvasionTermTests: reach for ships that can thrust one way only, over windows long enough that the long way round is best
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 16:19:49 +02:00
Meta Vens
5919c31948 FloatingBodyTests: pin one step's position and the zero-seed remap, the two Stryker survivors
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 15:49:14 +02:00
Meta Vens
ebfd4cbd73 Merge retire-unity-mines: the Unity mine, MineManager and the Mine Launcher prefab go; mines return as sim bodies
Soul gate closed at verdict cut-retire-unity-mines.s1 (head 17f5eb7d). Merged under aetheria-release:ruling:completed-cuts-merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:25:39 +02:00
Meta Vens
83bf1af106 FloatingBodyTests: launch-speed pin sized to the step's position error bound
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 15:03:12 +02:00
Meta Vens
17f5eb7d8c Retire the Unity mine: Mine, MineManager, the Mine Launcher prefab and ShieldManager's mine branch
Operator ruling mines-back-in-sim-asap: delete now, return as a simulation body.
Mesh, materials and BigExplosion stay for the sim-mines presenter. GridObject
stays for the pickups until loot-1 r2. Comments in FireControl.Detonate and
HullCollider drop the deleted callers. Builds not yet verified at this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 15:01:39 +02:00
Meta Vens
38c47d80ed Floating bodies: FloatingBodyId, KinematicBody.Step, Zone.NextBodyId and the three drift settings
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 14:52:12 +02:00
Meta Vens
9116946874 SimulationDice: fmix32 moves out of FireControl, with the structured per-zone dice stream
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 14:52:10 +02:00
Meta Vens
3035230bf9 Map: mines in the sim, the shared floating body, and the old mine's behaviour as body facts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:49:51 +02:00
Meta Vens
78daa12db5 EvasionTermTests: reach all the way round and for a ship that cannot turn, the face form past a right angle, the degenerate guards of the term and the track
Stryker on the batch's ranges left the corner faces, the wrap, the no-turn box support, the time before a face may thrust,
the zero line of sight and heading, the Observe guards and thresholds, and a step of no time alive; each is pinned here.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 14:40:41 +02:00
Meta Vens
5681e64c52 SteeringTests: pin Accelerate's thresholds, its velocity-error term and the exact-astern sign
Stryker survivors on the first run: the low-delta branches of Accelerate had no behavioural test,
the velocity error was only exercised from rest, and astern was asserted by magnitude only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 14:38:15 +02:00
Meta Vens
35ea0da431 Map: sim speed r2, the census of Unity-owned sim facts and their owners, body facts T11-T14, drawing ahead
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:30:31 +02:00
Meta Vens
6d427b7aa9 Map: sim speed, one fixed-step SimClock owning the scale, body facts T1-T10, for sim-speed r1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:03:31 +02:00
Meta Vens
eafc4352a1 Map: retiring the LonginusX and parking the aether drive, body facts R1-R6, for retire-longinusx r1 and evasion-term r6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:57:05 +02:00
Meta Vens
516af3e5c1 Map: authored per-weapon tracking table, top speed on the hull (M32 corrected), plight provenance, for evasion-term r5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:33:08 +02:00
Meta Vens
1c73f8e419 Map: evasion's mount term (angular velocity against tracking rate), the footprint ladder, body facts M30-M33, for evasion-term r4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:07:46 +02:00
Meta Vens
e494454941 EvasionTermTests: the diagonal jink fixture asks for a spread of 3 m, not 5 (it reads 4.997)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:47:31 +02:00
Meta Vens
8c5eb5b7c6 Helm split: the Unity-regenerated input wrapper and the metas for Steering and HelmInput
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:44:21 +02:00
Meta Vens
9beb5e9c9f SteeringTests: measure the rotation over a short window, before it can wrap
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:43:29 +02:00
Meta Vens
1458dbb676 SteeringTests: report the measured turn in the rotation test's failure
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:41:33 +02:00
Meta Vens
0ca7a7c98e EvasionTermTests: the forgetting probe jinks inside the window; the aggregate tolerance reads a negative torque
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:39:58 +02:00
Meta Vens
c4357eeee6 Map: tracking per gun, with body facts M27-M29, for evasion-term r3
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:35:42 +02:00
Meta Vens
5960beb3e7 Helm split, player input: A/D turn, Q/E strafe, Shift holds and Caps Lock latches face-the-aim
The player writes Ship.Turn through HelmInput.Demand, and the FACE AIM mark shows while the latch is
on. Bindings keep their ids so saved overrides still apply; Face Aim and Toggle Face Aim are new
actions, and the wrapper is regenerated to match the asset.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:33:22 +02:00
Meta Vens
c86423936e Helm split, simulation: Ship.Turn is the only facing command; LookDirection becomes Aim
Ship.Update reads Turn and feeds the rotation thrusters and aether drives; it no longer reads the
look direction or snaps Direction toward it. Steering.Toward is the one law from heading to demand
(a heading astern now turns at full demand). HelmInput owns the face-the-aim state. Accelerate,
Combat and MoveTo write Turn through Steering.Toward. Entity.LookDirection is renamed Aim in the
simulation, the Unity readers and the tests. Unity player input follows in the next commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:33:20 +02:00
Meta Vens
5f404d5094 EvasionTermTests: pin reach geometry, the oblique line of sight, the track window and forgetting, the drive's inputs and the live-thrust readers
Reach against a brute-force turn search (M26) on five envelopes, two windows, an oblique heading; a line of sight at
30/45/120/200 degrees rotated not reflected; evasion from the heading, not the velocity; the entity's track at the
solution window; the drive's offline gate and speed efficiency; the forget time as a function of the window, coasting
and burning; every Ship thrust aggregate and the strafe compensation against live thrust. TheSpeedDemonNumbers now
states what the code gives, to 0.5 percent.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 12:32:58 +02:00
Meta Vens
cf0979481f Merge station-services: sell and repair at a docked station, priced by one engine-free owner
Soul gate closed at verdict cut-station-services.s4 (head daa9a839). Merged under operator ruling aetheria-release:ruling:completed-cuts-merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:24:38 +02:00
Meta Vens
2a5fc00bcd Boss gate tests: the no-boss exit zone is unpacked with the items that generated it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 06:49:39 +02:00
Meta Vens
c8d40eaf74 Boss gate: the exit gate fails closed; it opens only for a boss that spawned and then died
ZonePack.BossSpawned records the spawn, since a dead boss leaves no entity. RunGoal.ExitOpen requires it, so an exit zone
without a boss stays sealed, and ZoneGenerator logs that configuration by field and code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 06:41:33 +02:00
Meta Vens
46b2850165 ASpeedAboveTheLimitIsNotEvasion reads every tick after the clamp: the track forgets within a window
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 06:02:34 +02:00
Meta Vens
522b5af0b4 ManoeuvreTrack forgets a whole window after the last change of vector; tests stop resetting it, and pin the three fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 05:39:41 +02:00
Meta Vens
2cf980e353 Entity.Acceleration puts back what a VelocityLimit removed: the ceiling is not a change of vector
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 05:39:40 +02:00
Meta Vens
f9d4f60a9e Thruster.Thrust is read live, so Ship's aggregates stop reading the construction value
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 05:39:39 +02:00
Meta Vens
cb56557b4d Boss gate tests: the gate geometry test places the exit zone away from the origin
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 04:38:36 +02:00
Meta Vens
daa9a83940 StationServicesTests: pin partial-cell armour wear and a repair fraction above the sell fraction
Armour repair is priced at fractional wear (a fraction of a cell on every cell, and a thousandth of one cell), and
gear repair is priced exactly when RepairFraction exceeds SellFraction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 04:05:50 +02:00
Meta Vens
90768de10e Boss gate tests: the exit gate's position is pinned against a sweep of every direction
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 03:54:04 +02:00
Meta Vens
2910a35dff EvasionTermTests: reach and evasion read each side of the envelope
An asymmetric forward-only envelope pins the clockwise and counter-clockwise sides, the
mirrored direction, the two-sided average capped by the observed spread, and the track's
cross term.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 03:37:31 +02:00
Meta Vens
f8065a4d2b EvasionTermTests: which thrusters are left decides the envelope
Destroy the Djinni's right-pushing thrusters and the envelope loses its right push and
the turn they gave one way; reverse push and the Traction drive's turn rate are checked
against the ship's own flight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 03:12:47 +02:00
Meta Vens
467a50431a StationServicesTests: armour repair is priced at odd and even hull prices
An armour price one credit low survived: ceil absorbs it at the fixture's even hull price. The armour test now runs
the same wear patterns at five hull prices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 03:01:19 +02:00
Meta Vens
2ac420edec StationServicesTests: pin the repair-sell seam and the armour and gear repair prices
A price and durability sweep (1..3000 by 20, three fraction pairs) and the 360 at 7 of 20 case assert repairing then
selling never nets a credit. Armour tests wear several cells, partial and full strip, different cell values, and
check every cell is restored and the cost is the worn share of the hull price. A gear test pins the repair share at
odd and even prices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 02:08:39 +02:00
Meta Vens
73dd96be00 StationServices: a repair share is never below the sell value it adds, rounded in the sell price's own function
Selling floors price * fraction * condition in doubles while repair ceilinged a separate expression, so the two
disagreed by one credit for some prices (GetPrice 360 at durability 7 of 20). SellValue is now the one sell
rounding, and RepairShare charges at least SellValue(whole) - SellValue(worn), so repair-never-profits holds exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 02:08:37 +02:00
Meta Vens
bb2f49f358 Boss gate tests: the unsold BossHull case builds its own unsold hull, as the catalog has none
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:24:29 +02:00
Meta Vens
9883d08dcd Exit gate: the exit zone shows a gate that ends the run as won once RunGoal says the boss is dead
ZoneRenderer adds an exit wormhole at RunGoal.ExitGatePosition; Interact asks RunGoal.ExitOpen and either
calls Win or names the boss that seals it. Die and Win share one EndRun.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:13:09 +02:00
Meta Vens
db4617d832 Boss gate: a boss zone spawns its faction's boss, and RunGoal derives whether the exit gate is open
EntityPack.Boss (key 21) carries Entity.IsBoss through save and Continue. GenerateZone adds one boss
per BossZones entry before the ambient return, flying the faction's BossHull or, with the gap logged,
its most expensive available ship hull. RunGoal (ServerShared) is the one owner of boss life and exit
state, derived from Zone.Entities.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 01:13:08 +02:00
Meta Vens
da2957b81c Evasion term: reachable spread from the thrust and turn envelope, realised by changes of vector
Every hit price gains one factor, PDeviation(Evasion, Tracking): how far the target can
and does move off the line of fire within SolutionWindow (0.75 s). Capability is Reach, an
eight-face closed form over the ship's ManoeuvreEnvelope (summed from what each live
thruster and aether drive reports with its own Execute arithmetic, read live: a thruster's
Thrust property is stale until it fires, which is why the Djinni moved 1.6 times its stats,
M25). Behaviour is ManoeuvreTrack, observed once per Entity.Update from the measured
acceleration; a steady burn, coasting and a dither much faster than the window do not
evade, and sideways speed alone does not (ruling evasion-speed). The commit price adds the
term at any flight time, so an instant weapon feels a jinking target. Forecast owns the
term for HitProbability and Inspect, which gain Evasion and PEvasion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:48:27 +02:00
Meta Vens
5100daa297 FireControl: one PDeviation shape for the deviation price
DeviationProbability's inline saturate becomes PDeviation(deviation, tolerance), defined
for a zero tolerance as well. No behaviour change for a positive tolerance. Delete-first
step of the evasion term: every later deviation-like price reads this one shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:48:14 +02:00
Meta Vens
68d80968e8 TradeMenu: the Price column shows and sorts by StationServices, and buys go through TryBuy
The column's sort key was the raw design price; it is now the shown price, the sell price while selling. Buy affordability and the credit charge move to StationServices.TryBuy, so a purchase costing exactly the credits held succeeds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:47:08 +02:00
Meta Vens
0857dbe15c StationServices: repair mends armour, never costs less than the sell value it restores, and owns the buy commit
RepairCost adds the worn share of hull armour priced as that share of the hull's price, and TryRepair restores it. The per-unit-of-wear charge is the larger of RepairFraction and SellFraction. TryBuy checks credits with the same boundary as TryRepair and charges after delivery. A 100-unit ore sale pins the commodity sell scale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:47:07 +02:00
Meta Vens
85d0a14808 Demo Terminus tests: the player's Longinus carries the default fit the game generates for it
The expected fit is the generator replayed from the staging seed, so a bare hull, a preset or one swapped item fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:04:46 +02:00
Meta Vens
e75083fec8 Map: evasion as unpredictability, with prior art, body facts M23-M26 and the revised design
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 23:56:56 +02:00
Meta Vens
787715ad4a TradeMenu prices every buy through StationServices.BuyPrice; the list column, the quantity cap, the check and the charge agree
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:56:06 +02:00
Meta Vens
1a42ac7758 StationServices.BuyPrice: the one number the station charges, which the buy path shows, checks and charges
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:56:05 +02:00
Meta Vens
864bb0c6a4 StationServices tests: hulls five cells square, so a second bay has an interior cell to sit in
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:53:10 +02:00
Meta Vens
1baa89645d StationServices tests: a full first station bay does not refuse a sale; worn docking bays are mended
Kills the two survivors Stryker left in StationServices.cs: Any() to All() over the station's bays, and Concat() to Except() over the docking bays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:50:58 +02:00
Meta Vens
c82b28851a StationServices tests: a full first station bay does not refuse a sale; worn docking bays are mended
Kills the two survivors Stryker left in StationServices.cs: Any() to All() over the station's bays, and Concat() to Except() over the docking bays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:49:57 +02:00
Meta Vens
ebe64600c1 Demo Terminus: the player starts in the base Longinus, not a Pirates-made hull
The Pirates hire the player, who is not one of them (ruling player-not-a-pirate);
the base Longinus with its default fit is the start hull (ruling
demo-start-hull-longinus). The hull is named in the script; StartingHull no
longer owns the demo's hull. The Pirates-hull test is replaced by one pinning
the Longinus, its Alakrita maker, a null ship faction and the origin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:47:47 +02:00
Meta Vens
646057f2c6 Map: the evasion term and missile odds, with body fact M20 and the revised missile design
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:35:57 +02:00
Meta Vens
7f51d46d71 Map: missiles with fuel and seekers, with prior art, body facts M15-M19 and the revised design
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:01:41 +02:00
Meta Vens
b4946613fd Target: reframe "legacy first" as "ship the game"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:59:06 +02:00
Meta Vens
bd77e3ed87 Demo Terminus tests: the name, the Pirates hull and its start, and the region's size are pinned
Each reads the compiled scenario as the run start builds it: the listed scenario's Name, the staged player's faction,
hull and position, and the generated galaxy's zone count and links against the same cast at density one half.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:35:55 +02:00
Meta Vens
c7432f39a8 Map: missiles and point defense, with prior art, body facts M1-M14 and the authority map
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 21:25:10 +02:00
Meta Vens
ff254b0269 Demo Terminus tests: a release build lists only the demo; the tutorial and main galaxy are development modes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:43:39 +02:00
Meta Vens
edeec0f610 Demo Terminus tests: compare zones by index, so a failing gate is a red test and not a dead test host
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:24:17 +02:00
Meta Vens
26f21e3206 Map: firing on solutions, with prior art, body facts and the revised authority map for the controls cuts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:18:48 +02:00
Meta Vens
b817541647 StationServices.cs.meta: the Unity import record for the new script
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:55:01 +02:00
Meta Vens
32b544936a Demo Terminus tests: Continue commits the run's own lot ledger
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:52:09 +02:00
Meta Vens
65464a0a0e Demo Terminus tests: the Pirates fixture reaches every manufacturer, as the entrance's station needs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:45:37 +02:00
Meta Vens
9308f71b78 StationServices tests: a single unit of seven-credit ore sells for three, rounded down
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:43:44 +02:00
Meta Vens
e1296f1fac Map: Controls section, with prior art, body facts and the authority map for the facing-separate-from-aim rebuild
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:41:16 +02:00
Meta Vens
c7c56e152c Demo Terminus tests: the Pirates fixture carries a name file, as generating zone names needs one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:39:16 +02:00
Meta Vens
1997a3da33 Demo Terminus tests: fixed cast, gate, standing across Continue, refused cast, tutorial unchanged
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:32:03 +02:00
Meta Vens
dd0253c45e Demo Terminus: a compiled scenario stages one fixed-cast prelude galaxy whose antagonist's home is the gate
DemoTerminus generates a prelude galaxy of the Pirates, Zhestokost, Lucent Media
and Aeronautics Unlimited with no quest faction, places the gate at the
antagonist's home (Galaxy.PlaceGate: boss zone and exit), and stages the player
in a Pirates hull with the cast's standing. The prelude constructor resolves
every cast name through one refusal that names the field, and places a quest
zone only when a quest faction is named. Release builds list only the demo; the
tutorial and main galaxies join the test arenas in editor and development builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:32:02 +02:00
Meta Vens
c204397cb0 TradeMenu sells and repairs through StationServices; credits seed from the stage or the save
The hardcoded credits initializer and its stale scene serialization go. Buy charges the hull price it checked. Sell is a
mode of the trade list over the selected bay; Repair is a foldout option for the docked ship.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:30:34 +02:00
Meta Vens
9651f62ad4 The run's credits are saved and seeded: SavedGame key 13, ScenarioStage.Credits, Staged.Credits
RunSave.Capture takes the credits; a scenario may set the starting amount, defaulting to the gameplay settings'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:30:32 +02:00
Meta Vens
39b6d28f3a StationServices: one engine-free owner for sell price, repair cost and the sale and repair commits
Settings gain SellFraction, RepairFraction and StartingCredits. A sale pays the price scaled by condition and moves the
item into a station bay or refuses with everything unchanged; a repair restores every durability and charges the wear,
or refuses when short.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:30:31 +02:00
Meta Vens
228f241e53 Merge eureka/aetheria-release-target: the release target and map land on master, rewritten for the demo
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:12:03 +02:00
Meta Vens
6a1bb47758 Target and map: the first release is the demo
Rewrites the release target for the demo cut (one gate, one region, one boss, a fixed cast of Pirates, Zhestokost, Lucent and AU, called a demo). Adds the map's Demo scope section with body facts D1-D6 and the scope table, and sweeps four stale docs the design review listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:11:46 +02:00
Meta Vens
2a6323cc72 Docs: mark the mining cut maps superseded in part and F1 fixed after the mining merge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 18:29:32 +02:00
Meta Vens
985e65696c Map: mining index as built on master df7c44f2
Records the targeting index and Entity's press queries as built: their owners, inputs, outputs, forbidden writers, verification layer, and live seams. Marks L3 and L5 as historical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 18:29:25 +02:00
Meta Vens
df7c44f2e1 Merge eureka/aetheria-release-mining: the targeting index, best-first target queries, and the end of the belt freeze
Mining Cuts 1-3, the general targeting index (ships and belts), and next/previous/reticle as index queries on Entity, with master merged in and the catalog's field kinds rebuilt. Soul held mining-index-pins, mining-target-queries (two passes) and mining-merge; the Unity compile and both ships smokes pass. Mining yield (Cuts 4, 5, 7) is not in this merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 18:24:29 +02:00
Meta Vens
a83aa54e09 Catalog: author the Asteroid field kind (AetherDb field-kinds apply on master's catalog)
GameData/Aetheria.cc 70a7b0a9 -> 78fe2afe (12703072 bytes): one FieldKindData
record, Asteroid, cross-section 5, weight 1. Run on Yggdrasil from the merge
commit's tree, output pulled back byte-identical. Fixes
TheShippedCatalogHasAPickableFieldKind and makes master's strict Exact weapon
assertion hold on the rewritten catalog.

Builds: both commits build; the previous commit fails one test by design, this one passes 837/837.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:41:49 +02:00
Meta Vens
d9f85dc639 Merge origin/master into mining: resolve five conflicts by owner, delete the belt-task machine
Mining owns belts, chunks and target picking; scenarios owns admission and run
staging; master owns ships and fire control (rule scenarios-cut.md S4).

- AetheriaStores.CatalogTypes: nine-type union, master's list plus FieldKindData, no Scenario.
- tools/AetherDb/Program.cs: both cases (ship-authoring, field-kinds), one usage string.
- Zone.cs: master's MineAsteroid dropped (mining deleted its inputs); scenarios' SettleBelts and its three calls deleted.
- RunStartTests: the two belt-task tests deleted (they read belt.Transforms and MineAsteroid).
- FireControlCut124Tests: master's strict Exact assertions; mining's CompatibleDrift allowance and its comment dropped.
- GameData/Aetheria.cc: master's pointer 70a7b0a9. This commit lacks the Asteroid field kind in the catalog, so
  TheShippedCatalogHasAPickableFieldKind fails here by design; the next commit rebuilds it.

Builds: this commit builds (verified at the end with commit 2); the catalog pin test fails at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:29:29 +02:00
Meta Vens
561a21f3b2 Mining target queries tests: the blind ship needs no tick; it has no equipment to bring online
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:20:37 +02:00
Meta Vens
9e10166c76 Mining target queries tests: press pruning pinned by per-press examined ceilings near the measured costs
A second density-equal belt size and reach, held-target presses and the reticle at three headings,
each ceiling within about 10% of the measured count; the shared ceiling drops from 1500 to 700.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:19:23 +02:00
Meta Vens
c57466a398 Mining target queries tests: tie-break across belts by field key, and nearest-first pruning from no target
Pins two Stryker survivors: Entity.Order's field comparison and DistanceKey.Bound's forward bound.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:06:30 +02:00
Meta Vens
7a01e608ba Mining target queries tests: a launcher-only ship may see a ship but picks no rock; name the press ceiling
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:49:55 +02:00
Meta Vens
793fdc8789 Mining target queries tests: pick the sensor that sees a share of the rocks in reach; report every press cost together
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:44:38 +02:00
Meta Vens
60383cf00e Mining target queries tests: brute-force order, farthest, smallest angle, cost, reach, enemies
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:38:21 +02:00
Meta Vens
ec2042b390 Mining target queries: reticle, next, previous and nearest are Entity's best-first index queries
The four handlers in ActionGameManager call Entity.TargetUnderReticle, TargetNext,
TargetPrevious and TargetNearestEnemy. TargetCandidates, which built, sorted and
searched every visible ship and rock per press, is gone. Previous with no target
takes the farthest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:38:20 +02:00
Meta Vens
a24ffd77db Merge eureka/aetheria-release-scenarios-menu: every new run comes from a scenario, launched from the New Game submenu
Tutorial Galaxy and Main Galaxy are scenarios; six test arenas show in editor and
development builds. RunStart owns new-run staging; Zone.Admit stays the one admission.
Galaxy zone linking moves to a double-precision Delaunay (the vendored float hull
dropped zones; ~2% of galaxies threw). A fixed seed fixes every fit; a failed start
keeps the saved run and says why. Soul s1 and s2 held (cut-scenarios-menu.h1, h2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 01:35:22 +02:00
Meta Vens
8cd68f4e65 Pin that a failed start's own writes are removed: the failed starts write a record the saved run does not hold, and the open store must not keep it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-03 22:36:04 +02:00
Meta Vens
d44df96fb0 SeedRules scrambles the item random between the arena and staging, so the staging step's own seed is pinned
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 22:04:17 +02:00
Meta Vens
8a1e205cf0 A new run replaces the saved run only once it has staged; a failed start says why and leaves the saved run
Launch cleared the run store before generating, and a generation or staging failure only reached the log: the
Generating Galaxy dialog stayed up, StartGame threw, and the saved run was already gone.

RunSave.Replace runs a start with the saved run still stored: when it returns a staged run the saved run's records go,
and when it returns null or throws, only the records it wrote (the arena's orbits and bodies) go. StartGame's
new-run branch is StartScenario, chosen by PendingScenario rather than by the absence of a SavedGame; it mints into an
empty ledger, and a failed start clears CurrentGalaxy (so quitting saves nothing) and refuses on the main menu with
every failure. Launch no longer clears; a galaxy that throws is refused on the title menu. The menu offers Continue
whenever no run is live, which replaces MainMenu.InGame (cut, with its prefab value and scene override), so a
failed start can resume the saved run in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 22:03:50 +02:00
Meta Vens
02e7fd4b7e A fixed seed fixes every fit: RunStart seeds the run's item draws from the galaxy's seed
ScenarioStage.Generated picked from ItemManager.Random, which is clock-seeded per process and advances in play, so a
relaunch of Djinni Shakedown or Long Haul in one session gave the player a different fit; every branded lot's
workmanship and role fills came from the same clock stream, so arena gear and explicit fits varied in quality too.
Galaxy now keeps the seed it was generated at, and RunStart.GenerateArena and Stage each reseed the item manager's
random from it, one stream per step, so what runs between them cannot shift either.

SeedRules relaunches every fixed-seed scenario around a clock-free Main Galaxy launch and a scrambled item random,
and compares the galaxy (links, factions, homes, exit too), the arena down to each item's maker and workmanship, and
the staged fits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 22:01:17 +02:00
Meta Vens
4d1334e044 Arcs runs at seed 103 again, as the spec sets it: its prelude galaxy generates now that every zone is linked
Reverts 0854d91d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:59:18 +02:00
Meta Vens
e56af28892 Galaxy links zones along a double-precision Delaunay triangulation: the vendored float MIConvexHull dropped zones, so ~2% of galaxies threw
The vendored MIConvexHull (NIH, ported from double to float) returned triangulations that left whole sets of
interior zones with no cell at all (prelude seed 103: 22 of 64 zones; main seed 4247651650: 182 of 196). Those
zones had no link, Distance lacked them, and the constructor threw KeyNotFoundException placing the antagonist
home (prelude) or the entrance (main). Galaxy was its only consumer; Delaunay.Edges (Bowyer-Watson, double) replaces
it, and the 3,896 vendored lines go.

The three RestoredHullsTests loops that skipped seeds whose galaxy threw now require every seed to build, and the
stale comment that Galaxy mutates Faction.InfluenceDistance goes with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:59:09 +02:00
Meta Vens
494d795550 Pin that generating a galaxy leaves the catalog's faction influence as authored
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:55:02 +02:00
Meta Vens
0854d91d77 Arcs runs at seed 107: seed 103's prelude galaxy fails generation (a pre-existing KeyNotFound in Galaxy's home-zone placement)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:45:31 +02:00
Meta Vens
c0be2843ea A galaxy's zone names are unique within the galaxy, not across the process
MarkovNameGenerator kept every name it ever gave in a static list, so each later galaxy in a session drew different
zone names at the same seed, and ZoneGenerator seeds a zone from its name: a fixed-seed scenario relaunched in one
session got a different arena. Galaxy now passes one used-name set to its factions' generators. The unused Reset goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:45:26 +02:00
Meta Vens
d0782a7d14 Every new run is a scenario: the script harness, the tutorial and main galaxies as scenarios, the New Game submenu and six test arenas
A Scenario is an abstract C# class compiled with the game: Generate picks the galaxy through GalaxyStage (Main or
Prelude, at the scenario's seed, the background noise drawn from the same seed), Stage places the run's first
entities through ScenarioStage (Fit, Bare, Generated, Preset, Player, Place, Cargo), which collects named failures
and admits nothing. RunStart generates the galaxy, the arena under Ambient and admits everything through Zone.Admit,
all or nothing. The aetheria.scenario record, ScenarioShip, ScenarioEntity, RunStart.Check and the null-scenario
branch are cut.

New Game opens a submenu: Tutorial Galaxy and Main Galaxy, then (editor and development builds) Djinni Shakedown,
Starved Reactor, Arcs, Duel, Launcher Angles and Long Haul, each with its brief. MainMenu.Launch is the one way into a
new run; ActionGameManager.PendingScenario carries the scenario to StartGame once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:33:55 +02:00
Meta Vens
8a0a29e0de Galaxy.IsPrelude is the one owner of whether a run is the prelude: ActionGameManager.IsTutorial and PlayerSettings.TutorialPassed are cut
IsTutorial duplicated Galaxy.IsPrelude; its readers read CurrentGalaxy.IsPrelude, and RunSave.Capture writes
SavedGame.IsTutorial from galaxy.IsPrelude with no isTutorial argument. TutorialPassed was never written and its only
reader was New Game's unreachable main-galaxy branch, which goes with it (S2 brings the main galaxy back as a
scenario). spawnturret's two identical generator branches collapse to one. Old player.cc files still load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:26:30 +02:00
Meta Vens
c37d6adfa8 Galaxy derives a prelude's halved faction influence instead of writing it into the catalog's Faction
A prelude halved every faction's InfluenceDistance on the shared catalog object, so each later generation in the same
session, prelude or main, started from an already-halved value, and a continued prelude read the unhalved one. A
fixed-seed scenario relaunched in one session therefore could not reproduce its galaxy. Galaxy.InfluenceOf derives
the reach from IsPrelude; Galaxy and ZoneGenerator read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:25:26 +02:00
Meta Vens
01a1ad3a1a Aetheria release map: ship authoring across Blender and Studio
Division of labour (Studio edits hull semantics, Blender owns space, strokes
and the body), Line Art strokes into Package's capture, the shared ship.cc with
a Studio disk guard as the bridge, mount gizmos and a read-only overlay, Thing
readiness facts and question ship-authoring-host, six cuts and their order
against the .cc move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 18:24:45 +02:00
Meta Vens
7e51423ad1 Aetheria release map: ship data all in the .cc
Ruling ship-data-all-in-cc. One ShipModel record (nodes, per-attribute
mesh streams, submeshes, surfaces, images with format and levels) at
mod-model:<id> replaces ship.glb and the planned PNG sidecars. C# seeds
and judges it, Python packs it at Package, Unity builds Mesh and
Texture2D from it, and glTFast leaves. Body facts M26-M30, sizes, the
authority map, questions ship-model-owner and ship-image-encoding, cuts
ships-cc-model, ships-cc-package and ships-cc-image-bc, and the specs
it supersedes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:54:32 +02:00
Meta Vens
4895c75236 Bind Ship Collection: compute the stored .cc path before binding, absolute when relative cannot hold
The bind called bpy.path.relpath after setting aetheria.asset_kind and aetheria.id, so a .cc on another drive than the
.blend raised and left the collection half-bound, and an unsaved .blend stored a path relative to the working
directory. The stored path is now computed first: absolute for an unsaved .blend, '//'-relative when relpath succeeds,
absolute when it raises ValueError. Every reader already resolves both through bpy.path.abspath.

smoke_package.py gains the bind cases: unsaved stores absolute and survives two Save As moves, a failing bind leaves
no aetheria.* property, same-drive stores '//'-relative, and with SMOKE_OTHER_DRIVE the final bind crosses drives
before the package passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:37:21 +02:00
Meta Vens
7d649d5c31 Package Ship: headless Blender smoke, and the authoring doc says how Package and create --like are used
smoke_package.py builds a primitive ship from role-tagged objects, creates it --like Djinni, saves a layout with an
internal reactor, packages it and requires validate to pass; then swaps the thruster disc for an empty and requires the
refusal naming the anchor; then restores and packages again so the left-behind package is good. Proof gate 2's
outstanding authoring action is now Package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:13:44 +02:00
Meta Vens
82ca9e9be1 aetheria_ships: Package Ship derives anchors and ship.glb from the bound collection and runs AetherDb validate
Every object tagged aetheria.role becomes a ShipAnchor whose Id and ModelNodeId are its aetheria.id (a muzzle's ParentId
is its parent's). The collection, Grease Pencil excluded, exports to ship.glb with custom properties as node extras;
replace_visual writes the anchors, a lone Grease Pencil object's lines are captured, and AetherDb's verdict shows in the
panel. The add-on preference 'Aetheria repo' names the checkout; by default it is the nearest folder above the .cc.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:13:42 +02:00
Meta Vens
aca1d53e6f ship_cc: replace_visual writes ShipAuthoring's model asset and anchors, pinned to the C# keys
MODEL_ASSET_SLOT, ANCHORS_SLOT and ANCHOR_MEMBERS sit beside the other slot constants and ShipSchemaPinTests binds them
to ShipAuthoring's and ShipAnchor's [Key]s. replace_visual carries an anchor's slots past Order by Id, refuses a blank
or duplicate id, a wrong-length row and a changed ship id, and leaves the hull record and the lines alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:07:10 +02:00
Meta Vens
f98be434f0 AetherDb ship-authoring: create --like a shipped hull, and validate reads the GLB when present
ShipAuthoringStore.HullLike copies a reference hull through its MessagePack round trip and resets Name, Shape,
Hardpoints, Prefab, Schematic and Visual. 'create ... --like <name>' opens the shipped catalog read-only and refuses an
unknown or non-ship hull. 'validate' runs ReadPackage when ModelAsset names an existing file and says which it judged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:07:09 +02:00
Meta Vens
f5743cbad2 Ship packages: a thruster or radiator anchor on a mesh-less GLB node is refused at bind
ReadNodeIds is the one GLB parse and now records, per aetheria.id node, whether it carries a mesh. Bind refuses a
thruster-emitter or radiator-mesh anchor whose node has none, naming the ship and anchor (ruling
thrusters-radiators-are-meshes), so Compose and validate refuse such a package before the catalog sees it. AetherDb
'ship-authoring validate' judges the GLB when it exists (next commit).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:07:08 +02:00
Meta Vens
16f7bdbfab Mining index pins: a belt region's bounds stay tight and a rock exactly at reach is found
Three tests in MiningIndexTests, no production change. RegionsStayNearTheSearchArc bounds the share
of a small search's regions that lie past reach on both sides (window widened, nearest loosened);
VisibilityBoundPrunesADimBelt bounds rocks examined against rocks in reach in a half-lit belt of
largest rocks; ARockExactlyAtReachIsFound searches from 1-300 units with reach set to a rock's exact
distance, a third of them radially outward from a belt's outermost rock. Each threshold's unmutated
and mutant values are in its comment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:48:05 +02:00
Meta Vens
de0d7ca0dd Merge remote-tracking branch 'origin/eureka/aetheria-release-target' into eureka/aetheria-release-target-mat 2026-10-03 16:46:40 +02:00
Meta Vens
b643b0a464 Aetheria release: hull materials as owned graphs
Blender-authored material graphs judged by AetherDb into a catalog record,
lowered to a CultMath expression IR, generated into compute kernels and baked
per (hull, livery) with per-ship wear only. Body facts M19-M25 (Blender pin,
Cycles point oracle, dump, interpreter bench, compute substrate, faction key
clash, CultMath seams), the authority map, parity chain, tape relation, cuts
and rationale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:46:38 +02:00
Meta Vens
c22033f287 Aetheria release map: the sublinear mining index, as two cuts after the merge
Ruling targeting-sublinear-wanted-not-critical supersedes the reading that
rejected it. mining-index-tree makes the provider seam a region tree with a
heap-ordered Best and a detection gate; mining-belt-cells rebuilds the belt
as rings of about-square cells in co-rotating frames, refreshed by drift.
Target: per-press cost grows as sqrt(rocks in reach), the exact-query floor,
measured on F1's fixed belt at 30k, 300k and 3M. Both land after
mining-merge and gate nothing. Forks: reticle-exactness, belt-size-tiers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:34:39 +02:00
Meta Vens
d2f0ee8933 Aetheria release map: the mining index fix is pins only
Ruling targeting-density-scaling-accepted accepts the index's growth with
rock density, so the sublinear region structure is recorded as rejected
under it. mining-index-pins adds the three tests for Soul's
cost-loosening-unpinned and exact-reach-unpinned findings and lands before
mining-target-queries, which stands as specced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:19:32 +02:00
Meta Vens
ed15d34b35 Tests: generated loadouts give every reader its hardpoint (Soul's headless probe)
Soul's scenarios-adopt probe S4 as a committed test: on generated ships,
stations and turrets every weapon, thruster and radiator holds a non-null
Hardpoint containing all its cells, and Tool gear and the hull hold none.
It pins the input the muzzle, arc, thruster-emitter and radiator readers
dereference (finding headless-reader-input).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:14:10 +02:00
Meta Vens
4b002b50bc Merge master 239f3599 into eureka/aetheria-release-scenarios: ship render fixes
The one conflict, ShipInstance.cs's thruster emitter lookup, keeps the
branch's thruster.Item.Hardpoint.Transform and master's new
ThrusterHardpoint.WireExhaust(particles, thrusterHardpoint). Master's side
as written would have brought back the origin-cell hardpoint lookup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:09:55 +02:00
Meta Vens
97bf1b8e03 Aetheria release: hull mask is a per-ship texture; prep steps include rebuild and rebake
Ruling hull-paint-mask-texture (option texture-sidecar). The material model
now samples ship.mask.png on UV0 (RGBA8, linear, DXT5 with mips, loaded by
ImageConversion; the sidecar rather than GLB extras, with the reason). M18
records Blender saving a byte mask raw. The per-hull steps add retopology,
a clean unwrap and the Selected-to-Active rebake, list who does each step,
and leave the time budget to the operator. Select Debris, the mesh report
and the triangle warning are dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:45:32 +02:00
Meta Vens
cfd9884a33 Merge master into eureka/aetheria-release-scenarios: take the ship-mounts lane
The one conflict is EntityInstance's SoundBank block, which this branch had
moved onto item.Hardpoint and ship-mounts deleted: it stays deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:41:54 +02:00
Meta Vens
239f359990 Ship exhaust: wiring an exhaust to an emitter turns Use Mesh Colors off
The emitter carries the invisible material, whose alpha is 0, so an exhaust
prefab left at Unity's default (Use Mesh Colors on) emitted nothing. The
shipped thruster prefabs only worked because theirs is off. ThrusterHardpoint
.WireExhaust now owns the wiring and turns it off; ShipInstance calls it. The
preview smoke wires a default particle system to each emitter on the clone and
requires every particle emitted and none transparent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:39:14 +02:00
Meta Vens
6709b06e2e Ship preload: a mod ship that fails to load or assemble is skipped, not fatal
PreloadAsync rethrew on the first failing hull, so one bad package faulted
Loading and no mod ship could spawn. Each hull now loads in its own try: a
failure destroys its partial visual, is logged with the hull's name, and the
rest still preload, as Compose skips a bad package. The play smoke installs the
package beside a broken sibling that composes but cannot assemble (its map icon
moved onto a meshless muzzle node) and proves the sibling has no prototype while
the good ship spawns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:38:35 +02:00
Meta Vens
fc73d7abcd Ship render: the hull collider carries the invisible material, so clones draw nothing
forceRenderingOff is not serialized, so Instantiate and SaveAsPrefabAsset dropped
it and every cloned mod ship (and every FBX-built prefab) drew its collision hull.
The collider renderer now takes the template's invisible material, as the thruster
emitter does. The preview smoke checks the collider on the clone and the prefab
smoke checks it on the configured prefab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:37:33 +02:00
Meta Vens
9787df6f4b Tests: a full hardpoint offers no space (Stryker survivor at TryFindSpace's last return)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:35:51 +02:00
Meta Vens
a4e8e14718 Mining index: the index alone decides reach; tests pin what Stryker found loose
BeltTargets drops its own reach skip (TargetRegion.CanHold owns it) and an
empty-belt guard AsteroidBelt already makes unreachable. Tests add an
off-centre sun, whole-belt searches across the antipode, cost after time
passes, a late short step that re-keys nothing, and an entity search off the
origin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:25:32 +02:00
Meta Vens
a69b36749c Aetheria release: map hull materials, mount meshes and per-hull prep
Rulings hull-runtime-materials and thrusters-radiators-are-meshes. Body facts
M13-M17 (probed: glTFast readability and vertex colours, Blender's named
colour export, the Tripo hulls' parts, UV islands and albedo clusters), the
hull material model (Aetheria/Hull, a glTFast material generator, COLOR_0
paint regions, factory and faction livery), the per-hull prep table and time
budget, the Tripo PBR check for the operator, and the cuts it adds or revises.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:23:37 +02:00
Meta Vens
944baa02a7 Mining index tests: fit the observer before it activates; break distinct rocks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:08:48 +02:00
Meta Vens
1482a35922 Mining index: BeltTargets uses Math.PI (CultMath has no PI_DBL)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:04:33 +02:00
Meta Vens
6a79f87a64 Mining index tests: brute-force equality, bounds, pruning and cost
The two chunk-query tests compare sets through Zone.Targets.Within.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:02:52 +02:00
Meta Vens
f803151681 Mining index: a general targeting index fed by providers; the linear chunk scan goes
Zone.Targets (TargetingIndex) answers Within and best-first Best over
ITargetProvider regions. EntityTargets offers the observer's VisibleEntities;
BeltTargets keys each belt's rocks into kinetic bands and bounds each segment's
annular sector for distance, bearing and visibility. Entity.VisibleChunksInReach
queries the index with DetectionReachPerVisibility, an upper bound from the
sensors' hull. Zone.ChunksNear and AsteroidBelt.InnerRadius are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:02:51 +02:00
Meta Vens
bba169cac5 Tests: an equipped item knows its hardpoint (Soul's P30 fixtures)
Soul's scenarios batch-4 probe P30 lived only in a session scratchpad. Its
fixtures are now tests: an L gun in an L hardpoint whose origin lies outside
it, an edge gun whose origin lies in a neighbouring radiator hardpoint,
TryFindSpace finding what ItemFits accepts (unrotated and turned), reload into
the same hardpoint, and Tool gear holding none. Three batch-4 minors are
pinned too: IsFilledBy against a cell oracle written in the test, the last-row
placement search, and billing independent of heater equip order.

The file is a part of RunStartTests, so it shares that fixture's scratch-hull
and catalog helpers instead of a second copy of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:00:00 +02:00
Meta Vens
5ea59ac6b5 Entity: an equipped item keeps the hardpoint it occupies
The placement rule (HardpointAt) already finds the one hardpoint an item lies
in at equip; TryEquip threw that answer away and eighteen readers recomputed it
from the item's origin cell, which need not lie in the hardpoint (Soul's
scenarios batch-4 P30). EquippedItem.Hardpoint now carries the answer, null for
Tool gear and the hull, and every origin-cell lookup reads it instead:
FireControl.ArcFor, the eleven weapon managers, EntityInstance, ShipInstance
and ActionGameManager's articulation grouping. Entity.Hardpoints[,] stays the
per-cell map for armour and display.

TryFindSpace's hardpoint search tries every origin the fit rule can accept,
including ones up and left of the hardpoint, so a design whose shape lacks its
origin cell is found wherever ItemFits would place it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:57:27 +02:00
Meta Vens
80de88f267 Ship mounts: each weapon needs a muzzle of its own
Kills the Stryker survivor that armed every weapon with any muzzle on the ship
(the && in the per-weapon muzzle check turned into ||): a second weapon mount
with no muzzle is refused even when the first has one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:54:03 +02:00
Meta Vens
2d39c83504 Merge master into eureka/aetheria-release-scenarios: adopt the scenarios lane onto master's base
The one conflict is AetheriaStores.CatalogTypes: keep ShipAuthoring from the
ships lane and Scenario from the scenarios lane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:53:29 +02:00
Meta Vens
e6ae392773 Aetheria release: map the scenarios and mining adoptions, the loot move and ballistic ammunition
Body facts L1-L9 (Soul's P30, merge-tree probes, the belt freeze, the loot
path, a catalog probe of weapons, ammunition and the Tractor Beam), model
page rows, the merge order of every lane and the faction-play cuts, and the
rationale for the cut specs admitted to the mind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:51:27 +02:00
Meta Vens
da2a299baa Ship mounts: hide the thruster emitter with the invisible material
forceRenderingOff is not serialized, so the prototype's clone drew the
emitter again; the preview smoke's clone check caught it. The emitter's
materials become the template's invisible material, which survives
Instantiate and which EntityInstance keeps as the renderer's own material.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:48:51 +02:00
Meta Vens
95c0fa621b Ship mounts: a thruster's mesh is an unrendered emission surface
Ruling thrusters-radiators-are-meshes: thruster and radiator mounts are meshes;
the thruster's is not drawn and is the surface its exhaust emits from, the
radiator's is drawn. The assembler already required a mesh for both; it now
turns rendering off on the thruster emitter, and the preview smoke checks it.
The authoring doc states the mount rules and the mesh rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:39:09 +02:00
Meta Vens
976b711905 Ship mounts: anchors only for visible hardpoints, every role rule in Validate
ShipAuthoringStore.Validate now alone decides which hardpoints carry anchors
and which role each plays. A thruster, radiator, energy, ballistic or launcher
hardpoint needs an anchor of its mount id with role thruster-emitter,
radiator-mesh or the new weapon-mount; every other hardpoint is internal and
no anchor may take its id. A mount-role anchor must be a hardpoint's mount, a
muzzle must hang off a weapon mount, and each weapon needs a muzzle; these
checks move out of ShipModPlan.Build, which now only maps a validated pair to
slots and throws nothing itself. 'articulation' stays in the vocabulary for
pivots and is never a mount.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:39:08 +02:00
Meta Vens
23976aada7 Ship mounts: delete EquipmentHardpoints and the plan's Equipment list
The array's only reader was the dead SoundBank block in EntityInstance, which
looked up a hardpoint transform and did nothing with it. ShipModPlan.Equipment,
ShipModShips' assignment, the preview check, the FBX builder's HP.Equipment
case and its smoke assertion all fed that one dead reader. An HP.Equipment node
is now refused by the builder as an unknown hardpoint kind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:34:05 +02:00
Meta Vens
7d1b74fca6 Merge master into eureka/aetheria-release-ships: adopt the moddable-ships lane onto master's base
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:18:39 +02:00
Meta Vens
0975dc2d6f Aetheria release: map the adoption of the moddable-ships lane
Body facts M1-M12 (merge probe, lane conflicts, the mount ruling still
only in docs, packages reachable only through the console, the grid
rule, Blender export axes probed, the Tripo hulls in Quiet.blend, the
missing radiator material, the unproven built player, LFS gaps, the
unpinned CultLib path). S2's owed checks split into agent-provable and
operator-only, the merge plan, the Blender package action designed for
one hull a day, S3 with Headliner first, and what the strand needs from
the variants campaign. Cuts ships-merge to ships-player and questions
ships-merge-gate, release-hull-home and s3-player-build are in the mind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:11:07 +02:00
Meta Vens
83459f8445 Aetheria release: faction-play proof is four cuts; ammunition fact F14
F14: only three weapons draw rounds, generation stocks none and stations
sell none, so the Zhestokost tender loop needs its weapons to draw a
commodity first (question zhestokost-ammunition). The proof splits into
four cuts along the primitives, each under a Hands budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:47:18 +02:00
Meta Vens
9c912daa86 Aetheria release: map the NPC scripting for faction play
The map gains "Faction play: the NPC scripting": body facts F1-F13 on the
agent graph, tasks, perception, hostility, target writers and generation;
what each extension point can and cannot carry; seven primitives (doctrine,
flight, engagement with grace and hail, slots and the duel, anchor and
leash, roles with break-off and rearm, follow and flee states) and three
after the proof; model page rows; rationale; cited prior art.

The target's faction-play strand cites ruling npc-scripting-may-grow and
names the three proof cuts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:39:52 +02:00
Meta Vens
9c7a2f8254 Aetheria release: target and map for the release campaign
The target defines what the release is, the invariants, what is out of
scope, the four strands (feedback, audio, content pipeline, faction play),
the sequencing, and how this campaign avoids the Codex lanes in flight. The
map records the body facts behind the first feedback and audio cuts, the
model page, and the rationale for the recommended audio route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:19:02 +02:00
Meta Vens
f1dee18409 Scenarios map: belt-freeze rulings (general targeting index; fix Previous off-by-one)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:04:00 +02:00
Meta Vens
1cc08e20c0 Scenarios map: mining fix batch landed on codex/mining; belt freeze stopped at structure fork
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:37:50 +02:00
Meta Vens
83d8371e9c Mining Cut 3 tests: commit Soul's probes and the shipped field kind check
- AFirstLoadKindIsSavedFromACleanStore: FieldKinds.Ensure's kind is saved
  when the store was clean at load (ZoneData.cs:162).
- SetTargetRefusesALitChunkBeyondSight: a lit rock too far to see is
  refused (Entity.cs:345).
- TheChunkQueryMatchesBruteForce: 3000 random queries, off-origin, two
  belts, across the outer skip edge (Soul F7).
- ThePingArmIsUnchangedByTheGainExtraction: Soul's ping sweep, golden
  recorded at cb4a1dbd; kills the Sensor.cs:168 and :189 mutants.
- TheShippedCatalogHasAPickableFieldKind (Soul F2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:02:27 +02:00
Meta Vens
f88d1fc1b3 Mining Cut 3 fix: launchers do not count toward rock reach (Q12 A)
Weapon.CanMine is the one mining predicate; LockWeapon overrides it to
false. Entity.VisibleChunksInReach counts only weapons that can mine.

Tests: LaunchersDoNotCountTowardChunkReach (a launcher-only ship is offered
no rock; a gun of 200 beside a launcher of 400 is offered the near rock
only) and AnOfflineWeaponAddsNoReach (Soul F8: reach reads Active, not
Enabled).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:02:26 +02:00
Meta Vens
22e9741984 Scenarios map: operator rules mining F1 fixed before merge; launchers excluded from rock reach
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:45:55 +02:00
Meta Vens
d00a16480d Scenarios map: mining Cut 3 Soul (hold for one fix batch); merge rule corrected
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 01:48:47 +02:00
Meta Vens
5dd03cab00 Scenarios map: Soul on batch 4 (origin-outside-hardpoint blocker); queued under drain
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:15:09 +02:00
Meta Vens
4809b0663f Scenarios map: F1 ruled a separate thermal balance campaign; Cut 1 merges with the freeze as a known defect
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:56:45 +02:00
Meta Vens
aa3baf12e4 AetherDb: retire the station-reactors and allegiance-self one-shots
Both landed their content; git history keeps them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:40 +02:00
Meta Vens
2d30403ab2 Tests: pin generation's fill preference, lot reuse and thermostat billing
Soul's S6. Generation always gives Zenith's 16-cell Reactor hardpoint a reactor
that fills it though smaller ones fit; a generated Djinni's eight thrusters
share one lot; across 5 K either side of a heater's target the bus bills it
exactly when its thermostat is open; and a thermostat gates only its own
behaviour group (a two-group fixture: the closed group's 10 is not billed, the
other group's 7 is).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:38 +02:00
Meta Vens
ff2be8e26f One placement rule for hardpoint gear
Soul's S3 and the S2 ruling ("B is the design intent, saving slots in a
hardpoint can be a valid tradeoff for crowded ships if you really need to fit
an extra tool"). Entity.HardpointAt is the one placement rule: at an origin,
the item lies within a hardpoint of its type at that hardpoint's rotation
(HardpointData.TakesAt), its own cells are free, and that hardpoint holds no
other hardpoint item. The origin no longer has to be a hardpoint cell, and
TryFindSpace tries every offset inside a hardpoint, the offsets the fit rule
tries, so an L-shaped hardpoint takes its L design instead of generation
throwing. Leftover hardpoint cells may hold general gear, and a hardpoint still
holds one hardpoint item.

Tests: an L hardpoint takes its L design by hand and in generation (Soul's
P11); a turret's gun goes back beside the tool gear in its leftover cells
(P21); a second gun in a roomy hardpoint is refused; a saved entity reloads to
the same loadout with its items in reverse order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:37 +02:00
Meta Vens
d50fd1b973 A faction reaches its own gear; allegiance names only other factions
Operator ruling, 2026-09-30: "removing the 11 self-entries was my intention".
IsAvailable, the one reach rule, now says a faction always reaches its own
manufacturer's gear, and a transient `AetherDb allegiance-self [apply]` drops
the self-entries from the eleven factions that had one (Rossum & Douglas never
did, which is why its stations could not carry its own gear).

Tests: in a main-sector galaxy every faction is offered all it makes and no
allegiance map names its own faction; and, through a fixture faction outside
the galaxy with no self-entry, its own product is on offer to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:34 +02:00
Meta Vens
f458206c76 Content: a station reactor for every reactor maker
Operator ruling, 2026-09-30: "Keep the variety, not every galaxy will have
Zhestokost in it." A transient `AetherDb station-reactors [apply]` gives each
manufacturer that makes reactors a design for Zenith's 16-cell Reactor
hardpoint, scaled by cells from its largest reactor with every other value,
stat term, role, temperature and sound bank its own, and a product by it:

  Vulcan Station Reactor     (AU, from Vulcan 12 cells x1.333)  charge 66.7..266.7, mass 666.7, price 1,550,000
  Notorious Station Reactor  (Lucent, from Notorious 9 x1.778)  charge 711.1..2133.3, mass 1333.3, price 1,800,000
  MoveOnPro Station Reactor  (NiteLife, from MoveOnPro 4 x4)    charge 100..500, mass 1200, price 3,600,000
  Core Power Station Reactor (R&D, from Core Power 4 x4)        charge 400, mass 200, price 1,000,000
  products: Vulcan Station, Notorious Station, MoveOnPro Station, Steadfast Station

The Manhattan-derived one is renamed "Manhattan Station Reactor" (product
"Manhattan Station").

Reach is read through the one rule, LoadoutGenerator.IsAvailable. Test: a
faction allied only to AU, Lightsail and NiteLife is offered none of
Zhestokost's products and AU's, its stations carry nothing it cannot reach and
nothing by Zhestokost, and they are powered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:31 +02:00
Meta Vens
09050ae920 Tests: drop the flaky failed-belt-task test
AFailedBeltTaskSurfacesOnce swapped a belt's asteroids while that belt's task
could still be running, so it failed in 5 of 8 runs including unmutated ones
(Soul S1). It tests belt-task machinery that codex/mining deletes (Cut 1,
22a54ccb), so it goes rather than being reworked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 23:13:27 +02:00
Meta Vens
55ca6d3d22 Mining Cut 3 tests: non-degenerate fixtures the mutation probes exposed
- SensorGainExtractionChangesNothing traced a saturated sensor: a hull's own
  heat makes a ship ~800 bright, so the observer's info sat at 1 every tick and
  the hash pinned nothing (a hand probe dividing by the bearing response, and
  one pricing a ping as a passive tick, both survived). The scene now observes
  through a weak sensor (Dim eye, sensitivity 0.01) and asserts the trace is
  unsaturated and carries a visible ping. Golden re-recorded against the
  pre-extraction Sensor.Execute (cb4a1dbd with this scene patched in); the
  post-extraction code gives the same hash, 919B7EE7...
- Cycling reach fits its guns 250, 120, 350, so the last active gun is not the
  longest (a "last weapon wins" reach survived the old order).
- The weighted pick uses three positive weights, so a pick that falls through
  to the last kind is told apart (it survived with two).
- The chunk query runs around a belt centred off the origin.
- TargetRef hashes an entity target and None.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:31:44 +02:00
Meta Vens
ad42ff5554 Scenarios map: S2 ruled B (leftover hardpoint cells may hold tool gear)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:23:28 +02:00
Meta Vens
8863f05ebb Scenarios map: belt code superseded by mining; merge rule for Zone.cs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:22:36 +02:00
Meta Vens
b2f74f0565 Scenarios map: Soul on batch 3 (flaky test, occupancy question, L-hardpoint crash, respawn timers)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 22:20:48 +02:00
Meta Vens
b3b550dbaf Scenarios map: self-allegiance ruled (own-faction reach implicit; 11 self-entries removed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 21:37:20 +02:00
Meta Vens
d19b7251ac Scenarios map: stations get radiators; per-manufacturer reactors kept; self-allegiance question
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 21:33:52 +02:00
Meta Vens
2125f2b181 AetherDb: retire the damage-curves one-shot
It landed its content; git history keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:35 +02:00
Meta Vens
c4af127280 Stations carry only gear their faction can reach
Operator ruling B, 2026-09-30: "a station with no access to Zhestokost gear
should not have Zhestokost gear." Test: in a main-sector galaxy (not the
prelude, which offers every product), every faction's generated stations carry
a heater and a reactor, and nothing, equipped or stocked, whose manufacturer is
outside the galaxy or the faction's allegiance.

With today's catalog every faction's allegiance names every faction (weights
only bias preference) except Rossum & Douglas, which leaves out itself; the
test killed a reach that ignores allegiance through an R&D station carrying
R&D reactors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:32 +02:00
Meta Vens
f879527158 Zone: every writer of what the belt tasks read settles them first
Soul's F5 and F6. The asteroid-belt tasks read the clock, the orbits and each
belt's damage and respawn state. Update advanced the clock before waiting on
last tick's tasks (Soul measured 242k transforms placed for the next tick in
576 of 3000 ticks), MineAsteroid wrote damage and respawn state under a
running task, CreateOrbit and AddOrbit wrote the orbits, and a task that threw
stayed in the list, so Wait rethrew it on every tick after.

SettleBelts waits for the tasks and clears the list even when one failed; Update
settles before it advances the clock, and MineAsteroid, CreateOrbit and
AddOrbit settle before they write.

Tests: over 3000 ticks every asteroid of a belt is placed for the time of the
tick that started its task; mining every asteroid of a belt, chipping and
breaking each four times a tick for 1000 ticks, never races the task; a task
that fails surfaces once and later ticks run clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:31 +02:00
Meta Vens
74d2cf8fc4 Power bus: a consumer its thermostat has closed is not billed
The bus billed every active IPowerConsumer, but a behaviour group stops at its
Thermotoggle: a heater above its target never runs its EnergyDraw, yet its
full draw (1000-2500/s) was charged every tick. On an idle station that kept
the reactor in permanent deficit, overloading at overload efficiency. The bus
now skips a consumer whose group has a closed thermostat ahead of it, the same
rule it already applies to inactive items; Thermotoggle.Open is the one
statement of when a thermostat is open, and Execute returns it.

Tests (Soul's F2; S17 survived before): from a hull at one uniform temperature,
one tick below the heater's target raises its cells and one above does not, so
the heater's own contribution is measured with no reactor heat in it; and the
bus bills the heater's draw below its target and not above.

This does not keep an idle station warm (Soul's F1, reported separately): the
reactor's throttled idle heat alone still drives it past its plateau.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:30 +02:00
Meta Vens
072a56f0b4 One loose fit rule for hardpoint gear
Operator ruling, 2026-09-30: "Hardpoint fit is loose: nobody's gonna stop you
from putting a small reactor in a large reactor's hardpoint." There is one rule,
HardpointData.Takes: gear of the hardpoint's type fits when its shape, at the
hardpoint's rotation, lies within the hardpoint's cells. TakesAt is the same
rule at one offset, and Entity.ItemFits (equipping, save load, presets) now
asks it instead of repeating the containment test. Generation's hardpoint
picks, HasHome (so station stock and loadouts), product reuse and `AetherDb
hardpoint-fit` all read Takes.

Generation keeps its own placement preference, named IsFilledBy and not a fit
rule: it offers gear that fills the hardpoint when any is on offer and falls
back to anything that fits only when none is, so loadouts change only where a
hardpoint used to stay empty. RestoredHullsTests pick fillers through
IsFilledBy.

Consequence: the Autocannon, Vulcan, scorched void policy, Notorious, pretty
pretty bang bang, Manhattan, plight, DeathCluster, Small Drive and pswarm now
have a home and are offered. Still homeless: CShot RainbowLite Lazer,
ChargeBlast SG, ChargeBlast+-, OK Disperser.

Tests: generation offers exactly the sold hardpoint gear some hull fits; a 7x7
design no hull fits is offered only once a hull that takes it exists; a 5x5
Reactor hardpoint nothing fills still gets a reactor; equipping and the rule
agree for every hull, hardpoint and design; the homeless list is stated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:28 +02:00
Meta Vens
87fae6e4f0 Content: damage curves for the five sold weapons that had none
Soul's F4: LRMM72, SRMM72, Autocannon, pswarm and plight had DamageCurve ==
null, and once they had products NPCs were generated with them and
CombatState.SampleDps threw at InstantWeapon.cs:64 / ChargedWeapon.cs:81.
A transient `AetherDb damage-curves [apply]` copies each one's curve from its
nearest comparable weapon, same class first, then closest range and damage:

  Autocannon <- DeathCluster (auto-fire Ballistic, 4 cells, range reaching 1000)
  LRMM72     <- GT 3K (the only other unguided launcher)
  SRMM72     <- scorched void policy (guided; 750 range and 128 damage inside its 500-1250, 128-512)
  pswarm     <- scorched void policy (guided; identical damage, range, cooldown)
  plight     <- ChargeBlast+- (charged Energy; nearest range)

Every curve in the catalog is the same one, keys (0, 1, 0, 0) and
(1, 0, -1.7656243, -1.7656243): full damage at minimum range falling to none
at maximum. Test: every weapon a product sells has a damage curve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:46:27 +02:00
Meta Vens
cb96f77c86 Mining Cut 3 tests: two-sensor parity, the cap at one, and a chunk's bearing
- ChunkInfoMatchesAnEntityHeldStillUnderTwoSensors pins that the settled value
  divides the summed rate by the number of sensors as well as the decay.
- ChunkInfoIsCappedAtOne pins the saturate the per-tick rule applies.
- AChunkTargetBearsThroughItsOwnPosition pins the arc gate reading a chunk's
  planar position (x and z, not swapped) and that a chunk never safes a weapon.
  The fixture's settings gain a 90-degree default arc for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:03:59 +02:00
Meta Vens
197c47c4ff Scenarios map: F3 ruled, hardpoint fit is loose (one rule everywhere)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:54:23 +02:00
Meta Vens
99adb2fc73 Scenarios map: Soul on batch 2 (do not merge; reactor burnout, inert heater test, two fit rules, null damage curves)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:35:15 +02:00
Meta Vens
2c3d4005b6 Scenarios map: station reactors per manufacturer (B); tractor/pickup becomes its own campaign
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:02:32 +02:00
Meta Vens
adad301b7a AetherDb: retire the product-gap and station-reactor one-shots
Both landed their content (653ba490, the station reactor commit); git history
keeps them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:36 +02:00
Meta Vens
d91ab8daf9 Generation never offers gear no hull can mount
Operator ruling, 2026-09-30, on the Autocannon: "Leave the autocannon unsold,
we'll need to author a bunch more hulls before all the gear variety in the game
has a home." The fit rule gets one owner, HardpointData.Takes (the gear's type,
laid in at the hardpoint's rotation, filling every cell); LoadoutGenerator's
hardpoint picks, its reuse of a previous product and `AetherDb hardpoint-fit`
all read it. RandomProducts, which both station stock and NPC loadouts draw
through, offers only gear with a home: Tool gear, hulls, or hardpoint gear some
hull in the catalog takes. The Autocannon keeps its product and price.

Test: the Autocannon is never drawn in 2000 draws of its hardpoint type; after
a scratch hull whose hardpoint takes it is authored, it is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:35 +02:00
Meta Vens
5c3cd599ac Zone: wait for last tick's belt tasks before clearing the orbit cache
Update cleared `_updatedOrbits` and only then waited on the previous tick's
asteroid-belt tasks, which read the cache through GetOrbitPosition. A task
still running could see the set mid-clear ("concurrent update ... corrupted its
state") or recompute an orbit into last tick's position. The wait now comes
first.

Test (Soul's orbit counter, committed): 3000 back-to-back 0.02 s ticks of a
quiet arena, and no orbit stands still against its parent. Clearing first gave
500+ stalls or the corruption exception. Measured against the parent because a
moon can genuinely pause in zone space: one such reading (tick 1321, a moon
whose motion cancels its planet's) is real motion, not the race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:34 +02:00
Meta Vens
b3e7995ceb Stations: a station reactor, so the heater has power
Operator ruling, 2026-09-30: "Yep, we need a station reactor." Zenith's 16-cell
Reactor hardpoint had no design to fill it, so generated stations had no power.
A transient `AetherDb station-reactor [apply]` authored it from Manhattan, the
largest and most industrial reactor, scaled by cells (16/9):

  Station Reactor (GearData, Reactor hardpoint, full 4x4)
    mass 500 -> 888.9, price 750,000 -> 1,350,000 (to the nearest 50,000),
    charge 500..1000 -> 888.9..1777.8; every other value, the efficiency,
    overload and throttling stats and all stat terms, the roles (core,
    regulator), temperatures, durability and sound bank are Manhattan's.
  Product "Station Reactor" by Zhestokost (Manhattan's maker), default role
  quality.

Station generation fills the slot through its ordinary hardpoint pass. Tests:
every generated station carries one heater and a reactor; an idle station (a
quiet arena, nothing else running) holds its heater's cells above freezing over
the second five of ten minutes (unpowered they fell to ~247 K); a station hull
with no room for a heater fails generation by name instead of skipping it
(Soul's S11 survived before).

The station's border cells still sit near 265 K with the heater and reactor
running (the reactor core reaches ~433 K); how warm the whole hull should run
is left as a tuning question.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:01:32 +02:00
Meta Vens
555f8815ce Scenarios map: autocannon stays unsold; unfittable gear is never stocked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:57:56 +02:00
Meta Vens
a1564c7d03 Scenarios map: everyone gets a tractor beam; pickup follows the shield/pickup presentation contract
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:08:22 +02:00
Meta Vens
eff52bbd97 Scenarios map: station reactor, heater is tool gear, no save retrofit, pickup needs a tractor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 16:03:49 +02:00
Meta Vens
89ef80d298 Stations: every generated station carries a heater
Operator ruling, 2026-09-30: an idle station has no heat source and cools
toward freezing and invisibility, so station generation (LoadoutGenerator, the
one owner of station loadouts) equips one heater after the docking bay, from
the products whose design is Tool gear with a low-pass Thermotoggle and Heat,
the cockpit's thermostat composition. It is required, like the docking bay.

Not yet warm: generated stations have no reactor (no reactor product fits
Zenith's 16-cell Reactor hardpoint), so the heater's EnergyDraw gets no supply
and the station still cools (280 K to ~247 K over ten idle minutes). The test
that an idle station stays above freezing waits on that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:32 +02:00
Meta Vens
f4703e8288 Scenarios Cut 1: every unsold design is a scenario test design
Q3 with the 2026-09-30 ruling: a design no product sells is a scenario test
design and nothing else. A test design is recognised as one a scenario places:
its preset's hull or a slot of it, or cargo it carries. The census holds for
the shipped catalog (today there is no unsold design at all), and in a scratch
copy a new unsold design is flagged until a scenario places it, once through a
preset slot and once as an entity's cargo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:30 +02:00
Meta Vens
653ba490a7 Scenarios content: delete five industrial placeholders; products for four weapons and the heater
Operator rulings, 2026-09-30 (docs/scenarios-cut.md, "the ten real designs with
no product"), landed through a transient `AetherDb product-gap [apply]`:

- Deleted, nothing referencing them: Assembly Line, Deep Ore Extractor, Surface
  Ore Extractor, Refinery, Shipyard (RTS-era placeholders, price and durability
  0, three with unreadable behaviour entries).
- Products, maker taken from the nearest analogue's product:
    Autocannon  -> Autocannon by Zhestokost (DeathCluster: Ballistic, 4 cells, AutoWeapon)
    LRMM72      -> LRMM72 by Rossum & Douglas (GT 3K: the only other unguided launcher)
    SRMM72      -> SRMM72 by Death Monkey Explosives (scorched void policy: guided, nearest size and price)
    Tractor Beam -> Space Tractor by Ewan Hart Inc (no analogue; the wishlist's
                   "Space Tractor: It's a tractor. In space.", content-batch-one section 10)
    Industrial Thermostatic Heater -> same name by Lightsail Express (Cockpit 2x2,
                   the same Thermotoggle/EnergyDraw/Heat group)
  Each product carries its design's roles at the default quality (0.5 +- 0.15).
- The heater design kept (operator), with Price 0 -> 100,000 (between Cockpit
  2x2 and Fire Control Array) and Durability 0 -> 100 (Cockpit 2x2's): at zero
  price generation never offers it, at zero durability it never comes online.

The rewrite stores every weapon record at the current schema, so
FireControlCut124's shipped-catalog check now expects an Exact migration
report instead of drift with slot 32 defaulted. `AetherDb census` reports no
unsold design. Tractor Beam keeps price 0, durability 0 and no behaviour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:18 +02:00
Meta Vens
27598a464a BaseState: an includeChildren walk keeps its state in locals
AddTransition's graph walk kept its visited, leaf and ignore sets in static
lists, so two Minions built at once on different threads (zones are built in
parallel) walked and cleared each other's state. Soul hit it as "collection
was modified" during parallel test runs. The sets are now the call's own.

BaseStateTests starts sixteen walks together behind a barrier, fifty rounds,
over prebuilt 200-state chains; with the statics restored every run failed
(several hundred of 800 walks wrong or throwing); with locals, clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:12:41 +02:00
Meta Vens
ff75b8ea34 Scenarios Cut 1: a stance survives docking; it goes only with an entity gone for good
Every entity's zone-removal subscription dropped its IFF override for whatever
left the zone, and TryDock removes the docking ship, so a scenario stance was
lost one way (the other entity forgot; the docked ship, deactivated, kept its
own) as soon as the player docked. The removal event already tells the two
apart: TryDock parents the ship to its dock before removing it, and every
leaving-for-good path (death, warp, unload) leaves with no parent. The override
is now dropped only for an entity that leaves unparented.

Tests: a hostile stance holds both ways, including the live hostility each side
tracks, across dock and undock; a destroyed entity takes the player's stance
toward it with it. UndockingAdmitsWithNoAgent commits Soul's probe: undock
admits unpiloted, active, with no agent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:09:12 +02:00
Meta Vens
929020e7df Scenarios Cut 1: a quiet arena drops a story station's turrets too
The quiet-arena test ran with an empty Narrative directory, so the story-station
branch of ZoneGenerator never ran under Ambient: false and keeping its turrets
went unnoticed (Soul's S06). The test now places a story station in the entrance,
as the narrative loader would, and checks it is generated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:00:44 +02:00
Meta Vens
178897ce7a Scenarios Cut 1: a failed staging reports what it admitted, not a crash
"Zone unchanged on failure" was defended only by xunit formatting an entity
sequence until the test host overflowed its stack. SafeAssert.Unchanged compares
the zone's entities and agents by identity and order and names what changed by
hull name; every Assert.Contains over zone.Entities in RunStartTests goes through
SafeAssert.In for the same reason.

AMissingDesignFailsNamedAndChangesNothing gains the partial-admission case: a
player and a piloted entity that build cleanly, then a later entity whose preset
is missing. Admitting the built player before the all-or-nothing return now fails
by name ("the zone's entities changed, 5 -> 6: added [Djinni]").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:59:50 +02:00
Meta Vens
b7ba401981 Scenarios map: stations spawn the heater (ruling A); heater is generic gear
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:48:49 +02:00
Meta Vens
48e638b8a8 Scenarios map: the Industrial Thermostatic Heater stays (stations need it)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:44:46 +02:00
Meta Vens
de2c659c55 Scenarios map: the ten product-less designs (industrial deleted, weapons get products)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:42:45 +02:00
Meta Vens
d24acff7b4 Catalog: author the "Asteroid" field kind (operator review)
tools/AetherDb field-kinds apply, run on Yggdrasil against catalog oid
2aa79c0a. One FieldKindData record: "Asteroid", cross-section 5 per schematic
cell, generation weight 1. Without a kind every belt is dark (Cut 3), so this
is what makes rocks seeable in play. The two numbers are placeholders for the
operator to review; Cut 7 authors the full content. If the catalog changes
upstream before this merges, rerun the command on the new catalog rather than
merging the binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:00:27 +02:00
Meta Vens
410173eb27 Fire control test: a catalog rewritten since slot 32 loads its weapons exactly
ShippedCatalogIsNeutralOnBlastRadiusAndFuse also pinned that every stored
weapon record predates slot 32 (CompatibleDrift, slot 32 defaulted). The field-
kinds authoring pass rewrote every catalog record through CultCache, so the
weapons now store slot 32 and load Exact. The rule the test protects stands:
no weapon authors a blast radius or fuse, and a record that does drift may
drift by slot 32 and nothing else.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:00:25 +02:00
Meta Vens
7e7c08bc73 Scenarios Cut 1: pin that admission activates
An admitted entity that was never activated tracks no hostility, so
targeting and grudges never see the stance. The stance test now also reads
each side's live EntityHostility, which only activation populates; dropping
Activate from Zone.Admit survived the suite before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:59:43 +02:00
Meta Vens
2724a0d8a7 Scenarios Cut 1: observe an unpiloted ship's steering, not its position
The zone's gravity moves every ship, so an unpiloted scenario ship drifts
(about 14 m over 5 s at the test's spot) with nothing flying it. The rule is
"no agent steers it": the test now checks its movement and look inputs stay
untouched every tick, and that it still has no agent afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:10:03 +02:00
Meta Vens
09d037cb41 Mining Cut 3 tests: tick a ship once before it looks, and open the shipped catalog copy scoped
A ship's equipment comes online on its first tick (UpdatePerformance), so a
sensor sees nothing before it: the chunk tests tick each observer once before
asking what it sees or picking a target. The generation test opens its copy of
the shipped catalog through a registry scoped to the shipped assembly, as
RestoredHullsTests does, so the test assembly's own catalog global is not
demanded of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:08:08 +02:00
Meta Vens
efd5118322 AetherDb: field-kinds authors the first field kind, "Asteroid"
A chunk's reflectivity comes from its belt's kind, so a catalog with no
FieldKindData leaves every belt dark. The command dry-runs by default and, with
"apply", authors "Asteroid" (cross-section 5 per schematic cell, weight 1)
through one validated Commit batch. Both numbers are for operator review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:57:41 +02:00
Meta Vens
3d17ba035b Mining Cut 3: the parked ResourceScanner stops evaluating stats nothing reads
Chunks are detected by reflected light (Cut 3), not by a scanner. The
behavior's per-tick Update of Range, MinimumDensity and ScanDuration had no
reader anywhere; it goes, with the three properties and the interface.
ResourceScannerData stays authored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:57:04 +02:00
Meta Vens
15723f4037 Mining Cut 3: a chunk is a target, detected by reflected light
- Entity.Target is one slot of TargetRef, read-only from outside
  (IReadOnlyReactiveProperty); Entity.SetTarget is its one writer. A chunk is
  taken only while the entity can see it, so a rock in darkness cannot be
  picked. Every handler, agent, turret and test writes through SetTarget.
- Entity.ChunkInfo (Q14 A): the value the per-tick sensor rule settles at,
  computed on demand through Sensor.PassiveRate/Sensor.Gain -- sum of the
  active sensors' passive rates over (sensors x TargetInfoDecay), capped at 1.
  Stored nowhere; no per-tick loop over chunks. ChunkVisible is the detection
  threshold through the chunk path.
- The lost-track rule reads through the chunk path: Activate's reconciliation
  and a per-tick check of the one slot drop a chunk target that has gone dark.
- Entity.VisibleChunksInReach (Q13 A): visible chunks within the longest range
  among active weapons -- the one reach rule for cycling and programmatic picks.
- Entity-only readers take .Entity: TargetedBy/TargetedByCount, target items,
  the stance gate (a chunk has no stance), lock (Q12 A: never on a chunk),
  turrets, Combat, Minion, FireControl (a chunk fires untargeted until Cut 4).
  TargetRange and the arc gate read a chunk's planar position.
- ActionGameManager: the reticle and next/previous offer visible ships and
  visible chunks in reach; nearest stays enemies-only; the target panel,
  indicator and fire-control debug take TargetRef. EntityInstance reads .Entity.
- MiningCut3Tests pin parity, darkness, monotone brightness, wear and break,
  reach, the chunk query, target survival and loss, TargetRef equality, lock,
  and field-kind assignment at generation and first load.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:56:39 +02:00
Meta Vens
d76756fd68 Mining Cut 3: field kinds, chunk visibility, the chunk query, and TargetRef
- FieldKindData, a catalog document (Q11): a kind's reflectivity per schematic
  cell and its generation weight. AetheriaStores routes it to the catalog.
- AsteroidBeltData.Kind, key 10 (Q16 B). FieldKinds.Assign is the one pick (a
  weighted choice by a stable hash of the belt's key); FieldKinds.Ensure gives
  a kindless belt its kind and saves it. ZoneGenerator calls it at generation
  and Zone calls it on first load, so an old belt is assigned once by the same
  rule and keeps its kind after later catalog edits.
- Zone.ChunkVisibility: Reflector's rule for a chunk -- kind cross-section x
  area in schematic cells x the light on it. Stored nowhere; a worn chunk dims,
  a broken one or a kindless belt's is dark.
- Zone.ChunksNear: the one chunk query, skipping belts whose annulus cannot
  reach. AsteroidBelt gains InnerRadius for that skip.
- TargetRef: an entity, a chunk, or none, with value equality and no ==.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:56:24 +02:00
Meta Vens
a1d27cfc04 Mining Cut 3: extract the detection gain rule into Sensor.Gain
Sensor.Execute's ping and passive gain arithmetic moves, term for term and in
the same multiplication order, into one static function, Sensor.Gain. The
entity loop calls it; Sensor.PassiveRate calls it for the on-demand chunk
query that follows. SensorGainExtractionChangesNothing holds the recorded
EntityInfoGathered trace bit for bit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:56:13 +02:00
Meta Vens
cb4a1dbd8a Mining Cut 3: record the per-tick detection trace before Sensor.Gain is extracted
SensorGainExtractionChangesNothing drives a fixed scene (two reflecting ships at
different ranges and bearings, a ping part way through) and pins the observer's
EntityInfoGathered trace, bit for bit, by hash. The golden value is recorded
against the pre-extraction Sensor.Execute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:55:29 +02:00
Meta Vens
72c58d365f Scenarios Cut 1: a bare hull updates
Entity.Update walks _orderedEquipment, which only TryEquip and TryUnequip
set, so an entity nothing was ever equipped on threw a
NullReferenceException on its first tick. Scenario presets stage bare hulls
(a turret, an unpiloted target), and RunStartTests found it: MapEntity now
sets the ordered equipment to the hull alone when it adds the hull.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:52:44 +02:00
Meta Vens
f527154e26 Scenarios Cut 1: StartGame stages through RunStart; the game's joins admit
StartGame's new-run branch no longer generates, unpacks or admits the
player: RunStart generates the arena and stages the run, and StartGame
enters the zone and binds the returned player (docs/scenarios-cut.md, 2.2,
deletion line). PopulateLevel's warp arrival and the spawnturret console
command admit through Zone.Admit, unpiloted. The console commands stay (Q4);
give's hull route moors a ship at the docked entity and joins a zone only
through Entity.TryUndock, which already admits.

Needs the Unity batchmode compile; Assembly-CSharp is not built headless.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:35:19 +02:00
Meta Vens
85ebe036e1 Scenarios Cut 1: RunStart stages a new run; the Scenario catalog type
RunStart (ServerShared, no Unity type) owns what a new run starts with
(docs/scenarios-cut.md, 2.2):
- GenerateArena: the galaxy's entrance pack, generated under the scenario's
  Ambient rule. ZoneGenerator.GenerateZone gains `ambient`; false keeps
  planets, orbits and stations and generates no ship, turret or wanderer.
- Check: every failure staging a scenario would hit, found with no zone,
  touching no store.
- Stage: all-or-nothing. With no scenario, the generated starting-hull ship
  at the origin, as StartGame built it. With one, the player preset and the
  entities at their authored place and heading with cargo, stance set both
  ways through SetIff, a Minion for each piloted one; all through Zone.Admit.

Scenario (aetheria.scenario v1) joins AetheriaStores.CatalogTypes.
RunStartTests stage into a real prelude arena from the shipped catalog and
authored settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:35:18 +02:00
Meta Vens
5706b657e3 Scenarios Cut 1: Materialize builds product-less designs unbranded; the hull picks the entity
Two rules on Loadouts.Materialize (docs/scenarios-cut.md, 2.2, Q3):
- A design no product makes is outside the economy and is built unbranded,
  with no maker, at Loadouts.UnbrandedQuality (.95, the console give's).
  A design whose products are all unavailable still fails, as before.
- The hull's type picks the entity: a ship hull builds a Ship, a turret hull
  an OrbitalEntity with no orbit; a station hull is refused. Materialize now
  returns Entity.

Loadouts.Resolve is the one rule for how a design is built; RunStart uses it
for scenario cargo. LoadoutTests.MissingDesignReports no longer uses the
product-less "Orphan" as a failure (it now builds); two tests pin the Q3 rule
and the unavailable-product contract it does not loosen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:33:00 +02:00
Meta Vens
fbda4c74fb Scenarios Cut 1: Zone.Admit is the one admission into a zone
Zone.Admit(entity, piloted) adds the entity to Entities, activates it and,
when piloted, gives it the zone's Minion. It is the only writer of
Entities.Add and the only creator of agents (docs/scenarios-cut.md, 2.2).
The constructor's pack loop admits every packed ship but the player's as
piloted and keeps its own origin-scatter rule, which is generation
placement, not admission. Entity.TryUndock admits the undocked ship
unpiloted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:32:59 +02:00
Meta Vens
39cec96a1e Mining maps: Q14 A and Q16 B are operator rulings; Cut 3 unblocked
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:14:55 +02:00
Meta Vens
702b454bea Scenarios map: record Q1-Q4 rulings; Cut 0 cancelled
Q1 A, Q2 B, Q3 A. Q4: every console command stays ("never toss a
single one"), so Cut 0 is cancelled and give/spawnturret admit through
Zone.Admit in Cut 1. Self restores the smoke weapons in the operator
tree when Cut 4 lands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:14:40 +02:00
Meta Vens
a93625c2f3 Ships map: mount anchors only for weapons, radiators and thrusters
Operator ruling 2026-09-30: mount points exist only for externally
visible hardpoints. No equipment role, no plain mount. Articulation
points stay; they are not mounts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:14:27 +02:00
Meta Vens
6f5ce55138 Ships map: S2 status (landed, Unity smokes pass, operator checks owed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:28:10 +02:00
Meta Vens
48cabc5f85 Ship S2: the prototype root is kept across scenes only in play mode
DontDestroyOnLoad throws outside play mode, so the edit-mode play smoke
failed before it reached assembly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:14:00 +02:00
Meta Vens
e9195763b6 Ship S2: the Unity-generated meta for ShipModPlaySmoke.cs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:13:10 +02:00
Meta Vens
910b51c3f8 Ship S2: an Editor smoke that composes, preloads and instantiates a mod ship the way ZoneRenderer.LoadEntity does
ShipModPlaySmoke.Run asserts thruster and weapon hardpoints, the hull MeshCollider and the map icon, prints
SHIP_MOD_PLAY_SMOKE and exits explicitly. The authoring doc gains a Unity batch smokes section.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:57:47 +02:00
Meta Vens
4f6bbbb8da Ship S2 smoke fixture: the node index test names the weapon nodes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:54:02 +02:00
Meta Vens
5b58b947bd Ship S2 smoke fixture: the weapon mount takes the hull other cell instead of moving the thruster off the schematic
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:53:26 +02:00
Meta Vens
54dcf5214c Ship S2 smoke fixture: the generated GLB carries a tetrahedron mesh on the map, collider and thruster anchors, plus a weapon mount and muzzle
The fixture package now has real vertices (BIN chunk written by the generator, no committed bytes), an energy hardpoint "gun" with a
muzzle anchor, and the thruster moved outside the schematic, so ShipModShips.Assemble accepts it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:52:47 +02:00
Meta Vens
34319b0df1 Ship S2 fixes: RequireDesigns refuses nulls explicitly, and a failing Compose falls back to the shipped catalog
- RequireDesigns names the null (entity, item, zone record, lot, lot ledger) instead of catching NullReferenceException.
- ResolveCatalog reports a Compose-level failure as an exclusion covering all mods and boots the shipped catalog.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 10:06:16 +02:00
Meta Vens
8f8b72be3c Ship S2 fixes: the edge-of-range hardpoint test re-roles its anchor with its type
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 08:34:54 +02:00
Meta Vens
5ed3b759c4 Ship S2 fixes: the RunSave designs fixture resolves its gear ref
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 08:31:24 +02:00
Meta Vens
54917bb39d Ship S2 fixes: structural anchors are not mounts, mod presets refused, one bad mod never bricks the boot
- Validate: a hardpoint's anchor role is fixed by its type (thruster-emitter, radiator-mesh, else articulation); ShipModPlan's
  duplicate role check is deleted.
- Loadouts.Commit refuses a preset naming a mod design (mod-hull:/mod-ship:), so the shipped catalog never references a mod.
- Compose quarantines each package: a bad package is excluded and named, a collision excludes every package involved; the
  game boots on the rest (or the shipped catalog) and the main menu lists the exclusions.
- RequireDesigns refuses a save with a null item or lot instead of throwing NullReferenceException.
- Tests: per structural role, muzzle id ties, every slot/zone/lot in RequireDesigns, listing order, exclusion cases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 08:30:52 +02:00
Meta Vens
7eebd21d29 Ship S2: commit the .meta files for ShipModShips and ShipModPlan
Unity generated them on import; without them the two scripts' GUIDs are
unpinned and differ per checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:20:33 +02:00
Meta Vens
81abd8ef2b Ship authoring doc: the game reads mod ships (S2)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 07:53:38 +02:00
Meta Vens
86318ec014 Ship S2 tests: muzzle order against ids, every weapon type, PackageOf validates
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 06:46:17 +02:00
Meta Vens
460bb85ed0 Ship S2: the game composes and loads mod ships
Boot opens the derived catalog when GameData/Mods holds packages
(ShipModCatalog.ResolveCatalog), preloads each hull's GLB into an assembled
inactive prototype (ShipModShips), and LoadEntity clones it when the hull names
a Visual. ShipModPlan decides which anchor fills which ShipInstance slot; a
ShipModTemplate prefab carries the shared effects. Continue refuses a run that
names a design the catalog no longer holds (RunSave.RequireDesigns).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 06:43:52 +02:00
Meta Vens
f470c1b775 Ship S1 fixes: refuse the retired embedded hull, one body per hull, closed validator gaps
Load reads the raw ship authoring payload and refuses a non-nil retired key 1 (the
pre-S1 embedded hull) naming the old shape, so a stale hull is no longer silently
ignored; ship_cc.py refuses the same file on read and therefore on every save.

A hull naming both a Unity prefab and a visual is refused by one predicate
(ShipAuthoringStore.RequireOneBody), called by Validate and by Compose over every hull
in the derived catalog, shipped ones included; a whitespace-only Prefab is unset. This
replaces the mod-ship-only "cannot name a Unity prefab" check.

The validator also refuses non-finite or negative hardpoint Armor and FiringArc, an
undefined HardpointType or ItemRotation, and an anchor Role outside the eight the
schema documents.

Load wraps MessagePack decode failures with the file path. Python replace_layout
refuses non-boolean layout and hardpoint-footprint cells.

Tests: exact Visual key comparison, HullData.Visual at key 32, a save refreshing
stored_at, plus one case per new refusal. HullData.Visual is now [Inspectable] like
Prefab (Unity editor only; not compiled here).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 06:18:20 +02:00
Meta Vens
d1648800ab Ship authoring doc: one hull record, a hull names its visual
Owner, shared-path and compose paragraphs describe the S1 shape: a ship
file holds a HullData and the ShipAuthoring visual it names through
HullData.Visual, and the derived catalog holds one hull per mod ship.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 03:48:47 +02:00
Meta Vens
1702e0549f Ship S1: one hull record, and a hull names its visual
A mod ship file now holds a HullData at mod-hull:<id> and the ShipAuthoring
visual package at mod-ship:<id>. HullData.Visual (key 32) is the typed ref
between them; ShipAuthoring.Hull (key 1) is retired.

- One joint validator over (hull, visual) is the only semantic check; Load
  owns the file structure (one hull, one visual, deterministic keys).
- Compose copies the mod store's records verbatim, so the derived catalog
  holds one hull per mod ship.
- ship_cc.py edits the hull record's slots directly; the body[HULL_SLOT]
  indirection is gone.
- The package fixture is generated from ShipAuthoringTests.Fixture() (glTF
  scene included) and exported when AETHERIA_SHIP_FIXTURE_DIR is set.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 03:06:43 +02:00
Meta Vens
de1b5b8fa2 Ships map: S0 Unity compile and smoke passed; fixture package owed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:57:08 +02:00
Meta Vens
01e9db1c27 Ship S0: correct the authoring doc, record the merge status in the map
Applies corrections 1-4 of docs/moddable-ships-cut.md B.1 to
docs/moddable-ship-authoring.md: label the Quiet probe numbers as unrecorded,
name the double-held mod hull in the derived catalog, name the ShipAuthoring
catalog-routing invariant, and scope "same semantic validator" to C# callers.
The map's status header gains the S0 result (615 tests on the merge), the
S-Soul status, the corrected TradeMenu.cs path, and anchors re-taken against
the merged tree.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:26:50 +02:00
Meta Vens
18e12d81ce Merge master (fire control 12) into codex/moddable-ships 2026-09-30 02:21:09 +02:00
Meta Vens
eb1401c20d Mining M0: correct the map against the v2 refresh
Applies corrections 1-11 of the refresh's A.1 to docs/mining-cut.md: the status
header records the 2026-09-30 rulings, Q14 and Q16 stay open (they block Cut 3),
and M-Soul content is unknown (the mutation sweep at 22fb4021 stands in). Cuts 3
and 4 are replaced with the refresh's versions; Cut 6 is deleted with a history
pointer (Q9 = C); the scanner-as-chunk-sensor plan and the fallback range tunable
are struck; Q2's detection paragraph is replaced with the operator's 2026-09-30
correction; the FireControl target table is marked history at 8bd25f6f.

The refresh's Cut 5 and Cut 7 texts are not folded in; the header says so.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:19:11 +02:00
Meta Vens
fe38f28865 Close the gaps a mutation pass found in the new ship tests (S-Soul F1-F3)
A pass of 137 hand-written mutations over ShipAuthoring.cs, ShipModCatalog.cs
and ship_cc.py, run against the tests from the last three commits, left six
surviving or unrunnable. Each is resolved:

- Validator: the hull Width/Height < 1 guards and the opacity IsInfinity
  guard could not change any outcome (an empty grid has no occupied cell;
  +Infinity exceeds 1 and -Infinity is below 0). Deleted.
- Two accepted shapes had no test: a hardpoint footprint with empty cells
  beside occupied ones, and an empty ParentId meaning no parent. Added.
- The GLB header length was pinned only from above. Added the shorter case.
- Compose's working-directory cleanup was invisible because the assertion
  listed files, not directory entries. It now lists both.
- ReadPackage runs the catalog's item validation on the hull (the derived
  catalog must reopen); that call now has a test.
- Python: a single non-ship record, a non-array payload long enough to fill
  every slot, and a hardpoint-only change to the layout revision each had a
  surviving mutation. Tests added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:14:10 +02:00
Meta Vens
fc90e93618 Merge master (fire control) into codex/mining
Conflict in Zone.cs: kept master's TryGetShot, kept Cut 1's deletion of the BeltUpdates field.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 02:12:50 +02:00
Meta Vens
65c6349537 Map the scenario cut: authored arenas launched from the main menu
Imagination pass 1 against dcd7bbc5, designed from the operator's own
words (quoted in the map). Cuts 0-4; four operator questions open
(Q1 arena in a real run, Q2 who records results, Q3 test-only designs,
Q4 which ad hoc affordances retire).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:11:09 +02:00
Meta Vens
dcd7bbc5f6 Merge fire control (codex/fire-control-12) into master
Fire-control batches 1-8 with Soul passes, verified headless (Aetheria
Shared tests). Play smoke 2026-09-30: compile clean, steps 3-6 played
(pass/partial), steps 7-20 and fire-control checks A-F unplayed. The
operator preferred to merge now; Self ruled merge, with the unplayed
checks carried as open behaviours to verify through authored main-menu
scenarios (new Eureka cut). Report: docs/merge-to-master-checklist.md
section 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:32:19 +02:00
Meta Vens
d3075eb06d Record the play smoke stop, operator direction and stale checklist expectations
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:15:06 +02:00
Meta Vens
f935c29b4b Fix console text input and route give through ship commissioning
- ConsoleView appended the control characters text input delivers (\b, \r),
  so Backspace inserted a glyph and Enter's \r got every command refused
  since d503f076 made the parser refuse instead of strip. Control characters
  are no longer text; Backspace deletes like Delete.
- give reports an unknown name or a full cargo bay. A ship hull is refused
  unless docked, and when docked is commissioned through
  ActionGameManager.CommissionShip, the primitive TradeMenu.Buy now uses: a
  bare player ship moored at the docked entity, no docking bay. Non-ship
  hulls are refused.
- Record play smoke results for steps 3-6 and the docking bay finding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 01:04:11 +02:00
Meta Vens
c6430c93e4 Make AetherDb the agent's data tool in project doctrine
Missing catalog or save capabilities are added to AetherDb as commands,
not written as scratch projects, loose scripts or byte readers. Records
the serializer options and the CultLib pin gate an agent hits on first use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:08:34 +02:00
Meta Vens
22fb402139 Mining Cuts 1-2: pin five chunk-surface rules that survived mutation
Every mutant of the Cut 1-2 chunk surface (Zone.ChunkExists, ChunkRadius,
Wear, EvaluateBelt, ChunkPose, PackZone/unpack, AsteroidBelt.Pose and its
sizes, ChunkId) was run against MiningCut1Tests and MiningCut2Tests. Six
survived; five are behaviour and get a test each:

- ChunkExists is false for a body that is not a debris field (a planet) and
  for a key naming no body.
- A hit on the exact respawn instant lands on the live chunk (Wear agrees
  with ChunkExists and ChunkRadius about the boundary).
- A chunk worn after respawning packs with no BrokenUntil.
- ChunkPose carries the worn size, and zero for a broken chunk.
- Chunk rotation wraps at one turn (the fixture never reached one before).

The Cut 2 fixture gains a non-belt body, and its settings the three curves
that body's constructor reads. The sixth survivor, a ChunkId hash that
ignores the index, changes no observable behaviour.

Tests only; no production change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:00:30 +02:00
Meta Vens
1f8c0ccd6d Give the Blender side tests and pin its hand-copied schema to C# (S-Soul F3)
ship_cc.py edited a ShipAuthoring record by bare slot numbers and hardpoint
positions (hp[3], hp[7:], raw[0..6]), and __init__.py copied the
HardpointType and ItemRotation enums by position. Nothing tested either
file and nothing tied the numbers to the C# [Key] attributes that own them.

- ship_cc.py names its schema facts once: the four record slots (each
  commented with the C# member it mirrors), HARDPOINT_MEMBERS (HardpointData
  member names in slot order), and the two enum name tuples. Hardpoint rows
  are built and read through encode_hardpoint/decode_hardpoint; replace_layout
  and the Blender operators no longer index a row by literal. __init__.py
  builds its enum items from the tuples. The rotation label
  "Counterclockwise" becomes "CounterClockwise", matching the C# member.
- tools/blender/tests/test_ship_cc.py (30 unittest cases, bpy-free, needs
  CultLib's cultcache-py and msgpack): read, replace_lines, read_layout,
  replace_layout (untouched slots and later-schema hardpoint slots preserved
  by mount id, schema catalog preserved, every refusal leaves the file
  byte-identical), the row codec, and capture_grease_pencil against stand-in
  objects.
- ShipSchemaPinTests (C#, 7 cases) reads ship_cc.py and fails when a slot
  constant, a HARDPOINT_MEMBERS name or position, or an enum name/value
  disagrees with the C# types, and when a serialized ship no longer has the
  nested array shapes the Python indexes (schematic [[w, h, cells]], cells
  x-major, hardpoint transform and footprint positions).

Reading the slots from the file's schema catalog instead was rejected: the
catalog lists only document members, and Hull, Shape and HardpointData are
nested types it does not describe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:55:46 +02:00
Meta Vens
1987009ba1 Pin Compose, ReadPackage and ReadNodeIds; refuse name collisions (S-Soul F2, F6)
Compose, ReadPackage and ReadNodeIds had no test. ShipModCatalogTests now
covers the derived catalog, the atomic replace of an existing one, every
failure path leaving the previous derived file byte-identical, the unsafe
source/output refusals, package binding (directory name, GLB existence and
extension, anchor node presence), and the GLB reader (each header guard, the
JSON chunk boundary, node index accounting, duplicate ids).

Writing them exposed three defects in Compose, fixed here:

- F6: AetheriaStores.CatalogTypes routes ShipAuthoring to the shipped
  catalog, and CultCache indexes names per concrete type with last writer
  winning while GetByName over a base type throws on a cross-subtype match.
  Compose checked keys only, so a mod hull named like a shipped item, or like
  another mod's hull, silently shadowed it or broke lookups. It now refuses
  a hull name matching any catalog ItemData and a ship ID matching an
  existing ShipAuthoring, naming the ship.
- The backing store writes a .lock file beside every file it opens, so each
  Compose left <output>.<guid>.tmp.lock behind, success or failure, once per
  boot. The working copy now lives in its own directory that is deleted whole.
- Deleted: the duplicate-ID check (ReadPackage already pins ID to directory
  name, so it could not fire) and ReadPackage's containment StartsWith
  (Validate already refuses rooted and `..` model paths on the same Read).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:47:13 +02:00
Meta Vens
5df72ba363 Pin every refusal in ShipAuthoringStore.Validate and Read (S-Soul F1)
Soul's mutation pass on 375d6bd4 found 8 of 9 validator mutations
surviving, including the `..` model-path guard and the prefab refusal. The
validator had five hand-picked cases. ShipValidationTests now carries one
case per guard: each starts from the valid fixture, breaks exactly one
thing, and names the message that guard alone produces. It also pins the ID
alphabet at both ends of each range, the accepted model-asset spellings
beside the refused ones, the range edges of point attributes, an anchor
naming its hardpoint as parent, and Read's exactly-one-record and
validate-on-load behaviour.

ShipAuthoringTests.Fixture becomes internal so the new file shares it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:46:44 +02:00
Meta Vens
97edf48cec Add the debug info panel and the shield panel test rig
ARPG.unity gains Debug Info Panel and Debug Info Text, which
ActionGameManager.DebugInfoText drives as the fire-control debug HUD.
FieldShieldTest.unity gains the ShieldInterceptor, ShieldEnvelope and
Panel prototype rig from shield-panel Cut 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:38:54 +02:00
Meta Vens
e0a802084e Use the generated accessor for Cycle Target Item
Regenerate AetheriaInput.cs from the committed Aetheria.inputactions so the
wrapper carries Cycle Target Item, and bind it through Input.Player like the
other target actions. The by-name FindAction lookup was a stopgap from when
the generator could not be run outside the editor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 23:38:48 +02:00
Meta Vens
113164fadb Record fire control batches 5-8 landing and their follow-ups
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:24:39 +02:00
Meta Vens
06001b57a8 Merge fire control fix batches 5-8: fused weapons follow player intent
One Solve decision feeds Fire, Inspect and Refuses. Literal arming distance
on every detonation path; no-lock rounds of any fuse stop at the first hull;
a round fired at a target that leaves does not burst; refusal is free,
cooldown included; AI decides per weapon and never fires a refused weapon;
the HUD shows the outcome. Soul passes 5-7; batch 8 closes their follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:21:12 +02:00
Meta Vens
7f317bd332 Freeze a guided round that waits on its verdict and place a positionless hit at its target
After its fade a round kept integrating Velocity through the BindingLifetime wait, then a Hit (which carries
no burst point) played HitEffect at the drifted position. The wait now holds still; a hit without a point
plays the effect at the round's target position, and is skipped when the round never knew one. OnEnable resets
BindingLifetime so a pooled split child, which is never bound, does not inherit the last round's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:15:53 +02:00
Meta Vens
742cb23f5b Gate a charged weapon's Activate on CanFire, and start a burst's cooldown with the tick it flew in
A released charge has a burst pending and no cooldown until its first round, so a second Activate in that
window started a second charge; Activate now asks CanFire. The round that starts a burst's cooldown does so
after the tick's decrement, which made every cooldown one tick long; it now charges that tick to the cooldown.
Pins both, and that a burst triggered after a fired one is not ready before its first round.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:15:51 +02:00
Meta Vens
819b282346 Pin that Combat picks no group whose weapon cannot reach the target
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:54:36 +02:00
Meta Vens
c0fb26fca1 Pin that a triggered burst is not ready before its first round
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:39:18 +02:00
Meta Vens
1c5872e7a8 Give the stance-test gun a burst and a cooldown
The default InstantWeaponData has Count 0, so the fixture gun never had a round to fire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:35:53 +02:00
Meta Vens
c4b628fad7 Resolve the stance-test gun before triggering it
A burst is sized from stats the first Execute resolves, so the untouched fixture gun fired nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:32:31 +02:00
Meta Vens
020a42fcb6 Execute the weapon directly in the stance tests
The stance fixture has a shooter the zone cannot tick; the weapon runs on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:31:38 +02:00
Meta Vens
7c1b1cd3d8 Tick the zone before reading the cooldown in the stance tests
BurstCount is set by the first Execute, so a trigger pulled with no tick has no burst pending. The
tests now run one tick and read whether the cooldown started.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:27:28 +02:00
Meta Vens
0e73bbac72 Read the pending burst, not Progress, as the mark that Trigger ran; sound the charged control by its own event
The cooldown now starts at a burst's first fired round, so Progress no longer moves at the trigger.
IffAndCombatTests read CanFire (false while a burst is pending) instead, and the charged-weapon
control uses the charge-start event name the sound bank resolves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:23:04 +02:00
Meta Vens
136fddf15a Start the cooldown at a burst's first unrefused round; refused charged weapons never charge
A burst whose every round is refused fires nothing and leaves no cooldown: the cooldown moves from
Trigger to the first round Execute does not refuse, and CanFire holds a triggered burst that has not
yet fired. ChargedWeapon.Activate asks FireControl before it starts charging, so a refused weapon pays
no charge heat or audio. InReach is deleted: Designated carries the one range test and the lock gate,
and Combat reads it. GuidedProjectile answers Resolve while alive and keeps its binding through the
shot's flight time, so a faded round still shows the simulation's detonation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:16:52 +02:00
Meta Vens
76e78db4b2 Record that a refused round starts no cooldown
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:52:21 +02:00
Meta Vens
d00d158007 Pin the flight distance of a pushed-out no-lock round
The mutation pass on the fuse fixes left one survivor: a no-lock round whose
aim ends inside the blast radius (a designated target out of arc) flew only to
its aimed point instead of the arming distance, and nothing noticed. Its arrival
is now pinned to the arming distance, beside the targeted case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:42:30 +02:00
Meta Vens
57c2560fc0 Fuse fixes: arming holds for every burst, no-lock rounds stop on the first hull, settle before user code
Operator ruling 2026-09-30: a no-lock round of any fuse stops at the first hull
on its aim line and detonates there (bomb fishing still bursts at max range on
a clear line). CommitBurst no longer special-cases Contact.

Soul's findings on 14f66634..7e620ff9:
- Arming (HIGH): a contact or delayed blast on a hull nearer the muzzle than the
  blast radius detonated at the hull. Armed is now the one owner of the arming
  rule; Solve plans its burst point through it and ApplyBlastHit pushes the hull
  point through it.
- A refused beam never starts (ConstantWeapon.Activate asks Refuses), so
  OnStartFiring no longer flashes visuals and audio for a beam that fires nothing.
- Step removes a shot from the queue before Apply runs damage observers, so a
  throwing observer cannot make the blast repeat every tick.
- AgentFires consults Solve for a fused weapon: a refused weapon is never fired
  and Combat's group pick no longer counts its damage.
- SingleAmmoBurst pays at its first unrefused round in Execute, judged with the
  Range that round flies with, instead of at the trigger on the previous tick's.
- Inspect reads Designated from Solve (FireSolution.Designated) instead of
  recomputing visible, in-range and locked; FireControlDiagnostic drops those
  three fields and the debug HUD shows the one. Combat's group range test is
  FireControl.InReach, the range half of Designated (a LockWeapon must be
  activated to acquire its lock, so Combat cannot ask Designated itself).

Tests pin each rule, plus the two surviving gaps: a pushed-out targeted round's
arrival at the arming distance, and the AgentMinHitProbability boundary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:31:59 +02:00
Meta Vens
63a2fcdaa4 Guided projectile: only the simulation's detonation shows an explosion
The overshoot branch of GuidedProjectile.Update (out of range, or flown past
its target) instantiated HitEffect whatever the simulation had decided. A round
the simulation never detonated could therefore explode on screen. The branch now
fades the round out; Resolve stays the one place a HitEffect is shown for a
detonation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:20:06 +02:00
Meta Vens
d3be00c23a Record the all-fuses first-hull ruling and the batch 5 Soul pass
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 20:10:06 +02:00
Meta Vens
7e620ff9f2 Run the refused-round cost test through Execute as well as the trigger
The trigger's own refusal check stopped a short-Range round before Execute
ever reached its refusal, so wear, heat, visibility and sound left ahead of
Execute's `continue` survived every mutation. The cost theory now also
authorises a burst directly, the way a trigger that passed leaves it, and the
separate ammo-only test folds into it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 18:51:57 +02:00
Meta Vens
8c63fbe50e Guided projectile: binding lives and dies with the projectile; no explosion without a detonation
Unity-only, compile-checked by reading.

* F5: GuidedProjectile.Binding is one owner: a new binding disposes the one it
  replaces, Kill disposes it, and OnDestroy does too, so a projectile torn down
  with its scene cannot leave an observer on the zone's subjects to touch a
  destroyed transform.
* F6: Resolve takes whether the simulation detonated. A miss (a contact or
  delayed round that missed, a target that left) fades out with no explosion.
* F7: BurstAt resets the previous target position and target velocity, so the
  retarget jump does not feed the guidance a bogus target velocity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 18:37:02 +02:00
Meta Vens
a193853d34 Fuse batch 5: agents fire per weapon, Solve owns the burst, refusal is free, arming is the blast radius
Operator rulings 2026-09-30.

* Combat and TurretController ask FireControl.AgentFires for each weapon. A
  fused weapon fires whenever its target is designated (Designated, the one
  visible / in-range / locked predicate PFire already used), whatever the arc;
  an agent never fires one at nothing. A direct-hit weapon keeps the
  AgentMinHitProbability threshold. The group's first weapon no longer speaks
  for the group, and the turret's own range test is gone.
* FireControl.Solve is the one decision about what a round does, extracted
  from Fire: Direct, Burst at a reach, or Refused. Fire, Inspect and the
  weapons' refusal check all read it. Inspect gains Outcome and BurstReach and
  the debug HUD prints them for fused weapons.
* A refused round costs nothing. InstantWeapon asks before its ammo and energy
  spend (at the trigger and at each round), ConstantWeapon folds the refusal
  into the gate its power request and Execute already share, so a refused beam
  draws no power, wear, heat or visibility and stops.
* The arming distance is BlastRadius, measured from the shooter's position and
  blind to hull size. HullAhead's exit, ArmingDistance and
  PendingShot.ArmingDistance are deleted; HullAhead survives as HullEntry for
  the contact fuse. A round fired at a valid target inside the radius is pushed
  out along its line but keeps its target, so a departed target cancels it.
* Step settles a shot's queue state before publishing about it, so a throwing
  presentation observer costs its own notification and cannot re-commit or
  re-resolve the shot on every later tick.

Tests: FireControlPerWeaponTests (new; includes a fused-beam fixture), the
arming tests in FireControlCut124Tests rewritten to the literal distance,
the hull-inclusive probe premises deleted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 18:36:59 +02:00
Meta Vens
96c2f6ba8d Record the literal arming distance and demoted-round rulings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:28:06 +02:00
Meta Vens
d6f1e19251 Record AI per-weapon firing, HUD outcome forecast, and free refusal rulings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:42:49 +02:00
Meta Vens
14f666347c Pin the arming-distance boundary: a Range equal to it fires
The clean mutation run left one survivor, `>=` for `>` in Fire's refusal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 17:27:47 +02:00
Meta Vens
543edee358 Guided rounds follow the committed burst and resolution; no-target launcher no longer throws
- GuidedProjectileManager passed target.transform to OnFireGuided for a
  no-target fused round: a NullReferenceException inside InstantWeapon.Execute
  after the shot was queued, which skipped audio, wear, heat and visibility
  and unwound Zone.Update. The tuple's transform is null-safe now, and the
  trackmissile console command falls back to the missile.
- Presentation follows the commit rather than predicting it. The manager binds
  each guided round to Zone.ShotCommitted (retarget to the burst point the
  commit names, so a Contact round bursts at its hull and a Range-clamped
  burst is not overshot) and ShotResolved (burst there, then). The binding is
  disposed when the projectile dies, so a pooled round does not accumulate them.
- Beams and barrel-fired projectiles stay with F5.

Unity-only; compile-checked by reading.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 17:05:15 +02:00
Meta Vens
24b4071b69 Arming distance: no round bursts nearer than its blast radius past the shooter's hull
Operator ruling 2026-09-30. A fused round's burst is at least BlastRadius
beyond the far edge of the shooter's own hull, measured along the flight line
against the hull as it stood at fire (HullAhead's exit). A close burst -- a
target inside that distance, in or out of arc -- is pushed out along the aim
and carries no target; a contact round is floored to it too.

- The F3 trigger gate is deleted. Fire refuses a round (returns 0) whose
  arming distance exceeds Range, per round, where Range is read after Execute
  refreshed it; InstantWeapon and ConstantWeapon skip a refused round.
- PFire's range, Inspect's range and the range clamp are planar (R7).
- HullEntryDistance becomes HullAhead (entry and exit); the max(...,0) clamp
  on entry is gone, the arming floor covers it.
- ShotOutcome.HasBurstPoint names the rounds that have a frozen burst point.
- SafeAssert: the tests no longer hand xunit an Entity, PendingShot or
  ShotOutcome to format; a failing assertion had been overflowing the test
  host's stack.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 17:05:14 +02:00
Meta Vens
1267efc9d2 Record that pivots own firing arcs (lands with HullData pivots)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:50:04 +02:00
Meta Vens
2d4474f859 Record out-of-arc, arming-distance and pivot-arc rulings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 16:49:36 +02:00
Meta Vens
9c0029931a Presentation follows the committed shot, not the selection (F7)
EntityInstance handed effect managers the shooter's selected target whatever
FireControl decided. A fused round whose target was invalid or out of arc
flies at none, and GuidedProjectileManager dropped a launcher shot with no
target entirely, so a real burst had no missile.

- Zone.TryGetShot: a presentation reads the shot the simulation committed
  (its target, its burst point) by the ShotId OnFire hands it.
- EntityInstance passes the shot's own target; a launcher round with none
  flies to the shot's burst point.

Unity-only; compile-checked by reading.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:27:54 +02:00
Meta Vens
640fa96787 Fused rounds fire out of arc; safe fuse; proximity misses type as Burst
Operator ruling 2026-09-30: a fused weapon with a selected but out-of-arc
target fires. Its round flies along the arc-clamped aim and bursts at the
target's range. Non-fused weapons still refuse.

- FireControl.ArcPermitsFire is the one trigger arc gate (fused weapons are
  exempt); Fire reads the same InArc through PFire's new designated/inArc
  outs, which replace `bears`. No valid targeting data still bursts at Range.
- F3: a fused weapon whose effective Range does not exceed its BlastRadius
  stays safed at the trigger (FuseCanArm, read from the runtime Range). The
  catalog check on Range.Min is deleted; it read the authored floor, which
  Evaluate can scale below.
- F4: a targeted proximity burst is pulled back along its line to Range.
- F8: a proximity round that detonates commits as Burst (or Hit); Apply's
  Proximity case collapses into the Burst path via Outcome.BurstPoint.
- Tests: arc-only and LockWeapon gates, out-of-arc burst, trigger gate,
  runtime-Range refusal, Range clamp, Burst typing, commit horizon, and
  Soul's adopted probes (aim clamp edges, contact point, target leaves,
  shooter destroyed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 16:27:46 +02:00
Meta Vens
6133a051a6 Merge origin/codex/fire-control-12 into hands/fuse-fix2 2026-09-29 16:11:47 +02:00
Meta Vens
e7bb1e14f0 Record the airburst intent ruling
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 14:02:42 +02:00
Meta Vens
91ed4ef91b Assert on the shot target and outcome identity without formatting entities
Assert.Null(shot.Target) and Assert.Same(committed, resolved) format the
entity graph when they fail, which overflows the xunit stack and crashes the
host instead of reporting a red. Use Assert.True with a message.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:50:41 +02:00
Meta Vens
f5c6729e7a No-lock fused rounds: aim, invalid targets, contact stops, outlived shooters
Operator rulings 2026-09-30 after Soul's pass on 8c002637:

- A no-lock round flies along Entity.LookDirection restricted by the mount's
  arc (FireControl.AimDirection: inside InArc's cone as is, outside it turned
  to the cone's edge; no aim falls back to the mount). The simulation had no
  aim clamp before; the old code used the hull-fixed mount direction.
- An invalid target (out of range, out of arc, not visible, not locked) counts
  as no lock for a fused round. PFire's gate is the one decider and now also
  reports `bears`; Fire reads it. The round carries no target afterwards.
- A no-lock Contact round bursts at the first hull its aim line crosses
  before max range, read through Lane's own cell admission (CellsOnLine,
  split out of Lane). Proximity and Delayed keep the max-range burst. Such a
  round commits at Fire, since it has no target facing to read late, and
  arrives when it has flown to the burst point. The seam for mining chunks is
  FireControl.ContactDistance.
- A round outlives its shooter: Step no longer cancels a shot whose source
  left the zone. Resolution reads the zone and the target; the shooter is an
  identity a shot carries. PendingShot.FireOrigin freezes where it left from.
- ShotOutcome.Result (Miss, Hit, Burst) replaces the stored Hit bool, which
  is now derived. A burst without a target is no longer reported as a miss,
  and the debug HUD labels it BURST.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:27:43 +02:00
Meta Vens
e3c9cbb282 Refuse a fused weapon whose Range does not exceed its BlastRadius
Soul: a no-lock round bursts at Range, so Range <= BlastRadius (or a zero
Range) lands the blast on the shooter. Made structurally impossible at the
catalog rather than policed at runtime: StatValidation.ValidateFuse joins
the checks CultRecordRefs.Validate runs on every Upsert, at the weakest value
the Range stat can take. Only a weapon that will detonate (a Fuse and a
BlastRadius above zero) is held to it.

AetheriaStores.Open now calls that same Validate for every equippable and
consumable document instead of carrying its own copy of the three checks, so
Upsert and Open can no longer disagree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:27:42 +02:00
Meta Vens
187caa7d81 Record the no-lock fuse rulings and their Soul follow-ups (2026-09-30)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:11:18 +02:00
Meta Vens
96321e4131 Record operator rulings on the moddable-ships map (2026-09-30)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:10:16 +02:00
Meta Vens
1d2db9acd5 Record operator rulings on the mining map (2026-09-30)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:09:45 +02:00
Meta Vens
3e8ee02276 Pin the no-lock fused shot: burst at max range, shooter unharmed
Proximity, contact and delayed shots fired with no target burst at Range
along a non-axis aim (2,1) and leave the shooter undamaged; the shot flies
there at the weapon's Velocity. A targeted proximity shot keeps the burst
point and the damage value measured at b66ba524 (5.65884256).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:28:11 +02:00
Meta Vens
8c00263740 A fused shot with no target bursts at max range along the aim line
Operator ruling 2026-09-30: fused weapons without a lock explode at max
range. Fire froze BurstPosition at the shooter's own position with flight
time 0, so a proximity shot detonated on its own shooter and contact and
delayed shots did nothing.

With no target and a fuse, Fire now freezes the burst point as the mount
direction times the weapon's Range stat from the source, and flight time as
Range over Velocity. Apply sends every such shot through Detonate at that
point whatever its fuse. Targeted shots and unfused shots are untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:28:10 +02:00
Meta Vens
568bc00256 Refresh the moddable-ships map for assimilation into Eureka (Imagination, 2026-09-29)
Re-anchored to the post-fire-control-12 Body (synthetic merge tested on
Yggdrasil: 379/364/381 green). Codex's map is raw material; this is the
proposal. Operator questions open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:26:14 +02:00
Meta Vens
d50a816a87 Refresh the mining map for assimilation into Eureka (Imagination, 2026-09-29)
Re-anchored to the post-fire-control-12 Body (synthetic merge tested on
Yggdrasil: 379/364/381 green). Codex's map is raw material; this is the
proposal. Operator questions open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:25:41 +02:00
Meta Vens
b66ba5246a Restore LF line endings in the fire-control map
c50029d5 committed the file with CRLF endings: the inserted paragraph had
mixed endings, and autocrlf does not normalise a mixed file. Content is
unchanged, and the net diff against c50029d5^ is the 26-line status
paragraph.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 08:00:22 +02:00
Meta Vens
c50029d511 Record fire-control 12.4 closed, and the no-target fuse ruling it needs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 07:59:29 +02:00
Meta Vens
c7e20f088a Fire control 12.4 closing batch: the new tests must fail without crashing the run
Assert.Contains on a Ship formats the whole entity graph on failure and overflowed the stack, aborting
the test run instead of reporting red; the new tests check membership with a boolean and a message. The
cockpit-kill test now gives the target a hull the blast also kills, the case where the double Death
actually occurred.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 07:54:46 +02:00
Meta Vens
4629bc6799 Fire control 12.4 closing batch: Death fires once; pin the blast loop's multi-kill and untouched-entity cases
Entity.Death, the owner of the stream, now ends after its first cause. A blast that destroyed a
cockpit fired Death, which removed and deactivated the entity, and the blast's own DamageHull then
raised a second Death to every subscriber but Zone's idempotent handler. Every damage path gets the
guard because none of them raise Death themselves.

New pins: one blast killing three ships (a break after the first kill survives the old suite), a
shieldless ship outside the disc receiving nothing, a cockpit-kill blast and a direct hull kill each
raising Death exactly once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 07:36:04 +02:00
Meta Vens
fd79201358 Fire control 12.4 fix batch F5: measure the steady state, not the first window
LaneAndSilhouetteAllocateNothingGivenAPooledBuffer failed in 1 of 12 full-suite
runs (1232 bytes over 1000 Lane calls) and in 0 of 100 runs of the test alone
or its class. The allocation is a one-off, not a per-call cost: under suite
load the runtime's background tier-up is delayed by other tests' JIT activity,
so first-use allocation lands inside the single measured window.

The rule stays: Lane and buffered Silhouette allocate nothing. The test now
measures up to 20 rounds of 1000 calls and requires the smallest round to be
zero. A per-call allocation appears in every round and still fails it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 04:17:43 +02:00
Meta Vens
76e98598b1 Fire control 12.4 fix batch F4: tests that could not fail now can
Each rule below was protected only by a test a mutant passed. New or
strengthened tests, with the mutant each one kills:

- AContactOrDelayedBlastOnAMissDoesNothing: ApplyBlastHit's miss guard.
- ToWorldPointIsTheInverseOfToSchematicPointAtANonAxisFacing and
  AContactBlastLandsOnTheCellItHitAtANonAxisFacing: ToWorldPoint's right axis,
  asserted per cell at facing (2,1); TurningAfterCommit now compares per cell.
- ProximityBurstPositionIsThePredictedInterceptForAMovingTarget: a moving
  target and an intercept solved in the test, not Durability <= before.
- AnUntouchedEntitysShieldIsNotConsulted: Detonate's skip of untouched
  entities.
- TheFusePointStaysOnMetalAcrossAConcaveGap: the delayed point clamps at the
  first gap (the lane's walk ends there).
- ShieldPaysForWhatReachesIt asserts the reserve dropped by the covered share;
  AShieldRaisedBetweenCommitAndArrivalAbsorbsTheBlast and
  AShieldDroppedBetweenCommitAndArrivalDoesNotAbsorbTheBlast replace the
  outcome-flags-only check with the shield state flipped between commit and
  arrival.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 03:48:29 +02:00
Meta Vens
8b4bf01eac Fire control 12.4 fix batch: tangent disc, candidate cull, lethal blast
F1: RectDiskOverlap counted a whole square when a cell edge sat exactly r from
the disc centre (`h < yhi`, `-h > ylo`). The comparisons are inclusive now, so
the chord bounds the piece. A proximity burst on an integer centre of mass
delivered 127.32 of 100 at BlastRadius 1 and 100.80 at 3.

F2: delete Detonate's distance prefilter and the radius <= 0 guard. The
prefilter measured from the centre of mass with the bounding box's
half-diagonal, which is not a bound on how far a hull's cells reach; it culled
real overlap on an L-shaped hull and on the shipped Longinus corners.
RectDiskOverlap is the single decider. An untouched entity is still skipped
(its covered list is never allocated).

F3: Detonate iterates a snapshot of zone.Entities, as Zone.Update does. A
lethal blast removed the entity from the live collection and the next MoveNext
threw, leaving the shot pending so it detonated again the next tick.

Tests: tangent discs through Fire and Detonate, an L-shaped hull, grazing
blasts at the farthest corner of Longinus and LonginusX (expected values from
a numeric overlap), and a lethal blast that must resolve once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 03:38:14 +02:00
Meta Vens
6b222564ee Add the operator checklist for merging fire-control-12 to master
One file with the checks only the operator can do before the merge,
folded into a single play session, with a map pointer on each line. It
also lists what was already done, what is not part of this merge, the
open questions, and the three uncommitted scene and input files to
decide on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 01:55:51 +02:00
Meta Vens
375d6bd40e Edit ship schematic and hardpoints in Blender .cc authoring 2026-09-26 19:23:01 +02:00
Meta Vens
24c2964046 Preview typed mod ship visuals and captured LineArt in Unity 2026-09-26 19:10:44 +02:00
Meta Vens
4ba4bbaf2e Compose validated mod ships into a derived catalog 2026-09-26 18:30:02 +02:00
Meta Vens
42eb5214ce Add parallel typed ship authoring and Blender LineArt capture 2026-09-26 18:14:36 +02:00
Meta Vens
4b594e116c Define collection-based ship prefab authoring 2026-09-26 15:26:46 +02:00
Meta Vens
354e2f05ba Record restored hull content as merged 2026-09-26 13:25:23 +02:00
Meta Vens
e160bbe5e8 Merge restored hull and thruster content 2026-09-26 13:19:42 +02:00
Meta Vens
12656b92d2 Retire stale Aetheria Persona priority cue 2026-09-26 13:06:52 +02:00
Meta Vens
d0022d9f5d Cut 1 fix batch 3 (F7): replace the vacuous turret-distance check with a real Phase-offset bound
TutorialEntranceWithNoLagrangeCandidateStillSeatsAStationWithFiniteNearbyTurrets
asserted a turret orbit's Distance matched its station's -- true unconditionally,
since PlaceTurret sets Distance from orbit.Distance directly the same way
CreateLagrangeOrbit does for the station itself, so the check could never
fail regardless of placement. Replaced with a bound on PlaceTurrets' actual
"near their station" claim: the Phase offset (20 * distanceMultiplier /
orbit.Distance), generous over PlaceTurrets' own max distanceMultiplier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:37:25 +02:00
Meta Vens
c3f52086a7 Cut 1 fix batch 3 (F5, F6 N1/N3/N9): throw reachability, per-seed and multi-root pins, station-offset pin
F5: committed ThrowReachableWithAuthoredSettings (from Soul's SoulL3Census.cs)
against a real seed-1 tutorial entrance -- RosetteProbability 0 and MassFloor
1e9 leave every planet a parentless root, so even the widened candidate set
(F3's fix) is empty and the throw fires through public construction, not a
hypothetical.

F6/N1: EntranceStationSitsOnAGenuineLagrangeOrbitWheneverOneExists strengthens
the existing across-seeds test with a per-seed pin: whenever a seed's entrance
actually has a genuine (non-rosette) Lagrange candidate, its station must sit
on one, not the widened fallback.

F6/N3: MultiRootEntranceStationOrbitsAreAlwaysParentedWithPositiveDistance
authors a fragmented, heavily-rosette entrance (RosetteProbability 1, a fixed
SubZoneCount of 8) and pins that every resulting station orbit is a real,
positioned orbit -- a set Parent and a positive Distance -- regardless of
which candidate selection produced it.

F6/N9: EntranceStationPhaseDiffersFromEveryPlanetAtItsOwnDistanceAcrossSeeds
pins CreateLagrangeOrbit's own Phase offset: a docked station's Phase must
differ from every planet's Phase at the station's own (Parent, Distance),
catching a mutant that seats a station directly on its source planet's orbit
object instead of an offset copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:31:32 +02:00
Meta Vens
95394f786f Cut 1 fix batch 3 (F6 N2, F7): entrance-widening leak test, robust orbit counting, real enemy-count check
F6/N2: added WideningDoesNotLeakToANonEntranceNoLagrangeZoneThatRollsAStation.
Seed 3's "EAC-7089" (the same no-Lagrange fixture the widened-candidate test
uses) naturally has no genuine Lagrange candidate; boosting one faction's
presence there via the same public SavedGame round trip
BuildGalaxyWithForcedEntrance uses makes its station-count roll nonzero
without touching ZoneGenerator's private RNG. Verified directly: dropping
ZoneGenerator's isTutorialEntrance guard on the widening condition turns
this fixture's station count from 0 into 2, so the fixture genuinely
exercises the leak path this test pins closed.

F7: fixed the leak test's comment (the widened-candidate fixture is seed 3,
not seed 1, so it no longer claims to share a fixture with a test that
doesn't). ForcedTutorialEntranceStationDoesNotInflateEnemyCount asserted
shipCount == 2, which was pinning TutorialZoneSettings' own default
NeutralWandererCount (2), not the enemy roll baseStationCount gates -- it
now filters ShipPacks by the same nearest-faction ZoneGenerator computes
internally (EntityPack.Faction), asserting the real enemy count (0) instead.

Also (Soul's finding): IsRosetteMember's planet-orbit count
(pack.Orbits.Count minus the OrbitalEntityPack count) over-counts whenever
a station or turret loadout generator returns null, since
CreateLagrangeOrbit already appended that orbit before the null check
skips adding the entity. It now derives the set from pack.Planets' own
Orbit refs directly (Census.cs's own approach), which sidesteps the bug
entirely.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 02:15:24 +02:00
Meta Vens
a5fb3b84d2 Cut 1 fix batch 3 (F1): load real GameplaySettings, fix the speed-cap test
RestoredHullsTests.Settings() hand-set thermal radiation/conduction at
their bare-class defaults (1/1/1) against the shipped 3 / 1e-8 / 0.01
(Assets/Resources/Settings.asset), so equipped parts froze toward 0 K on
real physics and every test built on that fixture ran on thermal behaviour
nobody ships. It now loads the real GameplaySettings through
AuthoredSettings (tools/AetherDb/AuthoredSettings.cs), the same headless
YAML reader tools/AetherDb already uses to inspect Settings.asset outside
Unity -- the tests project now references AetherDb.csproj to reuse it
instead of hand-copying the same fields a second time.

LonginusNeverExceedsItsRestoredTopSpeedUnderFullThrust no longer needs
OverrideShutdown to keep the ship flying (that was compensating for the
broken fixture shutting equipment down within ~1s); it now drives a
generated Longinus (seed-pinned, including ItemManager.Random, which
defaults to a DateTime.Now seed and was making item quality -- and so
the measured speed -- non-deterministic) for 5s, the window Soul measured
before this loadout's thrusters cross 386 K and shut down. The tolerance
is now asymmetric instead of the old +-10: +4 on the ceiling (the mixer's
own tick order settles real, unforced flight at the cap plus one tick's
acceleration, measured at ~103.3 for this loadout) and -3 on the floor
(tight enough to catch a nerfed TopSpeed catalog value, which +-10 or a
wider ceiling would not).

Every other test in the file now runs on real settings instead of the
frozen fixture; all 15 tests in RestoredHullsTests pass unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 01:48:58 +02:00
Meta Vens
7e63d7448a Cut 12.4(b): behavioural tests for Detonate and the fuse switch
Geometry, absorption order, symmetry/frame, shields and fuse tests from the
cut doc's own verification list, plus Soul's three fold-in probes (a
radius-without-a-fuse damage-outcome test, a moving-target proximity-burst
pin, and Detonate's nonpositive-radius guard) and the two catalog probes
(shipped-catalog neutrality on BlastRadius/Fuse, and a WeaponFuse/BlastRadius
round-trip through a written and reopened catalog copy).

Fixture: SchematicCellSize 2, target off the origin, hull centre of mass not
an integer cell, one facing with |fx| > |fy| -- the rules the cut doc names
for every blast test. Geometry expectations come from exact half-split
symmetry where possible (TheShareOffTheHullIsLost, ShieldPaysForWhatReachesIt)
and from an independent numeric area integral otherwise (EachCellTakesItsShare
OfTheDisc, TheFusePointStaysOnMetal), never from the SUT's own overlap code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 01:37:53 +02:00
Meta Vens
072e50d275 Cut 1 fix batch 3 (F3, F4): fix the entrance-throw condition, delete the dead FixedPosition copy
F3: the throw fired on selectedStationOrbits.Length == 0, which is also true
whenever stationCount rolls 0 -- an unrelated variable. It now checks
lagrangeCandidates.Length == 0 directly, the actual "no candidate orbit"
case, and the message says so.

F4: CreateLagrangeOrbit's FixedPosition copy and its comment described a
fallback orbit that no longer exists (widening always returns a real,
parented planet orbit). Deleted; nothing reads FixedPosition off a
lagrange/turret orbit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 01:23:43 +02:00
Meta Vens
0edbe0b455 Locomotion map: correct the restored TopSpeed values, record the VelocityLimit hull-gating hazard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 01:19:07 +02:00
Meta Vens
7c99909d2b Cut 12.4(b): Detonate replaces Splash and Entity.Absorb
FireControl.Apply now switches on the frozen shot.Fuse: a null fuse keeps
12.3's lane path (ApplyDirectHit), a proximity fuse detonates at arrival with
no roll, and a contact or delayed fuse detonates only on a committed hit
(ApplyBlastHit), locating P through Lane and the new Reach owner (moved
verbatim from Apply's own inline penetration clip; the delayed fuse point
reads the identical rule). Step has no damage branch left.

Detonate (FireControl.cs) is the one owner of blast damage: candidates by
centre-plus-half-diagonal, exact circle/cell overlap shares computed once,
every blast's shield decided live per Q12-9 = A (including the host of a
contact/delayed blast -- Commit now gates its own shield decision on
shot.Fuse == null), armour absorbed per cell, and each item's covered cells
pooled into one ItemAbsorb call. Entity.Absorb and FireControl.Splash are
deleted; Entity gains ToSchematicPoint/ToWorldPoint for the point conversion
Detonate and the delayed fuse point need. Mine.Explode now calls Detonate.

Existing Splash/Absorb-era tests across Cut4/5/6/11/123 are rewritten or
retargeted to the new public owners; behavioural coverage for the blast
model itself lands separately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 01:17:36 +02:00
Meta Vens
77be5cf433 Cut 12.4 map: slot 32 for Fuse, inert rule arrives with (b), measured drift
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 00:52:16 +02:00
Meta Vens
2bb245bc34 Cut 12 map: Q12-9 ruled A (the blast decides every shield)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 00:31:22 +02:00
Meta Vens
615008523e Cut 1 fix batch 2 (F1, F2, F3): commit Soul's behaviour tests
F1 (speed cap): assert against Longinus's legacy TopSpeed literal (100)
instead of reading the bound back out of the same catalog value being
tested -- the old assertion passed under TopSpeed=1000 because the
bound moved with the mutation. Also fixes the false "drag/thrust
balance" comment: there is no such balance near 100. At full throttle
Longinus's own thrusters heat their hull past ThermalOnline's shutdown
threshold within ~1s, and once the hull's own cell goes offline the
same way, VelocityLimit (a hull behaviour, gated identically) shuts off
with it, so the cap was only ever exercised for the first ~15 ticks.
OverrideShutdown -- a real, first-class field (the cockpit's "Override
Shutdown" control) -- forces the hull and both firing thrusters to keep
running for the whole 12s scenario, so the cap is what actually holds
speed down throughout, not an unreached ceiling.

F2 (entrance station): EntranceZoneAlwaysGetsADockedStationAcrossSeeds
now also requires the normal case to land on a genuine (non-rosette)
Lagrange orbit. Adds TutorialEntranceWithNoLagrangeCandidateStillSeats...,
built via a public SavedGame/SavedZone round trip (no reflection) that
re-targets a real galaxy's Entrance to a real zone already known to
have no Lagrange candidate (seed 3's "EAC-7089": four planets, one
rosette, no captured satellites) -- pins a docked station whose turrets
land on a real, finite, nearby orbit. Adds the leak checks (override
must not reach other tutorial zones or a non-tutorial game's own
entrance) and the enemy-count check (the override must not also raise
the enemy roll, which stays keyed to the pre-override station count).

F3 (asset identity): EveryAssetReferenceResolvesToAMetaGuid only checks
that a referenced GUID exists somewhere under Assets/, so it passed
when Djinni's Prefab was swapped for Longinus's. The new test compares
each reference against the specific legacy file's own GUID (Djinni's
own .prefab.meta; Thruster 1.prefab.meta for every restored thruster's
ParticlesPrefab).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 20:15:24 +02:00
Meta Vens
0fe7156d8b Cut 1 fix batch 2 (F2): collapse the entrance station to one orbit selection
Two writers decided the tutorial entrance's station orbit: the floor
(stationCount < 1 -> 1) and a synthesized fallback orbit, each masking
bugs in the other (removing either alone still passed the entrance
test). Collapse to one rule: the floor still guarantees stationCount
>= 1, but its orbit always comes from the same Lagrange selection. When
that selection has no candidate (a zone that is entirely one rosette),
widen it to every parented planet orbit ordinary placement draws from
before the rosette filter, instead of inventing an unparented,
zero-distance orbit -- which gave PlaceTurret's phase a division by
zero and left an orphan orbit record. If even the widened set is empty,
throw loudly instead of silently omitting the entrance's station.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 20:15:00 +02:00
Meta Vens
2625768f86 Cut 12.4(a): rename AirburstRange to BlastRadius, add WeaponFuse
WeaponItemData.AirburstRange (slot 29) becomes BlastRadius, same slot and
type so CultCache opens the catalog as compatible drift. A new nullable
slot 32 (30 and 31 belong to EquippableItemData) carries WeaponFuse?
Fuse. FireControl.Fire now decides "detonates" once, from BlastRadius
and Fuse directly, and freezes Fuse only when BlastRadius > 0 -- the
WeaponModifiers.Airburst label no longer decides anything (Q12-6).
PendingShot.BurstRadius is renamed BlastRadius and gains a Fuse field
that nothing reads yet; Step's Splash/Apply dispatch is unchanged.

No shipped weapon carries a blast radius or the Airburst label (Cut 12's
Probe4, reconfirmed against GameData/Aetheria.cc), so this is
behaviour-neutral on shipped content. Apply's fuse switch and deleting
Splash are Cut 12.4(b).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 19:15:26 +02:00
Meta Vens
27318cb39f Cut 12.4 map: re-anchor at d402283c, areas on the one-path absorption, Q12-9
Imagination pass: every anchor is re-probed; a disc runs armour per cell, then pools
each item through ItemAbsorb; Entity.Absorb dies with Splash; the penetrator's
fuse point reads the same Reach owner as the direct-hit walk; the ledger now
carries actuals for 12.1-12.3; Q12-9 (the host's shield for a blast) is opened.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:58:58 +02:00
Meta Vens
d402283c06 Cut 12.3 status: closed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:38:21 +02:00
Meta Vens
cccf3a2ac4 Cut 12.3 fix batch (F5, F1, F2): model sweep never meets a cycle; commit P3-P5
FixedPointItemResolution now throws "the model never meets a cycle" if a pool
is still open after its fixed point settles, instead of silently
force-settling in the reverse of first-encountered order. The sweep already
gates its own draws (LanesReaching) so a genuine cross-item cycle is never
actually presented to the model; a thrown exception here means the gating
missed a real case, not a numbers question the model should answer with its
own competing tie-break. The stale "opposite tie-break" comment describing
the deleted behaviour is gone with it.

Three of Soul's five probes (soul125-FireControlCut123Tests.probe.cs) are
committed here, ported from reflection onto the public Fire/Commit/Apply path
this file's own tests already use -- FireCentre/FireUntilHit retries until
the committed hit lands on the expected column, the same idiom
ZeroDepositDoesNotStall and PooledPathHonoursTheItemThresholdLikeTheSoloPath
already use, never a direct call into the private Apply:

- ZeroDepositContributorFiresNoItemDamageEvent (P3): a zero-deposit
  contributor must not fire a phantom ItemDamage event. Kills Entity.cs's
  `incoming[i] > 0f` boundary flipped to `>=`, and a swap that reports the
  post-split share instead of the incoming one (F2).
- ClippedLaneDoesNotHoldThePool (P4): an item beyond every lane's own
  penetration clip must never be waited on.
- OwnRepeatVisitDoesNotHoldThePool (P5): a lane's own later visit to an item
  must not hold that item's pool open -- only other lanes are future
  reachers. Kills FireControl.cs's `alreadyContributed` guard being deleted
  (F1).

The other two probes (Soul5_AngledMirrorAndConservationWithSharedItems,
Soul5_AngledMirrorCycleShapes) are NOT committed. They drive Apply directly
through reflection with a hand-built PendingShot.Outcome so they can sweep
1400 exact, mirrored (bearing, lateral) pairs per test and compare against an
independent model -- Commit's own bearing is reachable through the public
path (shooter/target positioning), but its lateral is a random draw from the
per-shot RNG, not a value either test can set or predict without either
control of that RNG's seed and Silhouette's exact sigma, or a decoy Apply
entry point. Reaching them without reflection needs one of:
(a) `[InternalsVisibleTo]` for Aetheria.Shared.Tests on FireControl.Apply, or
(b) a public/internal test seam that takes a pre-built ShotOutcome (bearing,
lateral) and runs Apply's own walk against it.
Neither is authorized by this fix batch's map; this is reported rather than
silently reflected. The Soul5_Alloc benchmark (also reflection-based, and not
one of P1-P5) is likewise left uncommitted.

Mutation verification (docs/fire-control-cut.md, Cut 12.3, one-apply-path):
F1 and both F2 mutants confirmed killed by the new tests; the earlier
fix batch's own forced-sequential, resolve-one-pool-only, and cycle-throws
mutants (Soul's M3/M4/M6 family) still die against CycleTieBreakIsMirrorSymmetric
and friends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:33:50 +02:00
Meta Vens
c07b4fee65 Cut 12.3 fix batch (F4, F6): delete unreachable guards, fix stale ArmorAbsorb comment
Entity.ItemAbsorb's `item == null` guard is unreachable: both callers (Absorb,
and FireControl.ApplyPooled's Resolve) already guarantee a non-null item
before calling in. Its `total > 0f ? ... : 0f` divide guard is unreachable
too -- the function already returned above whenever total <= 0.1f, so the
divide never sees zero. Both deleted; the surrounding comment now says why
instead of describing a guard that no longer exists.

ArmorAbsorb's own comment was stale from before the "one code path" ruling:
it described the item phase as deferred only for a cell shared with another
lane, when every occupied cell now defers to ItemAbsorb's pool, a lane that
turns out to be the sole contributor included (a pool of one, not a separate
solo path).

Soul's findings (docs/fire-control-cut.md, Cut 12.3): F4, F6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:33:23 +02:00
Meta Vens
64d17a290d Cut 12.3 fix batch (F4): one writer for lane completion, delete dead reachability offset
ApplyPooled.Resolve no longer calls FinishLane directly -- AdvanceLane is now
the single place that checks pointer >= walked and finishes a lane, so lane
completion has one writer instead of two. StillReachableByAnotherLane's own
`blocked ? pointer+1 : pointer` collapses to plain `pointer[li2]`: the
alreadyContributed check just above it already excludes a lane that is
blocked on the very item being asked about, so `pointer[li2]` is never that
item's own cell by the time the +1 would have mattered.

Soul's findings (docs/fire-control-cut.md, Cut 12.3): F4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:33:09 +02:00
Meta Vens
0dd16713b6 Cut 12.3 map: record the cycle rule as Self's default
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:01:38 +02:00
Meta Vens
aafc90aced Cut 1 fix batch: commit Soul's behaviour tests (asset refs, entrance station, speed cap, loadout fill)
Four tests against the real shipped catalog and the tutorial construction path, each pinning one
of this campaign's rules:

- EveryAssetReferenceResolvesToAMetaGuid: every hull's Prefab, every ThrusterData.ParticlesPrefab,
  and every non-empty Schematic names a GUID an Assets/**/*.meta actually carries. Adapted from
  Soul's own probe (AssetGuidsResolve); it is what caught Djinni's fabricated Prefab GUID and the
  five restored thrusters' null ParticlesPrefab.
- EntranceZoneAlwaysGetsADockedStationAcrossSeeds: replaces
  TutorialZoneGenerationCanProduceADockedStation, which never used the tutorial construction path
  and only claimed a docking bay shows up somewhere in 25 zone-name variants. This builds the real
  tutorial Galaxy with Assets/Resources/Settings.asset's own values and generates the Entrance zone
  the way ActionGameManager.StartGame/PopulateLevel does, requiring a docked station in every run
  that gets that far. Galaxy zone-graph generation has its own pre-existing, seed-dependent
  flakiness (a disconnected zone graph throws inside the Galaxy constructor on roughly 1 seed in
  15) confirmed unrelated to this cut by reproducing identically against the pre-fix-batch catalog;
  that failure belongs to Galaxy.cs and is skipped rather than asserted on, with a floor requiring
  at least 15 of 25 seeds to actually produce a Galaxy.
- LonginusNeverExceedsItsRestoredTopSpeedUnderFullThrust: straight-line full-thrust run against the
  restored VelocityLimitData cap (100).
- LoadoutGeneratorFillsEveryThrusterHardpointAcrossSeeds: LoadoutGenerator, filtered to each
  restored hull, fills every thruster hardpoint across ten seeds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 18:01:17 +02:00
Meta Vens
3a0b5892c9 Tutorial station: ZoneGenerator.GenerateZone always seats the entrance zone (operator ruling)
Operator, 2026-09-25 (docs/locomotion-cut.md): the tutorial's entrance zone always gets a
generated faction station with a docking bay, deterministically. Structurally, three defects made
that false on every seed: Galaxy.cs halves influence and picks the lowest-influence unowned zone
for Entrance, so stationCount rolled 0; a Lagrange orbit is only available when a planet has an
orbiting sibling, which a boring or empty system never has; and a null station loadout silently
skipped the slot.

GenerateZone now identifies the entrance zone by reference against the galaxy parameter it already
takes (isTutorial && galaxyZone == galaxy.Entrance), never by name:
- stationCount is floored to 1 for the entrance zone, after the roll that produced it.
- When no Lagrange orbit exists, a fallback orbit fixed at half the zone radius from centre is used
  instead of leaving selectedStationOrbits empty. CreateLagrangeOrbit now carries FixedPosition
  through so a Parent-less base orbit (the fallback) still positions correctly.
- A null station loadout throws for the entrance zone instead of continuing past it.
- The enemy count is based on the pre-override station count, so forcing the entrance's station
  doesn't also hand it a bonus enemy.

The story-station path (Locations/LocationStory) is not used: it isn't saved, and
EntitySerializer.cs:77 would break Continue, per the map's own ruling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:40:31 +02:00
Meta Vens
54cfe9d4ba Cut 1 fix batch: delete fix-loco1 now that its records have landed
Same pattern as restore-hulls itself: the one-shot command's carrying cost is
zero once it has run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:40:08 +02:00
Meta Vens
dd4375801c Cut 1 fix batch: Soul's catalog findings (Djinni asset refs, thruster curves, ThermalResilience, legacy keys)
Landed via `dotnet run --project tools/AetherDb -- fix-loco1 apply`, then deleted the command in
the same batch (Cut 9/Cut 1 precedent). Fixes, each against the decoded 2021-04-14 legacy record
or a named catalog precedent:

- Djinni.Prefab was a fabricated/truncated GUID; corrected to Djinni.prefab.meta's own GUID.
- All five restored thrusters' ParticlesPrefab (null) -> Thruster 1.prefab's GUID, the same one
  Large Drive uses (legacy record names the same prefab path for all of them).
- All five thrusters' invented OptimalTemperature/PlateauWidth (300/100) -> Large Drive's own
  200-400 precedent, 251/24 (docs/stats-power-cut1-migration.md).
- ThermalResilience: Medium Drive/Small Drive -> 10, Victoire/Talaria/RevvITup 2.0 -> 15 (legacy
  record). Victoire's Durability 100 -> 30 (legacy). Victoire and Medium Drive's legacy
  descriptions restored (Talaria/RevvITup 2.0's legacy descriptions are the literal placeholder
  "[TODO]" and are not).
- Djinni.Schematic (null) -> djinni_schematic_transparent.png's GUID, already in the tree, unused.
- Djinni's OptimalTemperature 250 -> 251, correcting a rounding slip in restore-hulls's own
  "apply LonginusX's optimal-fraction to Djinni's band" derivation ((275.15-173.15)/400 = .255 of
  band applied to Djinni's 200-unit band rounds to 251, not 250).
- All seven restored records (Longinus, Djinni, five thrusters) re-keyed from freshly minted GUIDs
  to their own legacy GUIDs, decoded directly from GameData/Legacy/AetherDB.2021-04-14.msgpack,
  matching the Cut 9 import precedent (tools/AetherDb/Import.cs, git history). Each record's own
  FactionProductData.Design ref repointed at the new key.

Verified: dry run then apply, second apply refused (Longinus already carries its legacy key),
`dangling` reports 0, `census` still names both hulls, `loadout` generates every hull cleanly
across seeds 1-5.

Re-keying changed GetAll<GearData> enumeration order, which
RestoredHullMovesAndTurnsUnderMovementAndLookDirection's design-selection (thrusterDesigns.First())
depended on implicitly: it started landing every Djinni thruster hardpoint on Victoire, the one
restored thruster with a real EnergyUsage draw, and the fixture ship carries no reactor. Fixed by
equipping the fixture ship's own Reactor hardpoint, which every restored hull actually has, instead
of relying on incidental unpowered-item ordering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:38:44 +02:00
Meta Vens
166b6202b1 Cut 12.3 fix batch: the model sweep is now an independent fixed point
Rewrite the shared-item model sweep instead of leaving it a follow-up:
the earlier ModelWithSharedItems copied FireControl.Apply's own
survey-then-walk shape closely enough that reverting production to a
plain sequential per-lane absorb (no pooling at all) still passed it.

FixedPointItemResolution settles items in a different order from
production: it batches every lane's own armour-only walk into full
passes, then checks every currently open pool for readiness once per
whole pass (a dynamic, re-derived-each-time check, not a table built
once up front -- a precomputed-once version deadlocked on a non-convex
item crossed twice by the same lane). Lane geometry is read from the
real FireControl.Lanes instead of a second hand-rolled walk, removing
a class of disagreement that had nothing to do with absorption order.
Durabilities are now drawn below a lane's own share so every shared hit
overflows, hull damage is compared alongside armour and items, and the
tolerance is tightened now that lane geometry can no longer drift.
Also fixes: rejected attempts in the retry loop were mutating real
state without resetting it, corrupting the "before" snapshot; the
model was missing Entity.ItemAbsorb's own pooled .1f threshold.

Reran M0 (control, green) through M4: M1 (forced sequential absorb)
now kills the sweep as well as the mirror/proportional tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:38:08 +02:00
Meta Vens
7ca2f64f43 Cut 1 fix batch: revert stray blank-line deletion in Program.cs
The Cut 1 restore-hulls command deletion also dropped a blank line separating
FitCommand from the dangling-refs command block. Restore it so the file is
byte-identical to base (git diff against pre-Cut-1 now empty).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:15:19 +02:00
Meta Vens
ab14552a1e Cut 12.3 fix batch: tests for the one-apply-path pooling rules
Commit Soul's probes as behaviour tests against the pooled walk:
CycleTieBreakIsMirrorSymmetric (a genuine two-item cyclic dependency,
mirror-symmetric and damage-conserving by construction),
PooledPathHonoursTheItemThresholdLikeTheSoloPath (the .1f threshold is
decided once on the pool total, never per contribution, and pins the
pooled ItemDamage event count), and ZeroDepositDoesNotStall (a lane
whose armour ate its whole share still deposits and never blocks the
pool it belongs to). Adds the Custom fixture hook (an arbitrary named
item shape) the cycle test needs to build two crossing non-convex items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:02:11 +02:00
Meta Vens
e9339a5673 Cut 12.3 fix batch: one apply path for every item (operator ruling)
Replace the survey-then-branch (ApplySequential vs. ApplyWithSharedItems)
with a single pooled walk. Lanes are clipped to penetration once, right
after Lanes returns; every item -- single-cell or multi-cell -- pools
whatever lanes reach it and resolves the moment no other unfinished lane
can still reach it down its own remaining clipped walk, with no separate
reachability survey. A cyclic dependency between two non-convex items
resolves every currently open pool at once, order-independent by
construction. Entity.ItemAbsorb becomes the one absorption function,
gated on the pooled total; Absorb (Splash's only remaining caller) now
funnels through it with a one-contribution pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 17:01:05 +02:00
Meta Vens
c339304000 Locomotion map: tutorial station ruling (faction station in the entrance zone)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:40:34 +02:00
Meta Vens
819bd6b8b9 Cut 1: delete restore-hulls now that its records have landed
Same contract Cut 10 applied to the Cut 9 importer: a one-shot restore
carries zero ongoing cost once its records are in the catalog. The
authored-choices review list this command printed lives in the cut's
report, not in source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:36:28 +02:00
Meta Vens
6b5bb87e91 Cut 1: RestoredHullsTests, against the real restored catalog
Read-only against GameData/Aetheria.cc: each hull exists with the
expected thruster hardpoint count (Longinus 4, Djinni 8), every thruster
hardpoint accepts a catalog thruster design through TryEquip at its own
position, and each hull moves and turns for a few ticks under
MovementDirection/LookDirection on the pre-Cut-3 mixer -- content proof,
not controller proof.

Also covers the operator's tutorial-station addition (2026-09-25):
Zenith (the live Station hull) is confirmed working already -- station-fit,
hardpoint-fit and `loadout` all pass for it, and the legacy record's only
station design ("Zenith Station") is that same hull, so nothing needed
restoring. ZoneGenerator's story-station path is dead code today (Galaxy's
tutorial constructor has its StoryProcessor call commented out), so
TutorialZoneGenerationCanProduceADockedStation drives the background
station path directly (real ZoneGenerator.GenerateZone call, real
catalog, a minimal SavedGame/Galaxy fixture) across 25 zone/seed
attempts and asserts at least one produces a station with a docking bay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:33:47 +02:00
Meta Vens
4f218e8534 Cut 1: land Longinus, Djinni and five thruster designs in Aetheria.cc
Landed via `dotnet run --project tools/AetherDb -- restore-hulls apply`.
Longinus (13 hardpoints, Alakrita) and Djinni (22 hardpoints, Rossum &
Douglas), plus Medium Drive, Small Drive, Victoire, Talaria and RevvITup
2.0 (approved 2026-09-22), each with a FactionProductData. Verified:
census names both hulls with makers, dangling reports nothing new,
LoadoutGenerator/`loadout` generates every hull in the catalog cleanly
across seeds 1-5, second apply refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:33:35 +02:00
Meta Vens
3cb6b1546e Cut 1: add the restore-hulls command (docs/locomotion-cut.md)
One-shot restore of Longinus, Djinni and their five thruster designs from
the decoded 2021-04-14 legacy record, in the shape of the existing
*-migrate [apply] commands: dry run by default, writes every record in one
Commit, refuses a second apply. Longinus's scalar fields and ReflectorData
come from LonginusX (confirmed byte-identical against the decoded legacy
record); its hardpoint layout is authored directly from the legacy decode,
since LonginusX's own interior was rearranged to fit its AetherDrive.
Djinni is authored entirely from the decode (no live twin exists).

Every legacy PerformanceStat's [Min, Max, HeatExp, DurabilityExp,
QualityExp] is translated into today's Min/Max/Terms shape, never copied.
Authored post-breach fields (roles, FactionProductData, PowerSupply terms,
FiringArc) are covered in the command's own header comment for operator
review. Deleted in a later commit of this same cut once landed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:33:24 +02:00
Meta Vens
14ee2a52ca Cut 12.3: one apply path for all items (operator ruling)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:22:44 +02:00
Meta Vens
b55894a02a Cut 12.3 fix batch: tests for proportional multi-lane item absorption
F8 tests, through the real Fire/Commit/Apply pipeline (no reflection):
- ProportionalAbsorptionSplitsTheLeftoverBetweenTheLanes /
  ...LeavesNothingWhenTheItemAbsorbsEverything: the ruling's own literal case
  (two lanes bringing D1=25/D2=15 onto one 2x1 item), both the partial- and
  full-absorption branches.
- MirrorSymmetryHoldsWithASharedMultiCellItem: a symmetric hull and its own
  mirror-image fixture must produce the same sorted leftover pair. Fails on
  the pre-fix-batch code (commit d1cc047a) at itemDurability 20 ({0,20} vs
  {5,15}); a durability equal to one of the two D values turned out
  degenerate and was rejected first (see the test's own comment).
- EveryAxisAlignedSpreadShotStrikesExactlyTwoNPlusOneFacingCells: Soul's own
  owed regression guard on lane spacing, independent of item sharing. Killed
  by hand-mutating FireControl.cs's laneSpacing by *.99f (R1b): 28/400
  interior-column hits drop a facing column.
- ModelSweepAgreesWithProductionIncludingSharedMultiCellItems: an independent
  model (armour-then-item-then-hull per lane, extended with the same
  survey/sum-then-split shape production uses) checked against production
  over a sweep of two hull sizes, three bearings and both 2x1 bars and
  non-convex L-shaped items (Build gains lBars/LShape for this).

Tool-hardpoint items (Bar, Marker) can only occupy interior cells
(Entity.ItemFits), so every fixture above needed a hull at least 3-4 cells
deep -- shallower hulls (used in an earlier draft) fail marker/bar equip
outright.

Hand-verified against the M13 "lane_order_reversed" mutant Soul recorded as
surviving on the pre-fix code (FireControl.cs, Lanes' own `var k = li - n`):
MirrorSymmetryHoldsWithASharedMultiCellItem fails on the pre-fix code under
that mutant and passes on this cut's code under the same mutant, confirming
the new resolution is order-independent of which physical lane a buffer index
happens to hold, not only of Apply's own loop order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:17:13 +02:00
Meta Vens
567579136a Cut 12.3 fix batch: proportional absorption for multi-cell items shared between lanes
Operator ruling (2026-09-25): "proportional absorption; go". A multi-cell item
struck by several lanes of one shot now absorbs their combined incoming damage
(up to its own remaining durability) and each lane's leftover is in proportion
to what it brought, replacing the old behaviour where whichever lane Apply
happened to visit first drained the item and the next lane inherited whatever
was left.

Entity.Absorb is split into ArmorAbsorb (per-cell, never shared) and ItemAbsorb
(the single-lane path), so FireControl.Apply can call armour immediately and
defer item resolution only for a cell whose item is reachable by more than one
lane this shot. FireControl.Apply gains a geometric survey (which items are
reachable by >1 lane, decided before any damage is applied) and takes the
untouched sequential walk (ApplySequential) whenever nothing is shared, or a
new coordinated walk (ApplyWithSharedItems) that deposits each lane's
post-armour remainder into a shared item's pool and resolves it once every
contributing lane has arrived, splitting the leftover proportionally
(sum-then-split, order-independent by construction). A deterministic tie-break
(smallest first-contact Entry) breaks the rare "opposite order" deadlock two
non-convex shared items can create between two lanes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 16:16:53 +02:00
Meta Vens
d1cc047a51 Cut 12.3: shared multi-cell items absorb proportionally (operator ruling)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:28:42 +02:00
Meta Vens
2d13541b9f Cut 12.3 status: closed apart from the multi-cell item ruling
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 15:17:25 +02:00
Meta Vens
cb71a3cfad Cut 12.3 fix batch: unify Lane and Lanes on one membership query
Self's review found that commit 4e6495dd's fix for F1 replaced the per-lane
forward-arithmetic defect with a second, still-independent membership
computation: Lane's own half-open admission (Lo <= s < Hi, from a cell's own
Extent) versus Lanes' ceil((cell.Lo - centreLateral) / laneSpacing) lane
index. The two agree only when a cell's own (Hi - Lo) equals the externally
supplied laneSpacing exactly in float -- the identical two-derivations trap
Cut 12.2's own fix batch already found and removed from Lane itself,
reintroduced one layer up. Confirmed reachable: on commit 4e6495dd, solid5
b=(0,1) s=0.49999997 n=1 leaves the ceil-based centre lane EMPTY while Lane(s)
itself finds all 5 cells of the row -- breaking R3 ("the centre lane always
meets metal", Commit's own guard) and the 12.2 placement contract.

FireControl.Lanes is now built entirely out of FireControl.Lane: it calls
Lane(hull, b, centreLateral + k * laneSpacing, ...) once per lane index, so
Lane(s) is literally this function's n = 0 case rather than a parallel
re-implementation of its rule. Commit's placement and Apply's damage split
now read one function. The narrower question left -- can two individually
correct Lane() calls, at two different lines, still walk the same cell? --
is resolved by ownership (the lane closest to the centre keeps a contested
cell; the centre lane, k = 0, never loses one), not by a competing formula,
so the centre lane's final cell set is always exactly Lane(centreLateral)'s
own output.

Lane() itself is unchanged (still called directly by Commit and by
FireControlCut12Tests' edge-seed and interval-edge tests, all still green:
HitsLandOnTheFacingEdge, LaneSeamIsHalfOpen, LaneNeverEmptiesAtAnIntervalEdge,
Cut12-edge-68442709, Cut12-edge-64078070).

Adds LanesQueryIsDisjointMatchesLaneAtCentreAndNeverEmptyOnHull: now that
Lanes is a public, pure geometric query, the boundary sweep is a behavioural
test of its own contract, no reflection -- over every cell's own shadow edge
and float neighbours, at exact-axis, 45-degree, |bx| > |by| bearings and
Soul's own two reproduction cases, spread 1-2: (a) no cell is walked by two
lanes, (b) the centre lane equals a plain Lane(s) call, (c) the centre lane
is never empty when the centre lateral is inside the hull's own shadow. Hand-
confirmed to fail on 4e6495dd's ceil-based Lanes (property (b), the same
input above) and to pass on this commit (fc123fix2-mut3.log).

Adds CommittedCellIsTheFirstCellTheCentreLaneDamages: an end-to-end check
through Fire -> Commit -> Apply (damageSpread 0, a single lane) that the
committed outcome.Cell is the first cell Apply damages.

Full suite: 286 tests, identical across 3 runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:24:55 +02:00
Meta Vens
742354c67a Cut 12.3 fix batch: F3 rework, F4 delete unreachable mirror test
F3 (medium, confirmed): NoCellIsStruckByTwoLanesAtAnAngledBearing used
penetration 0 (impact cells only) and one fixed-seed shot per bearing, at
only two bearings, so it survived R1e (one-cell spacing when |bx| > |by|),
R1h (spacing 1/max(|bx|,|by|)), R1c (spacing * 0.9), and R1b (spacing *
0.99). Its own comment also falsely claimed a plain revert "fails this at
both bearings" without ever checking a real revert.

Reworked as NoCellIsStruckByTwoLanesInOneShotAtAnyBearing: seven bearings
(exact axis, both 45-degree diagonals, |bx| > |by| and |bx| < |by| on both
sides, all within the fixture's own FiringArc), 300 hits sampled per bearing
at a wide targeting spread (so the committed Lateral's draw visits many
points along the hull's shadow), and ample penetration.

Hand-verified against fc123fix2-mut.log: reverting to one-cell spacing (R0)
and R1c/R1e/R1h are all caught by the full suite -- but not by this test.
F1's structural fix (this branch's earlier commit, FireControl.Lanes) assigns
each cell to exactly one lane index by a single computation, so a wrong
laneSpacing can misassign or drop a cell but can no longer make two lanes
claim the same one; R0/R1c/R1e/R1h are instead caught by the pre-existing
damage-shape tests (DirectHitAtAnAngledBearingMatchesAnIndependentModel,
FootprintWidensAtAnAngledBearingComparedToAxisAligned, and others). R1b (a
1% narrowing) survives the whole 97-test FireControl suite under any of
those tests, including this one, even at 5000 hits per bearing -- recorded
here as an open survivor for Soul's own mutation pass, not claimed dead.
This test's own job is now a standing regression guard on the disjointness
invariant through the real Fire/Commit/Apply pipeline, not a killer of
spacing-magnitude mutants (that job now belongs to the damage-shape tests).

F4: deletes MirrorImageShotsProduceStatisticallyMirroredHullDamage. Soul
showed it cannot fail on spacing -- it survives the full revert and every
spacing mutant, because no per-shot mirror pair is reachable through Fire
(LateralDraw's distribution reverses under mirroring, so a shot and its
"mirror" are independently drawn samples, not a matched pair). It was meant
to pin lane processing order under a shared-cell race; that question is
folded into the F2 disjointness rule (a shared cell can no longer arise) and
the pending F2 ruling on multi-cell item lane order, which remains on hold
per this fix batch's brief.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:07:38 +02:00
Meta Vens
4e6495dd63 Cut 12.3 fix batch: F1, decide lane membership once per cell
Soul's second pass (CONFIRMED): even after the F2 shadow-width fix, Apply's
per-lane loop still called Lane() once per lane index, each call re-deriving
its own lateral s(li) = Lateral + (li - n) * laneSpacing by forward float
addition, then testing that value against a cell's Extent interval
independently of every other lane. Two lane lines are only exactly
laneSpacing apart in real arithmetic; accumulating the offset by repeated
addition can shift a side lane by an ulp or two, letting it land inside a
neighbouring cell's half-open interval that its own unrounded value would
never reach -- the same "two derivations of one quantity" defect Cut 12.2's
own fix batch already removed from Lane itself, recurring one layer up in
Apply.

FireControl.Apply now calls a new Lanes() that decides each candidate cell's
lane index with one computation: k = ceil((cell.Lo - centreLateral) /
laneSpacing) is the unique integer for which centreLateral + k * laneSpacing
falls in the cell's own [Lo, Hi) -- derived once, from values no other lane's
arithmetic has touched. A single Ceiling call returns exactly one integer, so
a cell can be assigned to at most one lane by construction, not by float
luck. When k == 0 this is the same condition Lane() tests for centreLateral
itself, so the centre lane's cell set is unchanged (the 12.2 placement
contract, HitsLandOnTheFacingEdge, still holds). laneSpacing is still used,
unchanged, to place each admitted lane's own line for AlongBearing's slab
solve -- geometry, not membership.

Lane() itself is untouched (still used directly by Commit and by
FireControlCut12Tests' edge-seed tests).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 14:07:36 +02:00
Meta Vens
d301c0fbbd 12.3 map: lanes are disjoint by construction, not by float spacing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 13:22:09 +02:00
Meta Vens
283ce7dce2 Mining map: ChunkId is (Field, Index) throughout, and Cut 2 closed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:51:42 +02:00
Meta Vens
93bfdebd76 Cut 2 fix batch: drop dead MiningDifficulty from Settings.asset
The field was deleted from PlanetSettings but the authored asset still
serialized MiningDifficulty: 500. Byte-exact removal of the one line;
nothing else in the file changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:50:32 +02:00
Meta Vens
34994732d2 Cut 2 fix batch: a broken chunk absorbs no damage
Zone.Wear did not check whether the chunk was already broken. A later hit
read wear.Damage starting from 0 (the value ChunkWear carries while
BrokenUntil is in the future), stayed under hitpoints, and wrote
BrokenUntil = null -- un-breaking a chunk mid-respawn.

Damage delivered to a chunk that is currently broken (zone time <
BrokenUntil) now changes nothing: Wear returns false (this hit did not
break it -- it was already broken) and BrokenUntil, and Damage, are left
untouched. The chunk stays absent until its original respawn time, then
resumes wear from zero as before.

Adds two behavioural tests: a re-hit inside the respawn window, both
below and above hitpoints, must not un-break the chunk or move its
respawn time; and the same rule survives a save/reload round trip.
Confirmed by reverting the fix and watching both new tests fail with the
chunk reappearing early, then restoring the fix byte-exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:49:57 +02:00
Meta Vens
be5382170d Cut 12.3 fix batch: rework the F2 mirror test to compare hull totals, not per-cell sums
MirrorImageShotsProduceStatisticallyMirroredDamage compared per-cell armour
damage SUMS between a bearing and its mirror, using heavy (1000) uniform
armour. That armour never depleted, so no cell's absorption ever competed
with another lane's, and the test could not see the one thing the operator's
ruling is about: two lanes racing for one cell's finite armour under the old
one-cell spacing. Renamed to MirrorImageShotsProduceStatisticallyMirroredHullDamage,
it now resets a small, finite armour value before every individual shot (so
the race is live on every trial) and compares aggregate HULL damage, where a
lost race's leftover actually lands.

Finding, reported rather than hidden: even with this fix, the test does not
fail under the reverted one-cell spacing. Reasoning checked against measured
behaviour: FireControl.Apply always processes lanes in a fixed index order
(li ascending, i.e. lateral increasing), never based on the bearing's sign.
Over many INDEPENDENTLY random lateral draws, a bearing and its mirror sample
statistically equivalent distributions of "which side's lane goes first" --
the fixed-index tie-break rule respects the mirror symmetry in aggregate, so
independently-drawn trials wash out the order-dependent bias that Soul's own
LaneOrderDemo probe found (that probe compares ascending vs descending
processing of the SAME committed shot, not independently-drawn mirrored
bearings). A production-level test that reliably fails under the old spacing
for this specific property would need to force an exact, deterministic
lateral for two geometrically mirrored shots, which is not reachable through
Fire/Commit without reflection (Commit's lateral draw is randomised, and
Apply is private). NoCellIsStruckByTwoLanesAtAnAngledBearing and
FootprintWidensAtAnAngledBearingComparedToAxisAligned remain the two tests
that actually discriminate the ruling behaviourally (confirmed failing under
a hand-reverted one-cell spacing). The mirror test stays in the suite as a
true, currently-passing invariant and useful regression coverage, not as a
defense of this specific ruling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:17:59 +02:00
Meta Vens
c2e7a2166f Cut 12.3 fix batch: F1 angled-bearing parity, F2 spread-lane behaviour
F1: no existing test through Fire commits at a non-axis bearing.
DirectHitAtAnAngledBearingMatchesAnIndependentModel checks every cell's
armour, every item's durability and the hull's own total against an
independent double-precision ray/box model (ported from the Soul probe that
verified this cut's arithmetic to 14,984/15,000 shots), at 45 degrees, a
shallow angle and a bearing with |bx| > |by|.
DiagonalDirectHitReachesEveryCornerCellInOrderThroughFireCommitApply pins the
spec's own diagonal case (Probe1's corner-crossing lane) through the full
Fire -> Commit -> Apply path rather than a direct Lane call: the lane reaches
(0,0), then (1,1), then (2,2), in that order (a bearing this close to 45
degrees also admits the diagonal's row/column neighbours, so the walked lane
is usually five cells, not three -- the spec only requires the three corner
cells present and in order, the same standard the existing direct-Lane test
already pins).

F2 (operator ruling, 2026-09-25: spread lanes should diffuse sideways rather
than double up): three behavioural tests, deliberately not asserting the
spacing value itself (operator: "test behavior, not shape").
NoCellIsStruckByTwoLanesAtAnAngledBearing fires at 45 degrees and at a bearing
with |bx| > |by|, spread 2, heavy uniform armour, and checks no cell fires
ArmorDamage twice. MirrorImageShotsProduceStatisticallyMirroredDamage compares
300 hits at a bearing against 300 at its mirror image, and asserts the
per-cell damage totals are mirrored within tolerance.
FootprintWidensAtAnAngledBearingComparedToAxisAligned compares the lateral
span of hit cells for the same spread at 45 degrees against axis-aligned, and
asserts the angled footprint is wider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:08:29 +02:00
Meta Vens
a9538b205e Mining map: Q2 ruled (one slot, a chunk of a field), detection deferred to EW, Cut 2 status
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:07:18 +02:00
Meta Vens
daa645601a Cut 2 Stryker fix batch: chunk-index bounds, respawn boundary, ChunkId equality
Stryker over Zone.cs (concurrency 1, 111 mutants tested) surfaced four real
gaps on this cut's own lines, all now killed:

- ChunkExists's range check (`index < 0 || index >= length`) survived both an
  AND weakening and a `>` boundary weakening, because nothing tried an
  out-of-range index on either side alone.
- The broken-until comparisons in ChunkExists/ChunkRadius and the pack-time
  pruning in IsExpired all survived a `>`/`<` vs `>=`/`<=` boundary flip,
  because every prior test advanced zone time well past BrokenUntil instead
  of landing on it exactly.
- ChunkId.Equals survived an AND-to-OR weakening: the wear dictionary's own
  GetHashCode already separates same-field/different-index and
  same-index/different-field pairs into different buckets, so a bad Equals
  was never reached through a lookup. Testing equality directly closes that.

Two survivors on this cut's lines are recorded as equivalent, not chased:
ChunkRadius's `wear.Damage <= 0f` boundary (at damage == 0, DamagedSize and
UndamagedSize evaluate the same curve at the same point, so no input
distinguishes the two branches), and ChunkId.GetHashCode's exact formula (a
hashcode's bit pattern isn't a contract; any deterministic function of the
same two fields trivially keeps equal keys hashing equal, and this
dictionary is too small for distribution to matter).

The remaining survivors (lines 44, 75, 170, 200, 212, 216, 319, 336-412) sit
in Update/GetOrbitPosition/GetSecurityLevel/GetHeight/GetNormal/PowerPulse,
none of which this cut touches; they predate it and are out of scope here.

Mutation score 38.62% -> 42.33% (78/111 killed, 2 timeout, 31 survived, all
31 either pre-existing or one of the two equivalents above).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 12:05:47 +02:00
Meta Vens
078b1ff36d Cut 12.3 fix batch: F10, an independent AlongBearing expectation at several bearings
The previous AlongBearingReturnsTheExactSlabIntersection wrote out SlabAxis's
own threshold (1e-9f) and clamp a second time in its ExactSlab helper, so a
mutant that only moved that threshold (C7b, 1e-9 to .2) agreed with both
copies identically and survived.

AlongBearingReturnsTheExactSlabIntersectionAtSeveralBearings replaces it: the
expected entry/exit now come from an exact ray-box intersection that never
special-cases a near-zero bearing component -- IEEE division by a signed zero
already yields the correctly signed infinity, so an axis with no motion is
unconstrained without a hand-written epsilon to disagree with SlabAxis's own.
Checked at the original fixture's bearing plus two within about 11 degrees of
an axis, inside C7b's mutated .2f threshold but nowhere near the real 1e-9f
one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:53:47 +02:00
Meta Vens
435f905e8b Cut 12.3 fix batch: F4 first-gap, F5 side-lane remainders, F6 armour/item order, F7 handedness
F4: AnAPRoundStopsAtTheFirstGapAndLeavesTheFarSideOfTheNotchUntouched, a notched
U-shaped hull, pins Lane's own contiguity break (an AP round with ample
penetration must stop at the first gap, not reach the far side).

F5: EverySideLanesRemainderReachesTheHullNotOnlyTheCentreLanes, an
axis-aligned spread-1 fixture (lanes share no cells, so order cannot matter),
pins that every lane's own leftover reaches the hull, not only the centre
lane's.

F6: AbsorbSpendsArmourBeforeTheItemOnTheSameCell, direct Absorb calls (this
file's existing style for the function's own arithmetic) with armour and an
item on the SAME cell for the first time -- no prior fixture combined them.

F7: ADirectHitFromStarboardDamagesStarboardCellsWhenFacingIsMostlyLateral, a
direct-hit test at a facing with |fx| > |fy|, computing "starboard" as the
independent right-perpendicular of the facing rather than reading it from
Entity.ToSchematic. Cut 11's Splash tests are the only thing guarding this
handedness today, and 12.4 deletes Splash.

Both F4 and F5 track hull damage per-attempt (reset on each retry), not as a
before/after total across every retry: this fixture's off-target lanes carry
no armour, so a stray hit on the wrong column during a retry spends real
damage on the hull and would otherwise contaminate a cross-attempt total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:39:53 +02:00
Meta Vens
b82b7eab21 Cut 12.3 fix batch: F2 lane spacing by shadow width, F3 penetration boundary fixture
Operator ruling (2026-09-25): overlapping spread lanes should diffuse sideways
rather than double up. FireControl.Apply now spaces lanes by the shadow width
a cell casts at the committed bearing (Extent's own h, doubled) instead of by
one cell -- 1 at axis-aligned bearings (unchanged), up to sqrt(2) at 45
degrees. Reuses Extent, the one function that already owns h for Silhouette
and Lane, rather than re-deriving it a second way.

F3: PenetrationExcludesACellExactlyAtItsOwnBoundary's 1e6-durability marker
absorbed the whole shot before the walk could reach the boundary cell, so the
test could not fail under the `>=`-to-`>` mutant. The marker now carries 10
durability, leaving a remainder that would visibly damage the boundary cell if
the walk incorrectly included it. Adds
PenetrationExcludesCellsBeyondANonIntegerDepth, pinning the ordinary
"< penetration" comparison at a depth (1.5) that isn't an exact-integer
boundary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:32:02 +02:00
Meta Vens
c924bae0dc Cut 2: tests for chunk wear's accumulation, break, respawn and persistence
Fixtures use two belts of distinct sizes and authored-shape hitpoints/
respawn curves, exercised over uneven time steps, never the flat default
curves that would hide a broken formula.

Pins: damage accumulates and shrinks the chunk before it breaks; the break
threshold is strictly greater-than (equal-to-hitpoints does not break);
respawn is a comparison against zone time, reached through uneven dt steps;
a chunk broken, respawned, and damaged again starts from zero rather than
leaking stale wear; wear does not cross-talk between chunks that share a
field or an index; wear round-trips through PackZone/Zone(pack); a healed,
non-broken entry is pruned from the pack; and a record built as raw
MessagePack bytes with only the six pre-Cut-2 keys (not a default-
constructed ZonePack) deserializes with ChunkWear == null and loads with no
wear, per the nullable-key-6 persistence rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:31:22 +02:00
Meta Vens
3b9f0f1d09 Cut 2: the dead mining path goes, and chunks get one owner
MiningTool (its Execute range-checked against nothing, since no writer ever
set AsteroidBelt/Asteroid) and Zone.MineAsteroid (mints nothing; the
SimpleCommodity drop was commented out) are deleted, per Q1=A: "Bring back
the drill, indeed." Union tag 26 is retired, not reused. ResourceScanner's
dead survey Execute and its scan-target fields go too; its authored Range/
MinimumDensity/ScanDuration stay pending Q2. PlanetSettings.MiningDifficulty
had one reader, now gone.

Chunk wear (damage, broken-until) moves off AsteroidBelt's three per-belt
dictionaries and onto Zone as the one owner (Q3=A): Zone.Wear is the only
writer, ChunkExists/ChunkRadius are the readers, and respawn is a lazy
comparison against zone time, never a per-tick loop. ChunkId is
(CultRecordKey Field, int Index) -- "Field", not "Belt", because chunks are
meant to generalize past asteroid belts to other debris fields later.

Persisted in ZonePack's new key 6 (List<ChunkWearPack>, nullable so an older
record with no key 6 loads with no wear instead of throwing), pruned of
healed, non-broken entries at pack.

The break threshold stays strictly greater-than, matching today's behaviour:
damage exactly equal to hitpoints does not yet break the chunk.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:30:44 +02:00
Meta Vens
f2c94c29be Q12-2 amended: spread lanes are spaced by a cell's shadow, so none doubles up
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:20:45 +02:00
Meta Vens
e4d38f16fa Mining Q3 ruled: chunks respawn on the authored curve, wear persists
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:09:35 +02:00
Meta Vens
007771fe87 Mining Q1 ruled: MiningTool goes, the Drill Bit returns as a weapon
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 10:06:39 +02:00
Meta Vens
73b15d9f48 Cut 12.3 Stryker fix batch: exact-threshold and lane-count survivors
First Stryker pass over the changed lines (Entity.cs: Absorb/DamageHull;
FireControl.cs: Apply, Splash) killed 584/844 candidate mutants; these
six survivors on the cut's own diff get real behavioural tests instead:

- Entity.Absorb's `d > 0f` and `d > 0.1f` guards, and DamageHull's
  `damage > .1f` guard, each had their boundary flipped to `>=` and
  survived -- at the exact boundary (0 incoming, or exactly the .1f
  carry-forward threshold), real code does nothing while the mutant
  fires an extra event or spends an extra fraction. Not a rare float
  coincidence: a spent lane routinely reaches a cell with exactly 0
  remaining, and an authored penetration/armour value can land exactly
  on .1f.
- FireControl.Apply's `target.IncomingHit.OnNext(shot.Source)` (moved
  here from the deleted Entity.ApplyHit) had no test that it still fires.
- FireControl.Apply's two `walked[li] > 0` checks (metalLanes counting,
  and the absorb-loop entry) both flipped to `>= 0` and survived, since a
  lane count can never be negative -- a real bug class (a lane entirely
  off the hull would dilute the split and leak a damage share to the
  hull) that a hull no wider than the spread now catches.
- The penetration cutoff's `>= shot.Penetration` flipped to `>` survived
  at the exact boundary -- an axis-aligned lane's entry values are exact
  integers, so an authored integer penetration routinely lands exactly on
  a cell's own entry difference.

Recorded, not chased: `shot.Outcome.Lateral - (li - n)` (the lane-offset
sign) is an equivalent mutant -- 2n+1 lanes built symmetrically around n
cover the same SET of offsets either way, just enumerated in reverse, and
the loop's own per-lane work is order-independent. The missing
`ArrayPool<LaneCell>.Return` survivor is a perf-hygiene gap (GC pressure,
not a spec'd invariant -- only the forecast path is zero-allocation), not
yet reached by a dedicated allocation test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 09:09:16 +02:00
Meta Vens
7f1fde8e71 Cut 12.3: verification for the direct-hit lane's own new rules
DamageIsAbsorbedInOrderAlongTheRay, ArmourFacesTheShot,
BuriedCockpitNeedsPenetration, SpreadWidensTheImpactAcrossLanes,
ARayThroughACornerCrossesTheCornerCell and LaneRemainderReachesTheHull,
per docs/fire-control-cut.md's Cut 12.3 verification list. Builds its own
fixtures (the file's own Build), matching every other cut's own test file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 05:56:45 +02:00
Meta Vens
3fe66f555e Cut 12.2 carried items: pin Lane's seam contract and AlongBearing's values
Items carried into 12.3's brief from 12.2's third Soul pass, all on code
12.3's own lane walk builds on:

- LaneSeamIsHalfOpen pins the s >= Hi admission test (FireControl.cs) on
  the smallest fixture where the seam matters -- the s > Hi mutant that
  survived 12.2 would have interleaved two columns at a shared seam once
  12.3's walk started reading more than buffer[0].
- AlongBearingReturnsTheExactSlabIntersection gives AlongBearing/SlabAxis
  their first test of actual VALUES (every mutant there survived in 12.2,
  equivalent while only buffer[0].Cell was read) -- a diagonal fixture
  checks Lane's own Entry/Exit against an independent slab solve, cell for
  cell, in order.
- Corrected the allocation comments on Forecast and
  LaneAndSilhouetteAllocateNothingGivenAPooledBuffer: the ~120 B/call on a
  gated-in HitProbability is three GetBehavior<TargetingSystem> calls (not
  EquippedItem.Behaviors, which is a plain array), plus CellsOf's ~944 B
  when an item is aimed at; noted that the loose <500_000 bound doesn't
  catch a reintroduced comparer wrapper but the buffered zero-allocation
  asserts do.
- ZeroProbabilityShotCommitsAMissWithoutBuildingASilhouette is now
  behavioural: PFire 0 comes from closing VisibleEntities (the real gate),
  and "no Silhouette was built" is checked by asserting zero allocation
  rather than reading CommitProbability's own struct default.
- Dropped the unused System.Reflection import.

Also replaces ExpectedMarchCells, which reproduced Entity.ApplyHit's own
deleted 0.5-step march, with ExpectedLaneCells, built on the
already-verified FireControl.Lane plus an independent penetration cutoff --
used by TurningAfterCommitChangesNothing, whose fixture also gets real
per-cell armour (the flat 1000 armour every Build() authors would let the
new sequential Absorb model's first cell alone swallow the whole 5-damage
shot, leaving nothing to show on the rest of a several-cell lane).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 05:56:30 +02:00
Meta Vens
3b6b9e4a28 Cut 12.3: drop two Cut 12.3 tests that called the deleted Entity.ApplyHit
HardpointHitDamagesItemThenHull and PenetrationMarchIsPlanar both called
Entity.ApplyHit directly, which Cut 12.3 deletes. The rules they pinned:
"damage above armour plus item durability zeroes the item and passes the
remainder to the hull" is now FireControlCut123Tests.DamageIsAbsorbedInOrderAlongTheRay,
through the real Fire/Commit/Apply path. "The penetration march is planar,
in the target's own schematic frame" is subsumed by 12.2's own
HitsLandOnTheFacingEdge and TurningArmourIntoTheShotTakesItOnTheArmour
(which already exercise FireControl.Apply's committed, schematic-frame
bearing end to end) and by FireControlCut123Tests.ArmourFacesTheShot,
which pins planarity across several non-axis-aligned facings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 05:56:11 +02:00
Meta Vens
70c3e0ccdb Cut 12.3, sub-cut A: armour absorbs first down the direct-hit lane
Deletes Entity.DamageSchematic (the even split over the whole hit shape)
and Entity.ApplyHit (the 0.5-step penetration march), replacing both with
Entity.Absorb (armour then item, per cell) and Entity.DamageHull, moved
verbatim from DamageSchematic's own body. FireControl.Apply now builds
2n+1 parallel lanes from the committed Bearing/Lateral (Q12-2 = A),
shares damage evenly over the lanes that meet metal, walks each lane in
order via the already-verified FireControl.Lane, absorbing cell by cell
up to the penetration depth, and sends every lane's own remainder to the
hull where it ends (Q12-3 = A). Splash is rewritten onto Absorb/DamageHull
(arithmetically identical to before) since DamageSchematic is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 05:55:59 +02:00
Meta Vens
c7b6e80c70 Cut 12.2 closed: status, what three Soul passes found, and what 12.3 inherits
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 05:17:10 +02:00
Meta Vens
ca1670a216 Cut 12.2 Soul fix batch 2, S3: measure allocations, correct an overclaiming comment
Measured (Release, 7x9 solid hull -- the LonginusX shipped-hull fixture the
brief named is not available to this test file):

- Lane: 0 B / 1000 calls (was: 64 B/call from Array.Sort's comparer wrapper;
  now confirmed 0 after the earlier IComparable<T> change in this batch).
- Silhouette (caller-supplied buffer): 0 B / 1000 calls.
- HitProbability, gated in (a real, non-gated-out call): ~120 B/call. This is
  NOT from Lane, Silhouette or the comparer -- it comes from Accuracy/
  Resolution's own GetBehavior<T>, which walks Entity.Equipment and each
  item's Behaviors (both ReactiveCollection<T>); that type's enumerator is
  heap-allocated per foreach. This predates Cut 12.2 and is out of this cut's
  scope to fix.
- Inspect, gated in: ~280 B/call (same cause, more GetBehavior<T> calls).

The Forecast comment claiming "the forecast path (HitProbability, Inspect) no
longer allocates on a gated-in call" was not true and is corrected to say what
was actually measured: Silhouette itself is allocation-free given a pooled
buffer, and the residual cost belongs to Entity's own collection choice.
LaneAndSilhouetteAllocateNothingGivenAPooledBuffer asserts the true zero-alloc
claims exactly and records (with a loose regression bound, not a false zero)
the unrelated Entity-level cost on the full HitProbability path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:30:30 +02:00
Meta Vens
73c53a9335 Cut 12.2 Soul fix batch 2, :~483: pin the zero-probability guard
CommitProbability's `if (p <= 0f) return 0f;` guards against building a
Silhouette for a shot that cannot hit. Stryker's `p < 0` boundary mutant
(excluding only p == 0 exactly) survived because nothing exercised the guard
at that exact boundary. ZeroProbabilityShotCommitsAMissWithoutBuildingA
Silhouette sets a real, fired shot's PFire to 0, calls CommitProbability
directly and asserts sil stays the zeroed default (Intervals null, Count 0 --
no Silhouette was built), then resolves the shot through Zone.Update and
checks it lands as a clean miss.

Manually verified against the exact `p < 0` patch: it now fails (sil.Intervals
comes back non-null, a real Silhouette array).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:24:13 +02:00
Meta Vens
0ece224b0b Cut 12.2 Soul fix batch 2, S8: an L-shaped aimed item, not just a square
Only a 2x2 (BigMarker) aimed item was ever tested -- a square's centroid and
its bounding-box centre are the same point, so N11 (aim point = bounding-box
centre instead of the true cell-average centroid) survived. AimingAtAnLShaped
ItemCentresOnItsCentroidNotItsBoundingBox equips a 3-cell L-tromino (Build's
new equipLMarker fixture), fires from a diagonal facing so the shape's true
asymmetry projects fully onto the lateral axis, and asserts the empirical mean
lateral offset tracks the item's own true centroid (computed by the test) and
not its bounding-box centre.

Manually verified against N11's own patch: it now fails (empirical -2.139,
tracking the wrong bounding-box prediction -2.121, against the true centroid
-1.886); the existing BigMarker test is unaffected since a square's two
candidate points coincide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:21:40 +02:00
Meta Vens
4510a62c4f Cut 12.2 Soul fix batch 2, S7: author Tracking through Build, not by patching after Fire
TheHudEstimateIsTheCommitPrice used to fire each shot, then reach into
Zone.PendingShots and overwrite the frozen Tracking field after the fact. Build
now takes a `tracking` parameter (default 100000, matching the old fixed
value) alongside Precision and Accuracy, so this test authors Tracking = 6 up
front like every other frozen shooter stat, with no post-hoc patch loop.

Manually verified M15 (Commit applies PSpread twice) still fails this test
(empirical 0.070 vs forecast 0.126) after the rewrite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:17:38 +02:00
Meta Vens
7eadea88ab Cut 12.2 Soul fix batch 2, S4: pin flight time for an invisible target
F8 (Soul's earlier fix batch, 2026-09-24) moved range computation ahead of the
visibility gate in FireControl.PFire so Fire's own flight time stays real even
when the shot prices at PFire 0, but no test observed that behaviour --
N4 (Soul's own mutation set, reverting F8) survived every existing test.
InvisibleTargetStillResolvesAtItsRealFlightTime fires at a target removed from
VisibleEntities and checks the shot does not resolve before its real 5s
arrival (N4's bug would resolve it instantly, at range 0) and resolves as a
miss once it does.

Manually verified against the exact N4 patch: it now fails (arrival at ~1s
instead of ~6s, i.e. range treated as 0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:14:15 +02:00
Meta Vens
c2b27b10ee Cut 12.2 Soul fix batch 2, S2: pin the within-prong ratio, not just direction
TwoProngHullSplitsTheScatterAcrossBothIntervals's own within-prong check
(atNearColumn > atFarColumn) held under M12/M12b (an entire second silhouette
built at the wrong sigma) and the sigma/sqrt(2) Stryker mutants, because every
wrong sigma tried still puts more mass on the nearer column -- direction alone
cannot separate a sigma of 1.5 from 1.5*sqrt(2). Their analytic near/far mass
ratios are well apart (~2.9 true vs ~1.73 at sigma*sqrt(2)), so the test now
computes the true ratio from the same per-cell Gaussian integral it already
uses and asserts the empirical ratio (8000 shots) tracks it within a tolerance
that rejects the wrong-sigma ratio.

Manually verified against the exact M12 and M12b patches from Soul's mutation
script: both now fail this test (empirical ratios 581 and 1.68, matching a
collapsed and a sqrt(2)-shifted sigma respectively, against the analytic ~2.9).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:11:27 +02:00
Meta Vens
d82b6bf9ed Cut 12.2 Soul fix batch 2, S1: behavioural tests, not reflection, for the shadow fix
Replaces LateralDrawIsHalfOpenAtTheShadowsTopEdge (reflection into the private
LateralDraw) with:

- ShotAtBearingLoTouchingOnlyACellCornerHitsMetal and
  ShotAtBearingLoOnTurningArmourHitsMetal, Soul's two named-seed crash repros
  (Cut12-edge-68442709 and Cut12-edge-64078070 -- StableHash(zone name) seeds
  Zone.CombatSeed, so the exact name reproduces the exact die roll) run
  through the real public Fire/Zone.Update path, asserting the shot commits a
  hit whose cell's own projected lateral interval contains the drawn Lateral,
  instead of throwing.
- LaneNeverEmptiesAtAnIntervalEdge, the general sweep: every interval's Lo and
  the point just below its own half-open Hi, across several bearings,
  precisions and hulls (including a non-convex, holed one), must never return
  an empty lane from FireControl.Lane.

Build gained a zoneName parameter (Cut 6.1's one-fixed-name convention doesn't
serve a repro that needs an exact CombatSeed) and a tracking parameter and an
equipLMarker fixture, both used by later findings in this batch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:06:44 +02:00
Meta Vens
d38efba3a3 Cut 12.2 Soul fix batch 2, S1/S3: one shadow authority in Lane, sort without a comparer
S1 (HIGH, crash in play): Lane's own shadow prefilter (a re-derivation of
Silhouette's centre/h) and the independent SlabAlongB 2-axis intersection test
could disagree at a float edge, rejecting a cell the shadow sum had already
counted metal for -- an empty lane after a hit passed its roll (R3 violation),
reproducible through Zone.Update. Both are replaced by one shared admission
test (Extent(c, axis), the exact support of a unit square along an axis) that
Silhouette and Lane now both call; SlabAlongB is deleted, and its geometry is
kept only as a non-rejecting AlongBearing() that computes entry/exit for
already-admitted cells (the doc's own equivalence proof -- "s in the shadow" is
exactly "the line intersects" -- makes rejection there unreachable by
construction, not merely unlikely).

S3 (allocation): Interval and LaneCell now implement IComparable<T> (same
order as the deleted IntervalByLoComparer/LaneCellComparer) so Silhouette's and
Lane's sorts use Array.Sort(T[], int, int), which resolves T's own comparison
at JIT time, instead of the (T[], int, int, IComparer<T>) overload, which
wraps even a cached singleton comparer in a fresh delegate per call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 03:01:21 +02:00
Meta Vens
670831c8af Mining Cut 1 status, and a corrected cost baseline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 02:39:42 +02:00
Meta Vens
d9c887c129 Cut 1 Stryker fix batch: cover EvaluateBelt and belt Radius
Stryker over Zone.cs (231 mutants, scoped by --mutate to this cut's file)
found two real gaps, both NoCoverage/Survived, not equivalents:

- Zone.EvaluateBelt and AsteroidBelt.Evaluate -- the renderer's own path
  (ZoneRenderer.cs Update, AsteroidBeltUI.Update) -- were never called by any
  test, so the whole batch body and its loop bound were unreached.
  EvaluateBeltFillsEveryAsteroidExactlyAsChunkPoseWould pins that the batch
  path fills every index exactly as the per-index ChunkPose would, closing
  the gap without duplicating the orbit formula a second time.
- AsteroidBelt.Radius (data.Asteroids.Max(a => a.Distance)) had no assertion;
  a Max-to-Min mutant survived. BeltRadiusIsTheFarthestAsteroidsDistance pins
  it, since the renderer's visibility bounds and minimap mesh both size off
  this field.

Full suite: 262/262 green (260 + these 2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 01:49:51 +02:00
Meta Vens
22a54ccbaf Cut 1: belts are evaluated when asked, not simulated every tick
Zone.Update no longer threads a per-belt Task.Run over a double-buffered
Transforms/OrbitPosition pair. AsteroidBelt.Pose/Size are the one place a
chunk pose is computed, a pure function of zone time; Zone.ChunkPose and
Zone.EvaluateBelt read them at the zone's own time. MiningTool,
ResourceScanner and ZoneRenderer (belt matrices and AsteroidBeltUI) all read
through Zone instead of the deleted per-tick buffers; the renderer owns its
own float4[] buffer, filled fresh every frame.

Deleted: System.Threading/.Tasks usings, BeltUpdates, the wait loop, the
per-belt copy+Task.Run, NearestAsteroid (dead/broken reader), the private
UpdateAsteroidTransforms, and AsteroidBelt's four pose fields plus their
allocations. ~65 lines, matching the cut map's estimate.

miningprobe, densest zone of the operator's save (EAC-2265, 809 asteroids,
8 belts), rebuilt against this cut and rerun 10x each side:

before (branch point, 8bd25f6f/e729e6d6):
  Zone.Update wall 541-3654 us/tick, CPU 120-391 us/tick (7 clean runs)
  3/10 runs crashed: InvalidOperationException from Zone.GetOrbitPosition,
  the documented _updatedOrbits/Orbits data race between the main thread's
  Clear() and a belt Task.Run

after (this commit):
  Zone.Update wall 95-185 us/tick, CPU 99-152 us/tick, in line with the
  31-39 us "no belt work" baseline the map recorded -- belts are free per
  tick
  0/10 races
  ChunkPose has no buffer to go stale: ~0.12 u of parent+asteroid motion is
  visible across one 17 ms tick instead of being one tick behind

tests/Aetheria.Shared.Tests/MiningCut1Tests.cs (new, 260/260 suite green):
  ChunkPoseIsTheOrbitAtZoneTime, ChunkPoseDoesNotDependOnUpdateCadence,
  DamagedChunkShrinksAndABrokenOneHasNoSize -- each expected value is the
  closed-form orbit/size rule reimplemented in the test, never a call to
  AsteroidBelt.Pose/Size.

Negative grep (Zone.cs, "Zone Display", ServerShared/Behaviors) for
Task\.Run|System\.Threading|NewTransforms|\.Transforms\b|BeltUpdates|
NearestAsteroid|\.OrbitPosition\b|NewOrbitPosition: one hit, the commented
line in MineAsteroid that Cut 2 deletes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 01:27:16 +02:00
Meta Vens
e729e6d6d5 Mining campaign: target and cut map
Operator, 2026-09-25: target the chunk, hit it with a weapon whose damage
suits the ore, and roll a weighted loot table from damage type, composition
and weapon stats. First cut slims the belt simulation, which probes show is
the heaviest per-tick cost and a data race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 00:59:15 +02:00
Meta Vens
8bd25f6faa Cut 12.2 Soul fix batch: half-open clamp, split assembly, real rolls
F1 (correctness): LateralDraw clamped the drawn lateral to the closed
[Lo, Hi], not the spec's half-open [Lo, Hi). Soul enumerated all 2^24
NextFloat outputs against TurningArmourIntoTheShotTakesItOnTheArmour's own
geometry and found 3 that draw exactly Hi, which Lane's own half-open filter
then admits no cell for -- a hit that passed its roll landing nowhere (R3).
Fixed the clamp; Lane's silent int2.zero fallback on an empty lane is now a
thrown InvalidOperationException, since an empty lane is provably impossible
after the fix. Committed Soul's edge probe as
LateralDrawIsHalfOpenAtTheShadowsTopEdge.

F6/F8: HitProbability, Inspect and Fire each assembled bearing -> Silhouette
-> PSpread (or recomputed range) in their own copy; a shooter-frame bearing
bug in HitProbability's copy survived while the identical bug in Inspect's
copy was caught. Collapsed into one Forecast function and one PFire(out range)
overload; both callers, and Fire, read the one computation.

F2: FireControlCut12Tests' zone names carried a Guid, breaking every other
cut's fixed-seed convention (FireControlCut6Tests.cs:62-63) and reseeding the
die every run -- the actual source of the flake in
TurningArmourIntoTheShotTakesItOnTheArmour. Fixed to a fixed zone name.

F3/F4/F5/F7: added a two-prong hull fixture (LateralDraw's walk past the first
interval, and a wrong-sigma placement, were unreachable when every fixture
projects to one interval), a real-roll empirical test for CommitProbability
(the old one called the pure function twice and compared it to itself),
enough Penetration in TurningAfterCommitChangesNothing for ApplyHit to
actually read the bearing, and a 2x2 item fixture for ResolveAimPoint's
average (every "Marker" elsewhere is 1x1, so sum/length and sum*length agree).

F9: Lane's own comment claimed no allocation while its sort used
Comparer<T>.Create over a closure; LaneCell now carries its own precomputed
projection and Lane sorts with a stateless singleton comparer. Corrected an
overclaiming comment in FireAuthorityTests (SigmaFloor makes the aimed-lane
draw ~68% per shot, not deterministic; the fixture's fixed zone name is what
actually makes it reproduce).

Cost: Silhouette takes an optional caller-rented Interval[] buffer; the
forecast path (HitProbability/Inspect, via Forecast) rents from
ArrayPool<Interval>.Shared and returns it before returning, since neither
reads sil.Intervals after the call. Commit/CommitProbability still get an
owned array, since LateralDraw needs it alive past the call. Measured on
LonginusX (66 cells, Release): unaimed 672 B -> 184 B/call (1512-1637ns before,
1482-1560ns after); aimed 1160 B -> 672 B/call (2123-2140ns before,
2094-2162ns after) -- the remaining ~488B/call gap between aimed and unaimed
is ResolveAimPoint's own CellsOf allocation (a List<int2>+ToArray per call),
not in this batch's scope.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 23:08:19 +02:00
Meta Vens
efe4f7c954 Cut 12.2 Stryker fix batch: one range, five real gaps
The first Stryker pass (375 mutants, 69 survivors on this cut's own changed
lines) found one real split-authority bug and several untested edges:

- HitProbability recomputed target.Position - source.Position a second time
  for PSpread's range, a second place the same subtraction could flip sign.
  PFire now returns its own gate-computed range by out parameter; HitProbability
  reads that one value instead of a second copy.
- TravelDirection's point-blank fallback and Fire's null-target guard around it
  were only ever exercised at shooter/target pairs where the real direction
  happened to equal the (0,1) fallback by coincidence.
- diagnostic.PFire (presentation) was only ever checked at PSensor == 1, where
  Accuracy * PSensor and Accuracy / PSensor agree.
- CommitProbability's four-factor product was only ever checked with
  pDeviation == 1 (no fixture moved a target between fire and commit), where
  * and / by 1 agree.
- ResolveAimPoint's zero-cells fallback (an aimed item that no longer occupies
  any cell) was never reached; every fixture's marker survives to be hit.

New tests: TravelDirectionMatchesThePredictedInterceptAndFallsBackAtPointBlank,
DiagnosticPFireIsAccuracyTimesPSensor, CommitProbabilityIsTheExactProductOfItsFourFactors,
AimPointFallsBackWhenTheAimedItemNoLongerOccupiesAnyCell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 21:25:15 +02:00
Meta Vens
7dbb3bcf7a Cut 12.2: where a hit lands is priced and drawn from one silhouette
FireControl.Silhouette replaces HullKernel/WeightedPick/POnHull: the hull's
lateral shadow at a bearing, merged into intervals, integrated exactly with
CultMath.erf/erfinv instead of a discrete per-cell Gaussian sum. FireControl.Lane
does exact slab traversal to pick the impact cell from a lateral offset; only
its first element (the entry-nearest occupied cell) is used here, per the cut
map -- the rest is 12.3's armour-first absorption march.

Bearing timing: PendingShot.PBase is renamed PFire and now carries only the
shooter-side factor (Accuracy x PSensor) behind the gates; TravelDirection,
Spread and FireRange are frozen alongside it. The target's facing is read live
at Commit through FireControl.CommitProbability (steps 1-5 of the spec's
"Bearing timing"), not frozen at Fire, so a target that turns its armour into
an incoming shot takes the hit there. ShotOutcome gains Bearing/Lateral,
frozen at commit; Apply reads only those, never a live position or facing.
Entity.ApplyHit takes an already-schematic bearing instead of a world
direction, and the ToSchematic call 12.1 put inside it is gone.

Superseded tests: PlacementAndProbabilityShareOneKernel, EveryHitLandsOnMetal
and AimingAtTheSternHitsTheStern are replaced by
FireControlCut12Tests.PlacementAndProbabilityShareOneSilhouette,
HitsLandOnTheFacingEdge and AimingAtAnItemCentresTheScatterOnItsLane.
FireAuthorityTests.AimedHitLandsOnSelectedItem and PenetrationMarchIsPlanar are
updated for ApplyHit's new bearing parameter and Lane's entry-nearest-cell
placement (a solid hull's Tool item is never itself the entry cell; reaching
it now needs the same penetration march the new tests exercise).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 20:40:50 +02:00
Meta Vens
dc81867998 Cut 12.1 status
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:57:53 +02:00
Meta Vens
e91ba36976 Pin CultLib per package, as Unity's manifest does
The headless build pinned one CultLib revision for every package. CultMath
0.2.4 needs a newer revision than CultCache's, and bumping the single pin
would have compiled six commits of newer CultCache under the headless tests
while Unity stays on caching-unity-v1.4.0. CultMathRoot/CultMathRevision now
pin CultMath at the 0.2.4 tag; CultLibRoot/CultLibRevision keep CultCache at
45c2f40. Verified: 244 pass with both roots right, and each wrong root is
refused by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:17:40 +02:00
Meta Vens
2a68b4c077 Repin CultMath to 0.2.4: erf and erfinv reach Unity
Lock hash is the tagged merge 6d5e2096; batchmode resolve and compile clean.
Nothing calls erf yet; Cut 12.2 will.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 19:14:00 +02:00
Meta Vens
b851b0d1c3 Cut 12.1: one frame owner, and the dead outcome flag
Entity.ToSchematic(float2) is the one schematic-frame transform;
Entity.ApplyHit's penetration march and FireControl.Splash's
directional half both call it instead of each carrying an inline
forward/right copy. ShotOutcome.Aimed and its plumbing (Q12-4 = A) are
deleted: the aimed local/flag in Commit, MakeOutcome's aimed
parameter, and the AimedCells half of ResolveAimPoint's tuple, which
now returns float2 directly.

No behaviour change. All 244 tests pass unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 18:55:53 +02:00
Meta Vens
212121eb88 Cut 12.0 status: the code closes, the release is owed
Records what Soul found (the wrong-signed erfinv edge that would have put hits
on the opposite side of a hull), corrects three stale verification lines, and
sets a cost measurement 12.2 owes rather than assumes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 21:44:27 +02:00
Meta Vens
6f4c11fc01 Locomotion map: one full-wrench solve, a predicting planner, and TorqueFloor dies
Q5 is dissolved rather than answered: the controller asks for the force and
the torque it wants together and the solver minimises both, so the lurch is
spent only when the translation was wanted anyway. The planner rolls
candidates forward and scores where the ship ends up, which is what makes
strafing beat the big circle. The legacy hulls' second behaviour is
VelocityLimit, not VelocityConversion, as the operator said.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:50:14 +02:00
Meta Vens
7a515e6f45 Locomotion map revised: rulings recorded, content restore becomes Cut 1
Q1 (divergence accepted), Q2 (differential main thrust allowed, no thruster
exclusion) and Q3 (fixtures follow the data) are ruled. A content-restore cut
recovers the legacy thruster hulls, which the live catalog lost, and the
rotation design no longer excludes any actuator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:27:02 +02:00
Meta Vens
0984438c6c Cut 12: operator confirms bow is +y on the schematic
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:20:10 +02:00
Meta Vens
6ee30e1996 Cut 12: scope Q12-8 to warheads; a dumb AP round does damage in a line
The blast radius, not penetration, picks the model: no radius means the lane
walk with cell-by-cell absorption; a radius means the shot reaches fuse depth
and detonates as an area. AP round snipes a component, explosive penetrator
guts a section.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:18:57 +02:00
Meta Vens
8342e1c528 Cut 12.4: blasts are areas, not rays
Operator: distribute the damage over the affected area. A blast covers the
cells within its radius and each takes the share of the disc inside it;
damage over open grid is lost, so an airburst wastes most of itself and an
internal detonation delivers nearly all of it. A shot has a direction and
keeps the lane model; a blast does not. Q12-6 ruled out, Q12-7 dissolved,
Q12-8 ruled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:16:35 +02:00
Meta Vens
30f280a61f Cut 12 map revised: bearing at commit, spread as width, 12.4 detonation primitive, modifiers are labels
Records the operator rulings of 2026-09-22 (Q12-1..4, penetration retune as a
follow-up, WeaponModifiers as labels) and adds sub-cut 12.4, which replaces
Splash with one detonation owner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 19:06:09 +02:00
Meta Vens
75607bfd61 Locomotion campaign: target and cut map (control allocation, capability-aware AI)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 19:03:30 +02:00
Meta Vens
50781eafcf Correct the Splash handedness claim: an undefended mutant, not a shipped bug
The line is unchanged since 482c47bf; the operator's wrong-side bug was
legacy Unity code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 18:37:12 +02:00
Meta Vens
122baad04b Cut 12 map: shots arrive edge-on; and correct the Splash handedness claim
The Splash sign flip Cut 11 pinned was an undefended mutant, not a shipped
bug: the line is unchanged since 482c47bf. The operator's wrong-side bug
was legacy Unity code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 18:36:39 +02:00
Meta Vens
cd846916bc Merge Cuts 10 and 11: the hot path gates first, and mutation testing moves to Stryker
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:41:11 +02:00
Meta Vens
e8fbb6a6af Cut 11 status: Stryker progression and the triage of the 43 survivors
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:40:19 +02:00
Meta Vens
b0fd3cd06c Cut 11 second round: one owner for PBase, and tests for what the 51 survivors showed
Inspect.PBase is HitProbability's own answer instead of a second product of
the factors. New behavioural tests pin a beam shot carrying its override
damage, a fitted targeting system forgiving a jink, a shot orphaned before
commit committing as a plain miss, and the HUD's arrival countdown. The
tautological damage assertion in BeamRollsPerInterval is deleted.

Stryker on FireControl.cs: 51 survivors to 43, all triaged in the map.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:39:52 +02:00
Meta Vens
1b187db45b Cut 11.3: fix the degenerate fixtures that made mutants indistinguishable
Most of Stryker's surviving mutants in FireControl.cs traced to a handful of
fixture constants that make a mutant compute exactly the same number as the
original -- the same defect class as the zero-velocity target and the damage
that happened to equal an item's durability, found here as a pattern.

- The kernel fixture's shooter sat at float3.zero, where `target - source` and
  `target + source` are the same vector. HitProbabilityMatchesInspect gains a
  configuration with the shooter far from the origin: the correct separation is
  500, in range; the mutated sum is 1300, out of range.
- The kernel fixture's Resolution was 1000, which saturates pSensor to exactly 1
  above the detection threshold, so multiplying and dividing by it agreed. Now 2.
- EvasionCountsUntilCommitAndNotAfter fired at zone time 0, so `now - FireTime`
  equalled `now + FireTime`. Cut 5 gave this test a moving target to defend its
  own declared mutation and it still survived; the clock now advances first.
- Every fixture used zero spread and a cell size of 1, leaving the whole spread
  term untested. PSpreadIsTheSilhouettesShareOfTheSpreadCone pins what pSpread
  means -- a silhouette filling the cone scores 1, half the cone scores .5, and
  a bigger one saturates -- rather than how it is computed.

Triaged as equivalent, not chased: the float-threshold boundary flips, and the
three MixSeed mutants that turn a right shift left -- measured, the die stays
fair under all three (worst deviation from p .017-.030 against .022 correct), so
killing them would mean pinning the mixer's bit arithmetic, not its behaviour.

Recorded, not fixed: FireControl.Apply's derivation of hitDirection from the two
positions has no geometry test through the FireControl path, and
StatResolverTests.AModifierThatTargetsItsOwnMagnitudeStatIsRefusedAtEquip fails
intermittently in the full suite -- likely cross-class pollution through
CultCache's process-wide document registry.

241 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:20:45 +02:00
Meta Vens
a6543af741 Cut 11.4: behavioural tests for what Stryker found undefended, and Soul C4
Nine tests, each stating as behaviour a rule a real Stryker mutant survived:

- A shield that absorbs must eventually run dry, on both the discrete path and
  Splash's (whose absorb branch had no coverage at all). Deleting Shield.TakeHit
  survived because earlier tests asserted only that the hull was untouched.
- Splash damages the side the blast came from, across five facings and both
  sides. Flipping the sign of `right` survived every suite, and it survives at
  the default facing (0, 1) too: the flip only changes the damaged side when a
  ship faces more along world x than z. So the test spins the target through
  facings where it bites. The current code is correct; it can no longer regress.
- Different zones roll differently. Replacing `CombatSeed *` with `/` dropped the
  zone from the seed and survived, because the die test checks one zone only.
- A shot whose target left the zone resolves as a miss.

That last one is a real defect (Soul C4), fixed here. Step rewrote the outcome
only for uncommitted shots, so a hit committed inside the horizon and then
orphaned by its target dying was republished as a hit -- a hit marker on a
corpse. The resolution is now a fresh miss; the committed outcome is left
untouched, since R4 makes it immutable.

The fixture puts the shooter off the origin on purpose: at float3.zero,
`target - source` equals `target + source`, which is how four position mutants
survived.

240 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 16:06:33 +02:00
Meta Vens
724ec5e7d3 Cut 11.1: retire the hand-written mutation harnesses Stryker replaces
Twenty-three harnesses, 5,816 lines, across the fire control, stats and power,
shield reserve and condition ratio campaigns. Every one targeted code under
Assets/Scripts/ServerShared, which Stryker's pinned scope now covers, and every
one carried the same liabilities: literal-text anchors coupled to code shape, a
restore that could leak a mutant into the tree, a tree-clean verdict that
restored before it measured, and a red result that could not tell a killed
mutant from a compile failure. The behavioural tests they measured all stay.

Kept and recorded, not yet answered: the addressables harness and the three
shield panel harnesses. They target Unity Editor probes that Unity compiles
outside Aetheria.Shared, where Stryker cannot reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:59:45 +02:00
Meta Vens
b305debd49 Cut 11 map: mutation testing moves to Stryker, and the survivors it found
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:59:06 +02:00
Meta Vens
8ef3b34c94 Adopt Stryker.NET as a repo-local tool, for the mutation-testing spike
Pinned in dotnet-tools.json (dotnet-stryker 5.0.0) so any checkout reproduces
it with `dotnet tool restore`. Reports land in StrykerOutput/, now ignored.

Spike against FireControl.cs alone: 276 mutants in 7m18s, 208 killed, 67
survived, 4 uncovered, score 74.6%. It killed every mutation the hand-written
anchor harnesses defended, compiles all mutants into one assembly and switches
between them at runtime -- so it never edits a source file, has nothing to
re-anchor after a refactor, and cannot leak a mutant into the tree.

Among the survivors: Splash's handedness is untested (flipping the sign of
`right` passes every test -- the operator's "damage on the wrong side of the
ship"), deleting the discrete shield's TakeHit survives, and most of the rest
trace to degenerate fixture values -- shooter at the origin, fire time zero,
spread zero -- which make whole families of mutants arithmetically identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:50:34 +02:00
Meta Vens
b15cbbe5de Cut 10: the hot path stops looking like, and costing like, a diagnostic
The diagnostics refactor (72c0109c) kept the debug HUD and the simulation on one
fire-control model by routing HitProbability THROUGH Inspect. That was the right
invariant implemented at the wrong level: every AI and turret evaluation, per
weapon per tick, built the full diagnostic struct and ran IsRevealed's sort, the
aim-point cell walk and HullKernel's allocations and per-cell exp -- and only
then checked whether the target was even in range. A Soul pass measured 9.87 us
and 448 B per call on paths that used to bail in nanoseconds. Operator: it made
the hot path look like a diagnostic one.

One model is now shared at the level of its factors. HitProbability runs its
cheap gates first and bails, exactly as it did before the refactor, and computes
PSensor, PSpread and POnHull only for a shot that is actually possible. Inspect
calls the same four factor functions and fills the struct unconditionally,
because a HUD wants to see why a shot is impossible. The HUD panel and its one
test consumer are unchanged.

Two tests make the design enforced rather than conventional:
- HitProbabilityMatchesInspect: exact equality across 21 configurations covering
  every gate the hot path bails on plus Precision and info sweeps. Dies when a
  factor changes in only one caller.
- GatedOutHitProbabilityAllocatesNothing: 1000 out-of-range calls allocate zero
  bytes. Dies when HitProbability is routed back through Inspect.

Both mutations verified RED and distinguished from a compile failure, with
restores checked against a hash taken before mutating.

231 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:18:12 +02:00
Meta Vens
9db64c112a Merge fire control Cut 9: the die is not a die
The combat roll was not a roll. FireControl seeded CultMath's xorshift32 per
shot and drew once; 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 spanned about an eighth with its threshold fixed at zone
creation, so a shot was a step function of p -- below the band it never hit,
above it always did. An unaided shooter hit 0 of 18,926 shots, which is the
operator's "I can target and fire with no hits registering," and being stable
per zone is why it came and went.

Measured across six zone seeds: hit fraction at p=.3 went from 0.0% in five of
six zones to 29-31%, at p=.6 to 58-61%, spanning the full range. The seed stays
a pure function of (zone, shot id); only its diffusion changes.

Three cuts shipped over this because nothing in the campaign measured a
distribution -- every fixture uses accuracy 1 or 0, and a constant satisfies a
determinism test perfectly. The missing test, not the seeding line, was the
defect.

Also: pOnHull collapsed to zero above Precision ~4 because no shipped hull's
centre of mass is integral, so a better targeting system made a weapon unable to
hit anything; sigma is now floored at half a cell. And the LockWeapon crash Cut
8 did not actually fix -- that code only runs on active entities -- is closed at
its real route, dock/target dies/undock.

229 tests. All nine harnesses clean, run sequentially in an isolated worktree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 03:01:42 +02:00
Meta Vens
73e080d8d6 Cut 9: re-anchor cut3 and cut6 onto the mixed seed
9.1 changed the line those two harnesses pin, stranding five anchors including
cut6's own no-op control -- so cut6 was defending nothing until now. Same thing
the diagnostics refactor did to four harnesses earlier, and the second time in a
day that a change to Commit has stranded anchors elsewhere. The rules are
unchanged; only the text moved.

That maintenance cost is now a known property of pinning mutations to literal
source text. It buys a stale anchor failing loudly within one run, which is how
both instances were caught immediately, and it belongs in Cut 10's list beside
Soul's harness audit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 03:01:04 +02:00
Meta Vens
6db6dc78f3 Cut 9: the die is not a die
9.1, blocking. FireControl seeded CultMath's xorshift32 per shot and drew once.
NextFloat returns the top 24 bits of the FIRST round, and one round cannot carry
ShotId's low-bit variation into the high bits -- so every zone's hit roll spanned
about an eighth, with the threshold fixed at zone creation. A shot was a step
function of p: below the band it never hit, above it always did. 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.

The seed derivation is unchanged -- still a pure function of (zone, shot id),
Cut 6b's rule -- and only its diffusion into the first output changes, via an
fmix32 finalizer. Measured across six zone seeds: hit fraction at p=.3 went from
0.0% in five of six zones to 29-31%, and at p=.6 to 58-61%, with the roll
spanning the full range.

The defect survived three cuts because nothing in the campaign measured a
distribution -- every fixture uses accuracy 1 or 0, and a constant satisfies a
determinism test perfectly. TheDieIsUniform now asserts the observed hit
fraction is within .08 of p across several zone seeds, which is the test whose
absence was the real defect.

9.2. Sigma is floored at half a cell. HullKernel approximates a continuous
Gaussian with a discrete sum over occupied cells, and that sum collapses once
sigma falls well under one cell against an aim point that is not exactly on a
cell centre -- true of every shipped hull. Past Precision ~4, pOnHull went to
zero and a better targeting system made the weapon unable to hit anything.

9.3. An active entity's Target is now always a live entity it has info on.
Cut 8's _active guard could never have fixed the operator's LockWeapon crash --
that code only runs on active entities, and cut8's own harness header says so.
The live route was dock, target dies, undock; Deactivate disposed the
subscription that nulls a stale Target and Activate reseeded EntityInfoGathered
without reconciling it. Still not a TryGetValue in LockWeapon.

229 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 02:33:22 +02:00
Meta Vens
16d8493e0c Cut 9 map: the die is not a die
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>
2026-09-22 01:53:41 +02:00
Meta Vens
dcb8c448ce Merge fire control Cut 8: a removed entity is a dead entity
Fixes the crash from the operator's play smoke. Cut 5.6 moved death removal into
the simulation and did half the transition -- Zone.Entities.Remove with no
Deactivate, where TryDock has always paired the two -- so a dead ship kept live
subscriptions and stale references while every survivor dropped it, and
Zone.Update's snapshot iteration handed it one more Update after the world had
forgotten it. Entity.Update never consulted _active; the flag existed and
nothing asked it. LockWeapon's raw indexer into EntityInfoGathered was simply
where it surfaced.

Death now removes and deactivates as one transition, and a deactivated entity
does not update. Not a TryGetValue in LockWeapon: that would silence one call
site and leave every other behaviour running on a corpse.

Also re-anchors seven mutations stranded by the diagnostics refactor, two of
which were no-op controls -- four harnesses were defending nothing until now.

Still open and deliberately not patched: the heat spike, the motionless ships
and the shots that registered no hits. Unreproducible since the diagnostics
changed timing, so the map records them with the unclamped dt as the place to
probe.

226 tests; all eight mutation harnesses clean with tree-clean PASS, controls
included, run in an isolated worktree. Unity batchmode NOT run for this cut --
the operator's editor holds the project lock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 01:14:19 +02:00
Meta Vens
8a87dec90f Cut 8: a removed entity is a dead entity, and re-anchor the stranded mutations
The operator's play smoke crashed in LockWeapon reaching EntityInfoGathered
through a raw indexer as a ship vanished. Cut 5.6 moved death removal into the
simulation and did half the transition: Zone.Entities.Remove with no Deactivate,
where TryDock has always paired the two. The dead ship kept live subscriptions
and stale references while every survivor dropped it, and because Zone.Update
iterates Entities.ToArray() it received one more Update after the world had
forgotten it. Entity.Update never consulted _active; the flag existed and
nothing asked it.

Death now removes and deactivates in one transition, and a deactivated entity
does not update. Deliberately NOT a TryGetValue in LockWeapon: that silences one
call site and leaves every other behaviour running on a corpse.

Also re-anchors the seven mutations stranded by the diagnostics refactor
(72c0109c), which routed HitProbability through Inspect and rewrote the lines
four harnesses pin -- two of them no-op controls, so those harnesses were
defending nothing. The rules are unchanged; only the text moved. Anchors stay
strict: loudly stale is what surfaced this within one run.

The heat spike, motionless ships and shots that registered no hits remain
UNEXPLAINED and open. See the map's 8.3 -- unreproducible since the diagnostics
changed timing, so recorded with the unclamped dt as the place to probe rather
than patched speculatively.

226 tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 00:50:57 +02:00
Meta Vens
f446e5c2c2 Cut 8 map: a removed entity is a dead entity
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>
2026-09-22 00:17:25 +02:00
Meta Vens
72c0109cf1 Add live fire control diagnostics 2026-09-20 21:58:44 +02:00
Meta Vens
6056327935 Merge fire control Cut 6d: where a hit lands is a dart throw, not a coin flip
Precision was a coin flip between landing exactly on the aimed item and landing
uniformly anywhere on the hull, so aiming at a stern thruster scattered its
misses across the bow -- no nearer the thing aimed at than never aiming at all.
One Gaussian kernel over the hull schematic now answers both halves: its
per-cell weights place the hit, and its on-hull mass prices the stray into
HitProbability, so a thin limb costs visible hit chance before the trigger and
centre mass is the safe play. One function, so the placement and the probability
cannot drift apart -- Cut 3's named risk was exactly two functions answering
where a shot goes.

There is still only one roll. A shot that passes it always lands on metal,
because the chance of the dart straying off the hull was charged at the roll.

Operator-facing consequences, measured rather than assumed:

- pOnHull and the existing pSpread term do NOT double-charge. pSpread prices the
  weapon's own dispersion cone against the silhouette and is 1 for any zero-
  spread weapon; pOnHull prices the targeting system's aim scatter against real
  schematic metal around the actual aim point. Both keep their jobs.
- AI willingness shifts only where it should. Unaided fire is unaffected --
  UnaidedAccuracy already caps it below AgentMinHitProbability. Aided fire at
  centre mass is barely touched. Aimed shots at thin subsystems can now fall
  below the threshold, so NPCs get pickier about sniping small targets. That is
  the tradeoff working, and AgentMinHitProbability is the operator's knob.

Also fixes two pre-existing defects the kernel exposed. FireAuthorityTests.
ShieldTakesHit fired damage 10 at a fixture whose equipped gear had durability
10, so the item absorbed the hit whole and the hull never moved -- the shield
branch could have been deleted outright and the test would have passed. And the
Cut 3 harness still named a test Cut 7 had renamed.

222 tests, all seven mutation harnesses clean with tree-clean PASS, catalog
reads 53 designs / 47 products, 0 dangling refs, Unity batchmode exit 0 with 0
error CS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 22:46:10 +02:00
Meta Vens
e7be36ddd7 Apply targeting-catalog-6d: re-author Precision for the two targeting designs 2026-09-19 22:20:44 +02:00
Meta Vens
bf4744448f Add targeting-catalog-6d migration command to AetherDb tool 2026-09-19 22:20:22 +02:00
Meta Vens
aa850a3cbe Fix ShieldTakesHit coincidental pass and cut3 harness stale test name
ShieldTakesHit: damage raised from 10 to 50, past the Reactor/Shield gear's own Durability of 10. Under the dart-throw kernel, Build's default Precision groups unaimed shots tightly enough around this small hull's centre of mass that this fixture's deterministic single shot lands on one of the two equipped Tool items. At damage 10 that happened to exactly consume the item's own durability with zero remainder, so hull durability stayed unchanged with or without the shield-absorb branch -- the mutation this test is supposed to kill was surviving by coincidence, not because the rule held.

mutation_tests_fire_control_cut3.sh: its closing section still referenced FireAuthorityTests.OutOfArcConsumesNoDraw, a test Cut 7 renamed to CombatNeverDrawsFromTheSharedStream before this branch started (verified against the merge-base commit). Replaced the stale not-yet-reached note with a real mutation against the current test: Commit reads shot.Source.ItemManager.Random once, restoring the shared-stream touch Cut 6b removed.
2026-09-19 22:16:25 +02:00
Meta Vens
8212a0149d Cut 6d: mutation harness for the dart-throw kernel
Modelled on tests/mutation_tests_fire_control_cut5.sh: a no-op control, byte-exact I/O, sha256-verified restore after every mutation, and an explicit tree-clean verdict at exit. Runs the four mutations named in the spec's Verification block plus the fifth this cut's own test file declares for EveryHitLandsOnMetal. Verified clean: all five checks behaved as declared, tree-clean PASS.
2026-09-19 21:56:14 +02:00
Meta Vens
b3d4771358 Cut 6d: tests for the dart-throw kernel invariants
Adds AimingAtTheSternHitsTheStern, ThinLimbCostsHitChance, PlacementAndProbabilityShareOneKernel and EveryHitLandsOnMetal per the spec's Verification block. Each test builds its own synthetic hull/catalog fixture. The aim marker in every fixture is authored with very high durability so it survives the whole sample of shots without dropping out of the reveal ranking partway through.
2026-09-19 21:52:56 +02:00
Meta Vens
d528d88883 Cut 6d: the dart-throw kernel replaces the coin-flip landing rule
FireControl.Commit used to place a hit with a coin flip between exactly
the aimed item and a uniform-random hull cell -- no spatial term, so a
near-miss on a stern item was as likely to land in the bow as the stern.

One Gaussian kernel, in hull-schematic cell units, now decides both
halves of "where will this shot go": w(cell) = exp(-d^2/2*sigma^2) over
every occupied cell, sigma = 1/Precision. HitProbability folds the
kernel's on-hull mass share (pOnHull) into PBase at fire time (R10/Q6
unaffected); Commit draws the landing cell from the same weights. A shot
that passes the roll always lands on metal -- the off-hull chance is
priced into that one roll, never resolved as a second miss stage. The
uniform-random branch is deleted outright, not demoted.

Precision now feeds every shot's pOnHull, aimed or not, so its unaided
fallback (FireControl.Precision) reads GameplaySettings.UnaidedPrecision
instead of a bare 0 -- the same shape as the existing UnaidedAccuracy/
UnaidedTracking floors. pOnHull is saturated: the discrete sum over-
estimates the continuous kernel's integral once sigma drops below about
one cell, and a mass share cannot exceed the whole kernel.

Existing fixtures across FireAuthorityTests, FireControlCut4/5/6Tests and
TargetingSystemTests authored Precision as 0 (or relied on the old 0
fallback) purely as a don't-care value under the coin-flip rule, where it
only gated the aimed-item branch. Under the kernel it drives every shot's
sigma, so those fixtures are re-authored to keep pOnHull near its
ceiling and stay pinned on what they actually test.

mutation_tests_fire_control_cut3.sh's two anchors into HitProbability's
return line and the deleted coin-flip branch are updated to the
equivalent lines/mutations on the new code.
2026-09-19 21:37:39 +02:00
Meta Vens
077b08e662 Merge fire control Cut 7: the harnesses that were prose
Cuts 1-3 declared mutation tables in this document and nobody ever wrote them,
which is why a Soul pass could write five mutations against rules the campaign
claims to pin and watch all five survive a 197-green suite. Those tables now
exist as committed harnesses -- six in the repo where there was one this
morning, each with a no-op control and a sha256-verified tree-clean verdict.

Three findings came out of writing them, all the same shape: a test whose
fixture could not tell the mutant from the original.

- ShotResolvesOnArrival stepped the zone from t=4 to t=6 in one tick, crossing
  both the commit horizon and arrival, so it could not tell an outcome applied
  on arrival from one applied at commit -- R4's central distinction, undefended.
- OutOfArcConsumesNoDraw could not be killed at all, because Cut 6b had made it
  vacuous: the shared RNG stream it guarded no longer exists, so it passed
  identically with the target in arc. Rewritten to pin the rule that is live.
- 7.1 pins the reveal re-check at the shot's freeze, the fifth mutation Soul
  left standing.

And 7.4: the shipped catalog is now opened by a test that enumerates every
document type. Verified by reintroducing the exact defect that broke the 6b/6c
merge -- it fails with the same MessagePack nil error, so the one hole that let
a branch brick the catalog while passing every gate is closed.

218 tests, all six harnesses clean, Unity batchmode exit 0 with 0 error CS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 20:16:12 +02:00
Meta Vens
0ae8226ccb Cut 7: retire a test Cut 6b made vacuous, and the invariant it claimed
Cut 3's harness reported OutOfArcConsumesNoDraw as "not yet reached" -- no
mutation could turn it red. Chasing that rather than accepting it found the
reason, and it is not a fixture defect.

The test asserted that a shot gated to zero draws nothing from ItemManager.
Random, so the shared stream advanced exactly as if the shot had never queued.
Cut 6b moved every roll onto a per-shot local generator seeded from (zone, shot
id), so Commit stopped touching that stream on EVERY path. The test then passed
for a reason unrelated to arcs -- it passed identically with the target dead
ahead -- and the rule it named stopped existing along with the stream it was
about. The short-circuit it guarded is now a cheap guard, not an invariant, and
Commit's comment was still asserting otherwise.

Rewritten as CombatNeverDrawsFromTheSharedStream, a Theory over both an
out-of-arc and an in-arc target, pinning the rule that IS live after 6b: no
combat path draws from the shared stream at all. Verified by hand -- restoring
the shared-stream read in Commit turns the in-arc case red while the out-of-arc
case stays green, which is exactly why the old test could not have caught it.

218 tests pass. All six mutation harnesses run clean with tree-clean PASS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 20:14:16 +02:00
Meta Vens
76758dae5d Cut 7.2: the Cut 3 harness, and the fixture that let commit-is-not-arrival slip
ShotResolvesOnArrival stepped the zone from t=4 straight to t=6, crossing both
the commit horizon (4.5s) and arrival (5s) inside one Zone.Update. A mutation
collapsing Step's arrival gate to `if (shot.Committed)` therefore survived it:
one wide tick crosses both thresholds either way, so the test could not tell
"applied on arrival" from "applied as soon as committed". R4's central
distinction -- the commit decides the outcome, arrival performs it -- was
declared in Cut 3's prose, pinned by nothing, and this is the third rule in this
campaign found undefended by a fixture too coarse to distinguish the mutant.

Adds a tick at t=4.55, past commit and short of arrival, where the durability
must still be untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 19:56:39 +02:00
Meta Vens
d937364354 Cut 7.2: mutation harnesses for Cuts 1 and 2
tests/mutation_tests_fire_control_cut1.sh and cut2.sh, modelled on
cut5.sh: byte-exact I/O, sha256-verified restore per mutation, explicit
tree-clean verdict. Each runs the mutation table its own cut already
declares in docs/fire-control-cut.md.

Two adaptations forced by the Body having moved since those cuts were
written (both cut2.sh's own table entries, and its header comment):
Cut 1's CombatStateStepsHeadless mutation targets FireControl.MountDirection
instead of the now-deleted HardpointTransforms readback, since Cut 3 moved
the AI's aim-direction path there; Cut 2's EveryArmedLoadoutGetsATargetingSystem
mutation targets the surviving acquisition predicate instead of a
`required: true` flag Cut 6c.2 already turned into a deliberate
degrade-and-log path.

TargetingSystemTests.cs's RevealOrder fixture equipped its three items in
the same order FireControl.IsRevealed's ranking would put them in, so
dropping that ranking entirely was unobservable -- Entity.Equipment's raw
enumeration order already matched by coincidence. Reordered the fixture's
equip calls to the opposite order (size-ascending, hardpoint-last) so the
mutation is actually distinguishable; assertions are unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 19:43:57 +02:00
Meta Vens
fd7ef71c15 Cut 7.1/7.4: the reveal re-check pin and the live-catalog test
FireControlCut7Tests.cs adds the fifth mutation Soul found survived 197
green tests -- FireControl.Fire freezing source.TargetItem.Value instead
of the reveal-re-checked ResolvedTargetItem (7.1) -- and the campaign's
first assertion that the shipped GameData/Aetheria.cc catalog is actually
readable by the shipped code and can generate an armed LonginusX loadout
(7.3/7.4). The live-catalog test builds its own scoped CultDocumentRegistry
rather than AetheriaStores.Open's default shared one, because the shared
registry auto-discovers every [CultDocument] type loaded anywhere in the
test process -- including AetheriaStoresTests.cs's own TestCatalogGlobal,
a fixture type the real catalog has never heard of and was never meant to
satisfy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 19:33:09 +02:00
Meta Vens
ef223c1d9b Cut 7 amendment: the live-catalog test is the campaign's only readability check
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>
2026-09-19 19:13:04 +02:00
Meta Vens
c896489b39 Fix the merge of Cuts 6b and 6c: a new float field made the catalog unreadable
Cut 6b added WeaponItemData.AirburstRange as a non-nullable float at Key(29).
Every WeaponItemData record in GameData/Aetheria.cc was serialized before that
key existed, so the reader is handed nil for the absent slot and a float cannot
take nil -- AetheriaStores.Open threw MessagePackSerializationException and the
game could not read its own catalog. AirburstRange becomes float?, null meaning
no authored burst radius, which is also the more honest reading of a value no
product sets yet.

Neither cut could have caught this alone. 6b verified with unit tests over
synthetic fixtures and never opened the shipped catalog; 6c opened the catalog
constantly but on a branch without the new field. It appears only in the merge,
and only when something actually reads GameData.

The general rule, which will recur: a new non-nullable value-type field on a
persisted CultCache document cannot read records written before it existed.
Nullable, or a migration that rewrites every affected record -- and a migration
cannot run if the read already throws, so tolerant deserialization comes first.

Verified on the merged tree: catalog reads (53 designs, 47 products), 0 dangling
refs, 215 tests pass, and loadout with all three targeting sellers excluded
generates every hull with 1 armed hull falling back to unaided fire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 18:56:53 +02:00
Meta Vens
6636e757c7 Merge fire control Cut 6c: the formula gets fixed, and the single point of failure
Cut 6a authored the premium targeting system strictly worse than the cheap one,
because Resolution is consumed as a cost while its name promises a benefit.
Operator ruling: fix the formula, not the handle. HitProbability now derives its
ceiling reciprocally, so higher Resolution is a sharper instrument and the
unaided fallback of 1 becomes the floor by construction rather than by accident.
No rename.

Both designs also shipped from a single seller, and galaxy generation draws a
random subset of factions -- so ship generation still threw in any galaxy that
missed that draw, and Cut 6a's ten green seeds only sampled the die. Targeting
now comes from the roster's own sensor factions, Finch and Lucent, alongside
NiteLife; and FillInterior degrades to unaided fire instead of throwing when no
seller is present, which is only safe because Cut 5.1 gave unaided fire a floor.

Also records that the existing loadout command runs with a null galaxy, where
IsAvailable passes everything -- so availability had never been exercised by any
verification in this campaign until the exclude-sellers mode this cut adds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 18:52:26 +02:00
Meta Vens
06a9098244 Fire control Cut 6c data: Resolution re-authored, Finch and Lucent join NiteLife as targeting sellers
AetherDb targeting-catalog-6c apply, landed:

- Targeting Computer: Resolution .3 -> 2 (sensor-limited until info reaches
  .55 under the new reciprocal reading)
- Fire Control Array: Resolution .75 -> 4 (until .325) -- now unambiguously
  ahead of the 1-cell design at every info level, fixing the strictly-worse
  regression Cut 6a's review found
- 4 new products: Panopticon / Panopticon Prime (Finch Cybernetics, passive
  sensors) and ClapBack / ClapBack Ultra (Lucent Media, active sensors/lasers)
  -- each design now has three sellers instead of one

Census: 53 designs (unchanged), 47 products (was 43). AetherDb dangling: 0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 18:50:21 +02:00
Meta Vens
dcc38af6fd Fire control Cut 6c tooling: targeting-catalog-6c migration, loadout exclude-sellers, mutation harness
AetherDb targeting-catalog-6c (dry run unless "apply"): re-authors Targeting
Computer/Fire Control Array's Resolution onto the reciprocal-reading scale
(.3->2, .75->4, matching Cut 6c.1's operator ruling) and adds a Finch
Cybernetics and a Lucent Media product for each design, alongside the
existing NiteLife ones, so a galaxy missing any one seller still has two more
chances to sell a targeting system (Cut 6c.2).

AetherDb loadout gains "exclude-sellers:Short1,Short2,..." -- the only way to
actually exercise Galaxy.ContainsFaction from this command, since the default
null-Galaxy run treats every product as available and can never reproduce the
single point of failure 6c.2 fixed. Builds a minimal one-zone Galaxy via the
same SavedGame/Galaxy round trip as FireControlCut6cTests, backed by a scratch
run store under the OS temp directory so GameData/run.cc is never touched.

Adds tests/mutation_tests_fire_control_cut6c.sh, modelled on Cut 5's harness:
no-op control, byte-exact I/O, sha256-verified restore after every mutation,
explicit tree-clean verdict.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 18:50:11 +02:00
Meta Vens
507faf6e84 Merge fire control Cut 6b: a shot's dice belong to the shot
Commit drew from ItemManager.Random, a stream shared with wormhole exit
velocity, loadout generation, travel and every AI's own DPS sampling -- so
adding an NPC or opening a shop reordered every subsequent die, and Q5's
reproducible fight held only inside a hermetic fixture. The roll is now a pure
function of (zone identity, shot id): no stream, no ordering dependence, and
nothing outside Commit can seed or advance a combat draw.

Airburst was deleted with the Physics.OverlapSphere path in Cut 4 and never
rewired, so a flak round flew and did nothing. It now resolves in the simulation
-- Splash instead of Apply at arrival, never both -- rather than going back into
the Projectile MonoBehaviour, which is the authority Cut 3 spent itself
deleting. No catalog weapon authors a burst radius yet, so the flag is wired and
inert until an authoring pass sets one.

Verified independently of the agent report: 213 tests pass, all four mutations
die, the no-op control stays green, both negative greps are clean, and every
target file is byte-identical to sha256 hashes taken before the run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 18:44:18 +02:00
Meta Vens
1a1cb8f3d1 Fire control Cut 6b: mutation harness, and comments that leaked past the negative greps
tests/mutation_tests_fire_control_cut6.sh, modelled on Cut 5's harness: a no-op
control, four mutations (6.1's shared-stream generator and dropped-ShotId seed;
6.2's double-application and unconditional-splash), byte-exact I/O with
sha256-verified restore after every mutation, and the two negative greps the
Cut 6 spec names. All five mutations behave as declared and the tree-clean
verdict is PASS.

Fixes two of Commit's and Projectile's own explanatory comments that quoted the
literal strings the negative greps check for (ItemManager.Random, Airburst),
which the first harness run caught as false failures -- reworded, no behavior
change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 18:41:38 +02:00
Meta Vens
39ad4bfc80 Fire control Cut 6b: a shot's dice belong to the shot, and airburst resolves in the simulation
6.1 (Soul finding 6): Commit builds a local CultMath.Random from (Zone.CombatSeed,
shot.ShotId) instead of reading and writing the shared ItemManager.Random stream.
Zone exposes CombatSeed (the same expression that already seeds its own _random),
so a shot's outcome is a pure function of zone identity and shot id -- immune to
whatever else drew from the shared stream in between.

6.2 (Soul finding 5): airburst is wired into the simulation instead of back into
Projectile.cs. PendingShot gains BurstPosition/BurstRadius, frozen at Fire time
from PredictedIntercept and the weapon's authored WeaponItemData.AirburstRange
when WeaponModifiers carries Airburst. FireControl.Step resolves such a shot via
Splash instead of Apply, never both. Projectile.cs/ProjectileManager.cs drop the
dead AirburstDistance/AirburstRange fields and write-back.

Tests: FireControlCut6Tests.cs pins both rules (208 baseline + 5 new, all green).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 18:34:04 +02:00
Meta Vens
29fcc3ee9e Fire control Cut 6c.1/6c.2: Resolution becomes reciprocal, targeting degrades instead of throwing
6c.1 (operator ruling 2026-09-19): Resolution stays a benefit -- higher is
better -- so HitProbability derives its sensor ceiling as the reciprocal of
Resolution instead of reading Resolution as the ceiling directly. The
authored 1-cell/2-cell targeting systems' Resolution values move to the new
scale in the next (data) commit.

6c.2: LoadoutGenerator.FillInterior no longer throws InvalidLoadoutException
when no targeting-system product is available to a galaxy -- it degrades to
no targeting system and logs the gap, safe only because Cut 5.1 already gave
unaided fire a floor (GameplaySettings.UnaidedTracking).

Adds FireControlCut6cTests.cs pinning both: HigherResolutionYieldsHigherOrEqualHitProbability
(dies if Resolution is read as the ceiling directly) and
NoSellerDegradesToUnaidedInsteadOfThrowing (dies if the throw is restored).

dotnet test tests/Aetheria.Shared.Tests: 210 passed, 0 failed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 18:31:46 +02:00
Meta Vens
063804801f Merge fire control Cut 6a: the catalog data Cut 2 never shipped
Cut 2 landed LoadoutGenerator's required-targeting-system rule and no targeting
system to satisfy it, so AetherDb loadout threw InvalidLoadoutException and the
player's own hull could not be generated. The turret firing-arc migration was
likewise written and never run, leaving a turret engaging only within 60 degrees
of its spawn facing.

Two targeting designs with products, four products for previously unsold designs,
and the arc migration applied: 53 designs, 43 products.

Cut 6c amends two defects in this authoring -- Resolution reads as a cost so the
premium system is worse than the cheap one, and a single seller makes ship
generation depend on whether a galaxy happens to draw that faction.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 18:14:14 +02:00
Meta Vens
cf47f9d26e Merge fire control Cut 5: close the rules that landed on one path and not its twin
Seven code defects Soul confirmed across the campaign, every one the same shape:
a rule implemented on one path and left off the path beside it. Tracking gets a
floor instead of a cliff; a shot the shield cannot absorb now breaks it on the
discrete path as well as in Splash; a beam obeys its firing arc; one bearing
test owns the point-blank case; a destroyed subsystem stops being the aim point;
the simulation removes its own corpses instead of relying on Unity's loot-drop
subscription; and PendingShot drops two fields nothing read.

Cut 5b then repaired the mutation harness, which had been leaking un-restored
mutations into the working tree -- that leak, not a matcher bug, was also why two
anchors appeared unmatchable. Restore is now hash-verified with an explicit
tree-clean verdict, and ConstantWeapon's PowerRequest gate is pinned separately
from Execute's, which is where the one surviving mutation had been hiding.

Verified independently of the agent reports: 208 tests pass, all eleven
mutations die, the no-op control stays green, and every target file is
byte-identical to sha256 hashes taken before the run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 17:35:31 +02:00
Meta Vens
3bf1e40795 Fire control Cut 6d map: where a hit lands is a dart throw, not a coin flip
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>
2026-09-19 17:30:39 +02:00
Meta Vens
35b8b6a550 Fire control Cut 5b.3: make the mutation harness's restore provable
Three runs of tests/mutation_tests_fire_control_cut5.sh left mutated files on
disk (ArcAllowsFire hardcoded true in Weapon.cs, InstantWeapon.cs's arc gate
deleted, FireControl.cs still carrying 5.1's own mutation) despite its
`trap restore_all EXIT INT TERM`: a trap cannot survive a SIGKILL of the
process group, and nothing before this cut ever checked that a `cp -p`
restore actually reproduced the original bytes.

Records each target file's sha256 before any mutation runs. Every restore --
per-mutation, immediately after each check_mutation, and at exit -- re-hashes
and aborts loudly on a mismatch instead of trusting `cp -p` silently. The
final summary and the exit-time trap both print an explicit tree-clean
PASS/FAIL verdict so a reader never has to infer it. The no-op control stays
first, unchanged.

Investigated the two anchors reported as "found 0" (Zone.cs's Death
subscription, Weapon.cs's InArc line) before touching anything, per the
mandate not to hand-edit them into a shape that happens to match: on this
worktree at HEAD, both anchors are single-line literals with no embedded
newline, so CRLF-vs-LF in the surrounding file cannot affect whether the
substring is found -- the CRLF theory does not hold up. Both anchors match
exactly once against the current, clean tree (verified directly with the
same perl matcher this script uses, and confirmed by a full harness run).
The mutated replacement text for each of those two anchors is byte-for-byte
identical to the exact leaked mutation the task description names as having
been left on disk by an earlier run (Weapon.cs's `return true;`, Zone.cs's
deleted Death subscription) -- i.e. the "anchor never matches" failures were
not an independent matching-mechanism bug, but a direct symptom of the same
leaked-mutation-state problem this cut's hash verification now closes. No
anchor literal was changed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:28:48 +02:00
Meta Vens
0020d597f6 Fire control Cut 5b.1: pin ConstantWeapon's PowerRequest arc gate, not just Execute's
ConstantWeaponObeysArc only asserted PowerRequest()==0 after Zone.Update had
already run Execute, which safes _firing off for its own (also-correct)
reason first. PowerRequest short-circuits on _firing regardless of what
ArcAllowsFire mutates to, so a mutation dropping ArcAllowsFire from
PowerRequest alone was an unpinned survivor even though the harness's own
Execute-line mutation was already caught. Added the same assertion before
Zone.Update, while _firing is still true and StanceAllowsFire is true, so
ArcAllowsFire is the only thing it can be testing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:28:32 +02:00
Meta Vens
9b69286783 Fire control Cut 5: make TrackingIsAFloorNotACliff deterministic
The multi-tick, many-Update-call version of this test (5.1) was flaky under
repeated runs: stepping a 5s flight in 50 separate .1s ticks left the exact
commit-time reading of `now` sensitive to float-accumulation/JIT-tiering
drift, occasionally producing zero hits across all 30 shots even on
unmutated code. Rewritten with velocity 0 so each shot's flight time (and so
its commit horizon) is zero -- one Fire call, one Update call, no
accumulated ticks to drift. Confirmed clean across repeated standalone runs
and still kills the 5.1 fallback-to-0f mutation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 17:11:22 +02:00
Meta Vens
c4c241e999 Fire control Cuts 6, 6c and 7 maps
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>
2026-09-19 16:58:22 +02:00
Meta Vens
df5f763187 Fire control Cut 5: close the rules that landed on one path and not its twin
Soul's pass over the whole campaign confirmed eleven findings. Seven were code
defects of one shape -- a rule implemented on one path and left off the path
beside it -- and this is all seven.

5.1 Tracking falls back to GameplaySettings.UnaidedTracking (new, 10) instead of
    zero, and Commit drops the zero branch that turned a Tracking-less shooter
    into a hard wall. Unaided fire was meant to be really, really bad; it was
    334 shots and no hits against a target drifting at 5 u/s.
5.2 A shot the shield cannot absorb now breaks it. The decision is frozen into
    ShotOutcome.ShieldBroken at commit and performed in Apply, so a shield that
    recharges mid-flight cannot retroactively survive. Splash already did this;
    the discrete roll never did, which made the whole shield-break mechanic
    unreachable for every weapon in the catalog.
5.3 ConstantWeapon gates on ArcAllowsFire alongside StanceAllowsFire. A
    side-mounted beam was firing forward.
5.4 The point-blank bearing case moves out of Weapon.ArcAllowsFire and into
    InArc, which used to normalize the zero vector into NaN. The trigger said
    fire and the probability said impossible.
5.5 A destroyed item drops out of IsRevealed's ranking, so Precision stops
    concentrating hits onto a dead subsystem's footprint.
5.6 Zone subscribes Entity.Death and removes the corpse itself. That removal
    lived only in Unity's loot-drop subscription, so headless nothing ever left
    the zone, shots landed on corpses and no fight could end.
5.7 PendingShot drops PredictedIntercept and FlightTime, written and read
    nowhere.

208 tests pass (197 plus eleven new).

Known defect, recorded rather than hidden: the committed mutation harness is
unreliable. Across two runs it failed to restore FireControl.cs and Weapon.cs,
leaving live mutations in the working tree -- including its own 5.1 mutation,
which is how a green suite briefly reported two failures. Its verdicts are
therefore evidence only where re-run from a verified-clean tree. Two anchors
(Zone.cs's ObserveAdd line, Weapon.cs's InArc return) fail to match at all, and
5.3's ConstantWeaponObeysArc survives its own mutation, so that rule is written
but not pinned. Cut 5b owns the repair; nothing here is trusted on the harness's
word, and the suite result above was taken by hand from a hash-verified tree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 16:56:40 +02:00
Meta Vens
e5f1318a0c Fire control Cut 6a: land the targeting-catalog authoring output
Runs targeting-catalog apply: two new designs (Targeting Computer, Fire
Control Array) and six new products (LockOn / LockOn Pro by NiteLife Energy;
DragOnBreath by Lucent Media for plight; Leonid by Aeronautics Unlimited for
pswarm; Steadfast by Rossum & Douglas for Core Power; True North by Lightsail
Express for Large Drive).

Verified: census 53 designs/43 products (was 51/37); loadout over ten seeds
no longer throws for LonginusX and each gains exactly one interior targeting
system; dangling 0; a fresh census reopen carries 0 schema issues;
firing-arc-migrate dry run reports nothing left to migrate; dotnet test
tests/Aetheria.Shared.Tests is 197/197.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 16:36:22 +02:00
Meta Vens
365c20d82e Fire control Cut 6a: add the targeting-catalog authoring command
Cut 2 shipped TargetingSystemData and its FireControl/LoadoutGenerator
plumbing but never authored the catalog data it needs: no targeting-system
design exists, so tools/AetherDb loadout throws InvalidLoadoutException for
the player's own hull. This adds targeting-catalog, in the shape of the
existing *-migrate commands (dry run unless "apply"), which authors:

- Two GearData designs, "Targeting Computer" (1-cell) and "Fire Control
  Array" (2-cell), each with EnergyDrawData/HeatData behaviours alongside
  TargetingSystemData (the behaviour supplies no power machinery of its own),
  argued from the capacitor (the catalog's only other bare Tool gadget).
- One product per design from NiteLife Energy, the one manufacturer that
  already sells the capacitor, so IsAvailable finds one without falling back
  to "any manufacturer".
- One product each for the four designs nothing currently sells (plight,
  pswarm, Core Power, Large Drive), matched to the manufacturer the brief
  and the corporate roster already imply.

Not yet run against the catalog; the next commit lands its output.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 16:36:00 +02:00
Meta Vens
3cb077918c Fire control Cut 6a: run the firing-arc migration
tools/AetherDb firing-arc-migrate was written in Cut 2 and never run: the
Turret hull's two Ballistic hardpoints still carried a 0-degree arc, so a
turret only ever engaged within 60 degrees of its spawn facing. Applying it
sets both to 360, matching the operator ruling (fire-control-cut.md Q1) that a
turret's arc is authored data, not a new hardpoint type. A fresh dry run now
reports both hardpoints already authored.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 16:17:33 +02:00
Meta Vens
a44549133c Fire control Cut 5 map: the rules that landed on one path and not its twin
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>
2026-09-19 15:44:36 +02:00
Meta Vens
ca57819d5c Merge fire control Cut 4: no physics query decides damage anywhere
The last five weapon kinds route through FireControl; HullCollider's hit
and splash reporting is deleted. A beam rolls once per resolve interval.
Mines keep their proximity trigger (Q7) and resolve damage through the
same path. Also fixes a real defect: OnFire?.Invoke(FireControl.Fire(...))
never fired at all when nothing subscribed, which is the headless case.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:18:50 +02:00
Meta Vens
034e8d3e78 Fire control Cut 4: pin the beam roll, splash, and the OnFire short-circuit fix
tests/Aetheria.Shared.Tests/FireControlCut4Tests.cs, builds its own minimal
fixtures rather than reusing FireAuthorityTests.cs's InstantWeapon-shaped
Engagement:

- BeamRollsPerInterval: over one second a beam produces exactly
  1/BeamResolveInterval outcomes totalling Damage. Interval (.25s) and tick
  (.125s) are both exact dyadic fractions so float accumulation cannot drift
  the count, and the tick is strictly smaller than the interval so a "roll
  every tick" mutant and a "roll once for the burst" mutant both fail.
- InstantWeaponFiresWithoutAnyOnFireSubscriber: pins the InstantWeapon half
  of the null-conditional short-circuit fix, which no existing test could
  catch (FireAuthorityTests.cs always calls FireControl.Fire directly, never
  through Trigger()/Execute()).
- SplashHitsEveryEntityInRadius / SplashIsDirectional: FireControl.Splash
  called directly against a zone of bare Ship entities (Entity.MapEntity,
  run from the constructor, is enough to give a Ship Armor/GearOccupancy/
  Hull without Activate() or a weapon catalog).

tests/mutation_tests_fire_control_cut4.py is the committed harness: a no-op
control plus one mutation per rule above, run against
tests/Aetheria.Shared.Tests via `dotnet test -p:CultLibRoot=...`. All seven
mutations behaved as declared in this pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:17:35 +02:00
Meta Vens
78a4cf36bf Fire control Cut 4, part 2: the last five weapon kinds join FireControl
Deletes the last live Physics.* hit queries and every remaining SendHit/
SendSplash call in Assets/Scripts/Gameplay/Weapons: ConstantLaser's
RaycastAll, ConstantLightning's SphereCastAll, ConstantParticleWeapon's
trigger-collider plumbing, HitscanEffect's RaycastAll, and Mine's blast
OverlapSphere. Each becomes presentation only, the same convention Cut 3
gave Projectile/GuidedProjectile/Laser/Lightning: ConstantLaser/
ConstantLightning/HitscanEffect draw to TargetTransform (or out to Range with
no target); ConstantParticleWeapon keeps only its visual emission.
ConstantWeapon.Execute (previous commit) already rolled the damage before any
of these ever draw.

Mine keeps its proximity-arming OverlapSphere (Q7: contact detection, not hit
detection) but Explode() now calls FireControl.Splash instead of walking
colliders and calling SendSplash itself.

HullCollider.Hit/Splash/SendHit/SendSplash and their event-arg classes are
deleted outright -- their last callers are gone. HullCollider is now purely a
physics surface for ship-on-ship collision impulse; no Physics.* query
decides damage anywhere in Assets/Scripts/Gameplay/Weapons except Mine's own
named exception.

Every manager (ConstantLaserManager, ConstantLightningManager,
ConstantParticleWeaponManager, HitscanManager) is updated to match: no more
Damage/Penetration/Spread/DamageType plumbing into a presentation component
that no longer decides anything with it, and HitscanManager now passes
ShotId and TargetTransform the way LaserManager already does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:17:17 +02:00
Meta Vens
482c47bffe Fire control Cut 4, part 1: FireControl gains Splash and a beam roll
FireControl.Fire takes an optional damageOverride so a continuous weapon can
queue a shot for less than its full Damage. FireControl.Splash is the one new
rule this cut adds: an unconditional area effect (mines, airburst) applying
the shield-absorb-or-hull-takes-it branch per target, then DamageSchematic
over the directional half of each target's own hull that faces the blast --
the rule moved verbatim from the Splash subscription EntityInstance.cs
carried before Cut 3 deleted it (git show b7743789^).

ConstantWeapon.Execute rolls once per GameplaySettings.BeamResolveInterval
(new setting) for Damage*interval, through the same FireControl.Fire/Step
pair a discrete shot uses -- a beam's authored Velocity is 0, so the flight
commits and resolves in the same tick it fires (R4's short-flight
degradation). A beam is a sequence of rolls, not a continuous truth.

Fixes a real defect found while testing the above: both InstantWeapon.Execute
(Cut 3) and the new ConstantWeapon.Execute wrote `OnFire?.Invoke(FireControl.
Fire(...))` inline. C#'s null-conditional short-circuits the whole
expression, argument included, whenever the event has no subscriber -- true
of any headless run with no Unity EntityInstance wired up
(docs/headless-playground-cut.md) -- so a shot silently never fired. Both
now evaluate FireControl.Fire into a local before the null-conditional
invoke.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 15:16:57 +02:00
Meta Vens
8e719d6dba Add the CultMath bridge using that Cut 3 dropped
Cut 3 landed 39 compile errors in GuidedProjectile: it uses ToCultMath
throughout and lost the using directive. Caught by batchmode on merge, not
by the pass that wrote it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 14:10:59 +02:00
Meta Vens
a7c09e06fc Merge fire control Cut 3: dice decide hits, not physics
The raycast hit path is gone from Projectile, GuidedProjectile, Laser and
Lightning; FireControl owns whether a shot lands. A shot freezes its gun's
stats at the trigger, commits its outcome a fixed time before impact, and
resolves on arrival against how far the target deviated. Rolls are seeded,
so a seeded engagement reproduces. Five weapon kinds still on the old path
belong to Cut 4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 14:08:52 +02:00
Meta Vens
b7743789c8 Fire control Cut 3: hit authority moves to FireControl
Deletes the Unity physics hit path (HullCollider.Hit/Splash, and the
raycast/shield/SendHit blocks in Projectile, GuidedProjectile, Laser and
Lightning) and replaces it with a single owner in the same cut: FireControl
now decides whether a shot hits, Zone owns the pending-shot lifecycle, and
Entity.DamageSchematic/ApplyHit (moved verbatim from EntityInstance) apply the
result. Presentation subscribes to Zone.ShotCommitted/ShotResolved and applies
nothing.

FireControl.HitProbability is the pure targeting solution (Accuracy * pSensor
* pSpread, gated by detection/range/lock/arc). FireControl.Fire freezes the
weapon's payload and the shooter's resolved targeting stats at the instant the
trigger is pulled (Q6), computes the predicted intercept through the one
shared PredictedIntercept function (CombatState now calls the same function
instead of duplicating first_order_intercept), and queues a PendingShot.
FireControl.Step commits each shot's outcome at ArrivalTime - CommitHorizon --
deviation from the predicted intercept, measured once, live, at that instant
-- and applies it at ArrivalTime. A shot whose flight is shorter than the
horizon commits and resolves in the same tick it fires. Rolls draw from the
shooter's own ItemManager.Random (Q5, seeded and reproducible); an out-of-arc
or otherwise gated shot draws nothing.

Player fire is arc-gated through the same predicate AI and turret fire use
(Weapon.ArcAllowsFire, checked in InstantWeapon.Trigger -- the one point every
shooter's trigger passes through), closing Q2.

Adds GameplaySettings.CommitHorizon, SchematicCellSize and
AgentMinHitProbability (first guesses; the headless suite is the tuning
harness, operator play smoke is the arbiter).

FORK reported, not worked around silently: HullCollider.SendHit/SendSplash
cannot be deleted yet without breaking ConstantLaser.cs, ConstantLightning.cs,
ConstantParticleWeapon.cs, HitscanEffect.cs and Mine.cs, which still call them
from their own live Physics queries -- that's Cut 4's migration. They fire
into the void today: nothing subscribes to Hit/Splash any more for the four
weapon kinds this cut owns.

tests/Aetheria.Shared.Tests/FireAuthorityTests.cs pins the roll's seeding, the
gate-consumes-no-draw rule, resolve-on-arrival, the commit horizon and its
evasion window, short-flight degradation, the frozen-payload snapshot, aimed
hits, the item-then-hull damage order, the planar penetration march and the
shield-absorbs branch. FireControlTests.cs and InputCapacitorTests.cs are
updated for the new AI gate and OnFire(int) signature.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 14:07:07 +02:00
Meta Vens
3cf4603475 Merge fire control Cut 2: targeting subsystem and subsystem reveal
A new interior Tool behaviour carrying accuracy, resolution, precision and
tracking; unaided fire falls back to one authored setting. The two info
thresholds are finally read: a target's equipment reveals as target data
accumulates, and one predicate and one writer serve both the player and
the AI when aiming at a revealed subsystem.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:04:43 +02:00
Meta Vens
1875065477 Pin the targeting subsystem, reveal rule and Q4's required-equipment rule
TargetingSystemTests: selection needs a real reveal (and drops it again
on decay, with no clearing loop), the reveal ranking (hardpoint before
interior, larger before smaller), the two thresholds are the ones
actually read, unaided fire falls back correctly for no/destroyed/
disabled systems, a starved system's Accuracy halves with the grant
(a real Reactor + PowerBus tick, since PowerSupply's setter is internal
to a different assembly here), and every armed generated loadout gets a
targeting system across ten seeds.

LoadoutTests' shared fixture now authors a targeting-system product too:
its "Twin" hull can randomly draw the weapon-carrying "Gun" onto its
Sensors hardpoint, and FillInterior's new required item would otherwise
throw for a fixture that predates this cut.

174 tests before this cut; 180 after (174 unchanged + 6 new), all green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:03:12 +02:00
Meta Vens
04c0943fa0 Wire subsystem selection and reveal into player input and the HUD
A new "Cycle Target Item" action (hand-authored into Aetheria.inputactions;
no Unity editor here to regenerate AetheriaInput.cs, so ActionGameManager
looks it up by name through Input.asset.FindAction instead of a typed
accessor) cycles the local player's aim point among the current target's
revealed items via TrySelectTargetItem. SchematicDisplay's enemy view now
filters to what FireControl.IsRevealed actually resolves for the viewer,
and marks whichever row is the current ResolvedTargetItem through a new
SchematicListElement.SelectedIndicator (unwired in any prefab yet -- a
no-op until an editor pass assigns one).

Presentation only; decides nothing. Unverified here -- Unity batchmode
is unavailable in this environment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:02:54 +02:00
Meta Vens
52a18efcdc Require a targeting system on every armed loadout; AI aims through reveal
LoadoutGenerator.FillInterior equips a targeting-system product,
required: true, on any entity EquipHardpoints already gave a weapon --
Q4's "not an upgrade" ruling made structural. CombatState now selects
the target's most dangerous revealed weapon item each tick through the
same IsRevealed predicate and TrySelectTargetItem writer the player path
uses, instead of never touching TargetItem at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:02:37 +02:00
Meta Vens
c4a57a8df0 Add targeting subsystem, reveal rule and selection slot (fire control Cut 2)
TargetingSystem is required interior Tool gear: Accuracy/Resolution/
Precision/Tracking are PerformanceStats reached through the usual
Evaluate path, so lot quality, wear, heat and PowerSupply all apply
(a starved system rolls worse, never switches off). FireControl.Accuracy/
Resolution/Precision fall back to GameplaySettings.UnaidedAccuracy (new,
authored low per Q4) whenever an entity has no targeting system or its
own is destroyed/disabled.

FireControl.IsRevealed derives R5's reveal rule from EntityInfoGathered:
non-hull equipment ranks hardpoint-mounted first, then by size, and
reveals between TargetArmorInfoThreshold and TargetGearInfoThreshold --
the first code to read either setting. Entity.TargetItem/
TrySelectTargetItem/ResolvedTargetItem give both the player and AI one
shared, revoke-on-decay aim-point slot with a single writer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 13:02:20 +02:00
Meta Vens
3ea29acc3f Merge fire control Cut 1: combat steps without Unity
HardpointTransforms and its renderer readback are gone; mount direction
comes from the item's rotation and arcs are simulation data, default 120
with a per-hardpoint override. Combat no longer throws headless: a real
engagement steps two ticks and decides to fire through the same arc gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:39:47 +02:00
Meta Vens
81dbc89489 Add firing-arc-migrate: report Turret hardpoints needing FiringArc: 360
A Hands scratch console upsert, same shape as ShieldMigrate/BrownoutMigrate
(dry run unless "apply" is passed) -- follows the Cut C precedent named in
docs/fire-control-cut.md's Cut 1. Scoped to the Turret hull's own Ballistic
hardpoints, the only ones the cut names (Q1: turrets author FiringArc: 360).

Not applied here: GameData/Aetheria.cc is left untouched. Dry run against
the live catalog reports two hardpoints to migrate:

  hull             hardpoint  position     was   now
  Turret           Ballistic  (1,2)          0   360
  Turret           Ballistic  (5,2)          0   360

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:38:16 +02:00
Meta Vens
9a82b76390 Pin fire-control arc rules and the headless engagement
One check per rule Cut 1 lands, each with a stated mutation that would
defeat it: mount direction follows the item's authored rotation and not
the hull's facing (ArcFollowsMountRotation), FiringArc is a full width so
the boundary sits at half of it (ArcBoundaryIsHalfWidth), the arc test is
planar per R7 (ArcIsPlanar), and a per-hardpoint override wins over the
default while an authored 0 still means "use the default" rather than a
zero-width arc (HardpointOverrideBeatsDefault).

CombatStateStepsHeadless is the cut's real deliverable: a Minion with a
target in range steps through two Zone.Update ticks without Combat.cs
throwing (the KeyNotFoundException this cut exists to unbreak), and the
fight actually decides to fire, not just avoids a crash.

Builds its own hull/catalog rather than reusing IffAndCombatTests'
private BuildWorld/NewShip (fixed to one hardpoint) -- and along the way,
surfaces three catalog-authoring gotchas any headless-combat fixture
needs: Mass defaults to 0 (NaNs UpdateTemperature via ThermalMass),
default temperature bounds [0,100] don't cover wherever the heat model
settles, and Entity._orderedEquipment is only ever populated by TryEquip
so an entity that never equips anything throws on its first Update.

docs/fire-control-cut.md, Cut 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:38:06 +02:00
Meta Vens
2b98aaa762 Delete HardpointTransforms; mount direction and arc become sim data
Entity.HardpointTransforms was written only by Unity (EntityInstance.cs),
so the simulation's notion of where a gun points was a readback from a
renderer that never runs headless -- Combat.cs threw KeyNotFoundException
on the first combat tick outside Unity. Deletes the field, its writer, and
the readback branch in Behavior.Direction, leaving the item-rotation path
(the same convention reaction thrusters use, R6) as the only source of
mount direction.

Adds FireControl (ServerShared), a static class owning whether a weapon
bears on a point: MountDirection (planar, from ItemRotation), ArcFor (the
per-hardpoint HardpointData.FiringArc override, falling back to the new
GameplaySettings.FiringArc default of 120), and InArc (the planar dot-cone
test, R7 -- target height never enters it, and an arc of 360+ passes
unconditionally so a turret hardpoint needs no new type, just a number).
Combat.cs and TurretController.cs now gate AI fire through InArc instead
of the old hardcoded 0.99 dot-product test against a live Unity transform.
Settings.cs drops AgentFiringMinDot, which was declared and read by
nothing.

docs/fire-control-cut.md, Cut 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:37:52 +02:00
Meta Vens
678c1ea99a Rule fire control's forks: unaided fire is a last resort
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 07:01:37 +02:00
Meta Vens
e29b9b45fa Merge nominal power requests: brownout and request-independence coexist
A power request is what the item wants at full supply, not what it is
currently managing, so the circularity dies at the root and radiators and
drives can carry their brownout curve again. The static refusal goes; the
modifier-chain check stays. Six skipped tests pass on their merits and the
shipped catalog is legal again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:59:55 +02:00
Meta Vens
8bbf280756 Resolve request/brownout conflict: evaluate power requests nominally
A power request may not depend on power supply (Cut 6/F6), and continuous
consumers brown out through a power term on their own performance stats
(Cut 7). For Radiator (PumpedHeat) and AetherDrive (Torque) those were the
same stat, making six shipped catalog records illegal and leaving six
BrownoutTests cases skipped.

Resolved per the operator's ruling: a power request is evaluated
nominally -- what the item wants at full supply, not what it is currently
managing. EquippedItem.EvaluateNominalPower (mirroring ConditionRatio's
own NominalContext) pins only PowerSupplyFactor to 1; Heat/Durability
stay live, since they are not the term a request would be circular
through. Every PowerRequest/RefreshReserve/RefreshInputCapacitor
implementation now reads a StatValidation.PowerRequestFields stat through
it, so the same stat can carry a brownout curve and be a request field
without the request depending on its own answer.

StatValidation.ValidateNoPowerSupplyOnRequest (F6's static half of the
rule, forbidding the term outright) is deleted -- nominal evaluation
removes the circularity at the root instead. Only the dynamic
modifier-chain half (StatModifier.ValidateNoPowerSupplyChain) still
refuses anything, since EvaluateNominalPower forwards ScaleModifier/
ConstantModifier unchanged (real, not nominal).

Un-skips BrownoutTests' six Radiator/AetherDrive cases and adds two new
regression tests (a direct EvaluateNominalPower probe, and a two-tick
Radiator demand check) backed by a new mutation harness. Updates the four
PowerCurveTests/AetheriaStoresTests cases that pinned the now-superseded
static refusal to instead assert acceptance. GameData/Aetheria.cc is
unchanged and still validates.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:58:57 +02:00
Meta Vens
a62d52b64e Map fire control, superseding the playground draft
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:36:01 +02:00
Meta Vens
8a00fc9235 Place territory after fire control in the order
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:23:08 +02:00
Meta Vens
41282b05a0 Target faction territory: places with jobs, not just names
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:20:58 +02:00
Meta Vens
5c2f9bba67 Spec the first content batch, hulls first
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:06:20 +02:00
Meta Vens
cd47eefe9e Merge the power fixes: multiplier, active gating, honest tiers, shield repair
F1 power supply multiplies the resolved value (operator ruling), so zero
supply means zero and a flat stat still responds. F2 the bus agrees with
Active in both directions. F3 an empty tier reports no demand instead of
full supply, and sub-epsilon demand is rationed and subtracted. F4/F5 the
shield restores while inactive and CanTakeHit no longer mutates. F6/F7 the
validator names every stat a request reads and the tools validate before
writing. F8 re-anchors two dead mutation harnesses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:04:12 +02:00
Meta Vens
8dddda4d80 F8: re-anchor cut3/cut4 mutation harnesses after later cuts moved their code
Both scripts aborted with "anchor must occur exactly once, found 0" -- later
cuts moved the code their anchors pinned:

- cut3's fourth mutation anchored PowerBus.Step's old flat "write GrantRatio
  to every consumer" loop, which Cut 5 replaced with AllocateTiers' own
  tiered closing loop (draw.Item.PowerSupply = ratios[draw.Tier]). Re-anchored
  to that loop; the rule (every draw gets written, not just the first) and
  its test (PowerBusTests.EveryConsumingItemReadsTheSameGrantRatio, a
  single-tier fixture) are unchanged.
- cut4's shield mutation anchored CanTakeHit's old single-expression body
  (`return Item == null || _reserve.CanSpend(...)`), which the 2026-09-19
  shield reserve ruling split into an Item-null check, a Broken check and
  this CanSpend call as its own line, and F5 (this same pass) then made the
  whole method a pure query. Re-anchored to the CanSpend line; the rule (a
  partial draw is allowed, not gated on covering the whole reserve) and its
  test are unchanged.

Both scripts now run clean end to end against the pinned CultLib worktree:
every mutation kills its named test, the no-op control does not.

Scope note: mutation_tests_stats_power_cut0/1/2 also abort on stale anchors
(spot-checked while re-anchoring cut3/cut4, then the check was cancelled
partway through cut1 once the pattern was clear) -- not touched here, as F8
named only cut3 and cut4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 06:02:08 +02:00
Meta Vens
e3e228e036 F7: route AetherDb's identity-preserving repairs through the same validation
CultRecordRefs.Upsert is the one function every catalog write is supposed to
go through, but tools/AetherDb/Program.cs's Dangling, ShieldMigrate and
BrownoutMigrate commands each repair an existing record in place and must
preserve its key -- Upsert's own cache.UpsertAsync(document) cannot take a
caller-supplied key, so all three wrote raw and unvalidated through
`db.Cache.Commit(batch => batch.Upsert(document.GetType(), document, key))`.
`brownout-migrate apply` is how the shipped catalog's PowerSupply terms were
actually authored, unvalidated, the whole time.

Extracted Upsert's validation body into CultRecordRefs.Validate(object), and
call it directly from all three tool commands immediately before their own
identity-preserving commit -- the same rules, invoked where Upsert itself
cannot reach. The comment above StatValidation naming the write-bypass holes
(landed with F6) now names all four instead of two: CultCache Studio's
generic editor (still open -- not this repository's to patch) plus the three
tool commands above (closed).

Pinned in tests/Aetheria.Shared.Tests/AetheriaStoresTests.cs:
ValidateRefusesAnEquippableItemWithAZeroSpanHeatRangeTheSameWayUpsertWould and
ValidateRefusesAPowerRequestCarryingAPowerSupplyTermTheSameWayUpsertWould pin
that the extracted method actually refuses what Upsert would (fail under a
reverted Validate that is a no-op); ValidateIsANoOpForADocumentTypeItDoesNotGovern
pins that a document type it has no opinion about doesn't crash it.

Verified tools/AetherDb/AetherDb.csproj still builds clean against the pinned
CultLib worktree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:47:31 +02:00
Meta Vens
02e2ca9556 F6: name every field a power request actually reads, not just its top-level one
StatValidation.PowerRequestFields registered only each consumer's own
top-level request field (Thruster.EnergyUsage, Shield.Capacity, and so on),
on the premise that PowerRequest reads exactly one PerformanceStat. That was
false for five of the eight consumers: Radiator.PowerRequest also reads
PumpedHeat and WasteHeat (its own early-out gate), AetherDrive.PowerRequest
also reads Torque, LambdaMultiplier, MaximumRpm and PassiveCoupling (its
whole spin-up arithmetic), Shield.PowerRequest (via RefreshReserve) also
reads RefillDuration/RestoreDuration, InstantWeapon.PowerRequest (via
RefreshInputCapacitor) also reads Cooldown/Count, and Sensor.PowerRequest
also reads PingCooldown. Any of those could carry a PowerSupply term and sail
straight past ValidateNoPowerSupplyOnRequest, corrupting the very request it
feeds -- exactly Soul's reproduced "OK Disperser" oscillation
(SOUL_RadiatorRequestDependsOnItsOwnGrantAndOscillates).

Audited directly against each PowerRequest method's own body (and the
RefreshReserve/RefreshInputCapacitor helpers it calls into), not guessed from
the behaviour's public surface.

This correctly refuses the real catalog now: `GameData/Aetheria.cc` carries
exactly six violations --
  cold like my heart   RadiatorData.PumpedHeat
  Arctica               RadiatorData.PumpedHeat
  Skiron                RadiatorData.PumpedHeat
  OK Disperser          RadiatorData.PumpedHeat
  Iapyx                 RadiatorData.PumpedHeat
  Traction              AetherDriveData.Torque
-- re-authoring them (moving the PowerSupply term off the now-covered field,
or redesigning Radiator/AetherDrive's own PowerRequest to read a
nominal/undegraded value instead) is catalog and design work for Self/roles
authoring, not done here.

BrownoutTests.cs's own Radiator/AetherDrive brownout fixtures hit the same
wall -- they authored a PowerSupply term on PumpedHeat/Torque to test Cut 7's
"curve on the performance stat," which is now correctly refused since both
behaviours' PowerRequest reads that same stat. Neither behaviour has an
untouched field left to curve, so there is currently no valid catalog shape
that gives them a working brownout curve without also feeding it back into
their own request -- a real, scoped conflict between Cut 6 and Cut 7 for
these two consumers. The six affected tests are marked Skip with a header
comment explaining the conflict rather than silently reworked or deleted;
Thruster and ConstantWeapon are unaffected (their own PowerRequest never
reads the separate field their tests curve).

Pinned in tests/Aetheria.Shared.Tests/PowerCurveTests.cs:
UpsertRefusesARadiatorWhosePumpedHeatCarriesAPowerSupplyTerm and
UpsertRefusesAShieldWhoseRefillDurationCarriesAPowerSupplyTerm -- both fail
under the reverted (top-level-field-only) registry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:47:14 +02:00
Meta Vens
95d6fd3b14 F4/F5: shield restore survives inactivity, and CanTakeHit stops mutating
F4: a hit that breaks the shield usually also cooks it (TakeHit's own
AddHeat), which can knock the item thermally offline in the same tick. The
reserve's recharge and its Broken-clearing check lived inside Execute, which
Entity.Update only runs while Item.Active is true -- so a shield broken by a
hit that also shuts it down could never come back, no matter how long
RestoreDuration allows for. That logic now lives in Shield.Update
(IAlwaysUpdatedBehavior), which Entity.Update calls every tick unconditionally
(Cooldown.cs already relies on the same interface for the same reason).

F5: CanTakeHit broke the shield and drained the reserve as a side effect of
the query itself, on the premise that every caller queries it exactly once
per hit. That premise was false: RaycastAll/SphereCastAll/OverlapSphere hand
every caller under Assets/Scripts/Gameplay/Weapons both the shield collider
and the hull collider for one shot, so the same shield's CanTakeHit was
queried twice per hit. CanTakeHit is now a pure read (Broken + the reserve's
own CanSpend); the mutation moved to a new Shield.Break(), idempotent, called
by each weapon file exactly where it already decided to route a hit past the
shield instead of absorbing it.

Pinned in tests/Aetheria.Shared.Tests/ShieldReserveTests.cs:
RestorationProceedsWhileTheItemIsInactive (F4),
CanTakeHitNeverMutatesRegardlessOfHowManyTimesItIsCalled and
BreakIsIdempotentAcrossRepeatedCalls (F5). Updated every existing test that
relied on CanTakeHit's old mutating side effect to call Break() explicitly,
matching the new caller pattern.

Cannot compile-verify Assets/Scripts/Gameplay/Weapons/*.cs here (UnityEngine,
Unity batchmode unavailable in this environment) -- reviewed by hand for
brace/control-flow correctness; Self or a Unity batchmode pass should confirm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:32:29 +02:00
Meta Vens
f36effd70b F3: an empty tier is not a satisfied tier, and sub-epsilon demand pays its way
AllocateTiers treated any tier whose summed demand was at or below 1e-4 as
"fully met" (ratio 1) without ever subtracting it from `remaining`. Two bugs:
a tier with no consumers equipped in it at all read as 1f, the exact "fully
supplied" signal a UI is meant to trust, even on a fully blacked-out ship
(measured: Critical 0 demand reads "fine" right next to a genuinely starved
High); and a tier with a real but tiny demand (down to 5e-5) was granted out
of nothing and never charged against the ship's actual generation, letting a
lower tier get overfed by the sliver the higher one was never billed for.

AllocateTiers now tracks which tiers actually have a consumer separately from
their summed demand. A tier with no consumer reports the new PowerBus.NoDemand
sentinel (NaN), never 1f. A tier with a consumer whose own request truly is
zero this tick is trivially satisfied (ratio 1, nothing to be short of). Any
other demand, however small, goes through the same grant/remaining arithmetic
as every other tier.

Pinned in tests/Aetheria.Shared.Tests/PowerTierTests.cs:
SubEpsilonDemandGetsNoGrantAtTotalBlackout,
HigherTierSubEpsilonDemandIsStillSubtractedFromRemaining, and
EmptyTierAtBlackoutReportsNoDemandNotFullySupplied -- all fail under the
reverted (<=1e-4 free-pass) mutation. Updated
ATierWithNoDemandPassesItsShareDown's own empty-tier assertion, which had
pinned the bug itself ("empty tiers read as fully met").

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:15:30 +02:00
Meta Vens
881415d5e3 F2: gate the bus's reactors and consumers on Active, not Online
PowerBus.Step billed every equipped IPowerConsumer's request unconditionally
and admitted a reactor on Item.Online alone, but Entity.Update only ever runs
a behaviour's Execute when the item is Active (Enabled && Online). A consumer
the player switched off never executes and never spends anything, yet was
still billed, starving live consumers and draining capacitors for nobody. A
reactor switched off stayed Online and kept generating even though
Reactor.Execute (which produces the heat receipt) never ran for it: free,
heat-free power.

Both directions now gate on the same predicate the rest of Entity uses:
item.Active.Value.

Pinned in tests/Aetheria.Shared.Tests/PowerBusTests.cs:
DisabledConsumerContributesNoDemand and DisabledReactorGeneratesNoPower --
both fail under the reverted (Online-only / unconditional) mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:06:31 +02:00
Meta Vens
90e83234ed Merge authored design roles: items stop being one-dimensional
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>
2026-09-19 05:03:57 +02:00
Meta Vens
da5a710030 F1: power supply multiplies the resolved stat, it does not interpolate
PerformanceStat.Evaluate folded PowerSupply into the same Min/Max lerp factor
as Heat/Durability/Quality, so zero supply bottomed out at Min instead of 0
(measured: a radiator at zero power still pumped 19-25% of full; three of Cut
7's eight authored terms had Min == Max and were completely inert, since
lerp(x, x, anything) == x).

PowerSupply terms are now accumulated into their own multiplier and applied to
the fully-interpolated, fully-modified value instead of to the interpolation
factor. The term still lives in PerformanceStat.Terms -- it is still authored
per stat and still censused/validated the same way -- it is just no longer
blended into `factor`. Corrected the comments that stated the old premise
(Radiator.cs, Entity.cs, ItemData.cs's IStatContext.PowerSupplyFactor doc).

Pinned in tests/Aetheria.Shared.Tests/PowerCurveTests.cs:
APowerSupplyTermedStatWithNonzeroMinResolvesToExactlyZeroAtZeroSupply and
AMinEqualsMaxStatStillRespondsToItsPowerSupplyTerm -- both fail under the
reverted (lerp-based) mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:03:31 +02:00
Meta Vens
c4f6029e5d Cut 7: author roles into the catalog, and the operator review table
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>
2026-09-19 05:01:43 +02:00
Meta Vens
6d2b6e939d Cut 7: roles-migrate command and a census role-coverage check
roles-migrate declares roles on designs, points each design's own
StatTerm.Role at the role that governs it, and authors matching ProductRole
quality on every product selling a now-role-bearing design -- all through
AetherDb's own CultCache-backed types, one commit, nothing written if any
record fails to derive (same all-or-nothing contract as shield-migrate and
brownout-migrate). Field->role maps are per item kind (Weapon/Ballistic,
Weapon/Energy, Weapon/Launcher, Radiator, Reactor, Sensors, Thruster,
AetherDrive, Hull/Ship); Tool is keyed by design name since it is not a
shared kind. A stat only gets a role when it carries an unrouted
StatSource.Quality term AND still varies (Min != Max) -- Cut 1's flat
placeholder stats carry no observable role-vs-workmanship difference, so
routing one would be authoring fiction.

Product role means are deterministic generic placeholders (stable FNV hash
of product+role, not System.String.GetHashCode, which is randomized per
process and would make a dry run and the later apply disagree) flagged
"needs operator review" in the printed table, except Arctica/Alakrita's
`fins`, which item-provenance-target.md already gives a real brand identity
(heat efficiency).

census gains a role-coverage check: every sold, role-bearing design's
product must author a matching ProductRole spread, reported as "(product,
role) pairs where ... authors no matching spread" -- the gap the ruling
names directly (a newly minted lot from a product with no spread rolls the
default mean .5, silently pulling every maker toward average).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:01:30 +02:00
Meta Vens
395494f6a7 Cut 7: refuse a stat naming a role its design lacks
StatValidation.ValidateRoleUsage walks every PerformanceStat field on every
behaviour and refuses a StatSource.Quality term whose Role is not in the
design's own declared Roles -- wired into AetheriaStores.Open and
CultRecordRefs.Upsert alongside the existing heat/modifier/power-supply
checks. Lot.QualityForRole already falls back to workmanship for a role an
old lot never rolled (forward-compat for a role added after minting); this
is the other direction: a term naming a role the design never declared at
all is an authoring mistake, not a lot predating the role, and must fail
loudly.

RoleAuthoringTests.cs pins three rules with both a positive and negative
control: Upsert refuses an absent-role term but accepts a declared one, and
two products of one design with different ProductRole means mint lots that
resolve a role-termed stat to different, deterministic values.
tests/mutation_tests_stats_power_cut8.py (this repo's own numbering follows
cut7.py's brownout work) mutates ValidateRoleUsage in both directions
(never-refuse, always-refuse) and QualityForRole's fallback, plus
ItemManager.CreateLot's mean read -- all six behave as declared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 05:01:17 +02:00
Meta Vens
e6609c45f3 Rule power supply a multiplier, and record Soul's power findings
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:58:58 +02:00
Meta Vens
48ef551050 Merge the condition ratio: a starved or cooked thruster shows it
One ratio per item, resolved performance against the same item in perfect
conditions (quality and lot stay part of perfect; only durability, heat and
power count as degraded). Thruster and drive particles multiply intent by
it, and presentation stops computing durability itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:43:44 +02:00
Meta Vens
57c053d15f Cut 8: pin ConditionRatio -- perfect/dead/durability/heat/power/force-unchanged
ConditionRatioTests.cs (8 Facts): a perfect item reads 1; the ratio falls
with durability, temperature-off-plateau, and a partial power grant, each
in isolation; it is 0 when the item produces nothing (both the ordinary
durability=0 case and the degenerate Max=0 nominal, which relies on
CultMath's NaN-favoring min/max rather than a manual guard); thrust force
for a given input is bit-identical to BrownoutTests' own pinned values,
proving Execute()'s physics is untouched by Condition being read every
tick. mutation_tests_condition_ratio_cut8.py: one mutation per rule,
mirroring cut7's harness; all 7 confirmed red (2 control/guard mutations
revised after the first pass showed them un-killable -- see the harness's
own comments).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:41:43 +02:00
Meta Vens
ff7f8a5c2a Cut 8: presentation reads Condition instead of recomputing durability
ShipInstance's thruster and aether-drive emission were the operator's
actual complaint (2026-09-19): thrust intent times a raw durability ratio
that ignored heat and power and duplicated simulation arithmetic in
presentation. Both now multiply intent by Thruster.Condition /
AetherDrive.Condition -- no durability/heat/power math left in
presentation. Unity-side; not covered by the shared test suite. Small and
obvious for Self's batchmode run on merge to check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:41:23 +02:00
Meta Vens
4cdfa22fb0 Cut 8: EquippedItem.ConditionRatio -- how healthy a behaviour actually is
Operator ask (2026-09-19): thruster particles only reflected thrust intent,
so a cooked or starved thruster looked identical to a healthy one.

EquippedItem.ConditionRatio (Entity.cs) resolves a stat's actual value
against what the same item, same lot, same modifiers would produce with
Heat/Durability/PowerSupply pinned to their identity (NominalContext) --
quality and lot are not part of "perfect", so a cheap item still reads 1
at full health. The nominal side bypasses the resolver's cache (which is
keyed only by (owner, stat) and would otherwise collide with the real
cached value) with one direct Evaluate call, a handful of flops.

Thruster.Condition and AetherDrive.Condition expose that ratio against
each behaviour's own governing stat (Thrust, Torque) for presentation to
read next.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:41:13 +02:00
Meta Vens
d28815e8bd Merge brownout: continuous consumers degrade instead of flicking off
Removes the full-grant gates from the five continuous consumers, so a
partial grant means reduced thrust, torque, pumped heat and damage rather
than nothing, and a constant weapon keeps firing while starved. Authors a
linear PowerSupply term on the eight shipped stats that had none. Instant
items keep their all-or-nothing charge.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:11:59 +02:00
Meta Vens
7e3016c487 Pin Cut 7's brownout rules: BrownoutTests.cs
Pins, for each of the five continuous consumers: a partial grant produces a
reduced-not-zero-not-full effect, a full grant is unchanged from today, a
zero grant produces nothing, and (Thruster, ConstantWeapon) the degradation
follows the authored exponent rather than being linear by accident.
EnergyDraw is pinned separately as the one consumer with no performance
stat of its own -- its Execute return value is the whole effect. A regression
Fact pins that InputCapacitor's all-or-nothing rule for instant items
(Cut 4) is untouched.

Each rule has a matching mutation in tests/mutation_tests_stats_power_cut7.py
(modeled on mutation_tests_stats_power_cut6.py's own shape); all eight
mutations, including the no-op control, behave as declared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:11:00 +02:00
Meta Vens
e42299858c Author a PowerSupply term on the four shipped continuous-performance stats
Cut 7's gate removal (previous commit) only has anything to curve if some
shipped stat actually declares a PowerSupply term. Checked: none did --
removing the gates would have made brownout invisible (still full
performance at any nonzero grant) instead of graceful.

Added tools/AetherDb's "brownout-migrate [apply]" command (ShieldMigrate's
own dry-run/apply/report shape) and ran it against GameData/Aetheria.cc,
authoring exponent-1 (linear, the gentle default) PowerSupply terms on:

  design                behaviour        stat        before  after
  Arctica               RadiatorData     pumpedHeat    3   ->   4
  Iapyx                 RadiatorData     pumpedHeat    1   ->   2
  Large Drive           ThrusterData     thrust        2   ->   3
  OK Disperser          RadiatorData     pumpedHeat    3   ->   4
  Skiron                RadiatorData     pumpedHeat    1   ->   2
  Traction              AetherDriveData  torque        3   ->   4
  cold like my heart    RadiatorData     pumpedHeat    3   ->   4
  deep space burnout    ThrusterData     thrust        3   ->   4

No shipped ConstantWeaponData record exists yet, so ConstantWeaponData.Damage
has nothing to author against; the tool still targets it for whenever one
ships. None of the four targeted fields is a power-request field
(StatValidation.PowerRequestFields), so this does not trip
ValidateNoPowerSupplyOnRequest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:10:39 +02:00
Meta Vens
b4702bbc33 Cut 7: continuous consumers brown out instead of flicking off
docs/stats-and-power-target.md: "Continuous consumers brown out through a
power supply curve on their performance stats." Cut 6 wired the curve
(EquippedItem.PowerSupplyFactor) but every continuous consumer still gated
its own effect on Item.PowerSupply >= 1f, so an 80% grant produced nothing
instead of 80% performance.

- Thruster/AetherDrive: gate narrowed from ">= 1f" to a true-zero floor
  (> 1e-4f, PowerBus's own epsilon); Thrust/Torque are plain Evaluate()
  reads, so a curved stat already degrades once the full-grant demand is
  dropped.
- Radiator: the gate is deleted outright. PumpedHeat is already a curved
  Evaluate() read; waste heat is unaffected, so a starved radiator now falls
  behind instead of refusing to pump, and zero supply already zeroes
  PumpedHeat via the curve with no special case needed.
- ConstantWeapon: the weapon no longer safes itself off (_firing = false)
  on a partial grant -- only true zero still stops it. Damage already
  degrades via base.Execute's own Evaluate() read.
- EnergyDraw: has no performance stat of its own -- its Execute return
  value IS the effect (gates its BehaviorGroup). Narrowed the same way:
  a partial grant still passes, only true zero closes the gate.

InputCapacitor and the three instant consumers (InstantWeapon, Sensor,
Shield) are untouched: all-or-nothing on a partial charge still holds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 04:10:19 +02:00
Meta Vens
cc7ee7942e Merge the power-supply term and the request-independence rule
Cut 6 of docs/stats-and-power-cut.md. A stat may declare a PowerSupply
term applying as an exponent; the bus invalidates that source so the
resolver recomputes when the grant moves. A stat that decides a power
request may not depend on power, refused at catalog load, at Upsert and
at equip, including through a modifier chain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 03:48:25 +02:00
Meta Vens
d975e1d2cc Pin Cut 6's power-curve and request-independence rules: PowerCurveTests.cs
Seven tests: a PowerSupply-termed stat degrades by its own authored exponent when the
grant drops and reads unchanged at full grant (the second read is deliberately taken after
a real cached value exists, so the missing-invalidate mutation is actually reachable rather
than hidden behind a fixture that only ever reads once); a stat with no PowerSupply term
never asks the context for one, cache or no cache; a power-termed stat recomputes at most
once per tick, not once per read; a thruster-style EnergyUsage field carrying a PowerSupply
term directly is refused at AetheriaStores.Open and at Upsert, naming the item and the
field; and a modifier whose magnitude carries a PowerSupply term is refused at equip when
its target is a known power-request stat, naming both items.

123 tests total (116 baseline + 7). tests/mutation_tests_stats_power_cut6.py: 10 mutations
(1 no-op control, 9 rule-killing), all behave as declared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 03:47:23 +02:00
Meta Vens
1c1249e700 Cut 6: wire StatSource.PowerSupply and refuse a power request that reads it
docs/stats-and-power-cut.md Cut 6, purely additive per its own map: the enum member, the
resolver's generation-cache and the bus's PowerSupply write already existed (Cuts 2/3/5)
as an identity everywhere. This lands the two things Cut 6 actually adds.

The curve: EquippedItem.PowerSupplyFactor now returns pow(PowerSupply, exponent) instead
of the Cut-3 identity stub, so a stat that declares a PowerSupply term degrades as this
tick's grant falls and reads unchanged at full supply (pow(1, n) == 1 regardless of n).
PowerBus.AllocateTiers now invalidates StatSource.PowerSupply once per draw per tick -- the
missing half of the wiring named in the cut map -- so the resolver actually recomputes when
the grant moves, using the same per-source generation scheme Heat/Durability already use
(unconditional, at most once per tick, never touching a stat that did not declare the
source).

The request-independence rule: a stat that decides a power request may not depend on power
supply, directly or through a modifier chain. Direct dependency is checked statically
(StatValidation.ValidateNoPowerSupplyOnRequest, ItemData.cs) against a fixed registry of
(BehaviorData type, field) pairs -- the one PerformanceStat each IPowerConsumer's own
PowerRequest evaluates as its request, a compile-time fact rather than something authored
per instance -- and runs at catalog load (AetheriaStores.Open), at Upsert, and again at
equip (EquippedItem's constructor) as defense against the two named bypasses that write a
catalog document without going through Upsert. The modifier-chain half is dynamic
(StatModifier.ValidateNoPowerSupplyChain): a modifier's own magnitude stat is walked
through the same magnitude->target edges ValidateNoCycle already builds for the self-cycle
check, and refused at Initialize (equip time) if it is power-tainted and targets a known
request stat, naming both items.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 03:47:07 +02:00
Meta Vens
8a717542a4 Merge remote-tracking branch 'origin/codex/power-tiers' into codex/item-provenance 2026-09-19 03:00:02 +02:00
Meta Vens
8e4d847dc6 Mutation harness for Cut 5's tier rules
Nine mutations (one no-op control, eight rule-breaking) against
PowerBus.AllocateTiers and EquippedItem's tier-seeding guard: tier walk
order, committing a fed tier's grant before the next tier is considered,
proportional-within-tier rationing, an empty tier reading as met rather than
starved, allocating against TotalGrant rather than raw TotalDemand, remaining
vs. the original total (the no-leak boundary), reading the item's live
stored tier every Step, and never re-seeding a kind default once set. All
nine behave as declared against PowerTierTests.cs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:58:55 +02:00
Meta Vens
d07652b5bb Pin Cut 5's tier rules: PowerTierTests.cs
Six tests against the "rules worth pinning" list: critical fed in full while
a lower tier starves; two consumers in one tier rationed proportionally to
their own request, not split evenly; an empty tier passes its share down
instead of swallowing it; reactor throttling moves the line between what
starves and what doesn't; a starved tier cannot leak into a lower one; and a
tier change on an equipped item takes effect on the very next tick with no
unequip/re-equip round trip.

103 -> 109 tests. Each rule has a matching mutation in
tests/mutation_tests_stats_power_cut5.py.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:58:47 +02:00
Meta Vens
55249beb98 Cut 5: priority tiers replace PowerBus's single shared GrantRatio
PowerTiers.cs names five tiers (Critical/High/Medium/Low/Utility) and their
per-behaviour-kind defaults: Radiator is Critical (the closest thing this game
has to life support -- a starved radiator cascades into wear and shutdown
across the whole hull), Shield is High, Thruster/AetherDrive are Medium,
ConstantWeapon/InstantWeapon are Low, and Sensor/EnergyDraw are Utility.
IPowerConsumer.DefaultPowerTier lets each behaviour own its own default.

EquippableItem.PowerTier (Key 12) is the stored, player-choosable tier on the
unit rather than the design; EquippedItem's constructor seeds a kind default
the first time a unit is equipped, only when the field is still
PowerTiers.Unassigned, and never again -- a tier is a stored choice, not
something the bus re-derives.

PowerBus.AllocateTiers walks tiers lowest-number-first: a tier is granted in
full before the next tier sees anything left, an empty tier passes its whole
share down, and within a tier every consumer rations by the same
grant/demand fraction so unequal requests still divide proportionally. A new
TierGrantRatio[] exposes each tier's own ratio for a future UI (Cut 8) to
read starvation from directly, instead of reconstructing it from every item's
PowerSupply.

Deletes EquippedItem.SortPosition, IOrderedBehavior and Reactor.Order (its
only implementer): the bus already steps before any equipment's Execute, so
equip/behaviour order never decided who got fed even before this cut, and
nothing else needed the interface (subject to the map's O3 operator check).

docs/stats-and-power-cut.md Cut 5 / §1.3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:58:38 +02:00
Meta Vens
f1c8afcb83 Merge the authored shield reserve and its broken state
Capacity, refill duration and restore duration are authored on ShieldData.
A hit the reserve cannot cover breaks the shield: the hit passes through in
full, the reserve empties, and it restores from zero on the restore
duration, so the punish window is the same every time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:47:35 +02:00
Meta Vens
7d60405f32 Add shield-migrate: authors Capacity/RefillDuration/RestoreDuration for catalog shields
Catalog migration for the shield reserve ruling (docs/stats-and-power-cut.md). Scans
every GearData- and ConsumableItemData-hosted ShieldData, derives Capacity from
EnergyUsage (a per-damage-point multiplier, not an energy quantity -- capacity =
10 raw damage points x max(1, EnergyUsage) x cell count) and flat starting durations
(2s refill, 12s restore), and prints a derivation table. Dry run unless passed
"apply"; writes nothing if commit fails partway (single Cache.Commit batch).

GameData/Aetheria.cc is unchanged by this commit: the shipped catalog holds zero
ShieldData records (the pre-Cut-4 probe's 348-instance PerformanceStat table never
lists ShieldData among its owners either -- consistent with GameData/Aetheria.cc
being the post-breach bare-minimum rebuild, not the full pre-breach consumer set).
shield-migrate reports "0 shield designs" against it today and will migrate real
designs as soon as any are authored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:46:38 +02:00
Meta Vens
ad3a3d40cb Pin the shield reserve ruling: 7 rules, each with a mutation
ShieldReserveTests.cs covers what Cut 4's InputCapacitorTests.cs cannot: a hit within
the reserve is absorbed and spends charge; a hit beyond it breaks the shield; the
breaking hit is not partially absorbed; a broken shield absorbs nothing (gated on
Broken itself, not merely on the reserve reading empty); a break empties the reserve
regardless of pre-hit charge; a broken shield restores on RestoreDuration and not
RefillDuration; a partial bus grant stretches the refill proportionally.

mutation_tests_shield_reserve.py mutates each rule's own line and confirms the named
test goes red for exactly that reason, plus a no-op control. All 8 (7 rules + control)
verified against the pinned CultLib worktree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:46:26 +02:00
Meta Vens
b0e67cb36f Shield reserve is authored: Capacity/RefillDuration/RestoreDuration, and a broken state
Operator ruling, 2026-09-19, supersedes Cut 4's derived reserve (EnergyUsage refilling
every second, flagged as a guess). ShieldData now authors the reserve size and two
recharge speeds directly; EnergyUsage stays the per-damage-point cost multiplier.

A hit the reserve cannot fully cover now breaks the shield instead of a silent,
charge-preserving refusal. Two follow-up rulings settle the fork the first left open:
the breaking hit passes through in full (no partial absorption -- TakeHit never runs
for it), and the reserve empties to zero on break so RestoreDuration means the same
thing every time regardless of how full the shield was.

InputCapacitorTests' shield fixture now authors the three new fields explicitly --
without them the reserve defaults to zero capacity and breaks on every hit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:46:17 +02:00
Meta Vens
08c3bb8c64 Rule the shield reserve authored, with refill and restore durations
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-19 02:14:49 +02:00
Meta Vens
811cd27c0a Merge input capacitors: every draw is continuous now
Cut 4 of docs/stats-and-power-cut.md. Instant-activation items (weapons,
sensor ping, shield) get input-only buffers the bus fills; the direct
capacitor-spend path Cut 3 left as a named exception is gone. Size derives
from Energy and Cooldown, with ChargeEnergy as the authored rate override.
Shield's reserve sizing is Hands' judgement and wants an operator look.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 22:53:17 +02:00
Meta Vens
8dacabb3d8 Cut 4: input capacitors close the last direct capacitor spend
Deletes Entity.CanSpendCapacitorCharge/TrySpendCapacitorCharge (and the
now-dead _capacitors bookkeeping list that only fed them) -- Cut 3's
named, temporary exception for the four instant draws. InstantWeapon
(both fire sites), Sensor.Ping, and Shield.CanTakeHit/TakeHit now spend
from their own InputCapacitor, filled continuously by PowerBus like
every other IPowerConsumer instead of touching the entity's shared bus
capacitors directly.

InputCapacitor's Capacity/Rate derive from the owning item's Energy and
Cooldown, with an authored-override hook (ChargedWeapon repurposes its
previously-unused ChargeEnergy stat as that override, per the map's own
instruction, rather than adding a new field). A weapon/sensor fire
attempt only ever spends exactly Capacity, so it only ever succeeds at
full charge -- no fractional shot. Shield is the map's named exception:
its reserve is continuous, not an activation buffer, so it allows a
partial draw; its size (no Energy/Cooldown pair exists on Shield) is a
flagged judgment call, not a spec'd formula.

Adds InputCapacitorTests.cs (8 tests) and
mutation_tests_stats_power_cut4.py (7 mutations, all behave as
declared); removes the one PowerBusTests.cs test and Cut 3 mutation
case that exercised the now-deleted Entity methods.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 22:52:15 +02:00
Meta Vens
fc80c8944b Add the meta Unity generated for PowerBus
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:43:08 +02:00
Meta Vens
2e62f576d3 Merge the power bus: one grant per entity, no more free overdraw
Cut 3 of docs/stats-and-power-cut.md. TryConsumeEnergy and the reactor's
own capacitor plumbing are gone; PowerBus owns the grant, steps once per
tick before equipment executes, and rations every consumer by the same
fraction when supply is short. Tiers are Cut 5; the four instant-draw
sites still spend capacitor charge directly until Cut 4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:41:56 +02:00
Meta Vens
f1fd64ac60 Cut 3: PowerBus replaces TryConsumeEnergy/CanConsumeEnergy
Deletes Entity.CanConsumeEnergy/TryConsumeEnergy and Reactor's own capacitor
draining/filling (the demand-mechanism halves of Reactor.cs:90-141); adds
PowerBus (one per Entity, stepped once per tick before equipment executes),
IPowerConsumer on the five continuous draw sites (EnergyDraw, Thruster,
AetherDrive, Radiator, ConstantWeapon), and EquippedItem.PowerSupply as the
bus's grant ratio. Reactor keeps only its heat/throttle arithmetic, now driven
by PowerBus.NetDraw instead of an accumulator any behaviour could add into.

The four instant draws (InstantWeapon's burst/shot, Sensor's ping, Shield's hit
taken) are out of scope for the bus this cut per the map; they spend capacitor
charge directly and atomically via the new Entity.TrySpendCapacitorCharge/
CanSpendCapacitorCharge, replacing TryConsumeEnergy's old partial-drain-then-
refuse bug for that path too. Named, temporary exception closed by Cut 4.

docs/stats-and-power-cut.md Cut 3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:39:38 +02:00
Meta Vens
fb6062b8c6 Shield panel: gate reuse and Hit on the panel's own radius
The operator's play report on FieldShieldTest ("weak hits are very
janky, clicking outside the hex still makes it tremble and shatter,
pooling seems very rough") traced to two provable defects, not one
tuning constant:

- ShieldPanel.Hit had no bounds check at all. A point handed to it was
  always enqueued and injected regardless of how far outside the
  panel's own panelRadius it was.
- ShieldInterceptor.FindReusable decided reuse from a raw world-space
  chord distance to the panel's stale spawn-time Position, using
  PanelRadius*ReuseFraction (authored up to 2x) as the threshold. On a
  non-uniformly scaled/curved envelope a chord across curvature is not
  the panel's own in-plane extent, so a click clearly outside the
  rendered tiling could still measure inside threshold and get routed
  to Hit() -- which had nothing to reject it.
- Reusing a panel never refreshed its pooled DieAt, so a panel struck
  again could still expire and get returned to the pool mid-fracture
  ("pooling seems very rough").

Fix: ShieldPanel.ContainsWorldPoint is now the one owner of "is this
point within my own radius" (panel-local in-plane distance vs.
panelRadius), used both as Hit's hard gate and as FindReusable's
candidacy test (with ReuseFraction, now capped at 1, narrowing but
never widening past the physical radius). Reuse now also extends
DieAt from the moment of the new hit.

Pinned in ShieldPanelCut3Verify.CheckHitOutsideRadiusDoesNotReachPanel:
a direct Hit() and a routed Absorb() outside a panel's own radius must
enqueue nothing and leave its state buffer untouched, and a genuinely
outside click opens its own panel. Deterministic (checks the pending
queue and no-op state, not temper drift) because breakBudgetFraction
paces fracture over many frames on purpose, so temper keeps drifting
from an earlier hit alone -- a drift-based check would have been
measuring that, not this rule (caught this against the check's own
first run).

All four ShieldPanelCut<N>Verify probes pass (batchmode, real GPU
device, no -nographics).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 21:02:18 +02:00
Meta Vens
bfdde9c33d Merge the stat resolver: one per entity, no per-entity state on catalog objects
Cut 2 of docs/stats-and-power-cut.md, with Soul's gates closed: the
resolver forgets an owner on unequip and consumable expiry (F1), and
Initialize owns the modifier detach/reattach so a refit no longer
silently loses a modifier (F2).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:43:25 +02:00
Meta Vens
799c21913d Cut 5 follow-up: strengthen the echo so weak-hit tension actually clears zero
Cut 5's own probe passed while breaking Cut 3's reuse rule: with R7 holding
the rim, the through-thickness echo (KEcho/_EchoReflect) is the only
remaining source of sub-critical tension for a weak hit, and its magnitude
(-0.65) was weaker than the still-live residual compression velocity left
by the direct KInject kick by the time the echo fired. The echo's own
header comment says a free-surface reflection inverts with unit
magnitude, matching the pre-R7 rim's Dirichlet condition -- -0.65 was a
lossy fraction that could reduce but never flip the sign of u, so a weak
hit's u never crossed positive and KFracture's `u <= 0` guard skipped the
sub-critical erosion branch forever, no matter how many hits landed.

Raised echoReflect from -0.65 to -0.9 (ShieldPanel.cs) -- enough margin to
flip a weak hit's residual compression into net tension without needing a
delay/seeding change; echoDelaySteps and KInject's seeding were not the
defect. All four probes now pass, including Cut 3's reuse rule (temper
0.4180 -> 0.3997 on a reused panel).

Also lands the multi-hit-reuse rule Cut 5's own report flagged as unpinned:
CheckRepeatedWeakHitsBreakWhereOneDoesNot in ShieldPanelCut5Verify.cs.
Energy 15 (not 8, whose peak tension of ~0.14 sits under tensileStrength
0.2 and can never break at any repetition) breaks on hit 2 of a live,
reused panel while a cold single hit -- given equal idle time (720 steps,
matching the multi-hit run's total budget, to rule out "just needed more
time to ring out") -- never breaks. This is the Cut 3 reuse rule and the
temper mechanism producing the operator-facing payoff together.

Verified: ShieldPanelCut1Verify, Cut2Verify, Cut3Verify, Cut5Verify all
PASS via batchmode (graphics device required, not -nographics).

Operator watch: echoReflect at -0.9 is close to the physical "unit
inversion" ceiling implied by the header comment; if later tuning raises
hit energies or lowers damping, watch for the echo overshooting into an
immediate break on a single moderate hit (observed at -1.4 and even -1.0
in earlier tuning passes) rather than the intended multi-hit erosion.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:22:51 +02:00
Meta Vens
bdb45f6521 Cut 5: hold the rim, clamp v, fix fracture's clock, tune to spec
R7 (operator ruling): the panel's emitters hold its edge, so the rim is no
longer a free surface. Deletes the openW ghost term end to end -- its only
consumer in ShieldSim.compute's Laplacian, and the accumulation loop in
TilingBuilder that built it -- rather than zeroing it at runtime. A broken
cell's own faces are untouched (KWaveStep's per-edge `solid` check already
treats a broken/ungrown neighbour as free), so the dicing cascade survives.

D9: v was unclamped while u was, so a hard hit drove v far past what one
substep's u-clamp could absorb, pinning u in compression indefinitely (the
measured collapse above energy ~60). Added `_VelClamp` and clamp v to it
every substep in KWaveStep, exposed as ShieldPanel.velocityClamp (100).

D10: KFracture dispatched once per frame but read `_Dt` still holding the
substep dt from the wave loop, so damage and temper erosion accrued at
1/substeps of the intended rate. Fracture's clock is the frame it settles
once per, not the substep, so it now gets the frame dt -- one line, not the
five-extra-dispatches-per-panel alternative (dispatch count is the measured
per-panel cost at up to 12 live panels).

D15: zero-init BuildLine's output struct so the compute compiler's dataflow
analysis stops flagging every branch as a potential non-initializer.

Tuning (ShieldPanel.cs Material header): tensileStrength 0.9->0.2,
temperErosion 2.2->12, damageGain 6->100, breakAt 0.75->0.08,
storedEnergyGain 0.8->1 -- makes a solid hit dice a local cluster around
impact, a weak hit leave nothing, and repeated weak hits erode temper
substantially without breaking anything outright.

Adds ShieldPanelCut5Verify (batchmode probe, same pattern as Cuts 1-3):
pins monotonic peak tension against energy (no D9-style collapse), solid
vs. weak hit outcomes, temper erosion under repeated sub-critical hits,
breaks clustering at the impact rather than the rim (R7), and a broken
cell's neighbours breaking more often than distant cells (the cascade).
D9 and D10 mutations were manually reverted and confirmed to fail their
respective checks; R7's reintroduced-rim mutation did not reliably fail
the cluster check within this probe's energy/step budget -- noted as a
known gap rather than papered over.

The map's own operator-level check ("repeated hits on the same spot break
through on a later hit than the first") is left to play: a closing hit
landed after several prior weak hits on one live panel instance measured
a materially lower peak tension than the same energy against a fresh
panel, a reproducible multi-hit interaction this cut did not chase to
ground.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 20:04:05 +02:00
Meta Vens
9b85211f59 Merge the CultCache cutover and item provenance
codex/cultcache-cutover (modern CultCache from CultLib, lifecycle stores,
CultMath) and codex/item-provenance (lot provenance ledger, neutral
wanderers and IFF stance, capability presentation seam, settings and
content maps) stacked on it. Operator play smoke passed 2026-09-17: new
game, combat and grudges, stance toggle, loot, save and continue with lot
brand and quality intact, death clears the run across relaunch,
FieldShieldTest behaviour (materials broken by the dead Substance plugin,
not by this work).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 18:01:59 +02:00
Meta Vens
263ac421fb REC-095: delete confirmed-dead narrative test fixtures and zero-byte scratch file
Deletes only the two candidate groups that survived independent re-verification
and had zero collision with the live codex/aetheria-state-rebuild branch:

- GameData/Narrative/HeroOrZero.json, GameData/Narrative/Locations/TestA.json,
  GameData/Narrative/Quests/TestQuest.json: StoryProcessor.cs only ever calls
  DirectoryInfo.EnumerateFiles("*.ink"/"*ink") against these directories; no
  .cs, .csproj Content/None glob, or other file in the tree references these
  basenames. Confirmed via rg across the whole tree and voidbot search_sources
  (no hits either way).

- Vault/Aetheria/scratch.md: zero-byte Obsidian vault scratch file, no
  references anywhere in the tree, no voidbot search_sources hits.

Kill-attempts that came up empty (recorded for the record, not evidence of
absence beyond what's stated):
- rg for basenames HeroOrZero.json/TestA.json/TestQuest.json/scratch.md
  across the whole tree excluding Library/Temp/obj/bin/.git: no hits.
- Economy.Server.csproj and Economy.Shared.csproj inspected for wildcard
  Content/None includes that might implicitly sweep in the JSON files: none
  found (Economy.Shared only globs ServerShared/**/*.cs as Compile).
- mcp__voidbot__search_sources queried for both candidate groups: no
  consumer hits, only unrelated fuzzy matches.

NOT deleted here despite being in REC-095's candidate list (see coordinator
report for full detail): StrategyGameManager.csbak, CultClient.cs,
CultCache.cs backing-store classes, Economy.Server/appsettings.json, and
Economy.Shared/bin+obj all collide with commits already on
origin/codex/aetheria-state-rebuild (which has independently already deleted
or heavily rewritten those exact paths) and are therefore BLOCKED per the
no-touch-live-branch-paths rule, not executed from this worktree.

REC-095.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 14:02:49 +02:00
1342 changed files with 151675 additions and 32135 deletions

3
.gitattributes vendored
View file

@ -54,6 +54,9 @@
*.sbsar filter=lfs diff=lfs merge=lfs -text
*.msgpack filter=lfs diff=lfs merge=lfs -text
GameData/*.cc filter=lfs diff=lfs merge=lfs -text
GameData/Mods/**/*.cc filter=lfs diff=lfs merge=lfs -text
GameData/Mods/**/*.glb filter=lfs diff=lfs merge=lfs -text
tools/blender/tests/fixtures/*.glb filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
*AkSoundEngine filter=lfs diff=lfs merge=lfs -text
*AkWaapiClient filter=lfs diff=lfs merge=lfs -text

6
.gitignore vendored
View file

@ -66,6 +66,7 @@ GameData/*.lock
/Aetheria.Shared/obj/
/tools/**/bin/
/tools/**/obj/
/ModTools/
/tests/**/bin/
/tests/**/obj/
@ -93,7 +94,7 @@ crashlytics-build.properties
Packages/packages-lock.json
GameData/run.cc
GameData/player.cc
Vault/Aetheria/.obsidian/plugins/copilot/data.json
GameData/RemovedMods/
# Agent scratch, sandboxed toolchain caches, and throwaway checkouts. These had
# grown to 47 untracked entries; the worktree must stay legible, so they never
@ -109,3 +110,6 @@ tests/_scratch_*
.nuget-sandbox/
.dotnet-sandbox/
.appdata-sandbox/
# Stryker.NET mutation reports (regenerated per run)
StrykerOutput/

2
.lfsconfig Normal file
View file

@ -0,0 +1,2 @@
[lfs]
url = https://eureka.gamecult.org/forge/GameCult/Aetheria.git/info/lfs

Binary file not shown.

View file

@ -24,7 +24,11 @@
<Compile Include="$(Assets)Plugins\Ink\**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CultLibRoot)\packages\cultmath\src\CultMath\CultMath.csproj" />
<!-- Tests record reveals through Entity.RecordReveal, the book's one writer -->
<InternalsVisibleTo Include="Aetheria.Shared.Tests" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CultMathRoot)\packages\cultmath\src\CultMath\CultMath.csproj" />
<ProjectReference Include="$(CultLibRoot)\src\GameCult.Caching\GameCult.Caching.csproj" />
<ProjectReference Include="$(CultLibRoot)\src\GameCult.Caching.MessagePack\GameCult.Caching.MessagePack.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

BIN
Asset Sources/PBR Materials.blend (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,10 @@
# This is an Asset Catalog Definition file for Blender.
#
# Empty lines and lines starting with `#` will be ignored.
# The first non-ignored line should be the version indicator.
# Other lines are of the format "UUID:catalog/path/for/assets:simple catalog name"
VERSION 1
2c70f9d2-3a69-4004-8f42-4712b3e6c439:Aetheria:Aetheria
a71be0dc-105e-4c66-8ff3-acb25522e9cd:Aetheria/PBR:Aetheria-PBR

View file

@ -0,0 +1,150 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3437702659452284539
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3879893384158149147}
- component: {fileID: 8643339631069775210}
- component: {fileID: 7703217095432408775}
- component: {fileID: 7283754118921506074}
m_Layer: 0
m_Name: Mine
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3879893384158149147
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3437702659452284539}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8643339631069775210
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3437702659452284539}
m_Mesh: {fileID: -5495902117074765545, guid: dab8e1a18a1b825458e8e6356cf00cd2, type: 3}
--- !u!23 &7703217095432408775
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3437702659452284539}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 38f8ba6b169127249b6532be2b3926ee, type: 2}
- {fileID: 2100000, guid: 71e1f3613633dfa488fff097aaf97660, type: 2}
- {fileID: 2100000, guid: e879c37f3520bf14a8a6075581faf7b2, type: 2}
- {fileID: 2100000, guid: 33a2546b27ff92d4fb43d5a76a9693c0, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_MaskInteraction: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &7283754118921506074
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3437702659452284539}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 35c62f5e26769f645b1a1614a70422e1, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::MineInstance
MeshRenderer: {fileID: 7703217095432408775}
EmissionSubmesh: 2
EmissionCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0.051179443
outSlope: 0.051179443
tangentMode: 0
weightedMode: 3
inWeight: 0
outWeight: 0.24423963
- serializedVersion: 3
time: 0.5
value: 0.1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 3
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 1
inSlope: 0
outSlope: 0
tangentMode: 0
weightedMode: 3
inWeight: 0.22580647
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
ActiveCycleDuration: 1
ArmedCycleDuration: 0.25
ActiveEmission: 100
ArmedEmission: 1000
RotationSpeed: 1
HitEffect: {fileID: 1121192042590650, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
HitEffectScale: 10

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1f1bfa2175a13b647888e2949e0cb138
guid: b04728b2b65e057429eb6e8529299c8a
PrefabImporter:
externalObjects: {}
userData:

View file

@ -0,0 +1,51 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4001
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4002}
- component: {fileID: 4003}
m_Layer: 0
m_Name: ShipModTemplate
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4002
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4001}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4003
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4001}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c3e9a52d8b14f0e8a6d2b1f4c95e703, type: 3}
m_Name:
m_EditorClassIdentifier:
Shield: {fileID: 8402070500206635106, guid: 897fa55d98f1f7f40b889f93ce9146f4, type: 3}
TractorBeam: {fileID: 2009124798951080406, guid: 1df59848be1db8547bc662080d0d6000, type: 3}
Ping: {fileID: 3496685214803260731, guid: bfcaa66e173f6a44cb640aabbcb5e429, type: 3}
DestroyEffect: {fileID: 1121192042590650, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
Invisible: {fileID: 2100000, guid: c94a225de88e5ce42af01c34df3521e6, type: 2}
MapIcon: {fileID: 2100000, guid: 64d1c3f8a4422884b88363be07521fb0, type: 2}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 151cf0ff54a22274caf671ece149fa6e
guid: 5d1f3a8c7e2b4f60a9c4b7e1d3f2a860
PrefabImporter:
externalObjects: {}
userData:

View file

@ -81,87 +81,6 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &7783244517717541194
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7783244517717541195}
- component: {fileID: 7783244517717541175}
- component: {fileID: 7783244517717541174}
m_Layer: 9
m_Name: Gravity Well
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7783244517717541195
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7783244517717541194}
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 7783244518521719148}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
--- !u!33 &7783244517717541175
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7783244517717541194}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &7783244517717541174
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7783244517717541194}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 2100000, guid: 44a8bbb89acb4e34c9f41a9da5842bb4, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!1 &7783244518317531027
GameObject:
m_ObjectHideFlags: 0
@ -289,7 +208,6 @@ Transform:
m_Children:
- {fileID: 589192530128514016}
- {fileID: 7783244518317531036}
- {fileID: 7783244517717541195}
- {fileID: 7783244516809707565}
m_Father: {fileID: 0}
m_RootOrder: 0
@ -307,7 +225,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
Body: {fileID: 7783244518317531038}
GravityWell: {fileID: 7783244517717541174}
Icon: {fileID: 7783244516809707566}
Generator: {fileID: 741236912059895623}
--- !u!114 &741236912059895623

File diff suppressed because it is too large Load diff

View file

@ -4818,6 +4818,3 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
ParticleSystem: {fileID: 5087162364086924483}
Radius: 25
Traction: 25
Distance: 75

View file

@ -1,336 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &756302067359749329
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3605572244125604411}
- component: {fileID: 5473211974529592485}
- component: {fileID: 4535912766998605946}
- component: {fileID: 2069293240452108309}
- component: {fileID: 951258163572815990}
- component: {fileID: 6357237398779034136}
m_Layer: 21
m_Name: Mine
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3605572244125604411
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 466182245789483358}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &5473211974529592485
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_Mesh: {fileID: -5495902117074765545, guid: dab8e1a18a1b825458e8e6356cf00cd2, type: 3}
--- !u!23 &4535912766998605946
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 3720744386649352057, guid: 504c7bfe0d50ff64a88b8eac2ceb46f8, type: 3}
- {fileID: 3720744386649352057, guid: a1d39ea984432bf44b4a0686afe2bf1a, type: 3}
- {fileID: 2100000, guid: e879c37f3520bf14a8a6075581faf7b2, type: 2}
- {fileID: 9178725544925813344, guid: 58e16b7dbc1c31f4585e11544cdce127, type: 3}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &2069293240452108309
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1281fe44325f9b548aa42dc331b17266, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &951258163572815990
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f190191fe8c8419f85767868c50cde5f, type: 3}
m_Name:
m_EditorClassIdentifier:
GridObject: {fileID: 6357237398779034136}
MeshRenderer: {fileID: 4535912766998605946}
EmissionSubmesh: 2
EmissionCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: 0.051179443
outSlope: 0.051179443
tangentMode: 0
weightedMode: 0
inWeight: 0
outWeight: 0.24423963
- serializedVersion: 3
time: 0.5
value: 0.1
inSlope: 0
outSlope: 0
tangentMode: 34
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 1
inSlope: -0
outSlope: -0
tangentMode: 0
weightedMode: 0
inWeight: 0.22580647
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
ActiveCycleDuration: 1
ArmedCycleDuration: 0.25
ActiveEmission: 100
ArmedEmission: 1000
HitEffect: {fileID: 3349939966709198091}
Lifetime: 30
ActivationDelay: 2
BlastRange: 25
BlastDelay: 2
--- !u!114 &6357237398779034136
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 756302067359749329}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 737f47c158214f0995ba2835f040ed96, type: 3}
m_Name:
m_EditorClassIdentifier:
RotationSpeed: 1
GridOffset: 0
GridAttraction: 10
Gravity: 1
Drag: 0.05
LaunchDrag: 0.2
--- !u!1 &951357816492268516
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 466182245789483358}
- component: {fileID: 2749986269966238105}
m_Layer: 0
m_Name: Mine Launcher
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &466182245789483358
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 951357816492268516}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3865250807623958572}
- {fileID: 3605572244125604411}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2749986269966238105
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 951357816492268516}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6e048d9c74a84343befd496907ee2126, type: 3}
m_Name:
m_EditorClassIdentifier:
ProjectilePrototype: {fileID: 2069293240452108309}
InheritVelocity: 1
--- !u!1001 &3867385469207619610
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 466182245789483358}
m_Modifications:
- target: {fileID: 1121192042590650, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_Name
value: BigExplosion
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_RootOrder
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalScale.x
value: 10
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalScale.y
value: 10
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalScale.z
value: 10
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 198917022394846920, guid: e1b08032bec16ba4eb1ae23cbd572664,
type: 3}
propertyPath: stopAction
value: 3
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: e1b08032bec16ba4eb1ae23cbd572664, type: 3}
--- !u!4 &3865250807623958572 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 4388947112716342, guid: e1b08032bec16ba4eb1ae23cbd572664,
type: 3}
m_PrefabInstance: {fileID: 3867385469207619610}
m_PrefabAsset: {fileID: 0}
--- !u!1 &3866425147859458464 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 1121192042590650, guid: e1b08032bec16ba4eb1ae23cbd572664,
type: 3}
m_PrefabInstance: {fileID: 3867385469207619610}
m_PrefabAsset: {fileID: 0}
--- !u!114 &3349939966709198091
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3866425147859458464}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1281fe44325f9b548aa42dc331b17266, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &5700147869379115258
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3866425147859458464}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: db021a309de3d324588c5603de40c29f, type: 3}
m_Name:
m_EditorClassIdentifier:

View file

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 24eddacc819f20542962f2395930f261
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,116 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Build.Reporting;
using Debug = UnityEngine.Debug;
// The one way to make a player directory, for Windows or Linux. Owns what the directory contains: the player and its data,
// GameData/Aetheria.cc, GameData/Narrative/**, GameData/Mods/** and ModTools/AetherDb. Manual builds, smokes and
// release cuts all call this and stage nothing themselves.
//
// Unity -batchmode -quit -projectPath <repo> -executeMethod AetheriaBuild.Build
// -aetheriaVersion <semver> -aetheriaOut <dir> [-aetheriaTarget win64|linux64] -logFile <log>
//
// AetherDb is published from tools/AetherDb, so the headless build's CULTLIB_ROOT / CULTMATH_ROOT (Directory.Build.props)
// must be set for dotnet when the defaults do not hold the pinned revisions.
// Any failure logs "AetheriaBuild FAILED at <step>" and exits 1.
public static class AetheriaBuild
{
private static readonly Regex SemVer = new Regex(@"^\d+\.\d+\.\d+([-+][0-9A-Za-z.-]+)?$");
// A target: the player Unity builds, its executable, and the runtime AetherDb is published for.
private static (BuildTarget target, string player, string runtime, string aetherDb) Target(string name) => name switch
{
"win64" => (BuildTarget.StandaloneWindows64, "Aetheria.exe", "win-x64", "AetherDb.exe"),
"linux64" => (BuildTarget.StandaloneLinux64, "Aetheria.x86_64", "linux-x64", "AetherDb"),
_ => throw new InvalidOperationException($"-aetheriaTarget {name}: expected win64 or linux64"),
};
public static void Build()
{
var step = "arguments";
try
{
var version = Argument("-aetheriaVersion");
if (!SemVer.IsMatch(version)) throw new InvalidOperationException("-aetheriaVersion is not a semver");
var output = Path.GetFullPath(Argument("-aetheriaOut"));
var target = Target(Argument("-aetheriaTarget", "win64"));
var repoRoot = Directory.GetParent(UnityEngine.Application.dataPath).FullName;
step = "version";
UnityEditor.PlayerSettings.bundleVersion = version; // the game has its own global PlayerSettings
step = "addressables";
AddressableAssetSettings.BuildPlayerContent(out var content);
if (!string.IsNullOrEmpty(content.Error)) throw new InvalidOperationException("Addressables build reported an error: " + content.Error);
step = "player";
Directory.CreateDirectory(output);
var scenes = EditorBuildSettings.scenes.Where(scene => scene.enabled).Select(scene => scene.path).ToArray();
if (scenes.Length == 0) throw new InvalidOperationException("EditorBuildSettings has no enabled scene");
var report = BuildPipeline.BuildPlayer(new BuildPlayerOptions
{
scenes = scenes,
locationPathName = Path.Combine(output, target.player),
target = target.target,
options = BuildOptions.None,
});
if (report.summary.result != BuildResult.Succeeded || report.summary.totalErrors != 0)
throw new InvalidOperationException($"BuildPlayer ended {report.summary.result} with {report.summary.totalErrors} errors");
step = "gamedata";
PlayerStaging.Stage(repoRoot, output);
step = "aetherdb";
Publish(repoRoot, Path.Combine(output, "ModTools"), target.runtime, target.aetherDb);
step = "burst";
var burst = Path.Combine(output, "Aetheria_BurstDebugInformation_DoNotShip");
if (Directory.Exists(burst)) Directory.Delete(burst, true);
Debug.Log($"AetheriaBuild OK {version} {output}");
}
catch (Exception error)
{
Debug.LogError($"AetheriaBuild FAILED at {step}: {error.GetType().Name}: {error.Message}");
EditorApplication.Exit(1);
return;
}
EditorApplication.Exit(0);
}
private static void Publish(string repoRoot, string modTools, string runtime, string aetherDb)
{
var info = new ProcessStartInfo("dotnet")
{
Arguments = $"publish tools/AetherDb -c Release -r {runtime} --self-contained -p:PublishSingleFile=true -o \"{modTools}\"",
WorkingDirectory = repoRoot,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
};
using (var process = Process.Start(info))
{
var errors = process.StandardError.ReadToEndAsync();
var text = process.StandardOutput.ReadToEnd();
process.WaitForExit();
if (process.ExitCode != 0)
throw new InvalidOperationException($"dotnet publish exited {process.ExitCode}:\n{text}\n{errors.Result}");
}
if (!File.Exists(Path.Combine(modTools, aetherDb)))
throw new InvalidOperationException($"dotnet publish produced no ModTools/{aetherDb}");
}
private static string Argument(string name, string fallback = null)
{
var args = Environment.GetCommandLineArgs();
var at = Array.IndexOf(args, name);
if (at < 0 || at + 1 >= args.Length)
return fallback ?? throw new InvalidOperationException(name + " is required");
return args[at + 1];
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d38caad223051494ba36c734ce79950d

View file

@ -0,0 +1,41 @@
using System;
using System.IO;
// What a player directory holds beside the executable's data: GameData/Aetheria.cc, GameData/Narrative/** and, when
// the repo has one, GameData/Mods/**. Nothing else under GameData ships (run.cc and player.cc are the player's own).
// Unity-free so the headless suite can prove the rules; AetheriaBuild is the only caller.
internal static class PlayerStaging
{
public const string Catalog = "Aetheria.cc";
public const string Narrative = "Narrative";
public const string Mods = "Mods";
// Replaces <playerDir>/GameData with a copy of the three shipped entries of <repoRoot>/GameData.
// Throws InvalidOperationException naming the entry when the catalog or Narrative is absent.
public static void Stage(string repoRoot, string playerDir)
{
var source = Path.Combine(repoRoot, "GameData");
var destination = Path.Combine(playerDir, "GameData");
var catalog = Path.Combine(source, Catalog);
var narrative = Path.Combine(source, Narrative);
var mods = Path.Combine(source, Mods);
if (!File.Exists(catalog)) throw new InvalidOperationException($"GameData/{Catalog} is missing; a player never ships without its catalog.");
if (!Directory.Exists(narrative)) throw new InvalidOperationException($"GameData/{Narrative} is missing.");
if (Directory.Exists(destination)) Directory.Delete(destination, true);
Directory.CreateDirectory(destination);
File.Copy(catalog, Path.Combine(destination, Catalog));
CopyTree(narrative, Path.Combine(destination, Narrative));
if (Directory.Exists(mods)) CopyTree(mods, Path.Combine(destination, Mods));
}
private static void CopyTree(string from, string to)
{
Directory.CreateDirectory(to);
foreach (var directory in Directory.GetDirectories(from, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(Path.Combine(to, directory.Substring(from.Length + 1)));
foreach (var file in Directory.GetFiles(from, "*", SearchOption.AllDirectories))
File.Copy(file, Path.Combine(to, file.Substring(from.Length + 1)));
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 16dce8087f9149b44b6e294cb0851dd8

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 4a109a0b0bb6e8f40935ca2ec55e5bd7
guid: 5e0ef88f85924e146855ca7bb57bbdb6
folderAsset: yes
DefaultImporter:
externalObjects: {}

BIN
Assets/Fonts/Emoji/Emoji.asset (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4cbb1005dc560d54ba85c3d091dbe30b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,410 @@
Twemoji v17.0.3: https://github.com/jdecked/twemoji/archive/refs/tags/v17.0.3.tar.gz
Copyright (c) 2022–present Jason Sofonia & Justine De Caires
Copyright (c) 2014–2021 Twitter
Graphics licensed under CC-BY 4.0: <https://creativecommons.org/licenses/by/4.0/>
Change notice (CC BY 4.0 section 3(a)(1)(B)): the SVG graphics are converted to a COLRv0 colour
font (Twemoji.ttf) by tools/emoji/fetch_emoji_font.py using nanoemoji. No artwork is edited.
Attribution Requirements (upstream README)
As an open source project, attribution is critical from a legal, practical and motivational perspective in our opinion. The graphics are licensed under the CC-BY 4.0 which has a pretty good guide on [best practices for attribution](https://wiki.creativecommons.org/Best_practices_for_attribution).
However, we consider the guide a bit onerous and as a project, will accept a mention in a project README or an 'About' section or footer on a website. In mobile applications, a common place would be in the Settings/About section (for example, see the mobile Twitter application Settings->About->Legal section). We would consider a mention in the HTML/JS source sufficient also.
LICENSE-GRAPHICS (upstream, verbatim)
=======================================================================
Attribution 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution 4.0 International Public License ("Public License"). To the
extent this Public License may be interpreted as a contract, You are
granted the Licensed Rights in consideration of Your acceptance of
these terms and conditions, and the Licensor grants You such rights in
consideration of benefits the Licensor receives from making the
Licensed Material available under these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
d. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
e. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
f. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
g. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
h. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
i. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
j. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
k. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
4. If You Share Adapted Material You produce, the Adapter's
License You apply must not prevent recipients of the Adapted
Material from complying with this Public License.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material; and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public licenses.
Notwithstanding, Creative Commons may elect to apply one of its public
licenses to material it publishes and in those instances will be
considered the "Licensor." Except for the limited purpose of indicating
that material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the public
licenses.
Creative Commons may be contacted at creativecommons.org.

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1e43b383bf860524986a6947496776d0
guid: db23d2e6bc295794888af02d32cbae60
TextScriptImporter:
externalObjects: {}
userData:

BIN
Assets/Fonts/Emoji/Twemoji.ttf (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: bde541f3fd3b82b4aa6aa068e4a205a7
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Aetheria Emoji
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,25 @@
source_url=https://github.com/jdecked/twemoji/archive/refs/tags/v17.0.3.tar.gz
source_version=v17.0.3
source_sha256=a0855654b633045ae2337537e77f1bb4361162f7fcd910e613eaab1d6d9c5fca
emoji_test_version=17.0
emoji_test_url=https://unicode.org/Public/17.0.0/emoji/emoji-test.txt
emoji_test_sha256=1d8a944f88d7952f7ef7c5167fef3c67995bcae24543949710231b03a201acda
svg_count=4009
single_codepoint_count=1400
unsupported_count=0
sequence_count=2760
tool_nanoemoji=0.16.0
tool_fonttools=4.66.1
tool_picosvg=0.23.0
tool_ninja=1.13.2
source_date_epoch=1780352497
color_format=glyf_colr_0
python_version=3.13.15
platform=linux
container_image=python:3.13-slim
fe0f_less_twins=15
font_file=Twemoji.ttf
font_sha256=283b775ce3715a84065212985ebbdecb8fa0c457b7ccf2c9c15c99b5a83ef702
singles_sha256=7ad887a16ef5386df040e1e8988e9bdc55ae5cab461ffc9df4613d0cb5770b4e
unsupported_sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
sequences_sha256=18529154b14f75f54db5dedd72910de35af9ca05aef284b7d121be249b3c3bb2

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6290b5397f6ae1d47a19c6886ebd87e2
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -7,8 +7,8 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Gravity Well
m_Shader: {fileID: 4800000, guid: 268da230635cfb34ab4ed6ad39503fa0, type: 3}
m_Name: Gravity Field
m_Shader: {fileID: 4800000, guid: 08d8efa80af84065b54c9bfed784e435, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
@ -57,8 +57,6 @@ Material:
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 1
- _Depth: 80
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
@ -68,7 +66,6 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Power: 16
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

View file

@ -8,7 +8,7 @@ Material:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Sector Tint
m_Shader: {fileID: 4800000, guid: 268da230635cfb34ab4ed6ad39503fa0, type: 3}
m_Shader: {fileID: 4800000, guid: 782740c1a3d7455ea75dc87fafdc8432, type: 3}
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
@ -59,8 +59,8 @@ Material:
m_Ints: []
m_Floats:
- _BumpScale: 1
- _Cutoff: 1
- _Depth: 0.025
- _EdgeBrightness: 0.12
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Frequency: 6.2832
@ -72,7 +72,6 @@ Material:
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Phase: 0
- _Power: 2
- _SinePower: 1.25
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1

View file

@ -1,82 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Wormhole Gravity
m_Shader: {fileID: 4800000, guid: 268da230635cfb34ab4ed6ad39503fa0, type: 3}
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.15
- _Depth: 2000
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Power: 64
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ef2f6090d5cc14a4e9ce38def3bed9ac
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,73 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Fog Marching 1
m_Shader: {fileID: 4800000, guid: 7a890b6ceccf53c44bfc54b18b5daa58, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _Displacement:
m_Texture: {fileID: 8400000, guid: 06ec5ef8a5830fc44b1ac1a6e123add5, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Patch:
m_Texture: {fileID: 8400000, guid: c618a6b20b3c7394590c59a9fa467e86, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Surface:
m_Texture: {fileID: 8400000, guid: 2fc21a9d3e9647948b56e384cd9378b3, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TintTexture:
m_Texture: {fileID: 8400000, guid: d196505464047f04a97f28689041209b, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaFloor: 0.01
- _DepthBlend: 512
- _DepthCeiling: 4096
- _FlowSpeed: 2
- _Gamma: 0.5
- _GridCeilingBlend: -300
- _GridCeilingDensity: 0.01
- _GridCeilingFollow: 0
- _GridCeilingOffset: 0
- _GridFillDensity: 0.001
- _GridFloorBlend: 100
- _GridFloorDensity: 2
- _GridFloorOffset: 20
- _GridPatchBlend: 50
- _GridPatchDensity: 2
- _NoiseExponent: 2.25
- _NoiseFrequency: 0.015
- _NoiseSpeed: 0
- _NoiseStrength: 500
- _SafetyDistance: 20
- _Scattering: 0
- _ScatteringDensityExponent: 0.5
- _ScatteringDistExponent: 0.5
- _ScatteringMinDist: 500
- _StepExponent: 2
- _TintExponent: 0.1
- _TurbulenceAmplitude: 100
- _TurbulenceScale: 100
m_Colors:
- _Tint: {r: 0.0627451, g: 0.0627451, b: 0.0627451, a: 1}
m_BuildTextureStacks: []

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: a72896cb7097bfa46a1a8f4092e47c72
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,99 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Fog Marching Main Menu
m_Shader: {fileID: 4800000, guid: 7a890b6ceccf53c44bfc54b18b5daa58, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _Displacement:
m_Texture: {fileID: 8400000, guid: 06ec5ef8a5830fc44b1ac1a6e123add5, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaPatch:
m_Texture: {fileID: 8400000, guid: c618a6b20b3c7394590c59a9fa467e86, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaPatchHeight:
m_Texture: {fileID: 8400000, guid: 06ec5ef8a5830fc44b1ac1a6e123add5, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaSurfaceHeight:
m_Texture: {fileID: 8400000, guid: 2fc21a9d3e9647948b56e384cd9378b3, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaTint:
m_Texture: {fileID: 8400000, guid: d196505464047f04a97f28689041209b, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Patch:
m_Texture: {fileID: 8400000, guid: c618a6b20b3c7394590c59a9fa467e86, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Surface:
m_Texture: {fileID: 8400000, guid: 2fc21a9d3e9647948b56e384cd9378b3, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TintTexture:
m_Texture: {fileID: 8400000, guid: d196505464047f04a97f28689041209b, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaFloor: 0
- _DepthBlend: 512
- _DepthCeiling: 1024
- _Exposure: 100
- _FlowAmplitude: 1
- _FlowScale: 1
- _FlowScroll: 1
- _FlowSpeed: 5
- _Gamma: 0.3
- _GridCeilingBlend: -300
- _GridCeilingDensity: 0.01
- _GridCeilingFollow: 0
- _GridCeilingOffset: 0
- _GridFillDensity: 0.001
- _GridFloorBlend: 50
- _GridFloorDensity: 1
- _GridFloorOffset: 100
- _GridPatchBlend: 50
- _GridPatchDensity: 1
- _NebulaFillDensity: 0.00075
- _NebulaFloorBlend: 50
- _NebulaFloorDensity: 1
- _NebulaFloorOffset: 80
- _NebulaPatchBlend: 25
- _NebulaPatchDensity: 0.1
- _NoiseExponent: 2
- _NoiseFrequency: 0.02
- _NoiseSpeed: 0.00001
- _NoiseStrength: 200
- _SafetyDistance: 50
- _Scattering: 0
- _ScatteringDensityExponent: 8
- _ScatteringDistExponent: 0.5
- _ScatteringMinDist: 1
- _StepExponent: 2
- _TintExponent: 1.2
- _TurbulenceAmplitude: 20
- _TurbulenceScale: 30
m_Colors:
- _Tint: {r: 0.09411765, g: 0.09411765, b: 0.09411765, a: 1}
m_BuildTextureStacks: []

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: e21702a5e6e98b7409d6913663ceab7e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,65 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Fog Marching Test
m_Shader: {fileID: 4800000, guid: 7a890b6ceccf53c44bfc54b18b5daa58, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _Displacement:
m_Texture: {fileID: 8400000, guid: 06ec5ef8a5830fc44b1ac1a6e123add5, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Patch:
m_Texture: {fileID: 8400000, guid: c618a6b20b3c7394590c59a9fa467e86, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Surface:
m_Texture: {fileID: 8400000, guid: 2fc21a9d3e9647948b56e384cd9378b3, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TintTexture:
m_Texture: {fileID: 8400000, guid: d196505464047f04a97f28689041209b, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaFloor: 0
- _DepthBlend: 512
- _DepthCeiling: 4096
- _Gamma: 0.66
- _GridCeilingBlend: -300
- _GridCeilingDensity: 0.01
- _GridCeilingFollow: 0
- _GridCeilingOffset: 0
- _GridFillDensity: 0.000025
- _GridFloorBlend: 100
- _GridFloorDensity: 4
- _GridFloorOffset: 0
- _GridPatchBlend: 5
- _GridPatchDensity: 0.1
- _NoiseFrequency: 0.01
- _NoiseSpeed: 0.02
- _NoiseStrength: 50
- _SafetyDistance: 0
- _StepExponent: 2
- _TintExponent: 8
m_Colors:
- _Tint: {r: 2.0078435, g: 2.0078435, b: 2.0078435, a: 1}
m_BuildTextureStacks: []

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ad63650ae6d6cc542a5aad16694b3c46
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,99 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Fog Marching
m_Shader: {fileID: 4800000, guid: 7a890b6ceccf53c44bfc54b18b5daa58, type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _Displacement:
m_Texture: {fileID: 8400000, guid: 06ec5ef8a5830fc44b1ac1a6e123add5, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaPatch:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaPatchHeight:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaSurfaceHeight:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NebulaTint:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Patch:
m_Texture: {fileID: 8400000, guid: c618a6b20b3c7394590c59a9fa467e86, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Surface:
m_Texture: {fileID: 8400000, guid: 2fc21a9d3e9647948b56e384cd9378b3, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TintTexture:
m_Texture: {fileID: 8400000, guid: d196505464047f04a97f28689041209b, type: 2}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaFloor: 0.01
- _DepthBlend: 512
- _DepthCeiling: 4096
- _Exposure: 10
- _FlowAmplitude: 512
- _FlowScale: 1024
- _FlowScroll: 0
- _FlowSpeed: 1
- _Gamma: 0.3
- _GridCeilingBlend: -300
- _GridCeilingDensity: 0.01
- _GridCeilingFollow: 0
- _GridCeilingOffset: 0
- _GridFillDensity: 0.0005
- _GridFloorBlend: 50
- _GridFloorDensity: 1
- _GridFloorOffset: 10
- _GridPatchBlend: 150
- _GridPatchDensity: 1
- _NebulaFillDensity: 0.00075
- _NebulaFloorBlend: 150
- _NebulaFloorDensity: 1
- _NebulaFloorOffset: 0
- _NebulaPatchBlend: 51.47
- _NebulaPatchDensity: 0.25
- _NoiseExponent: 3
- _NoiseFrequency: 0.005
- _NoiseSpeed: 0
- _NoiseStrength: -400
- _SafetyDistance: 200
- _Scattering: 50
- _ScatteringDensityExponent: 1
- _ScatteringDistExponent: 1.5
- _ScatteringMinDist: 10
- _StepExponent: 2
- _TintExponent: 2
- _TurbulenceAmplitude: 20
- _TurbulenceScale: 60
m_Colors:
- _Tint: {r: 0.01, g: 0.01, b: 0.01, a: 1}
m_BuildTextureStacks: []

View file

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2ff39f5d101241043ba1dcde19d92f77
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a6e88469e3b81a541a0bc8a66e60d0c7
guid: 5b293e272c024dc999b28fe49925e1d5
folderAsset: yes
DefaultImporter:
externalObjects: {}

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0f3e518a4c9bcc2469abe6cebdcb3691
guid: 636104c9ca48436da05c3f6003fd3eae
folderAsset: yes
DefaultImporter:
externalObjects: {}

View file

@ -7,9 +7,9 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Wormhole Waves
m_Shader: {fileID: 4800000, guid: 8681ac064d59d15458d16cc9b884262c, type: 3}
m_ShaderKeywords:
m_Name: Carbon_Fibre
m_Shader: {fileID: 4800000, guid: ddff0b48b92c991499817d2a0f5d5059, type: 3}
m_ShaderKeywords: _MAINTEX _METALLICGLOSSMAP _NORMALMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
@ -20,7 +20,7 @@ Material:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 5723eb533deb4d73a2b015bb75b523b4, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
@ -39,12 +39,16 @@ Material:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadeTex:
m_Texture: {fileID: 2800000, guid: df0632a08c5f1a1498fa325c755dc459, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 32fc9d1c4304495da5350f8a8b52e14b, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 15a9bba7a82740718ad2d3913f7297af, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
@ -58,27 +62,25 @@ Material:
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _Depth: 33.9
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Frequency: 2
- _FrequencyDist: 60
- _Fade: 0
- _FadeEdge: 0.05
- _FadeSharpness: 16
- _GlossMapScale: 1
- _Glossiness: 0.5
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 0
- _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Power: 2
- _SinePower: 1.25
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _Speed: 15
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EdgeColor: {r: 3.0117648, g: 3.0117648, b: 11.984314, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 11fbaa87dcc7a3743a6bd3aa5c86e5ae
guid: 8e5a779dec614c80a12925ba063bb99f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000

BIN
Assets/Materials/PBR/Carbon_Fibre/Carbon_Fibre_Color.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 32fc9d1c4304495da5350f8a8b52e14b
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 15a9bba7a82740718ad2d3913f7297af
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Materials/PBR/Carbon_Fibre/Carbon_Fibre_NormalGL.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 5723eb533deb4d73a2b015bb75b523b4
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Materials/PBR/Carbon_Fibre/Carbon_Fibre_Roughness.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: b8e5cd91353441ebb42296a830fef845
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 5bf99a94223c6e1458c243cb68091852
guid: 22e47659e8e14482b3466711751b01b8
folderAsset: yes
DefaultImporter:
externalObjects: {}

View file

@ -7,9 +7,9 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Wormhole Gravity 1
m_Shader: {fileID: 4800000, guid: 268da230635cfb34ab4ed6ad39503fa0, type: 3}
m_ShaderKeywords:
m_Name: Gunmetal_Dark
m_Shader: {fileID: 4800000, guid: ddff0b48b92c991499817d2a0f5d5059, type: 3}
m_ShaderKeywords: _MAINTEX _METALLICGLOSSMAP _NORMALMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
@ -20,7 +20,7 @@ Material:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: dc71e34b4a1f4de7aa826d18b67b5852, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
@ -39,12 +39,16 @@ Material:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadeTex:
m_Texture: {fileID: 2800000, guid: df0632a08c5f1a1498fa325c755dc459, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 1ed06708491744fe944217d19e450157, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 31e7d642ff8a49a28390c82626c4b6b9, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
@ -57,18 +61,19 @@ Material:
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 1
- _Depth: 54
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Fade: 0
- _FadeEdge: 0.05
- _FadeSharpness: 16
- _GlossMapScale: 1
- _Glossiness: 0.5
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 0
- _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Power: 4
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
@ -76,5 +81,6 @@ Material:
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EdgeColor: {r: 3.0117648, g: 3.0117648, b: 11.984314, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 0ec0689c58b99c64297b3e429e1d9112
guid: 32199fedf9ce473191d8a734a74f3d5f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000

BIN
Assets/Materials/PBR/Gunmetal_Dark/Gunmetal_Dark_Color.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 1ed06708491744fe944217d19e450157
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 31e7d642ff8a49a28390c82626c4b6b9
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 51e45f19716b43128ce5d2aac5b5aed4
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: dc71e34b4a1f4de7aa826d18b67b5852
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 5677a8acff8f49358627841b9be8e2dd
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3e9d00e0b2454cc08632c972d2ee499b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Metal_Scratched
m_Shader: {fileID: 4800000, guid: ddff0b48b92c991499817d2a0f5d5059, type: 3}
m_ShaderKeywords: _MAINTEX _METALLICGLOSSMAP _NORMALMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 2800000, guid: 3a10044baac4438f9fc0930783eccdf7, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadeTex:
m_Texture: {fileID: 2800000, guid: df0632a08c5f1a1498fa325c755dc459, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 5a9cee903a2d48718aaf6b224126f279, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: 8b24d7ea11c341408a146fa39f59b7b0, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Fade: 0
- _FadeEdge: 0.05
- _FadeSharpness: 16
- _GlossMapScale: 1
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EdgeColor: {r: 3.0117648, g: 3.0117648, b: 11.984314, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 244f3e4c0c030a24b8d7aa944895bdcf
guid: a5874fba9e2242c79aea6b21ddb63af0
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 5a9cee903a2d48718aaf6b224126f279
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 8b24d7ea11c341408a146fa39f59b7b0
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 2eace05436f24d15944266ed3b841f21
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 3a10044baac4438f9fc0930783eccdf7
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 986a2475c1e248d7be5208d88ee17a15
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c2497e59922c471b935a06c396acb73e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Paint_Clean_Light
m_Shader: {fileID: 4800000, guid: ddff0b48b92c991499817d2a0f5d5059, type: 3}
m_ShaderKeywords: _MAINTEX _METALLICGLOSSMAP _NORMALMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 2800000, guid: f548cd63b5734e04a284018fefc81b30, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadeTex:
m_Texture: {fileID: 2800000, guid: df0632a08c5f1a1498fa325c755dc459, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 2c82a94e33b64fd481cbfeb7df9516bd, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: ad8a50784ce04f5d9b3bab2115eeea34, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Fade: 0
- _FadeEdge: 0.05
- _FadeSharpness: 16
- _GlossMapScale: 1
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EdgeColor: {r: 3.0117648, g: 3.0117648, b: 11.984314, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a9ef17c902709ce41a837c54b809184b
guid: 132cb2f99d9f42fe9b05db1c0d653897
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 2c82a94e33b64fd481cbfeb7df9516bd
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: ad8a50784ce04f5d9b3bab2115eeea34
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: f548cd63b5734e04a284018fefc81b30
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 1
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 21721bf50f1f407d8e0f2b5e06bf4ef5
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 22c55f60ad784e7495f2ddbae1e2799e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Paint_Worn_Dark
m_Shader: {fileID: 4800000, guid: ddff0b48b92c991499817d2a0f5d5059, type: 3}
m_ShaderKeywords: _MAINTEX _METALLICGLOSSMAP _NORMALMAP _OCCLUSIONMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 2800000, guid: b37cce6dfe8a45d0a7ba4e9a844c68b9, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _FadeTex:
m_Texture: {fileID: 2800000, guid: df0632a08c5f1a1498fa325c755dc459, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 8f9bc4377cc4451aae71a877219e700f, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 2800000, guid: b5158bc316ef42bead7fa70b7bc08a7a, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 2800000, guid: e8713adbe3e74ac4a4f431581bb31a4b, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _Fade: 0
- _FadeEdge: 0.05
- _FadeSharpness: 16
- _GlossMapScale: 1
- _Glossiness: 1
- _GlossyReflections: 1
- _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EdgeColor: {r: 3.0117648, g: 3.0117648, b: 11.984314, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e081b7d98e6d424fa42a6876a8e0bab3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Materials/PBR/Paint_Worn_Dark/Paint_Worn_Dark_AO.jpg (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: e8713adbe3e74ac4a4f431581bb31a4b
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 8f9bc4377cc4451aae71a877219e700f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: b5158bc316ef42bead7fa70b7bc08a7a
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 4
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show more