Planner burn rates rarely get two fuel samples: a fuel-only change writes no history row #19

Closed
opened 2026-10-13 19:23:43 -04:00 by vinny · 0 comments
Owner

Found while building the fuel watch (issue #5).

What happens. planning/fuel.py estimates burn only from at least two observed fuel samples, and PlanningStore._fuel_samples (operations/planning_store.py) takes them from observation_history. ObservationStore.apply writes a history row only when semantic(old, False) != semantic(new, False), and semantic() covers fields, position (not with motion off), route and relations, not fuel_quantities. So an aircraft flying steadily (no change of condition, status, fuel state or route) gets no new sample while its fuel falls.

Effect. Burn rate, endurance, station time, bingo time and reserve margins in planning come out unknown for most airborne aircraft until something else about them changes. The planner can't tell when a package needs a tanker on the way, and its bingo abort rule has no planned time.

Reproduce. Apply one own aircraft twice with only its fuel quantity lower (10,000 then 9,000, ten game minutes apart). observation_history has one row for it, and assess_fuel reports endurance_unknown. tests/stage4/test_fuel_watch.py builds this world.

Workaround in the fuel watch (#5). agents/fuel_watch.py keeps the readings it sees in memory. The planner has no such store.

Possible fixes.

  1. A fuel-only history row at most every N game minutes per unit (reason fuel_sample). The agent router ignores it because material_changes has nothing to route, but history views and rules would see it.
  2. A small fuel_samples table (one row per unit, fuel type and game time, bounded per unit). This needs a schema migration, and the planner and the watch would both read it.

Option 2 keeps history meaningful; option 1 needs no migration.

Found while building the fuel watch (issue #5). **What happens.** `planning/fuel.py` estimates burn only from at least two observed fuel samples, and `PlanningStore._fuel_samples` (`operations/planning_store.py`) takes them from `observation_history`. `ObservationStore.apply` writes a history row only when `semantic(old, False) != semantic(new, False)`, and `semantic()` covers `fields`, position (not with motion off), route and relations, not `fuel_quantities`. So an aircraft flying steadily (no change of condition, status, fuel state or route) gets no new sample while its fuel falls. **Effect.** Burn rate, endurance, station time, bingo time and reserve margins in planning come out `unknown` for most airborne aircraft until something else about them changes. The planner can't tell when a package needs a tanker on the way, and its bingo abort rule has no planned time. **Reproduce.** Apply one own aircraft twice with only its fuel quantity lower (10,000 then 9,000, ten game minutes apart). `observation_history` has one row for it, and `assess_fuel` reports `endurance_unknown`. `tests/stage4/test_fuel_watch.py` builds this world. **Workaround in the fuel watch (#5).** `agents/fuel_watch.py` keeps the readings it sees in memory. The planner has no such store. **Possible fixes.** 1. A fuel-only history row at most every N game minutes per unit (reason `fuel_sample`). The agent router ignores it because `material_changes` has nothing to route, but history views and rules would see it. 2. A small `fuel_samples` table (one row per unit, fuel type and game time, bounded per unit). This needs a schema migration, and the planner and the watch would both read it. Option 2 keeps history meaningful; option 1 needs no migration.
vinny closed this issue 2026-10-14 16:48:47 -04:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
vinny/CMOnet#19
No description provided.