35 KiB
Передача разработки AirDef
Это журнал фактически сделанных изменений и ограничений проверки, а не список обещанных функций.
Рабочая ветка kimi-work; issues не закрывать, публиковать комментарии с коммитом и проверками.
Движок — отдельный chexit/horizon-airdef, ветка airdef, подключён точным gitlink horizon/.
Текущее состояние: 4 ноября 2026
Последнее продолжение пяти задач: CONTINUATION-2026-11-04.md.
Движок 57f8b2853c4443f7e3ff5701600cbb262b53118f, API29. В этом файле ниже сохранён
исторический журнал предыдущих серий; старые SHA и числа тестов не заменяют новую контрольную точку.
Контрольная точка 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. Это исправляет наблюдавшееся на Windowsupload-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-intest-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.
Исправление оценки покрытия: второй запрос исходного 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.
Двойные налёты и плотность следов
Перед продолжением читать RAID-STABILITY.md: один соответствующий класс
отключения теперь воспроизведён и исправлен (1f28f83), приёмка конкретного Windows-сеанса остаётся.
Текущий исправленный WASM stress проверяет две принятые волны, обслуживаемую плоскую геометрию
и 184 воздушные цели в конкретный момент; новый 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 — инструкция с различием номеров своего С-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-тест баланса (см. ниже).
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.
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 и поздний ответ без повторного урона/запросов; прямое попадание; устаревшая геометрия;
пропуск исходного блока. Все четыре прошли в объединённом наборе.
Что следующему агенту проверить в первую очередь
- На Windows: обновление сабмодуля через
all, сохранение/перезаход, рабочий цикл игры. - В GUI: полный холодный пуск крупным планом; карточка On/Off; маршрут ТЗМ по сложной местности; разрушение стены одним взрывом и защита от того же взрыва по исходной геометрии.
- Прослушать прекращение голоса двигателя при burnout и seek/экспорт вокруг этой границы.
- Расширить баланс #120 на разные батареи, пределы дальности и классы целей; исходная CSV — ориентир.
- Продолжить оставшиеся архитектурные #87/#88/#89/#91/#102 и художественный #115 по статусной таблице.
Это незавершённая платформенная/визуальная приёмка, а не отсутствие перечисленного выше кода. Прогон четырёх задач не запускал GUI/MP4. В продолжении API27 есть два коротких игровых smoke, но новый MP4, прослушивание и платформенная приёмка Windows/Linux по-прежнему не выполнены.
Правила продолжения
- Не закрывать issue даже после исправления; сообщать проверенный объём и остаток в комментарии.
- Не переписывать gitlink на плавающую ветку. Изменения движка сначала публикуются отдельно.
- Не путать наблюдённый трек с настоящим положением цели и
own_tickс relay. - Не менять live-мир при seek; replay воспроизводит последствия, не применяет урон повторно.
- Не считать Unknown свободным пространством или подтверждённой стеной без явной игровой политики.
- Новые числа — игровой масштаб, не реальные характеристики вооружения.
- Токен Gitea читать из локального файла во время запроса; не коммитить и не печатать.