docs: archive the reproduced fuel failure and bounded cache fix
build / mod (push) Failing after 18s

Preserve the diagnostic trigger, scenario, before/after logs and scope of equivalent counters. Update ground strike guidance, Windows acceptance status and profiler semantics.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
2026-11-03 11:39:23 +03:00
parent ab737e7390
commit d410e2c92d
13 changed files with 1803 additions and 9 deletions
+20 -2
View File
@@ -8,7 +8,7 @@
Код предыдущих четырёх задач интегрирован до `6e2d661`. Продолжение #102/обратного вывоза
опубликовано до `aab3e78`; последнее продолжение расследования налётов — `2932364`.
Текущий движок — `ed7615d362490f57bca5ac239c64eb9360913a4b`, API 27.
Текущий движок — `f95f03c08ec2916a0e5bd3b2d4a2a790e7937b47`, API 27.
README описывает доступное поведение; `IMPLEMENTATION-STATUS.md` отделяет реализацию от приёмки.
Ни одно issue не закрыто. Участники: Codex (интеграция, #119, ревью, документация) и три
GPT-6.1 Terra (энергетика, типизированная доставка, излучение). Новые числа — только игровые.
@@ -64,7 +64,8 @@ awaiting-backend. Выход через quit подтверждён. Это не
## Двойные налёты и плотность следов
Перед продолжением читать [RAID-STABILITY.md](RAID-STABILITY.md): Windows-вылет ещё не воспроизведён.
Перед продолжением читать [RAID-STABILITY.md](RAID-STABILITY.md): один соответствующий класс
отключения теперь воспроизведён и исправлен (`1f28f83`), приёмка конкретного Windows-сеанса остаётся.
Текущий исправленный WASM stress проверяет две принятые волны, обслуживаемую плоскую геометрию
и 184 воздушные цели в конкретный момент; новый [JSON](measurements/flat-wasm-raid-budget.json)
заменяет прежнее недостаточное доказательство покрытия. Лимиты fuel/memory не увеличивались.
@@ -82,6 +83,23 @@ SAM/RM48U, крылатые/сверхзвуковые/баллистическ
Нативные 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`; движок закреплён на
+17 -1
View File
@@ -63,7 +63,7 @@ runtime закреплённого движка. Используется вре
## Акустика и владение захватом (API 27)
Текущий pin: `ed7615d362490f57bca5ac239c64eb9360913a4b` (API 27). Новые
Текущий pin: `f95f03c08ec2916a0e5bd3b2d4a2a790e7937b47` (API 27). Новые
`render.acoustics-status` и `render.capture-owner-status` возвращают поколение,
`available`, `enabled`, `request-accepted`, `prepared` и причину. В игре всё это показывает
`/airdef capabilities`. Отсутствие запроса, выключение, ожидание backend и ошибка различаются.
@@ -128,3 +128,19 @@ enabled/request=true, prepared=false, awaiting-backend; HD smoke переход
Остаток #102: аналогичные статусы света/камер/источников звука, полные query/voice/peak budgets,
GPU/готовый MP4 и платформенная приёмка. Эти результаты текущими тестами не объявляются выполненными.
## Измеренный fuel и массовые взрывы
В runtime добавлен выключенный по умолчанию профиль вызовов. У тестового CLI флаг
`test --fuel-profile` выводит mod/callback, число вызовов, максимальный израсходованный guest fuel,
бюджет и число ошибок; результат печатается и при неуспехе сценария. Init до включения профиля
и предыдущие поколения после reload в эти значения не входят. Это гостевые инструкции,
не время CPU, не heap peak и не работа GPU/host. Обычный `test-budgets` без этого флага по-прежнему
не выдаёт свои исходные caps за измеренный расход.
С профилем воспроизведён остановившийся tick на двух максимальных составах меню и HD:
полный обход height-cache при каждом взрыве доводил его до 300M. `1f28f83` заменяет обход
удалением только затронутого квадрата. В контрольном диагностическом WASM-прогоне после исправления
3602 тика прошли, max tick fuel = 135273690/300M, failures=0. Лимиты не менялись.
Диагностический гость содержит только временный способ запуска точного меню-состава;
это не исходный пользовательский Windows-сеанс. [Данные и воспроизведение](RAID-STABILITY.md).
+1 -1
View File
@@ -28,7 +28,7 @@
## Откуда берётся разведка
Она автоматическая. Рабочая включённая РЛС может заметить **сам пуск** с наземной площадки,
Она автоматическая. Поставьте и включите РЛС **до налёта**. Рабочая включённая РЛС может заметить **сам пуск** с наземной площадки,
если он попадает в её игровой обзор и не закрыт рельефом. Это даёт оценку позиции; несколько
наблюдений могут её уточнить. Обнаруженная позже летящая цель даёт лишь слабое предположение
о направлении старта — оно не превращается в координаты от ожидания или от количества радаров.
+1 -1
View File
@@ -40,7 +40,7 @@
| #119 | Три read-only луча в известной геометрии ослабляют непрямой blast для корпуса/узлов/объектов; проёмы дают частичное воздействие; прямой контакт сохранён | Unknown/stale: прежний урон без защиты, нулевое ожидание; partial blocks считаются занятыми кубами; GUI-проверка разрушения укрытия ещё нужна |
| #120 | Конечное горение, powered/coast, сопротивление и снижение доступного манёвра, один остаточный pk по фактической скорости; swept-встреча; события burnout/energy loss; согласованное прекращение факела/дыма/звука | Игровой профиль, без аэродинамики и реальных параметров; сравнительная выборка 12 рейдов, расширенная балансировка и прослушивание остаются |
| #121 | On/Off в команде и карте, save/replay; Off не создаёт own measurements и сохраняет сетевой приём; раскрытие работающего радара наблюдателем; SEAD использует last-known и возраст | Условный наблюдатель по расстоянию, без радиотехнической модели и ошибки пеленга; выбор на карте ещё не проверен в GUI |
| #122 | Добавлены callback/fuel/full-chain diagnostics, настоящие перекрывающиеся native/WASM сценарии с ответами мира; тесты прошли | Пользовательский Windows-вылет не воспроизведён, причина и исправление не заявлены; нужен лог/точный профиль |
| #122 | Воспроизведён tick fuel exhaustion на двух максимальных составах, HD; полный обход height-cache на каждом взрыве заменён удалением нужных ключей; тест эквивалентности и WASM421/3602 прошли, max135.3M/300M; callback diagnostics/profile | Требуется приёмка на Windows; без старого лога нельзя подтвердить ту же причину пользовательского сеанса; FPS/GPU не измерялись |
Точные коммиты, формат сохранения, тесты и порядок продолжения:
[CODEX-HANDOFF.md](CODEX-HANDOFF.md). Формальный open-статус не меняется после реализации.
+40 -2
View File
@@ -2,10 +2,48 @@
Пользовательский отчёт: AirDef часто перестаёт работать при двух больших налётах,
резкого обвала FPS перед этим не замечено. RTX 3060 + Ryzen 5600X — около 50 FPS во время налёта.
Точный build, профиль эффектов и отличие отключения мода от падения всего процесса пока не подтверждены.
Пользователь уточнил: игра продолжает работать, отключается только AirDef; режим эффектов — HD.
Точный build и старый лог не предоставлены. Horizon архивирует предыдущие логи в `logs/YYYY-MM-DD-N.log.gz`,
поэтому запись может сохраниться и без ручного копирования.
Задача: [#122](https://gitea.maoniao.team/chexit/airdef/issues/122).
**Причина вылета не установлена; исправление причины и прирост FPS не заявлены.**
**Воспроизведена и исправлена одна конкретная причина отключения при таком классе нагрузки.**
Без старого лога не утверждается, что Windows-сеанс имел именно её; GPU/FPS отдельно не измерялись.
## Найденная причина и фикс
Два максимальных состава меню (11 видов × 40, два принятых приказа), 64 ПВО, расстояние 300,
HD и grid, обслуживаемый плоский мир: tick 1835 исчерпал ровно 300M fuel и мод остановился.
Grid, запись и обновление дыма не были необходимы для этого spike: исследовательские абляции
не убирали остановку. В производственном исправлении эти функции не отключаются.
`Ground::forget` при каждом взрыве делал `retain` по всему кэшу известных высот. Тот же полный
обход выполнялся при обработке просроченных blast replies. Когда приходило много взрывов,
затраты росли как произведение количества взрывов и размера/ёмкости таблицы высот.
`1f28f83` удаляет непосредственно координаты прежнего квадрата: при радиусе 8 это 17×17 ключей,
а не просмотр всей таблицы. Вызов `world.touched` сохранён. Тест сравнивает весь результат со
старым predicate, включая отрицательные координаты и границы; правила урона и лимиты не менялись.
Контрольный диагностический гость с полными записью, дымом, HD и grid, без phase markers:
421 шаг, 3602 тика — PASS; max tick fuel 135273690/300M, command 92658271/1B, failures=0.
Финальные показатели: 0 в воздухе, 209 сбито, 3435 поражений, 15 столкновений.
На тике 1834 до прежней остановки вывод `/stats` до/после совпал побайтово,
включая счётчики мира. Это не утверждение о равенстве каждого скрытого поля симуляции.
Для воспроизведения огромного меню-состава использован временный hook команды mix,
вызывающий тот же `WaveConfig/order_raid`; сам hook **не входит в мод**.
Исходник — `10f24b5`, после фикса добавлен только новый `forget`. Данные, hook и точный
сценарий: [summary.json](measurements/max-raid-fuel/summary.json),
[trigger.patch](measurements/max-raid-fuel/trigger.patch),
[scenario.toml](measurements/max-raid-fuel/scenario.toml),
[до](measurements/max-raid-fuel/before.txt), [после](measurements/max-raid-fuel/after.txt).
Patch предназначен для отдельного диагностического worktree, а не для обычной игры.
Два checkpoint-лога намеренно заканчиваются несовпадением с `probe`, чтобы получить `/stats`;
это не реальные traps. Успешный полный прогон отдельно в `after.txt`.
Публичный native-тест `two_maximum_menu_raids_with_answered_flat_terrain` использует настоящий
максимальный `RaidOrder` без hook, terrain replies и запись. Он также прошёл.
## Найденные пробелы старых тестов
@@ -0,0 +1,5 @@
running 1 scripts against /tmp/airdef-raiddiag/airdef-mod/target/horizon-mod/airdef.hmod
fuel airdef command: calls=69 max=92658271 budget=1000000000 failures=0
fuel airdef tick: calls=3602 max=135273690 budget=300000000 failures=0
test tests/mix.toml ... ok (421 steps)
test result: ok. 1 passed
@@ -0,0 +1,6 @@
running 1 scripts against /tmp/airdef-raiddiag/airdef-mod/target/horizon-mod/airdef.hmod
fuel airdef command: calls=68 max=92658271 budget=1000000000 failures=0
fuel airdef tick: calls=1835 max=300000000 budget=300000000 failures=1
test tests/mix.toml ... FAILED
step 244 (10 ticks, 5 frames): the mod stopped: it exceeded its execution limit
error: 1 failed, 0 passed
@@ -0,0 +1,8 @@
running 1 scripts against /tmp/raiddiag-fixed-instrumented.hmod
fuel airdef command: calls=68 max=92323272 budget=1000000000 failures=0
fuel airdef tick: calls=1834 max=136123919 budget=300000000 failures=0
test tests/mix.toml ... FAILED
step 244 (/airdef stats): feedback
expected: Some("probe")
got: Some("В воздухе: 489, ракет: 0, ПВО: 64, сбито: 209, поражений: 2447, разбились о препятствия: 4; удары по ПУ: пущено 0, уничтожено 0, подавлено 0, промахов 0, сбито ПВО 0; мир: 11990 секций (562 КБ), запросов 44224, неизвестно 0, лучей 574840 (ударов 2867, неизв. 4700), клеток 10800173; взрывы в блоках: 2669 (подтверждено 0, без перемен 651, нет чанка 1094), чужих ответов 0")
error: 1 failed, 0 passed
@@ -0,0 +1,8 @@
running 1 scripts against /tmp/raiddiag-original.hmod
fuel airdef command: calls=68 max=92232498 budget=1000000000 failures=0
fuel airdef tick: calls=1834 max=295473677 budget=300000000 failures=0
test tests/mix.toml ... FAILED
step 244 (/airdef stats): feedback
expected: Some("probe")
got: Some("В воздухе: 489, ракет: 0, ПВО: 64, сбито: 209, поражений: 2447, разбились о препятствия: 4; удары по ПУ: пущено 0, уничтожено 0, подавлено 0, промахов 0, сбито ПВО 0; мир: 11990 секций (562 КБ), запросов 44224, неизвестно 0, лучей 574840 (ударов 2867, неизв. 4700), клеток 10800173; взрывы в блоках: 2669 (подтверждено 0, без перемен 651, нет чанка 1094), чужих ответов 0")
error: 1 failed, 0 passed
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,57 @@
{
"baseline": {
"at_tick": 1835,
"callback": "tick",
"failures": 1,
"fuel_budget": 300000000,
"max_used": 300000000,
"stopped": true
},
"baseline_guest_sha256": "572f4c4ed320e183a9e59455a23e1c871b447309bd0805cdfbcc4a12aeadaa2e",
"baseline_source": "10f24b5",
"checkpoint": {
"after_max_tick_fuel": 136123919,
"after_profile_has_phase_markers": true,
"before_max_tick_fuel": 295473677,
"expected_probe_assertions_fail_deliberately": true,
"reported_stats_equal": true,
"scope": "equality of reported combat/world counters, not every hidden simulation field",
"stats_sha256": "8a7b2f7ec19a1ce462807bde24923f7d97ae46841cc600e43bb722b8933243f7",
"tick": 1834
},
"fixed": {
"airborne_at_end": 0,
"collisions_at_end": 15,
"command_budget": 1000000000,
"failures": 0,
"hits_at_end": 3435,
"kills_at_end": 209,
"max_command_fuel": 92658271,
"max_tick_fuel": 135273690,
"passed": true,
"steps": 421,
"tick_budget": 300000000,
"ticks": 3602
},
"fixed_guest_sha256": "0d59654fba9842d481a7f04e84d795f5fb2f7be8389e917e35c5598876f3a415",
"gpu_or_fps_measured": false,
"guest_change": "trigger.patch replaces only mix command composition with the exact maximum UI WaveConfig; no gameplay or rendering feature is disabled",
"kind": "diagnostic_guest_comparison_not_exact_user_session",
"limits_unchanged": true,
"production_fix": "1f28f83",
"scenario_sha256": "af4e0486256239d87c940bfba81caedb47914ad7aaf6b14806c9745dc0979e1c",
"schema": 1,
"setup": {
"defenses": 64,
"distance_blocks": 300,
"each_of_11_kinds": 40,
"grid": true,
"hd": true,
"per_order": 440,
"raid_orders": 2,
"recording": true,
"smoke_update": true,
"synthetic_ground_y": 64
},
"user_windows_session_confirmed_same_cause": false
}
@@ -0,0 +1,18 @@
diff --git a/airdef-mod/src/lib.rs b/airdef-mod/src/lib.rs
index 2255f57..f1da2c6 100644
--- a/airdef-mod/src/lib.rs
+++ b/airdef-mod/src/lib.rs
@@ -2338,7 +2338,12 @@ impl Mod for AirDef {
.unwrap_or(DVec3::new(p.x, p.y, p.z));
if *kind == "mix" {
let objects = self.objects(DVec3::new(p.x, p.y, p.z));
- self.sim.order_raid(&wave::WaveConfig::mix(count, dist), &objects, &mut out);
+ let mut wave = wave::WaveConfig::default();
+ wave.counts = [40; wave::KINDS.len()];
+ wave.dist = dist;
+ wave.approach = sim::Approach::AllSides;
+ wave.aim = sim::Aim::Smart;
+ self.sim.order_raid(&wave.order(), &objects, &mut out);
} else {
let kind = DroneKind::from_key(kind).ok_or(
"Тип: shahed, geran3, lancet, gerbera, kh101, kalibr, kh22, zircon, iskander, kinzhal, oreshnik или mix",