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>
This commit is contained in:
Meta Vens 2026-10-03 13:19:02 +02:00
commit 9c7a2f8254
2 changed files with 410 additions and 0 deletions

View file

@ -0,0 +1,216 @@
# Aetheria Release: Map
Date: 2026-10-03
This map holds body facts, the model page and rationale for campaign
`aetheria-release`. It has no progress section, no per-cut sections, no rulings
and no ledger: those are typed documents in the Eureka mind. Ends live in
`docs/aetheria-release-target.md`. The Eyes inventory this pass started from is
`F:\Projects\aetheria-release-inventory.md`, which is outside the repo.
Every anchor below is against `origin/master` `f1dee184` and was read in a sparse
scratch worktree on 2026-10-03, unless the line says otherwise.
## Body facts
**B1. No impact event carries a world point.**
- `Entity.IncomingHit` (`ServerShared/Entity.cs:138`) carries only the source.
- `ArmorDamage` (`:139`) carries a schematic cell. `ItemDamage` (`:140`) carries the
item. `HullDamage` (`:143`) carries the amount.
- `Zone.ShotCommitted` and `ShotResolved` (`Zone.cs:41-42`) carry a `ShotOutcome`
(`FireControl.cs:1902-1930`), which holds a schematic cell, bearing and lateral
offset but no world point.
- The world point of a direct hit is never computed. `ApplyDirectHit`
(`FireControl.cs:944-998`) walks lanes in the schematic frame. A
contact or delayed blast computes it at `:1030` and `:1043` and passes it to
`Detonate`. `Detonate` (`:1341-1414`) has the world point and the share each entity
took, and publishes neither.
- So nothing can show a hit at the place it landed without recomputing
`FireControl`'s geometry.
**B2. Weapon hits on a shield show nothing.** `ShieldManager.ShowHit`
(`Gameplay/ShieldManager.cs:88`) has one caller, ship-on-ship collision (`:80`).
`FireControl` calls `Shield.TakeHit` and `Break` (`FireControl.cs:952-956`,
`:1378-1385`) with no presentation hook. The inventory's "shield impact: present"
refers to the shield-panel rig, which `FieldTester` drives in `FieldShieldTest.unity`.
It does not run in the game.
**B3. A capability event contract already exists for this.** `CapabilityEvents`
(`ServerShared/CapabilityEvents.cs`) defines `AbsorbEvent` (position, direction,
magnitude, damage type) and one `Subject` per event kind.
`CapabilityPresentationBinder` (`Gameplay/CapabilityPresentationBinder.cs`) wires
`IAbsorbPresenter` components on an object and its children. The contract's own
comment says the simulation will own and publish these events, and presentations
will subscribe and decide nothing (ruling fork L, 2026-09-17). Today its only
publisher is `FieldTester`. `AbsorbEvent` has no way to tell a shield absorb from a
hull absorb.
**B4. The weapons already announce what they do.**
- `InstantWeapon.OnFire(shotId)` (`Behaviors/InstantWeapon.cs:272`) fires only for a
round that was not refused.
- `ChargedWeapon` has `OnStartCharging`, `OnStopCharging`, `OnCharged` and
`OnFailed` (`ChargedWeapon.cs:87-90`).
- `ConstantWeapon` has `OnStartFiring` and `OnStopFiring`.
- `EntityInstance.SetEntity` subscribes the effect managers to all of these
(`Gameplay/EntityInstance.cs:209-240`).
**B5. The Wwise-shaped audio path is dead at its source.**
- `EquippedItem.SoundBank` (`Entity.cs:1353`) is never assigned outside two tests
(`FireControlPerWeaponTests.cs:424`, `:672`).
- So every `FireAudioEvent` and `SetAudioParameter` call returns at its null check.
The calls sit in `InstantWeapon.cs:275`, `ChargedWeapon.cs:137,154,169,185`,
`Reactor.cs:97`, `Thruster.cs:96` and `AetherDrive.cs:170-172`.
- No production code subscribes to `EquippedItem.AudioEvents` (`:1375`).
- `WwiseSoundBinding` and `WwiseLoopingSoundBinding` (`WwiseSoundBinding.cs`) have
zero use sites.
- `GameData/SoundbanksInfo.json` (2,648 lines) is read by no code. Only
`docs/build-delivery-cut.md:231` mentions copying it.
- `EntityInstance.cs:243-251` reads `item.Data.SoundBank` and does nothing with it.
- Catalog fields that hold Wwise ids:
- `EquippableItemData.SoundBank` (`ItemData.cs:403`);
- `AetherDriveData.RpmAudioParameter` and `TorqueRatioAudioParameter`
(`AetherDrive.cs:44-48`, keys 11 and 12);
- `Faction.OverworldMusic`, `CombatMusic` and `BossMusic` (`Corporations.cs:52-59`,
keys 13 to 15).
**B6. Unity audio is switched off and has no listener.**
`ProjectSettings/AudioManager.asset` has `m_DisableAudio: 1`. A YAML grep found
`AudioListener:` count 0 in `ARPG.unity` and in `Main Menu.unity`; the two test
scenes have one each. The editor is Unity 6000.3.24f1
(`ProjectSettings/ProjectVersion.txt`).
**B7. The 2021 sound library is on disk and usable.**
- The Wwise project is `Aetheria-Economy_WwiseProject.wproj`, `WwiseVersion="v2021.1.1"`
and `SchemaVersion="103"`.
- Its 225 `.wav` are in LFS and present in the operator's checkout:
`Originals/SFX` holds 731 MB.
- The SFX include fire, hit and miss for cannon, ioncannon, lightingGun, machinegun
and railgun. They also include charge and charge-fail, ship destroyed (two), and
shield up, down and active. Overheat alarm, docking, undocking, wormhole, reactor
states and sensor ping are there too.
- Interface sounds are `blip`, `equip`, `mouseover`, `pickup`, `putdown`, and trade
buy and sell.
- Music: menu, Gen overworld and combat, Metal overworld, combat and boss, Daya
overworld, Kawaii Future Bass. There are also 30 ambience layers.
- The 20 `Originals/Plugins/SoundSeed Grain` sources feed a Wwise plugin, and
their procedural behaviour does not carry over outside Wwise.
- `*.wav` is an LFS pattern in `.gitattributes`.
**B8. The camera has the tooling for shake; nothing uses it.**
`com.unity.cinemachine` 2.10.7 is in `Packages/manifest.json`. It ships
`CinemachineImpulseSource` and `CinemachineImpulseListener`. A grep found no
`Impulse` and no `shake` in `Assets/Scripts`. The follow camera is
`ActionGameManager.FollowCamera` (`ActionGameManager.cs:122`).
**B9. Graphics settings are not saved.**
- `MainMenu.ShowGraphicsSettings`'s Back button (`UI/MainMenu.cs:258-263`) never calls
`ActionGameManager.SavePlayerSettings()`.
- Gameplay's Back button does call it (`:236-241`).
- `PlayerGraphicsSettings` (`ServerShared/PlayerSettings.cs:63-67`) holds keys 0 and 1.
- `PropertiesPanel.AddField(name, float read, write, min, max)` exists
(`UI/Properties Panel/PropertiesPanel.cs:290`).
**B10. The lanes overlap the feedback files in these hunks** (`git diff
origin/master...origin/<lane>` hunk headers):
- **mining** (`83d8371e`):
- `FireControl.cs` at `:72` and `:522`;
- `Entity.cs` at `:43`, `:198-240`, `:295-395` and `:1075`;
- `EntityInstance.cs` at `:236` and `:410`;
- `ActionGameManager.cs` across `:362-1432`, including `:1076-1100`;
- `ZoneRenderer.cs` and `Zone.cs`.
- **scenarios** (`aa3baf12`):
- `Entity.cs` at `:204`, `:601` and `:786-1003`;
- `ActionGameManager.cs` at `:583`, `:732` and `:801`.
- **moddable-ships** (`a93625c2`):
- `ActionGameManager.cs` at `:42-70`;
- `ZoneRenderer.cs`;
- `Packages/manifest.json`, which adds glTFast.
`feedback-1`'s edits are disjoint from these: `FireControl.cs:944-1045` and
`:1375-1412`, `Entity.cs:138-150`, and `EntityInstance.cs:159-170`.
**B11. The headless tests compile only `ServerShared`.** That covers
`Aetheria.Shared/Aetheria.Shared.csproj:20` and `tests/Aetheria.Shared.Tests`. A rule
that must be pinned headless must live in `ServerShared`.
## Model page
| Kind | Identity | Lifecycle | Authority |
|---|---|---|---|
| Impact (`AbsorbEvent` with a layer) | Transient. The receiving entity's `Capabilities` stream, plus the shot. It is not stored. | Published once per landed hit, before the hull damage is applied. It is never replayed or persisted. | `FireControl` alone, in `ApplyDirectHit` and `Detonate`. Presenters only read it. |
| Impact cue | Derived from one impact and the receiver. | Computed at presentation time and discarded. | `Feedback` (engine-free, `ServerShared`). Visual and audio presenters render it and do not re-derive it. |
| Player feedback preferences (shake, volumes) | `PlayerSettings` global, player store, keys under `GraphicsSettings` (shake) and a new `AudioSettings` (volumes). | Edited in the settings menu and saved on Back. A new key defaults on load. | The player, through the menu. No runtime writer. |
| Presentation tuning (effect prefab, intensity scale, impulse shape, sound bank) | A Unity component or asset in `Assets/Content`. | Authored in the editor and versioned with the scene. | The operator. It stays Unity-serialized by fork M (a). |
| Sound assets | The file under `Assets/Audio`, copied from the Wwise `Originals`. Provenance is recorded per file. | Added per cut. The Wwise project stays as the source archive until `audio-route` and `audio-source-rights` are ruled. | The operator, on rights (`audio-source-rights`). |
| Ship content (`ShipAuthoring` with GLB) | `aetheria.ship_authoring` id. GLB nodes carry an `aetheria.id` extra. | Owned by the moddable-ships lane until it merges. | The moddable-ships rulings (MQ1-MQ5). This campaign adds no owner. |
No cell is empty for the two mapped cuts. The content rows defer to a lane this
campaign does not own until question `content-lane-owner` is ruled.
## Rationale
**Why the impact is published by `FireControl` and not derived in Unity.** B1 shows
that the world point exists only inside `FireControl`'s lane walk and blast
resolution. If a presenter derived it, it would have to recompute lanes from the
`ShotOutcome`. That rebuilds the second hit authority that fire control Cuts 3 to
12.4(b) deleted. So the owner of where a round landed publishes where it landed.
**Why reuse `CapabilityEvents` rather than a new subject.** The contract was ruled
for exactly this (B3): the simulation publishes absorbs and presenters subscribe.
Its binder already exists. Reusing it adds one field (the layer) instead of a
second event family. It also brings the shield-panel presenters within reach of real
hits later, with no new wiring.
**Why the cue derivation lives in `ServerShared`.** Intensity and shake are rules
("in proportion to the damage", "zero at zero preference"). B11 says only
`ServerShared` is under headless test and Stryker.NET. Keeping the function
engine-free puts the rules where mutation testing reaches them. Audio then renders
the same cue (target: one cue, two channels).
**Why native Unity audio is recommended** (question `audio-route`):
- The simulation already announces fire, charge, impact and death (B4 and
`feedback-1`).
- The Wwise path is dead at its source (B5).
- Unity audio is only switched off (B6).
- Of the Wwise project, what carries over is the wav files (B7). The
2021.1 project, its events, banks and SoundSeed plugin sources would need
migrating to a Wwise release that supports Unity 6.
- Wwise adds three costs:
- a native plugin per platform;
- a second authoring application;
- a sound-bank build step. Its authoring console runs on Windows and macOS, not
on Yggdrasil's Linux.
Agents cannot easily author Wwise work units, and the operator's AquaSynth renders
would have to pass through it.
- Licensing is not the obstacle. Wwise is free under a $250K development budget,
with no asset limit (Audiokinetic pricing page and indie-license blog). FMOD is
free under $200K yearly revenue and a $500K budget.
- What the middleware would buy is interactive music and parameter-driven
mixing, authored by a sound designer. The release bar asks for neither yet.
- Unity's limits are known: 32 real voices by default (`AudioManager.asset`
`m_RealVoiceCount`), no authored containers or RTPC graph, and mixer assets that
cannot be created from script.
- Unity 6's `AudioRandomContainer` has no public scripting API for its clip list.
The first cut therefore uses a small `ScriptableObject` sound bank with random
pick and jitter.
Confidence: medium-high. It falls to medium if the operator expects a contracted
sound designer working in Wwise, or adaptive music with transitions and stingers
before release.
**Why content runs in parallel.** The release quota is met at the operator's pace,
one hull a day, and that clock starts only when the first Tripo mesh flies. The steps
in front of it are the operator's owed S2 play checks, the moddable-ships merge, and
the add-on's package action. Each is cheap and none depends on feedback or audio.
Serializing them behind audio would idle the slowest resource in the project.
**Sources consulted for the audio fork:**
- https://www.audiokinetic.com/en/wwise/pricing/
- https://www.audiokinetic.com/en/community/blog/free-wwise-for-indie-developers/
- https://www.gamedeveloper.com/audio/small-developers-and-creators-can-now-use-fmod-studio-for-free
- https://gamefromscratch.com/fmod-studio-now-free-for-indie-game-developers/
Two claims were not verified from primary sources on 2026-10-03: which Wwise
release first supports Unity 6000.x, and the scripting surface of
`AudioRandomContainer`.

View file

@ -0,0 +1,194 @@
# Aetheria Release Target
Date: 2026-10-03
Status: target. This document owns the ends. The typed `target` in the Eureka mind
(campaign `aetheria-release`) owns the labelled invariants and the not-in-scope list;
this file gives their reasons. Cut specs, questions and rulings are typed documents in
the mind and are not restated here. Body facts, the model page and the rationale for
the cut order are in `docs/aetheria-release-map.md`.
## Why
The game has enough systems to ship: fire control, stats and power, heat, item
provenance, locomotion, and the mining and scenario lanes in flight. What keeps it
unreleasable is presentation and breadth. It plays no sound at all. A hit on a hull
shows nothing where it lands, and the camera never reacts. Three hulls on two models
and one station are all a player can fly or dock at.
## Operator direction (2026-10-02 and 2026-10-03)
- "we already have plenty of game here, especially once we merge everything in flight
(and maybe another campaign or two geared at making the world feel more alive). The
only thing making it unreleasable to me is the lack of polish, content and feedback.
We need audio, we need ships, stations and gear for the player to covet and collect,
and we need our mechanics to be visible and visceral."
- "If we get the moddable ships pipeline usable and a Tripo3D subscription I can pump
one of these out every day, game ready." The pipeline is GPT Image 2.5, then
Tripo3D, then minor cleanup.
- "I don't think Asura is the way to go for content."
- The announcement bar (2026-10-02): a wider selection of ships and gear, a UX polish
pass, and audio feedback throughout.
## What "release" means
The release is the public announcement to players and Patreon, with a build they
can download. It is done when every line below holds on one build made from
`master`, and the operator has played that build and called it. The operator's call
is part of the definition: a ticked list without it is not a release.
1. **The lanes in flight have landed.** `codex/mining`, `codex/scenarios` and
`codex/moddable-ships` are merged into `master` or explicitly parked by the
operator. A release does not ship around half-merged work.
2. **Every player action that changes the world makes a sound.** That covers weapon
fire and charging, impacts on shield and hull, ship destruction, docking and
undocking, the wormhole, thrusters and the drive, inventory and trade actions, menu
clicks, the overheat alarm, and music in the menu, overworld and combat. The
player can set master, music, effects and interface volume, and the settings
persist.
3. **Every hit is seen where it lands and felt by the one who takes it.** An impact
on a shield shows on the shield at the side it came from. An impact on a hull
shows at the struck point. A hit on the player's own ship moves the camera in
proportion to the damage. The player can turn shake down to zero, and the hit is
still shown.
4. **Damage, heat and exposure are visible before they are fatal.** Lost armour,
a destroyed item and a critical hull each look different on the ship and in the
HUD. Overheat and hull-critical warnings use two channels, sound plus a visual,
and the more urgent one wins. The player can see how visible they are, how close
that is to being detected, and the largest source of it.
5. **There is enough to covet.** The content quota is set by the operator's ruling
on question `release-content-bar`. Every hull and station in the quota is
flyable or dockable and enters through the moddable-ships package path. Rarity
tiers show their colours, and every weapon type sounds and looks distinct.
6. **A new player can play for thirty minutes on the Windows build without hitting
a blocking defect.** The build is published through the build-delivery path.
## Ends
- **The simulation states what happened, and presentation shows it.** Fire control,
shields, damage, heat and detection publish typed facts. Visual and audio
presenters subscribe to them, derive a cue from each, and render it. They decide
no rule and recompute no geometry.
- **One cue, two channels.** Each fact becomes a cue in one engine-free function.
The visual and the audio presenter render that same cue, so the two channels
cannot disagree about what happened or how hard.
- **New content is data.** A new hull, station or piece of gear arrives as a catalog
record or a mod package. Nobody hand-wires a prefab array. The operator's daily
ship goes through the image model, Tripo, cleanup and the Blender add-on, and
comes out as a `ShipAuthoring` package with its GLB.
- **The player controls intensity without losing the signal.** Shake, flashes,
particle density and each audio channel have settings. Turning any of them down
never removes the tactical information it carried.
## Invariants that must survive
The typed target carries these as labelled statements. The reasons:
- **Legacy first** (operator, 2026-09-11). All work lands in the restored Unity tree.
There is no daemon, CultMesh or Eve re-architecture here. Shared infrastructure
is adopted, not invented.
- **The simulation owns the facts.** Fire control was rebuilt (Cuts 3 to 12.4(b)) so
that no Unity collider or effect decides a hit. Feedback must not reopen that
path. It reads `FireControl`'s facts and never re-derives them.
- **The simulation names no sound.** Today the simulation calls `FireAudioEvent`
with Wwise ids, against a sound bank that is never assigned. Audio becomes a
presenter of the same semantic events that visual effects use (`OnFire`,
`OnStartCharging`, impacts and deaths).
- **State is CultCache.** Player preferences such as shake and volumes go in the
player store (`PlayerSettings`), and authored data goes in the catalog. Engine
asset references are Addressables GUIDs (ruling of 2026-09-17). Presentation
tuning stays on its Unity component (fork M (a) of `docs/settings-globals-cut.md`).
- **Instruments bound what is shown** (`Visual and Sensory Direction`). A cue
never shows the player more than their sensors know.
- **The lanes are respected.** This campaign never commits to a `codex/*` branch or
to the operator's checkout. It branches from `origin/master` and rebases after
each lane merges.
- **Rules are tested headless.** Every rule decided in `ServerShared` has a
behavioural test in `tests/Aetheria.Shared.Tests`. A presentation-only behaviour
is an operator check, reachable through ordinary play or a scenario.
- **The operator judges whether the bar is met.**
## Not in scope
- Asura and procedural planet content. The operator ruled it out for content.
- New mechanics. Contact tiers beyond the current threshold, fused tracks, thermal
capture, probes and new weapon classes are not added here. This campaign makes
the existing mechanics visible.
- Faction mechanics beyond what `Faction Play.md` and its rulings name.
- "World feels alive" work such as ambient traffic and events. The operator named
it as a possible separate campaign.
- Build publishing machinery. `docs/build-delivery-target.md` owns it. This
campaign needs it done before release, but does not build it.
- Platforms other than Windows 64-bit, multiplayer, narrative and Ink work.
- Finishing other lanes' cuts: mining, scenarios, moddable-ships S2 and S5, thermal
balance, and the settings-globals tier-colour fix. This campaign depends on them
and does not do them.
## Strands
- **Feedback.** Impacts, damage states, warnings and detection, made visible and
felt. The first cut is mapped (`feedback-1`). It gives impacts a world point and a
layer, then shows them on the shield or hull and in the camera.
- **Audio.** The route is open as question `audio-route`. The first cut is mapped
for the recommended route (`audio-1`) and is blocked until the ruling. Its sketched
sequel covers interface, inventory, trade, docking and wormhole sounds, then
music, then continuous loops (thrusters, reactor, drive) and the overheat alarm,
then AquaSynth renders for whatever the 2021 library lacks.
- **Content pipeline.** This strand is a sketch until `codex/moddable-ships` merges.
1. The Blender add-on gains a collection-to-package action. It places anchors
with `aetheria.id` extras for weapon, radiator and thruster mounts, the collider,
map icon, shield and tractor, then exports the GLB with the `ship.cc`. This is
proof gate 2 of `docs/moddable-ship-authoring.md`.
2. Moddable-ships S3. The first playable mod ship is a Tripo mesh of a concept
whose image already worked (the Headliner or the Quiet Sense), taken through
the whole path.
3. Repeatability. A convex collider from the render mesh, and one material-slot
convention that leaves room for a later livery slot.
4. Throughput. One hull a day from the operator, plus stations, then gear.
- **Faction Play.** The design is `Game Design/Faction Play.md` in AetheriaLore,
at `5c45e27` plus `f3e0e6d`. It covers behaviour, relations, loadouts, resources,
visuals and hooks. On 2026-10-03 the operator accepted every proposal in it, and
the acceptance is recorded as three rulings:
- `faction-relations-field`: relations are their own authored field, not derived
from allegiance;
- `faction-lore-changes`: the five lore changes;
- `lucent-duel-bait`: Lucent's need for glory lets the player bait it into a
duel.
The strand's first cut, when mapped, is the note's smallest proof: Zhestokost,
Lucent and AU in one run, with implementation steps 1 to 3. Those steps are
`Personality`-driven engagement range and fire discipline, the four shared agent
states, and hail barks. The feedback and content strands leave room for faction
colour and livery, and decide nothing about them.
## Sequencing
Self proposed feedback, then audio, then content. Feedback goes first because it is
the cheapest per unit of perceived quality and it makes later content read. This
target keeps that order for agent-paced work, with one change: **content is the
calendar-critical path, so its unblocking runs in parallel rather than last.** The
quota is met one hull a day of operator time, and that clock cannot start until a
mesh flies. The steps that start it cost the agents little:
- the operator's owed S2 play checks on `codex/moddable-ships`;
- the merge;
- the add-on's package action.
Agent order: `feedback-1`. Then `audio-1`, once `audio-route` is ruled; it consumes
`feedback-1`'s impact cue. Then the content strand's add-on action as soon as
moddable-ships merges. After that, the remaining feedback and audio cuts alternate.
## Lanes and collisions
| Lane | Owner | This campaign |
|---|---|---|
| `codex/fire-control-12` (operator checkout, modified `.blend`) | Codex / operator | Never touched. Reads use `git show` or a scratch worktree. |
| `codex/mining` | Codex | Waits for its merge. `feedback-1` edits `FireControl.Apply`, `ApplyDirectHit` and `Detonate`, which mining does not change (it edits `FireControl.cs:72-100` and `:522-535`). Mining Cut 4 (shots at chunks) should publish impacts through the same contract (follow-up). |
| `codex/scenarios` | Codex, blocked on a fix batch | Waits. Operator checks in this campaign are reachable through ordinary play. Where one is not, it waits for scenarios Cut 4. |
| `codex/moddable-ships` | Codex, S2 owing operator checks | Waits for the merge. Ownership of anchor authoring and S3 after the merge is question `content-lane-owner`. |
| `eureka/aetheria-release-*` | This campaign | One branch per cut, from `origin/master`, each in its own worktree. |
The hot files are shared with the lanes: `Entity.cs`, `FireControl.cs`,
`ActionGameManager.cs`, `EntityInstance.cs` and `ZoneRenderer.cs`. Each cut keeps
its hunks out of the regions the open lanes change, which are listed per spec. New
behaviour goes in new files wherever an existing owner allows it.