12 lines
2.4 KiB
Markdown
12 lines
2.4 KiB
Markdown
# One mortar response per delivered observation
|
|
|
|
The first firing experiment exposed a second order for the same unchanged observation after the native activity was cancelled. A cooldown alone does not make a report new. Each physical battery now owns a bounded ledger of attempted report message IDs, retained through cancellation and activity completion.
|
|
|
|
Scheduling checks report eligibility before creating a downlink; `BeginRequest` claims it before cancelling an older order or incrementing the order ID. A failed/interrupted delivery consumes that battery's attempt at that observation. A newly observed and actually delivered report has a new HQ message ID and can authorize a later attempt; the code never renews observation timestamps. Different batteries maintain independent histories, although the current authored mission has one battery.
|
|
|
|
Entries expire only after the original report is older than the unchanged 60-second report lifetime. The ledger rejects future, negative and stale observation times, invalid message IDs and excessive live entries. Its 128-entry bound exceeds the HQ's 64 retained contacts; a full ledger fails closed until entries expire. Each new mission owns a fresh ledger.
|
|
|
|
`test_mortar_report_ledger.py` executes the actual availability/claim bodies, including repeated reads without a claim, A/B/A replay, attempted timestamp renewal, exact freshness boundary, expiry pruning, capacity and fresh-round ownership. Scheduler ordering is also checked.
|
|
|
|
The [091306 native expiry run](evidence/native-2026-09-19-091306/report.json) passes 48 assertions with zero captured errors. Its unchanged synthetic observation travels through real uplink/HQ/downlink and native firing. Two physical shells are committed at original observation ages 40.459 and 50.514 seconds, then emitted; the next attempt is explicitly withheld at 61.004 seconds because that report expired. HQ remains active beyond the original deadline and through another twelve-second closure interval: the order remains the first order, two shells remain consumed, and no extra projectile appears. The observer records commitment before native inventory transfer and binds subsequent projectile events to those commitments; it does not incorrectly revoke a shell already committed while fresh. This is source-bound local evidence, not full eight-round salvo, impact accuracy or multiplayer qualification. Later production changes need their own regressions.
|