test(engine): enable Bevy system-order ambiguity detection in a headless test #143
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Review finding L5 (2026-07-06). Nothing enables Bevy's schedule ambiguity detection, so conflicting system pairs in the 49-plugin Update schedule (two systems writing the same resource/component with no ordering constraint) would only surface as rare frame-order bugs. Fix: add a headless test that builds the full app with ambiguity detection set to error (Bevy 0.18:
ScheduleBuildSettings { ambiguity_detection: LogLevel::Error, .. }viaapp.edit_schedule(Update, ...)— verify the exact API, this was flagged uncertain in the review) and asserts a clean build. Expect an initial triage pass to add.ambiguous_with/ordering where pairs are benign.Principle: in ECS, two systems that mutate the same data without an ordering edge run in nondeterministic order — make the scheduler prove there are none, rather than hoping.
🤖 Generated with Claude Code
Resolved as a ratchet (PR #145): first measurement found 302 ambiguous pairs in the headless gameplay cluster — far too many for one-pass triage, most likely benign but unproven. The schedule_checks test now pins the count at 302 and fails CI if it grows; burning the backlog down (add .before/.after or .ambiguous_with, lower AMBIGUITY_BASELINE) is incremental follow-up work. Keeping this issue open to track the burn-down; pair names need bevy's debug feature (see module doc).
Batch 1 merged (PR #146): 302 → 198 pairs (−34%). Fixed structurally: game-state ordering spine (pre-mutation chain + readers after GameMutation) and a self-ambiguous NewGameRequestWriters set. Remaining backlog: Sprite (72) and Transform (48) pairs across the card/marker/shadow/badge visual domains — needs per-domain system sets (e.g. Layout → CardVisuals → HudVisuals chain); SettingsResource (21) is the next mid-size chunk. Extraction recipe for named pairs is in the module docs + scratchpad review file.