1 gameplay authority replay fixtures and drift gates
forgejo-actions edited this page 2026-07-15 12:43:13 +00:00

Gameplay Authority Replay Fixtures And Drift Gates

Purpose

Gameplay authority replay fixtures prove that recorded or constructed authority outcomes still produce the expected command audit, wire-facing snapshots, gameplay facts, quest projection, and mob encounter state. Use them when an authority resolver, mutation id, replay adapter, quest projection, transport payload, or pack/export gate changes.

The runner is deterministic and domain-level. It does not start a game server or re-execute database writes. Server-edge tests first normalize live service output into the shared fixture shape, then use the same runner to compare stable facts.

Steps

  1. Choose the fixture kind that matches the boundary under test.

    ReplayFixtureKind Use it for
    GameplayAuthorityJson A persisted GameplayAuthorityReplayFixture with explicit steps and expected audit, wire, state, and quest values.
    RawCommandAuditJson Full recorded command_audit rows that the loader rehydrates into deterministic replay steps.
    BuiltInGameplayAuthority A fixture constructor in gameplay_authority_replay.rs for gameplay, dialogue, service, quest, or trigger flows.
    BuiltInMobEncounter A constructor covering normalized spawn, aggro, leash, reset, death, reward, actor, and gameplay-state behavior.
    ServerEdgeInline A fixture assembled inside a game-server test from service output, such as combat respawn.
    GateCommand An aggregate command that runs an owning replay test family. It describes a gate step, not one data fixture.
    RuntimeReplay A protocol, scene-preview, cutscene, or other replay command outside the gameplay-authority fixture runner.
  2. Keep the schema and identity stable. Persisted gameplay, raw command-audit, mob encounter, and manifest schemas are currently version 1. Give every fixture a non-empty, stable fixture_id; use the same id in its manifest descriptor and diagnostics.

  3. Author deterministic inputs and expected values.

    • A direct gameplay fixture supplies initial gameplay state, quest catalog/input, ordered steps, expected audit records, optional expected wire snapshots, expected authority state, and expected quest snapshot.
    • A raw command-audit fixture supplies full server row context. command_type, request_id, action_kind, session/account/character/realm fields, source and target zones, and mutation-id tags must be non-empty. Tile and revision fields are retained as source context, while the normalized replay assertions live in audit, wire, state, and quest projections.
    • A mob fixture supplies initial actor/state, ordered encounter steps, expected events, final authority state, and final actor.
    • A server-edge fixture should be built from GameplayAuthorityReplayOutcomeInput, GameplayAuthorityReplayAuditRecordInput, or the shared wire input adapter instead of inventing a second normalized DTO.
  4. Model acceptance and replay independently.

    • An accepted gameplay step applies both preview_effects and authority_effects; the runner then compares the two resulting states.
    • A rejected gameplay step still produces an audit record and wire snapshot, but applies neither effect set. If no wire snapshot is supplied, the derived snapshot reflects the unchanged authority state.
    • replayed describes where the authority result came from. It does not suppress fixture effects. An accepted, replayed step still advances the deterministic replay to the recorded result.
    • Rejected mob steps are skipped entirely: they do not update actor state, apply effects, or append the event.
    • An accepted raw audit row must have a replayable payload: mutation ids that derive gameplay effects, explicit preview or authority effects, or an explicit wire snapshot. Rejected rows may contain only audit context because they do not mutate state.
  5. Register the fixture in the static REPLAY_FIXTURE_DESCRIPTORS manifest. Set id, label, kind, repo-relative path when file-backed, consumers, gate_profiles, optional command, and human-readable assertions. Use world-domain-replay for gameplay data fixtures and pack-export for descriptors that should contribute a command to the pack/export plan.

    Manifest registration is discovery and gate metadata, not dynamic execution. The raw-audit test iterates all manifest entries of kind RawCommandAuditJson, but direct JSON, built-in, mob, and server-edge fixtures still need an owning test that loads or constructs them and calls the correct runner. A descriptor contributes to pack/export only when it has both the pack-export profile and a command; the existing world-domain-gameplay-authority-replay gate command runs the domain replay test family.

  6. Run the narrow replay tests first.

    cargo test -p aether-world-domain gameplay_authority_replay
    cargo test -p aether-game-server gameplay_action_service_output_replays_server_audit_and_transport_effects
    cargo test -p xtask replay_fixture_specs_drive_gate_commands_outputs_and_assertions
    
  7. Inspect the assembled replay gate before running the full pack/export workflow.

    cargo run -p xtask -- pack-export-gate --root . --out target/pack-export-gate --plan --format markdown
    cargo run -p xtask -- pack-export-gate --root . --out target/pack-export-gate
    

Expected Outputs

A clean gameplay report has no mismatches, no validation issues, and is_clean() == true. Its actual audit records, wire snapshots, authority state, and authority quest snapshot match the fixture; preview state and quest projection also match authority.

Gameplay drift becomes a blocking PreviewAuthorityParity validation error targeted at gameplay_authority_replay_fixture:<fixture_id>:

Drift Issue id Compare
Audit gameplay_authority_replay.audit_drift Expected and normalized command audit records.
Wire gameplay_authority_replay.wire_snapshot_drift Expected and normalized authority wire snapshots.
State gameplay_authority_replay.state_drift Preview versus authority and authority versus the golden final state.
Quest gameplay_authority_replay.quest_snapshot_drift Preview versus authority and authority versus the golden quest snapshot.

Mob reports use mob_encounter_authority_replay.event_drift for event changes and mob_encounter_authority_replay.state_drift for actor or shared gameplay-state changes. Their target kind is mob_encounter_authority_replay_fixture. Mismatch entries include stable serialized expected and actual values for test and CI output.

Common Mistakes

  • Adding a descriptor but no test that executes the new direct, built-in, mob, or server-edge fixture.
  • Marking a descriptor pack-export without a command and expecting it to create a gate command by itself.
  • Treating replayed: true as "do not apply effects" instead of as authority-result provenance.
  • Giving an accepted raw audit row only opaque mutation ids, such as an NPC label, with no derivable effects or wire payload. The loader rejects it with needs replay payload.
  • Expecting currency mutation ids to change GameplayConditionState. They are syntax-checked, but currency results belong in the explicit wire snapshot.
  • Omitting server audit context, using malformed item:quantity mutation ids, or changing a fixture schema version without changing the loader contract.
  • Updating golden expected values immediately after a failure without deciding whether authority behavior, preview behavior, or the fixture is actually stale.

Recovery Paths

For a fixture-load error, fix schema version, empty identity fields, malformed mutation ids, or the missing accepted-step payload before investigating drift. Use raw_command_audit_fixture_reports_missing_replay_payload and raw_command_audit_fixture_rejects_malformed_currency_mutation_ids as boundary examples.

For audit drift, compare command type, request id, action kind, accepted/replayed flags, normalized mutation ids, and message. For wire drift, inspect the edge adapter and explicit snapshots. For state drift, compare preview and authority effects at the first differing accepted step. For quest drift, compare the fixture's quest catalog/input and the final gameplay facts before changing the expected projection.

If a behavior change is intentional, update the owning constructor or JSON, its expected values, manifest entry, and execution test together. Rerun the domain replay test, the relevant server-edge test, the xtask descriptor test, and finally the pack/export replay step. Do not repair a code regression by changing only the golden output.