refactor(engine): ambiguity gate covers the full cluster — batches 1-3, 585 pairs burned to zero
Test / fmt (pull_request) Successful in 4s
Test / test (pull_request) Successful in 4m13s

Port the July 7 gate-extender branch onto current master (the You-hub,
touch action bar, glass tab bar, Phase L, and hint-ghost work all landed
since) and finish batch 3. cluster_app now includes the mode, replay,
input, radial, tooltip, cursor, touch-selection, and safe-area plugins on
top of batches 1-2; the 585 ambiguous pairs the expansion exposed are
annotated down to zero and the gate stays assert_eq!(count, 0).

New ordering machinery:
- ReplayPlayback: playback driver chain on the pre-mutation spine
  (PointerInput < ReplayPlayback < overlay chain < GameMutation)
- ModeStart: mode-start handlers between the stats abandon-recorder and
  GameMutation; ChallengeCompletion < DailyCompletion < WeeklyGoalsEval
  pinned inside ProgressUpdate so `.after(ProgressUpdate)` readers see
  settled progress
- PointerInput: public set wrapping the input chain; AbandonRecord on the
  stats abandon-recorder; PendingHint around the async hint pipeline;
  HintGhostFx for the ghost chain (after the full visual spine)
- Clubs: MoveRequestWriters, WarningToastWriters join the existing
  request/toast writer clubs; UiTextFx grows the overlay/tooltip/safe-area
  chrome painters; SettingsAccess grows the lag-tolerant settings readers

Gate: cargo test --workspace green (993 engine tests), clippy
--all-targets -D warnings clean, rustfmt applied.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-16 17:42:46 -07:00
parent 099b7a263f
commit 838342649c
37 changed files with 1155 additions and 174 deletions
+23 -4
View File
@@ -11,8 +11,7 @@ use solitaire_data::{challenge_count, challenge_seed_for, save_progress_to};
use crate::events::{
GameWonEvent, InfoToastEvent, NewGameRequestEvent, StartChallengeRequestEvent,
};
use crate::game_plugin::GameMutation;
use crate::progress_plugin::{ProgressResource, ProgressStoragePath, ProgressUpdate};
use crate::progress_plugin::{ProgressResource, ProgressStoragePath};
use crate::resources::GameStateResource;
/// Minimum player level required to start a Challenge run.
@@ -38,8 +37,28 @@ impl Plugin for ChallengePlugin {
.add_message::<StartChallengeRequestEvent>()
.add_message::<InfoToastEvent>()
// Run after ProgressUpdate so we don't fight ProgressPlugin's add_xp.
.add_systems(Update, advance_on_challenge_win.after(ProgressUpdate))
.add_systems(Update, handle_start_challenge_request.before(GameMutation));
// Ordering comes from the mode-completion chain configured in
// progress_plugin; the toast it emits joins the writer club
// drained by the toast pipeline this frame (#143).
.add_systems(
Update,
advance_on_challenge_win
.in_set(crate::progress_plugin::ChallengeCompletion)
.in_set(crate::game_plugin::InfoToastWriters)
.ambiguous_with(crate::game_plugin::InfoToastWriters),
)
// ModeStart places it between the stats abandon-recorder and
// GameMutation; it shares the new-game request/toast streams
// with the other writers (#143).
.add_systems(
Update,
handle_start_challenge_request
.in_set(crate::game_plugin::ModeStart)
.in_set(crate::game_plugin::NewGameRequestWriters)
.ambiguous_with(crate::game_plugin::NewGameRequestWriters)
.in_set(crate::game_plugin::InfoToastWriters)
.ambiguous_with(crate::game_plugin::InfoToastWriters),
);
}
}