Commit Graph

162 Commits

Author SHA1 Message Date
chexit d45629ae29 Fix the UI-event fuel trap on a second large raid order
build / mod (push) Failing after 22s
The Windows log for #122 showed the mod stopping in the UI event
(fuel budget 1e9, remaining 0) with known_units <- order_raid <-
launch_wave <- ui_select: order_raid recomputed the planner snapshot
known_units() for every drone, and the snapshot itself rescanned the
whole force and the dedup list per intel entry. A second big Smart
order cost drones x intel-log x force-size inside one event.

Reproduced in actual WASM with measured per-callback fuel through the
exact ui_select(BTN_LAUNCH) handler (diagnostic guest, trigger.patch):
before, a 111-drone second order at revealed=13172/known=144 exhausted
exactly 1e9 and stopped the mod (an 11-drone order at the same state:
247805865); after, the same scenario passes with max command fuel
32946177/1e9, failures=0, and /stats at tick 2602 byte-identical.
A stacked single-point layout dies to one warhead (known=0, cheap
order), so the scenario deploys spread clusters with a moved player.

Fix: one known_units snapshot per order_raid passed to radar_strikes
and choose_target; known_units is a single O(log + force) set pass;
price_grid_on reuses its snapshot. Emitter/network targeting and
carrier choice semantics are unchanged (native equivalence test
against the former predicate; WASM checkpoint counters equal).
Limits unchanged; HD/recording untouched; wave size unrestricted.

Committed regressions: native snapshot-equivalence and
second-smart-order tests; the heavy WASM fixture now orders two Smart
raids through the wave screen's launch function (airdef preset +
airdef raid) with EW and a combat intel log, four accepted orders
asserted; the light contract covers preset and the empty-wave refusal.

Core release 195 + 8 scenarios; adapter 65 + 1 boundary + 5 scenarios;
light WASM 30 steps; heavy WASM 283 steps (tick max 182413686/300M,
command max 6939810/1e9, failures 0). Windows GUI acceptance remains
external and is not claimed.

Co-Authored-By: Kimi Code (Moonshot AI) <noreply@moonshot.cn>
2026-11-06 10:29:36 +03:00
chexit 61aaa0bf35 Record the Metal/offscreen camera picture acceptance
build / mod (push) Failing after 22s
The final engine 6a53a626c with the API30 AirDef build was run in the
real game (macOS, Apple M5, Metal, --offscreen, a clean HORIZON_HOME and
copied test worlds), not only in the sandbox: the monitor and the film's
main view report ready with the picture actually drawn (screenshots show
the panel and picture area, not a registered target), an empty set-views
drops the request, a world change bumps the generation and clears it, and
AirDef's next submission prepares the camera again in the new world.

Fixes nothing: no defect showed. It also records what the run does not
prove (a human visual check, Windows/other GPUs, two runs with the same
local id on the GPU, a mod reload on the GPU), the per-tick
set-views/set-main-view ordering that can honestly read awaiting-frame
between tick and note (not flicker), and that a title trip back into the
same world keeps the request because the generation is per world.

Co-Authored-By: Kimi Code <noreply@moonshot.cn>
2026-11-04 21:10:34 +03:00
chexit 9217f9a5cc Report camera readiness in /airdef capabilities
Pin the engine at 6a53a626c (API 30) and show render.camera-status: the
calling run's set-views cameras, whether the last noted frame was a world
frame, the request's world generation, each camera's reason and the run's
own main-view selection. As the other lines, this is a host milestone:
availability, request, preparation and why, not a GPU frame or a visible
picture. A unit test pins the line: readiness stays per camera and apart
from the run's main-view selection.

docs/ENGINE.md, the 4 November continuation and the status table now say
what prepared means (a picture encoded into the camera's target, or a
world frame drawn from it as this run's screen view, only for the run
whose selection the screen used), the per-run/per-world resets, and what
remains: GPU acceptance.

Verified: python3 tools/airdef.py check (gitlink, packer, mod needs 30,
fork 30, game 30); test-wasm 27 steps; airdef-mod 65 unit, 1 boundary and
5 scenarios; python3 -m unittest discover -s tools 28 tests.

Co-Authored-By: Kimi Code <noreply@moonshot.cn>
2026-11-04 21:08:23 +03:00
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
chexit 325119b726 refactor: validate specs without a per-kind name list
The armed/support check in load_specs named the ten armed kinds, so a new
unit type would still have required a code edit and repeated the coupling
#91 is removing. Drop it: optional missile/gun rows are still validated
generically, and the existing kind-coverage check against content.json
already ties specs to the catalog.

validate_specs now takes the document, content identities and sound
events, and a test shows a hypothetical unit kind is accepted from a
specs row plus its content entry alone. No data or balance changes.

Verified: gen_catalog --check fresh, test_gen_assets 10 tests, core
release 195 passed + 8 scenarios (7 ignored), adapter 64 unit +
1 boundary + 5 scenarios, WASM contract 27 steps.
2026-11-04 21:00:35 +03:00
chexit 0937ac9e05 fix: keep the P1-SUN motor voice at its played 1.6 pitch
The old engine_voice returned early for flame == 0 with
(DRONE_LANCET, 0.8, 1.6), so the later `P1sun => 1.7` match arm was
unreachable. The catalog migration mistook that arm for the played value
and stored 1.7, which changed the interceptor drone's flight sound.
specs.json is back to 1.6 and specs_generated.rs is regenerated.

Adds missile_engine_voices_keep_their_played_values, pinning P1-SUN to
(DRONE_LANCET, 0.8, 1.6) and M48N6 to (MISSILE_FLIGHT, 1.0, 0.88).

The continuation and handoff text now describe the early return instead
of the dead arm, and tools/airdef_assets/catalog.py gets its final
newline back.

Verified: gen_catalog --check and test_gen_assets, core release
195 passed + 8 scenarios (7 ignored), adapter 64 unit + 1 boundary +
5 scenarios, WASM contract 27 steps.
2026-11-04 21:00:35 +03:00
chexit ead87343d2 feat: generate simulation numeric profiles from catalog/specs.json
catalog/specs.json is now the single copy of the numeric rows for
DroneSpec, MissileSpec and SamSpec: speed, guidance, warheads, models'
parts, RCS, seekers, launch and motor sounds, mount drives, gravity,
the Oreshnik split height and logistics limits, plus the named part
sets. tools/gen_catalog.py generates airdef-mod/src/sim/specs_generated.rs
(included by mod.rs, so the mod and airdef-core compile the same rows)
and unit_specs_generated.rs (included by units.rs). The hand-written
spec matches are gone; DroneKind::spec, MissileKind::spec and
SamKind::spec read the generated constants.

load_specs validates the schema, sound references, kind coverage against
content.json, named-part references and unused rows. gen_catalog.py
--check already runs in the CI generated-assets step, so a JSON/Rust
drift fails the build.

Every value was compared with the literals at 632061d field by field.
The only mismatch was the P1-SUN motor voice pitch in JSON (1.6 instead
of the actual 1.7, the flame == 0 branch in voices.rs); the JSON was
corrected and behaviour is unchanged. Save keys, raid order, RNG and
gameplay traces are untouched.

Verified: core release 194 passed + 8 scenarios (7 ignored), adapter
64 unit + 1 boundary + 5 scenarios, WASM contract 27 steps, catalog and
model generators fresh, asset/sound/model-bound/report tests pass.
2026-11-04 21:00:35 +03:00
chexit abf3d76fdb docs: record the real MP4 acoustics check (#96)
Pairs of the same replay exported with acoustics on and off on the
scratch world (no HORIZON_NO_AUDIO): acoustics and capture ownership
both ready. The open field has no reverb send by design, so it shows
occlusion/air absorption only; the stone court's on-track is quieter
and darker, and its residual after a gain fit is low-passed and
stereo-decorrelated, i.e. the wet path. A clean reverb tail/RT60 in a
real MP4, echoes alone and listening remain open. No code changes.

Co-Authored-By: Kimi Code <noreply@moonshot.ai>
2026-11-04 20:52:11 +03:00
chexit e6a7000440 docs: record the engine cleanup for failed film takes
Engine 60cc7b11d removes a failed or cancelled take's video, raw sound
and log, carries the log's last lines in the error, and only creates
<name>.mp4 after a successful finish. A real failing encoder on the
scratch world left no temporaries and kept the earlier film byte for
byte; successful audio and no-audio control films still verified.

Co-Authored-By: Kimi Code <noreply@moonshot.ai>
2026-11-04 20:19:51 +03:00
chexit cec7257ea1 Pin the engine that frees a failed film take's files
horizon 60cc7b11d (on top of 57f8b2853, API 29) removes a failed or
cancelled take's video, raw sound and log, carries the log's last lines
in the error, and only creates <name>.mp4 after a successful finish.

Co-Authored-By: Kimi Code <noreply@moonshot.ai>
2026-11-04 20:17:52 +03:00
chexit 503e6e29af Fix dynamic model lighting and document GPU comparison (#123)
Co-Authored-By: Kimi Code <noreply@moonshot.ai>
2026-11-04 17:53:10 +03:00
chexit 675967ce42 End the show when its world closes and verify the MP4 lifecycle (#89)
A frame hook ends an active film or export when the world is gone. The game
stops ticking at the title screen but keeps rendering, so an export used to
keep recording the title with its playback clock frozen (a sec=10 request
produced 3898 frames) and went on after re-entering the world. Session
cleanup runs once with WorldChange and cancels the capture.

Real short exports on a scratch home and world (pin 57f8b2853, API 29,
Metal): h264+AAC both 2.07 s with non-silent audio, reported frames equal
ffprobe nb_frames; cancel, SDK refusal, encoder failure and restart all
leave no capture running; 1920x1080 works. The engine still leaves
*.audio.raw and *.ffmpeg.log behind on an encoder error (game/film.rs).

Co-Authored-By: Kimi Code <noreply@moonshot.ai>
2026-11-04 17:44:28 +03:00
chexit 632061d2ad docs: archive clean API29 WASM fuel acceptance
build / mod (push) Failing after 20s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:23:22 +03:00
chexit 56339b076e docs: hand off catalog, model, API29 and acoustics continuation
build / mod (push) Failing after 20s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:21:29 +03:00
chexit c1a595b773 feat: expose light and sound processing diagnostics with isolated cameras
build / mod (push) Failing after 21s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:19:06 +03:00
chexit 914f723d1f Verify aircraft models as lit mod instances
build / mod (push) Failing after 20s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:16:47 +03:00
chexit d45d59df9f build: pin source-manager processing handshake
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:12:53 +03:00
chexit cfae0c1253 Refine cruise silhouette and document model comparisons
build / mod (push) Failing after 19s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:09:14 +03:00
chexit 53669887dd Refine Lancet silhouette with swept X wings
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:09:14 +03:00
chexit 4c7c887917 build: pin point-light handshake and mass acoustics fixture
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:09:14 +03:00
chexit daa9ed7cbc Use catalog sound identifiers throughout runtime
build / mod (push) Failing after 19s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 16:01:19 +03:00
chexit 1553976484 Share sound identifiers and metadata with resource generation
build / mod (push) Failing after 18s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:59:18 +03:00
chexit 0c870c10d5 Represent damage diagnostics as typed reasons
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:59:18 +03:00
chexit eea1b3692e Share aircraft and item catalog with asset generation
build / mod (push) Failing after 20s
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:55:45 +03:00
chexit cb73cb7ccc Move world cache report to presentation adapter
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:55:45 +03:00
chexit 375fdf2d80 Separate battery status from player-facing text
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:55:45 +03:00
chexit 63aefc7621 test: record measured callback fuel in budget reports
Co-Authored-By: Codex <noreply@openai.com>
2026-11-04 15:55:45 +03:00
chexit d410e2c92d 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>
2026-11-03 11:39:23 +03:00
chexit ab737e7390 test: verify empty nearby depot feedback in WASM
build / mod (push) Failing after 18s
Co-authored-by: Codex <codex@openai.com>
2026-11-03 11:34:02 +03:00
chexit 3b470ddc8a build: pin optional per-callback WASM fuel profiling
The opt-in test CLI reports measured guest fuel separately from host and GPU costs; runtime limits remain unchanged.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 11:34:02 +03:00
chexit cbd6067e8f fix: explain empty strike stock and ground attack prerequisites
build / mod (push) Failing after 19s
Show typed depot cargo separately, identify an empty nearby depot, and document loading, reconnaissance, two ID namespaces and reverse pickup.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 11:26:52 +03:00
chexit cc48302b36 Exercise two maximum menu raids with terrain replies
Co-authored-by: Codex <codex@openai.com>
2026-11-03 11:26:52 +03:00
chexit 1f28f8361f Bound height cache invalidation per explosion
Co-authored-by: Codex <codex@openai.com>
2026-11-03 11:23:47 +03:00
chexit 10f24b5df8 docs: record verified overlap stress and unresolved Windows report
build / mod (push) Failing after 19s
Keep the corrected historical coverage claim, archive the real flat-world WASM run, explain trap diagnostics and the small HD trail density change.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:54:57 +03:00
chexit 293236490b test: freeze the exact budget fixture used by the runtime
build / mod (push) Failing after 17s
Derive synthetic terrain metadata from the fixture and copy the same bytes that were hashed before building.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:49:21 +03:00
chexit bf8551e1a8 Run flat terrain scenario in budget report
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:43:01 +03:00
chexit 3afebae6bd Cover HD grid during overlapping raids
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:43:01 +03:00
chexit 326817db9a Add overlapping raids budget scenario with flat terrain
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:43:01 +03:00
chexit 8f5603847e test: pin real render-query fixtures and correct raid coverage claims
build / mod (push) Failing after 18s
Archive the original budget report as insufficient proof of overlapping raids. Pin callback/fuel diagnostics and an opt-in flat render world that services actual guest queries.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:36:45 +03:00
chexit bd091e60df Exercise overlapping Oreshnik splits and recording
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:36:42 +03:00
chexit 296a64ffaa Exercise overlapping menu raids on answered terrain
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:34:31 +03:00
chexit a41a4d17cf Verify sequential raid requests in budget scenario 2026-11-03 10:32:31 +03:00
chexit 692ae77af7 Slightly densify missile smoke trails
build / mod (push) Failing after 18s
Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:25:56 +03:00
chexit 19c53fda4c docs: record API27 readiness and reverse logistics verification
build / mod (push) Failing after 19s
Document capability milestones, budget limits versus measurements, real-game no-audio observations, reverse pickup reservation and the Windows stale-URL fix.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 10:22:53 +03:00
chexit aab3e784b8 build: reuse the pinned engine target cache for its packer
build / mod (push) Failing after 18s
Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:27:02 +03:00
chexit 8d5d0d1dd7 Test WASM budget report failure paths
Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:25:28 +03:00
chexit 910f02ca92 feat: consume scoped engine capabilities and preserve safe fallbacks
build / mod (push) Failing after 19s
Pin API27, diagnose prepared states, gate capture ownership and keep far-sound fallback until acoustics is prepared. Retain engine changes in build provenance and cancel invalid return reservations after cell loss.

Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:24:46 +03:00
chexit 4dddea2e8c Add opt-in heavy WASM budget tier
Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:23:25 +03:00
chexit b0085cb3e8 Test interrupted return pickup
Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:18:44 +03:00
chexit e9fbaba1d6 Preserve pending delivery and command completion behavior
Co-authored-by: Codex <codex@openai.com>
2026-11-03 00:18:44 +03:00