Files
airdef/docs/CODEX-HANDOFF.md
T
chexit 46d2274c8d Measure the #120 balance grid across batteries, ranges and target classes
Wider same-seed sampling of the finite-burn/coast change: baseline 2689d93
(pre-#120) against the current tree, 6 variants x 8 seeds of a 46-drone raid
(batt10/20/50, near200, far1500, hills20). Harness-only: Result carries the
tally's fuse/expired/orphaned/energy_lost counts and a new ignored
sim::balance::issue_120_grid test; no simulation parameters changed.

Findings: kills are equal or up and leaks equal or down in every variant;
fuse misses drop (far1500 70 -> 38 over 8 seeds); hills terrain losses fall
(scrubbed 6 -> 2). MotorEnergyLost never fires in the 48 scenarios and
expired stays <= 1: coast ends before drag reaches the 25% guidance
threshold. Leaks stay concentrated in the ballistic/fast classes
(Iskander/Kinzhal/Kh22/Zircon). No confirmed defect, so no tuning.

Full airdef-core suite: 193 + 8 passed, 0 failed (baseline side 169 + 4).

Co-Authored-By: Kimi Code <noreply@moonshot.cn>
2026-11-04 21:03:01 +03:00

360 lines
38 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Передача разработки AirDef
Это журнал фактически сделанных изменений и ограничений проверки, а не список обещанных функций.
Рабочая ветка `kimi-work`; issues не закрывать, публиковать комментарии с коммитом и проверками.
Движок — отдельный `chexit/horizon-airdef`, ветка `airdef`, подключён точным gitlink `horizon/`.
## Текущее состояние: 4 ноября 2026
Последнее продолжение пяти задач: [CONTINUATION-2026-11-04.md](CONTINUATION-2026-11-04.md).
Движок `57f8b2853c4443f7e3ff5701600cbb262b53118f`, API29. В этом файле ниже сохранён
исторический журнал предыдущих серий; старые SHA и числа тестов не заменяют новую контрольную точку.
След #91 продолжен: `catalog/specs.json` — единственная копия числовых строк дронов, ракет и
комплексов; `python3 tools/gen_catalog.py` генерирует `specs_generated.rs` и
`unit_specs_generated.rs`, `--check` (CI) валит расхождение. Числа не менялись; сверка с литералами
подтвердила 1.6 как фактический голос P1-SUN (недостижимый `P1sun => 1.7` в старом match не в счёт);
на это добавлена Rust-регрессия. Остаток: варианты комплексов и игровая приёмка.
### Контрольная точка 3 ноября
Код предыдущих четырёх задач интегрирован до `6e2d661`. Продолжение #102/обратного вывоза
опубликовано до `aab3e78`; последнее продолжение расследования налётов — `2932364`.
Текущий движок — `f95f03c08ec2916a0e5bd3b2d4a2a790e7937b47`, API 27.
README описывает доступное поведение; `IMPLEMENTATION-STATUS.md` отделяет реализацию от приёмки.
Ни одно issue не закрыто. Участники: Codex (интеграция, #119, ревью, документация) и три
GPT-6.1 Terra (энергетика, типизированная доставка, излучение). Новые числа — только игровые.
| Issue | Опубликованные контрольные коммиты |
|---|---|
| #119 | `c96676f`: укрытия, read-only geometry, четыре проверки |
| #118 | `c775f31`, `952a10f`: доставка ТЗМ, возврат снятой ракеты ПВО, реальное движение и save/restore |
| #121 | `26b258f`, `0df225a`, `88f9405`, `9e1e0f5`, `b377a5d`, `ce76f20`: излучение, UI/save/replay, наблюдения, last-known SEAD |
| #120 | `143d9b2` → `e38ca0d`, затем `a7b8cb9`: конечное горение, coast, swept impact, диагностика, звук, исправленное ветвление фаз |
| WASM | `6e2d661`: проверка On/Off и запрета управления отсутствующим радаром, 24 шага |
Для обновления существующей установки сначала `git switch kimi-work`, затем `git pull --ff-only`,
`python3 tools/airdef.py all`, `python3 tools/airdef.py play`. `all` обновляет точный сабмодуль,
собирает игру/мод и устанавливает пакет. На Windows обычно используется `python` вместо `python3`.
### Продолжение #102 и обратного вывоза RM48U
- `d3378b3`: `fork()` синхронизирует URL из `.gitmodules` даже на fast path совпавшего pin.
Реальная Git-регрессия воспроизводит старый upstream URL и новый коммит, отсутствующий в локальном clone.
Это исправляет наблюдавшееся на Windows `upload-pack: not our ref 86b1014…`; пользователь подтвердил
ручное исправление через `git submodule sync --recursive` до публикации автоматизации.
- `bb931ab`, `e9fbaba`, `b0085cb`: `ground-unload` вдали от склада резервирует одну RM48U и вызывает
ТЗМ. `ground-cancel` отменяет ещё ожидающий вывоз/доставку; после забора груз продолжает путь на склад.
Проверены физическое движение и полный save/restore до забора и после забора, без телепортации запаса.
- `910f02c`: потеря зарезервированной ракеты вместе с ячейками сбрасывает заявку на вывоз.
Иначе можно было создать сохранение, которое loader сам отвергал как несовместимое состояние.
- Двигатель: `f4c1131d3`, затем `c89c78c47` опубликованы в `horizon-airdef:airdef` до обновления gitlink.
API27 добавляет acoustics-status и capture-owner-status, scoped к запуску мода и поколению мира.
Остановка capture проверяет владельца; смена мира снимает незапущенный запрос или посылает cancel.
- `910f02c`: команда `/airdef capabilities`; дальний звуковой fallback сохраняется до подготовки
акустического пути, экспорт принимает только своё подтверждённое состояние; Arming ждёт до 600 тиков.
`prepared` — milestone хоста, не GPU fence, не результат каждой акустической трассы и не готовый MP4.
- `4dddea2`, `8d5d0d1`: opt-in `test-budgets`, отдельный ручной workflow и JSON provenance;
тесты ошибок сборки, stale identity и ненулевого runtime exit. Native success не заменяет actual WASM.
- `aab3e78`: repo-local packer использует target-cache закреплённого движка; `CARGO_TARGET_DIR`
не переопределяется для сборки самого мода и не уводит `.hmod` в чужое дерево.
Проверки объединённого состояния: core release **190 + 4 сценария**, 7 ignored;
адаптер **60 + 1 boundary + 4 сценария**; лёгкий WASM **26 шагов**, тяжёлый **69 шагов**;
Git-регрессия и три теста failure report прошли. Исходный профиль запрашивал 64 ПВО + 160 целей,
602 tick / 300 frame; JSON фиксирует clean `aab3e78`, pin API27 и совпадающий build identity.
Полные данные: [budget report](measurements/api27-wasm-budget.json).
**Исправление оценки покрытия:** второй запрос исходного 69-шагового сценария отклонялся во время
подготовки первого. Его успешный exit не подтверждает 160 запущенных или одновременно летящих целей.
В архивный JSON добавлена поправка; исправленный сценарий проверяет ответы. Для настоящего stress
также нужны ответы render-world: прежний sandbox их не давал и часто проверял лишь ожидание земли.
Дополнительно два свежих профиля игры на Metal/no-audio: smoke off не ready, HD smoke ready;
при HORIZON_ACOUSTICS=1 + HORIZON_NO_AUDIO=1 акустика enabled/request=true, prepared=false,
awaiting-backend. Выход через quit подтверждён. Это не прослушивание, не benchmark и не новый MP4.
Правила API, пределы проверок и команды: [ENGINE.md](ENGINE.md).
## Двойные налёты и плотность следов
Перед продолжением читать [RAID-STABILITY.md](RAID-STABILITY.md): один соответствующий класс
отключения теперь воспроизведён и исправлен (`1f28f83`), приёмка конкретного Windows-сеанса остаётся.
Текущий исправленный WASM stress проверяет две принятые волны, обслуживаемую плоскую геометрию
и 184 воздушные цели в конкретный момент; новый [JSON](measurements/flat-wasm-raid-budget.json)
заменяет прежнее недостаточное доказательство покрытия. Лимиты fuel/memory не увеличивались.
`86e1d272e` в движке улучшает callback/fuel/error-chain diagnostics; `ed7615d36` добавляет только
необязательную flat-world среду тестов и отказывает неожиданным ошибкам команд в Script.
Основная клиентская логика сцены этим test helper не заменяется.
`692ae77`: HD-треки ракет оптически плотнее на 12% через общий `rocket()` и cruise style.
SAM/RM48U, крылатые/сверхзвуковые/баллистические треки покрыты; сегментов, радиусов и времени не добавлено.
Пожары и дымка винтовых дронов не менялись. Обычные ванильные fallback-частицы этим множителем не меняются.
Пять существующих smoke-тестов прошли; прирост FPS и приёмка новой плотности на Windows не заявлены.
Последний общий прогон: core release190 + 6 сценариев, 7 ignored;
адаптер60 + 1 boundary + 4 сценария; лёгкий WASM26; тяжёлый WASM271; 5 тестов отчёта.
Нативные overlap-тесты — `airdef-core/tests/scenarios.rs`:
два стандартных массовых пресета и два налёта с разделением «Орешников», оба со встроенной записью.
Продолжение по пользовательскому HD-отключению: `1f28f83` заменяет полный `known.retain` при
каждом взрыве на удаление прежнего квадрата; семантическая эквивалентность проверена.
В диагностическом WASM max-menu ×2 раньше был trap tick1835 на 300M; после фикса полный
3602-tick прогон прошёл, max135273690. Гость отличается от baseline только временным trigger hook
состава меню и исправлением. Это измерение fuel, не прирост FPS. Артефакты/ограничения — в RAID-STABILITY.
`cc48302` добавляет публичный native max-menu regression; `3b470dd` закрепляет опциональный
engine `test --fuel-profile` (не новый SDK API и не увеличение лимитов).
`cbd6067` исправляет сообщение о пустом соседнем складе, показывает типизированные запасы на M,
уточняет подсказку разведки и убирает устаревшую строку README о якобы отсутствующей доставке.
[GROUND-STRIKES.md](GROUND-STRIKES.md) — инструкция с различием номеров своего С-400/склада и вражеской ПУ.
Default RM48U=0; `ground-stock` задаёт остаток, `ground-load` грузит одну; поздний трек не даёт fix.
`ab737e7`: actual WASM теперь 27 шагов с проверкой ошибки пустого соседнего склада.
После фикса полный core: 192 passed + 6 сценариев / 7 ignored; новый max-menu сценарий отдельно
прошёл седьмым. Адаптер60 + 1 boundary + 4 сценария; light WASM27; engine /spin fuel-profile test прошёл.
## Исходная контрольная точка этой серии
Исходное состояние этой серии: `2689d93`; движок закреплён на
`86b1014a9218e68041444cbf52db02a85107c815`, уровень API 26. Рабочее дерево было чистым,
коммиты опубликованы. Текущий точный pin всегда смотреть в `git ls-files --stage horizon`,
а происхождение собранного пакета — в `airdef-mod/target/horizon-mod/build-identity.json`.
Четыре задачи были заказаны владельцем отдельно:
| Issue | Заказанный остаток |
|---|---|
| #120 | Конечная работа двигателя перехватчика, coast, энергия манёвра, согласованные эффекты |
| #118 | Типизированная доставка RM48U через ТЗМ; не создавать неподтверждённые носители |
| #121 | Переключение излучения, сохранение разрешённого внешнего целеуказания, разведка излучателей |
| #119 | Ослабление непрямого урона известным укрытием, ограниченная политика Unknown |
Исполнители работали в отдельных worktree; их проверенные коммиты перенесены в `kimi-work`.
В ветках `codex/issue-*` сохранены промежуточные версии; продолжать нужно от `kimi-work`,
где разрешены конфликты общего формата сохранений и сигнатур боевых функций.
## Что уже сделано в предыдущей серии Codex
- `airdef-core` компилирует исходники `airdef-mod/src/sim/mod.rs` через `#[path]`.
Это единый источник симуляции, но разделение домена и представления ещё не завершено (#87).
- Исправлены остаточные терминальные коллизии ответных ударов и скачок после world-query (#106/#117).
Восстановление ответов мира не даёт права телепортироваться к плановой точке.
- Доработаны запись ответных ударов, launch one-shot и live-след (#109), lifecycle показа и часы
отложенного звука (#88/#89). Полная унификация всех потребителей сцены ещё не закончена.
- Движок вынесен в отдельную репу; сборщик берётся из закреплённого форка, а не случайного PATH.
Есть build identity, настоящий WASM contract и handshake доступности дыма API26 (#102/#104).
- Обновлён upstream Horizon 0.2.97, исправления очереди/инвалидации акустики сохранены.
Измерительные fixtures, notices и лицензии добавлены; прослушивание и массовый CPU-тест ещё нужны (#96).
- Pipeline поддерживает authored overrides, manifest и экспорт итоговых габаритов в
`sim/generated_bounds.rs`. Навигация учитывает footprint. Generated output вручную не редактировать.
- Улучшены модели наземной техники; степень сходства и материалы ещё промежуточные (#115).
Галерея: `MODEL-PILOTS.md`, `VEHICLE-MODELS.md`; это не приёмка всех летательных аппаратов.
- `966b52f`: раздельные ПУ С-400/С-500, роли Radar Search/Engagement/Height/Multi.
Чужая подсказка разрешает огневому радару уточнение, но не подменяет собственное измерение.
- `966b52f`: резерв конкретной ячейки, отдельные крышки ТПК, выброс до включения двигателя.
RM48U — условный игровой профиль С-400; AA и ground rounds делят четыре физические ячейки.
Боеприпас списывается при выбросе, не при выдаче отложенного приказа; отмена не расходует его.
- Конфигурация, маска использованных ячеек и положение крышек включены в save/replay.
Smoke начинается в точке зажигания. С-500 ограничен двумя ракетами по числу ТПК;
старое сохранение с четырьмя загруженными ракетами при загрузке ограничивается двумя.
- `2689d93`: документированы источники архитектуры батареи, команды, скриншоты и границы визуальной проверки.
## Проверки и воспроизведение
На `966b52f`: 169 тестов ядра + 4 сценария прошли, 7 ignored; адаптер — 53 теста,
1 boundary и 4 сценария прошли; WASM contract — 21 шаг. Это исходная контрольная точка,
не результат новых четырёх задач. На `2689d93` был собран чистый пакет (`airdef_dirty=false`).
На итоговом объединённом коде `6e2d661` прошли:
- `airdef-core --release`: **187 passed, 7 ignored**, плюс **4 сценария**.
- `airdef-mod`: **56 passed**, **1 boundary**, **4 сценария**.
- Настоящий WASM-пакет: **24 шага**, включая команды излучения и typed ammunition.
- `gen_models.py --check`: различий нет; в этой серии геометрия ассетов не менялась.
Полный core здесь запускался с `--release`; это не прогон всех семи ignored-тестов.
Отдельно выполнен сравнительный ignored-тест баланса (см. ниже).
```sh
cargo test --release --manifest-path airdef-core/Cargo.toml
cargo test --manifest-path airdef-mod/Cargo.toml
python3 tools/airdef.py test-wasm
python3 tools/gen_models.py --check
python3 tools/test_gen_assets.py
git diff --check
```
На этой macOS cargo находится в `~/.cargo/bin/cargo`. GUI-проверки запускать с отдельным
`HORIZON_HOME` и рабочим каталогом тестового мира; не использовать реальные сохранения владельца.
Metal-проверки не подтверждают Windows/Linux, HDR всех платформ или прослушивание звука.
Скриншоты крышек подтверждают только их позу: полного видео выброса/зажигания пока нет.
## Технические детали новой серии
### #120: энергетика и единственный исход перехвата
`MissileKind::burn_ticks` задаёт конечное время горения: простой профиль равен 2/3 игрового
`spec.life`; для электрического P1-SUN используется весь срок жизни. Это не отдельная модель
топлива и не реальные кривые тяги. `Missile::engine_lit` — общий источник состояния мотора.
Три ветки скорости разделены явно: cold (`age <= cold`, множитель 0.97 с прежним минимумом 0.4),
powered (`+accel`, ограничение `spec.speed`), coast (множитель 0.995 без холодного минимума).
После выгорания доступный поворот масштабируется текущей скоростью; при падении ниже 25%
игрового максимума перехват заканчивается диагностикой `MotorEnergyLost`. Срок жизни остаётся
отдельным ограничением. Полноценной аэродинамики, гравитационной баллистики и расхода топлива по тяге нет.
Swept fuse учитывает движение обоих объектов за тик; `Impact` получает точку closest approach
и относительную скорость того же проверенного отрезка, включая удержание на Unknown.
Геометрию не заменяет отдельный бонус «встречная/догонная». Один остаточный pk зависит от
фактической скорости перехватчика и существующего состояния носителя/дальности.
Повторный штраф по stealth и старый штраф по абсолютной скорости цели удалены из этого броска;
обнаружение/сопровождение по-прежнему учитывают stealth в своих местах.
`MotorBurnout` и `MotorEnergyLost` записываются в scene journal; tally отличает потерю энергии.
Live и replay прекращают факел и новый дым по одному состоянию. `Out::engine_stops` немедленно
снимает голос мотора на burnout, не ждёт обычной трёхтиковой grace пропавшего источника;
при переходе на replay/export live-команды остановки отбрасываются вместе с live-выводом.
Перемотка восстанавливает моторное состояние из записи, включая возврат до выгорания.
При ревью был найден и исправлен недостижимый coast: ранний прототип проверял `!lit`,
что перехватывало и cold, и coast. Не переносить один `143d9b2` без последующих исправлений.
`a7b8cb9` содержит отдельный тест точных правил скорости всех трёх фаз.
Сравнительная выборка **только изменения #120**, отдельно от #119/#118/#121:
baseline `2689d93`, агентская итоговая ветка `508f9a0` (её исправление перенесено как `a7b8cb9`).
12 одинаковых seed, `SAMS=20 SIZE=12`: 204 цели в каждой версии;
baseline — 202 сбитых, 2 прорыва, 367 ракет; новое — 203, 1, 355.
Это небольшой регрессионный ориентир, не доказательство баланса всех типов/дальностей.
Данные каждого seed: [CSV](measurements/issue-120-balance.csv).
Расширенная сетка остатка #120 (ветка `agent/issue-120-balance`, коммит см. в git):
baseline `2689d93` против текущего `e6a7000` (то есть с #118/#119/#121 и сменами движка, не только #120),
6 вариантов × 8 одинаковых seed, рейд `SIZE=36` (46 целей: Gerbera 10, Shahed 13, Geran3 5, Х-101 5,
«Калибр» 4, Х-22 2, «Циркон» 1, «Искандер» 4, «Кинжаль» 2; «Орешник» harness исключает, как в `one_raid`):
`batt10/20/50` (10/20/50 ЗРК, дистанция 500), `near200` (20 ЗРК, пуск в 200), `far1500` (20 ЗРК, пуск в 1500),
`hills20` (20 ЗРК, холмы, 500). Кластер тот же `MIX` из 10 систем: `SAMS=10` — по одному комплексу каждого типа.
Итого 2208 целей на сторону, 96 строк: [CSV](measurements/issue-120-grid.csv). Команда (игнорируемый тест
`sim::balance::issue_120_grid`, только harness-поля в `Result`, поведение симуляции не менялось):
```sh
SEEDS=1-8 cargo test --release --manifest-path airdef-core/Cargo.toml issue_120_grid -- --ignored --nocapture
```
Факты сетки (суммы по 8 seed каждого варианта, baseline → текущий): сбитые 297→301 (batt10), 331→334 (batt20),
357→363 (batt50), 313→318 (near200), 328→338 (far1500), 328→334 (hills20); прорывы 70→66, 37→34, 11→5,
53→48, 40→30, 39→33. Промахов по взрывателю заметно меньше (например far1500: 70→38). Расход ракет близок
(516→504 … 597→583). На холмах потери у рельефа: разбито 14 и 14, самоуничтожений у хребта 6→2.
Прорывы во всех вариантах — преимущественно баллистические и быстрые классы («Искандер», «Кинжаль», Х-22,
«Циркон»); у медленных Shahed/Gerbera прорывов почти нет (0–2 на вариант), у ложных Gerbera — ноль ни разу.
`MotorEnergyLost` не сработал ни в одном из 48 сценариев текущего кода, `expired` ≤ 1 на вариант: coast
существует, но бои на этих дистанциях заканчиваются раньше, чем сопротивление 0.995/тик опустит скорость
ниже порога 25% (и раньше выработки ресурса). Это измеренное свойство профиля, не подтверждённый дефект,
поэтому параметры не менялись. Путь потери энергии покрыт юнит-тестом регресса (`regress.rs`), а не этой сеткой.
```sh
SAMS=20 SIZE=12 cargo test --release --manifest-path airdef-core/Cargo.toml sim::balance::one_raid -- --ignored --nocapture
```
### #118: один физический груз и восстанавливаемая заявка
`ground_request` у С-400 — заявка на **одну** RM48U. Рядом со складом остаётся прямая передача;
вне радиуса склада та же команда `ground-load` создаёт заявку, если есть запас и живая ТЗМ.
ТЗМ забирает одну ракету из конечного запаса, едет к исправному развёрнутому носителю и передаёт
её в общие ячейки. Если вытеснена ракета ПВО, ТЗМ везёт её обратно на склад. Generic reload
не создаёт RM48U. Ударная заявка имеет приоритет перед generic reload.
Поля `ground_stock` / `air_48n6_stock` на складе — остатки, на ТЗМ — физический груз двух типов.
Заявка, груз и марш сохраняются; оперативный `job` реконструируется после загрузки.
Передача запрещена во время движения, подготовки пуска, перезарядки, отказа ПУ и при отсутствии
вместимости. Разрушение очищает заявку/груз; repair не восстанавливает уничтоженный typed stock.
Проверены настоящее движение `Sim.step` по плоскому WorldSource, передача/возврат, истощение,
прерывание, несовместимость, заполненные ячейки, unload и полный `state_text → apply_state`
с продолжением маршрута. GUI-доставка на сложном рельефе ещё не проверена.
Новых носителей вроде Бука не добавляли: один публичный игровой профиль не даёт основания
приписывать его всем ЗРК. Обратный вывоз из удалённого носителя автоматизирован в продолжении выше.
Новая команда `ground-cancel` отменяет ожидающую заявку, но не возвращает уже забранный груз в ПУ.
ТЗМ вмещает два типизированных места RM48U/48Н6; прежние абстрактные generic reload-пакеты учитываются отдельно.
Вывезенная ракета возвращается в конечный запас; ПВО восстанавливается при заборе только из реально
имеющейся у ТЗМ ракеты 48Н6 и свободной ячейки. Резерв одной RM48U учитывается при выборе носителя удара.
### #121: излучение отдельно от сети
`radar_on` — сохраняемая настройка, default=true для старых миров. Команда
`/airdef radar <номер> on|off` и кнопка карты меняют её; у launcher-only нет своего активного радара.
`radar_up` учитывает этот флаг. Off запрещает новые own measurements, но старые треки стареют
обычно и разрешённый сетевой приём сохраняется. Это не выключение корпуса/связи/ГСН ракеты.
Огневой радар, обязательный для отдельной ПУ, в Off не авторизует новые пуски.
Условный наблюдатель-противник раз в 20 тиков обнаруживает работающие радары в 1600 блоках.
Это упрощённый игровой датчик по расстоянию, без LOS/радиопеленгации и ошибки оценки позиции.
Контакт хранится как последняя наблюдённая точка и стареет за 6000 тиков. Off не стирает
контакт, не телепортирует его вслед за носителем и не предотвращает раскрытие пуском/РЭБ.
В `raid::radar_strikes` удалён отдельный обход: раньше SEAD выбирал любую Radar и её настоящий
`pos`, даже если общий planner уже работал по наблюдениям. Теперь SEAD берёт те же last-known
контакты и их возраст. Явный sandbox-режим `Aim::ObjectsAndSams` по-прежнему выбирает расстановку
напрямую; не путать его с умным противником. Проверки покрывают необнаруженную молчащую РЛС,
смену позиции без наблюдения, повторное раскрытие, старение, relay freshness и seek.
### Совместимость текстового состояния
Сохраняем строки `sam` расширением справа; индексы ниже включают слово `sam` как поле 0.
| Индекс | Значение |
|---|---|
| 22–24 | ground_rounds, ground_stock, air_48n6_stock |
| 25–27 | mode, radar_role, spent_cells |
| 28 | ground_request: 0/1, только С-400 |
| 29 | radar_on: true/false, отсутствие означает true |
| 30 | ground_return: true/false, резерв вывоза одной RM48U из С-400 |
| 31 | return_cargo: true/false, возвращаемая RM48U на ТЗМ |
Две агентские ветки сначала заняли поле 28 одновременно; при интеграции излучение перенесено
в 29, опубликованная совместимость заявки сохранена. Проверка полного roundtrip одновременно
содержит ожидающую доставку и выключенный радар. Новые значения входят в durable mark;
настройка излучения также в `SamKey` и ghost replay. Не переиспользовать эти позиции для нового поля.
### #119: непрямой взрыв и укрытия
`WorldCache::blast_cover` читает текущую occupancy без запросов мира и без загрузки чанков.
Три луча к репрезентативным точкам корпуса дают общий множитель для корпуса и узлов;
для отмеченного объекта считается своя тройка. Известное укрытие оставляет 15% игрового
воздействия по перекрытому лучу, открытый — 100%; края/проёмы дают промежуточное значение.
Все лучи этого вызова читаются до отправки разрушения в движок. Исходный воксель пропускается,
чтобы контакт на поверхности стены не закрывал взрыв сразу во все стороны.
Unknown, stale и слишком старые секции считаются **неразрешёнными**. Ожидание равно нулю:
для них сохраняется прежний неослабленный урон как консервативная игровая политика,
а не утверждение, что там воздух. После ответа мира этот взрыв не пересчитывается.
Нет очереди отложенного урона и повторного применения на world reply. Частичные блоки
на этом этапе считаются занятым кубом; тонкая collision shape для blast отдельно не запрашивается.
Прямой вооружённый контакт не ослабляется этим множителем.
Проверки `sim::damage::cover_tests`: стена/проём для корпуса, узлов и объекта;
Unknown и поздний ответ без повторного урона/запросов; прямое попадание; устаревшая геометрия;
пропуск исходного блока. Все четыре прошли в объединённом наборе.
## Что следующему агенту проверить в первую очередь
1. На Windows: обновление сабмодуля через `all`, сохранение/перезаход, рабочий цикл игры.
2. В GUI: полный холодный пуск крупным планом; карточка On/Off; маршрут ТЗМ по сложной местности;
разрушение стены одним взрывом и защита от того же взрыва по исходной геометрии.
3. Прослушать прекращение голоса двигателя при burnout и seek/экспорт вокруг этой границы.
4. Расширенная балансировка #120 (батареи/дальности/классы) записана в `measurements/issue-120-grid.csv`;
остаются прослушивание голоса мотора и платформенная приёмка.
5. Продолжить оставшиеся архитектурные #87/#88/#89/#91/#102 и художественный #115 по статусной таблице.
Это незавершённая платформенная/визуальная приёмка, а не отсутствие перечисленного выше кода.
Прогон четырёх задач не запускал GUI/MP4. В продолжении API27 есть два коротких игровых smoke,
но новый MP4, прослушивание и платформенная приёмка Windows/Linux по-прежнему не выполнены.
## Правила продолжения
- Не закрывать issue даже после исправления; сообщать проверенный объём и остаток в комментарии.
- Не переписывать gitlink на плавающую ветку. Изменения движка сначала публикуются отдельно.
- Не путать наблюдённый трек с настоящим положением цели и `own_tick` с relay.
- Не менять live-мир при seek; replay воспроизводит последствия, не применяет урон повторно.
- Не считать Unknown свободным пространством или подтверждённой стеной без явной игровой политики.
- Новые числа — игровой масштаб, не реальные характеристики вооружения.
- Токен Gitea читать из локального файла во время запроса; не коммитить и не печатать.