Add typed field-flight prototype and preserve native qualification failures

This commit is contained in:
2026-09-19 21:01:20 +02:00
parent 83ea247e62
commit 61e165ef5b
91 changed files with 40570 additions and 85 deletions
+7 -1
View File
@@ -10,6 +10,12 @@ Each group, pilot and seat can appear only once in a service. A separate weak se
`StartRoute(aircraft, qualification, positiveToken, absoluteDeadline)` requires a registered, currently ready original asset and a caller-supplied `ERR_AircraftRouteEnvelope`. The controller performs the existing single qualification claim; the service never calls `Claim` or constructs a substitute qualification. The original 18–20.05 m range, terrain/clearance checks, finite fuel, native callback proof, flight bounds and deadline limits are unchanged.
`StartField(aircraft, qualification, positiveToken, absoluteDeadline)` is a separate, unqualified prototype entry point accepting only `ERR_AircraftFieldEnvelope`. It constructs only `ERR_AircraftFieldFlight`, retaining it through the common `ERR_AircraftFlight` base. No caller-supplied controller is accepted. The existing `StartRoute` still constructs its exact original route class and preserves its admission and failure behavior. Neither entry point is connected to HQ or ordinary scenario activation here.
Both kinds share the same four-asset reservation limit, 128-attempt history, `BeginAttempt` bookkeeping and start-result handling. A token attempted through one kind cannot be replayed through the other, including on a different aircraft. A pending or retired asset cannot switch kinds to bypass its state. Each controller alone validates and claims its typed certificate. Field-specific refusal, including its stricter lease or 50-native-unit fuel admission, retires the attempted asset and burns the recorded token just like a route-controller refusal; it does not trigger a fallback controller or retry. Basic null-certificate/common-admission refusals still consume no attempt.
The field controller's 100 m geometry, candidate PI/braking response, initial fuel quantity and 20-unit low-fuel abort reserve remain **unqualified physical behavior**. These quantities are not a demonstrated range model or an asserted unit of litres. The prior twenty-metre native archives above do not qualify this typed-service change or a field flight. See [the field plan](aircraft-field-route-plan.md). The allocating owner still must retain and tick the service until terminal; common-base storage does not weaken that requirement.
An accepted start attempt records its immutable token, absolute deadline and destination before calling the controller. Attempted tokens cannot be reused on any aircraft in that service, even after successful completion or a native start refusal. History is bounded to 128 attempts per service/round; exhaustion refuses additional work without dropping replay protection. Basic refusals before a ready, valid-deadline attempt consume no token. The future HQ owner must issue globally unique order tokens and must not reconstruct services to replay an old order.
If controller startup refuses after the attempt is recorded, that asset is conservatively retired for the service's lifetime. This includes a stale/already-used qualification or an external flight conflict. The service does not automatically retry, replace the pilot or mint a second order. An unexpected refusal after a nonterminal lease was established retains that flight and requests cancellation until its terminal result can be observed.
@@ -30,7 +36,7 @@ Retired entries continue to count toward the four registered assets. The service
## Verification and next integration
`python tests/test_aircraft_service.py` executes the actual service context, registration, readiness gate, start, cancellation, Tick, Stop and observation methods with fake physical/controller boundaries. It checks the four-asset limit, cross-service conflicts, duplicate tuple members, immutable tokens/destination/deadline, one delegated claim, repeated cancellation, retained airborne work, final physical readiness, capture/terminal retirement, partial-start failure and the 128-attempt replay bound. The test also checks the actual native-readiness call sites and absence of spawning, deletion, physics/input writes and scheduling. These checks are not native flight or multiplayer evidence.
`python tests/test_aircraft_service.py` executes the actual service context, registration, readiness gate, start, cancellation, Tick, Stop and observation methods with fake physical/controller boundaries. It checks the four-asset limit, cross-service conflicts, duplicate tuple members, immutable tokens/destination/deadline, one delegated claim, repeated cancellation, retained airborne work, final physical readiness, capture/terminal retirement, partial-start failure and the 128-attempt replay bound. The typed integration adds actual-method checks for known controller construction, cross-kind token replay refusal, mixed-kind attempt-budget exhaustion, field partial-start failures, and retained cancellation/Stop across both kinds. The WORKBENCH route observer casts the retained base reference back to its exact route subtype and returns null for a field flight, preventing route evidence from being relabeled. The test also checks the actual native-readiness call sites and absence of spawning, deletion, physics/input writes and scheduling. These checks are not native flight or multiplayer evidence.
The bounded native normal-route follow-up now registers the fixture's one finite aircraft/pilot after its usual physical readiness gate, then runs the same qualified20m route through this service. The separate cancellation run keeps the service alive after Stop and verifies actual continued airborne callbacks, contact landing, unchanged token/deadline, and Drained only at completion. Test refusal and capture without claiming a successful return. Production HQ radio delivery, asset authoring, empty-server scheduling and useful field-length routes remain separate work.