Add bounded aircraft control and verify current packaged runtime closure

This commit is contained in:
2026-09-19 13:31:51 +02:00
parent 4125018d04
commit a880e0485c
695 changed files with 79317 additions and 44 deletions
+52
View File
@@ -0,0 +1,52 @@
# Prepared physical aircraft controller
`ERR_AircraftFlight` is a production-code mechanism in the AI addon with no automatic force allocation, target selection or HQ dispatcher. The separate opt-in Workbench fixture now calls the actual controller: [123439](evidence/native-2026-09-19-123439-aircraft-controller/report.json) passes 37 assertions, including native post-spawn clearance qualification, signed pilot controls, takeoff, sustained hover, contact landing and engine-off completion. The ordinary game also compiles this code without Workbench. Operational HQ integration, longer routes, repeated-flight reliability and multiplayer remain unfinished. Earlier Core flight experiments use a separate implementation and retain separate evidence.
## Public integration contract
A future owner must already possess one finite, initialized, seated AI Mi-8 and keep the controller alive until its terminal state:
1. Call `ERR_AircraftFlightEnvelope.Qualify(mode, aircraft, pilot)`. Failure returns null, never an approximate or caller-asserted certificate.
2. Call `flight.Start(mode, aircraft, originalGroup, pilot, exactPilotSlot, qualification, uniqueOrderToken, absoluteDeadline)`. The deadline must be in the next 240 seconds. One controller is single-use; the exact aircraft also has an exclusive active-controller registry entry.
3. After the native helicopter's `OnPrepareControls`, call `PrepareHelicopter` for that exact controller. Before the pilot's native `OnPrepareControls`, call `PrepareActions` with its exact character, owner, AI-owned action manager and real frame interval. The global hardware input manager is rejected. No hook was added by this change.
4. Call `Tick()` regularly; it reads the native world clock itself. Continue after `Cancel(reason)` until `Finished()` and inspect `State()` and `Reason()`. Each input entry independently checks the stage/overall deadline and physical envelope, so a stalled owner tick cannot extend control indefinitely.
The allocating owner, eventually HQ, must supply and retain the order identity, asset reservation and authority to dispatch. This class does not claim that a positive token represents a delivered radio order. It never marks a physical asset available. A future caller must not treat every terminal state as successful completion or release a lost/captured/faulted asset for another task.
## Qualification and ownership
The immutable qualification record binds the exact mission, aircraft, seated pilot, measured world origin and conservative complete model/rotor radius. Issuance checks terrain and a 40m horizontal column swept to 60m, then the proven successor footprint algorithm: bounded entity/depth/hitzone traversal, native world model bounds, both real rotor damage pivots/sweeps and simulation rotor extents. It is restricted to the audited stock unarmed Mi-8 resource and sweep dimensions. The column query excludes only the already-existing aircraft/pilot hierarchies, each traversed with strict bounds; foreign objects remain obstacles. The 123439 native fixture executes these actual post-spawn exclusion traces and accepts their exact-instance certificate.
A record can be claimed once, within two seconds according to the native clock, by the same mission/aircraft/pilot and a positive order token. More than 0.1m of aircraft movement refuses the claim. A default-constructed record cannot be claimed. The caller cannot renew a record or set its validity fields.
`Start` additionally requires the exact original pilot/group/seat/controller relationship, enemy affiliation, no human in the group or aircraft, live conscious pilot, working fueled airframe/engine/rotors, initialized native simulation/input, awake dynamic physics and actual native ground contact. It does not wake, teleport or repair the aircraft. The future preparation owner must establish those physical prerequisites. All native control writes retain these identity/ownership checks. Missing game/world/player-manager context during teardown makes ownership false and prevents writes.
## Flight and cancellation states
The controller applies actor-local directional actions in Direct collective mode. It proves positive and negative collective consumption against the existing native rotor signal before enabling autohover. One normal engine start, fuel consumption, five continuous seconds of 7–9m hover, a native contact landing stable for two seconds, and engine-off verification complete the vertical operation. Native autohover supplies lateral stabilization; vertical Start has no horizontal command. The optional bounded translation described below has no attitude PD or route-following mode. Minimum collective remains applied while the stopped engine's rotors coast. Engine-off is not proof of rotor stop.
The original measured home stays fixed. Limits remain below 8m horizontal drift, -3m through 18m relative height, uprightness at least 0.85 and a maximum 240-second operation; each preparation/flight phase has its own shorter deadline. Failed or interrupted observations reset continuous holds. No position, velocity, health, fuel or signal setter exists.
Cancellation before flight can complete on verified ground or request a normal grounded engine shutdown. Once flight has begun, cancellation enters or retains the normal landing path and keeps its control lease; even a fresh ground-contact sample must pass the two-second landing observation. Repeated cancellation cannot renew the deadline. A completed grounded abort is `CANCELLED`; normal completion is `COMPLETE`.
Capability loss, envelope violation, deadline expiry or input failure is explicitly `FAILED`, with a reason printed and sent to the existing HQ journal when available. It is not normal completion. Grounded failures restore saved modes/LOD. An airborne fault clears only owned action requests and does not disable autohover, stop the engine, delete the pilot or claim that a safe landing occurred. Its allocating owner must retain/quarantine the physical asset as appropriate; this controller does not prove that an expired or damaged flight can always recover.
Human capture or any original group/seat/aircraft/controller ownership loss is `RELINQUISHED`. No zeros or settings restoration are written into the captured controller. The destructor is defensive cleanup only, not an airborne cancellation scheduler; owners must retain and tick live operations rather than drop them to cancel flight.
## Optional immutable horizontal target
`StartTranslation(mode, aircraft, originalGroup, pilot, exactPilotSlot, qualification, uniqueOrderToken, absoluteDeadline, worldTarget)` preserves `Start(...)` as the unchanged vertical default. It copies the absolute target X/Z **before** Start performs any native writes, requires it within five metres of the original qualified home, and fixes Y to the existing eight-metre hover altitude. There is no target setter, home rebasing or second command. It is a bounded migration of the separately proven Core translation mechanism, not route support or operational aircraft dispatch.
After the usual five-second physical hover, the controller measures the distance from its actual hover origin to that preselected target. A distance above 4.05 metres (four metres plus an explicit five-centimetre numerical/measurement tolerance) refuses translation and enters the normal retained cancellation/landing path. It never changes the target to make the test pass. Missing native cyclic signals also request controlled cancellation. Near-zero distances are permitted as a hold command but cannot substantiate movement in the native fixture.
The appended `TRANSLATING` state preserves all prior numeric state values and is explicitly nonterminal. Native autohover remains enabled. Horizontal error requests velocity capped at 0.5m/s, then a measured-velocity correction capped at 0.03 cyclic; actual world forward/right projections feed the existing exact pilot's action pairs. There is no attitude PD and no physics write. The target must remain within 0.75m with horizontal speed below 0.25m/s, the existing hover conditions, and measured progress consistent with the initial distance for five continuous seconds. Movement plus settling is limited to 45 seconds under the unchanged 240-second overall deadline. The original below-eight-metre drift, 18-metre height and tilt limits remain active in both Tick and native callbacks. Success enters the existing stable contact landing and engine-off path; cancellation during translation also retains that path. Deadline/capability faults retain the existing explicit `FAILED` quarantine contract, not a guarantee of recovery.
Read-only `TranslationStarted`, `TranslationOrigin`, `TranslationTarget`, `TranslationUpdates` and `TranslationProven` expose observation only. The opt-in `aircraft-translate` Chat fixture requests the original qualified home before takeoff. It can legitimately refuse if natural hover drift is outside the proven bound, or fail its evidence threshold if the initial drift is too small: no displacement is manufactured. The 130038 native run below qualifies this bounded path on its exact source. The existing [normal controller](evidence/native-2026-09-19-123439-aircraft-controller/report.json) and [airborne cancellation](evidence/native-2026-09-19-124915-aircraft-cancel/report.json) archives qualify their respective frozen pre-translation sources only. The latter records one Cancel at 5.08964m, 13.15s of continued control, an unchanged absolute deadline and engine-off `CANCELLED`, with 39 assertions and zero captured errors.
## Source-local checks
Run `python3 tests/test_aircraft_flight_policy.py`, `python3 tests/test_aircraft_flight_envelope.py` and `python3 tests/test_aircraft_translation.py`. The translation test executes the actual immutable-target Start wrapper, geometry/demand/hold policy and Begin/Check stage bodies, including excessive natural drift refusal, absent cyclic signal refusal, copied target ownership, interrupted hold, insufficient callbacks and original deadline preservation. They execute the actual policy, cancellation, landing/shutdown/tick, callback-lease, certificate-claim and release bodies with native boundaries adapted in the C++ harness. Cases include bounded deadlines independently enforced by callbacks, cancellation while airborne/on contact, repeated cancellation, interrupted hold, stale/moved/reused certificates, capture, ground failure restoration, and explicit fault rather than successful completion. The source-bound 123439 native fixture supplies collision, compilation, scoped input and physical vertical-flight evidence. Ordinary startup establishes compilation only; ordinary-game flight, operational dispatch and multiplayer remain separate requirements.
## Native fixed-target result
The [130038 fixed-target fixture](evidence/native-2026-09-19-130038-aircraft-target/report.json) passes 38 assertions and zero captured errors using this actual controller. The target was the original qualified home, fixed before takeoff. Native hover drift produced a 3.3096m requested movement; the helicopter physically moved 2.91183m and finished 0.399235m from that target after the sustained hold and contact landing. There were 484 translation updates, 1,572 callbacks on each native control path, one engine/controller start and one original aircraft/pilot. Its final state was COMPLETE with engine off. This establishes a bounded target command only; longer routes, dispatch and multiplayer remain unqualified.