[INFO] cloning repository https://github.com/tfgast/osr_ai_gm [INFO] running `Command { std: "git" "-c" "credential.helper=" "-c" "credential.helper=/workspace/cargo-home/bin/git-credential-null" "clone" "--bare" "https://github.com/tfgast/osr_ai_gm" "/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Ftfgast%2Fosr_ai_gm", kill_on_drop: false }` [INFO] [stderr] Cloning into bare repository '/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Ftfgast%2Fosr_ai_gm'... [INFO] running `Command { std: "git" "rev-parse" "HEAD", kill_on_drop: false }` [INFO] [stdout] b92161aedb24d704dadccbd073cfb0b7be447bad [INFO] testing tfgast/osr_ai_gm against try#8da20828b6ea601dfd8e2448cb50ace88876bd78 for pr-150933 [INFO] running `Command { std: "git" "clone" "/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Ftfgast%2Fosr_ai_gm" "/workspace/builds/worker-2-tc2/source", kill_on_drop: false }` [INFO] [stderr] Cloning into '/workspace/builds/worker-2-tc2/source'... [INFO] [stderr] done. [INFO] started tweaking git repo https://github.com/tfgast/osr_ai_gm [INFO] finished tweaking git repo https://github.com/tfgast/osr_ai_gm [INFO] tweaked toml for git repo https://github.com/tfgast/osr_ai_gm written to /workspace/builds/worker-2-tc2/source/Cargo.toml [INFO] validating manifest of git repo https://github.com/tfgast/osr_ai_gm on toolchain 8da20828b6ea601dfd8e2448cb50ace88876bd78 [INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "metadata" "--manifest-path" "Cargo.toml" "--no-deps", kill_on_drop: false }` [INFO] crate git repo https://github.com/tfgast/osr_ai_gm already has a lockfile, it will not be regenerated [INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "fetch" "--manifest-path" "Cargo.toml", kill_on_drop: false }` [INFO] [stderr] Blocking waiting for file lock on package cache [INFO] [stderr] Updating git repository `https://github.com/tfgast/ttrpg_dsl.git` [INFO] [stderr] Updating git submodule `https://github.com/tfgast/ttrpg-ose-data.git` [INFO] [stderr] Blocking waiting for file lock on package cache [ERROR] error running command: no output for 300 seconds [INFO] testing tfgast/osr_ai_gm against try#8da20828b6ea601dfd8e2448cb50ace88876bd78 for pr-150933 [INFO] running `Command { std: "git" "clone" "/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Ftfgast%2Fosr_ai_gm" "/workspace/builds/worker-2-tc2/source", kill_on_drop: false }` [INFO] [stderr] Cloning into '/workspace/builds/worker-2-tc2/source'... [INFO] [stderr] done. [INFO] started tweaking git repo https://github.com/tfgast/osr_ai_gm [INFO] finished tweaking git repo https://github.com/tfgast/osr_ai_gm [INFO] tweaked toml for git repo https://github.com/tfgast/osr_ai_gm written to /workspace/builds/worker-2-tc2/source/Cargo.toml [INFO] validating manifest of git repo https://github.com/tfgast/osr_ai_gm on toolchain 8da20828b6ea601dfd8e2448cb50ace88876bd78 [INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "metadata" "--manifest-path" "Cargo.toml" "--no-deps", kill_on_drop: false }` [INFO] crate git repo https://github.com/tfgast/osr_ai_gm already has a lockfile, it will not be regenerated [INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "fetch" "--manifest-path" "Cargo.toml", kill_on_drop: false }` [INFO] [stderr] Blocking waiting for file lock on package cache [INFO] [stderr] Blocking waiting for file lock on package cache [INFO] [stderr] Downloading crates ... [INFO] [stderr] Downloaded ratatui-image v3.0.0 [INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "metadata" "--no-deps" "--format-version=1", kill_on_drop: false }` [INFO] [stdout] e23925f4f1a448311b30792eb47f7370c22f0921a9a546056db069bfeae8fc04 [INFO] running `Command { std: "docker" "start" "-a" "e23925f4f1a448311b30792eb47f7370c22f0921a9a546056db069bfeae8fc04", kill_on_drop: false }` [INFO] running `Command { std: "docker" "inspect" "e23925f4f1a448311b30792eb47f7370c22f0921a9a546056db069bfeae8fc04", kill_on_drop: false }` [INFO] running `Command { std: "docker" "rm" "-f" "e23925f4f1a448311b30792eb47f7370c22f0921a9a546056db069bfeae8fc04", kill_on_drop: false }` [INFO] [stdout] e23925f4f1a448311b30792eb47f7370c22f0921a9a546056db069bfeae8fc04 [INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "build" "--frozen" "--message-format=json", kill_on_drop: false }` [INFO] [stdout] a9850607393ace0360b805abd3b792941c610acee08dc8ea36f96bb29f94fa24 [INFO] running `Command { std: "docker" "start" "-a" "a9850607393ace0360b805abd3b792941c610acee08dc8ea36f96bb29f94fa24", kill_on_drop: false }` [INFO] [stderr] Compiling proc-macro2 v1.0.106 [INFO] [stderr] Compiling quote v1.0.44 [INFO] [stderr] Compiling serde_core v1.0.228 [INFO] [stderr] Compiling serde v1.0.228 [INFO] [stderr] Compiling zerocopy v0.8.38 [INFO] [stderr] Compiling winnow v0.7.14 [INFO] [stderr] Compiling toml_write v0.1.2 [INFO] [stderr] Compiling libc v0.2.180 [INFO] [stderr] Compiling syn v2.0.114 [INFO] [stderr] Compiling getrandom v0.2.17 [INFO] [stderr] Compiling rand_core v0.6.4 [INFO] [stderr] Compiling serde_json v1.0.149 [INFO] [stderr] Compiling serde_derive v1.0.228 [INFO] [stderr] Compiling ppv-lite86 v0.2.21 [INFO] [stderr] Compiling rand_chacha v0.3.1 [INFO] [stderr] Compiling rand v0.8.5 [INFO] [stderr] Compiling toml_datetime v0.6.11 [INFO] [stderr] Compiling serde_spanned v0.6.9 [INFO] [stderr] Compiling toml_edit v0.22.27 [INFO] [stderr] Compiling toml v0.8.23 [INFO] [stderr] Compiling osr_ai_gm v0.1.0 (/opt/rustwide/workdir) [INFO] [stderr] Finished `dev` profile [unoptimized + debuginfo] target(s) in 36.54s [INFO] running `Command { std: "docker" "inspect" "a9850607393ace0360b805abd3b792941c610acee08dc8ea36f96bb29f94fa24", kill_on_drop: false }` [INFO] running `Command { std: "docker" "rm" "-f" "a9850607393ace0360b805abd3b792941c610acee08dc8ea36f96bb29f94fa24", kill_on_drop: false }` [INFO] [stdout] a9850607393ace0360b805abd3b792941c610acee08dc8ea36f96bb29f94fa24 [INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "test" "--frozen" "--no-run" "--message-format=json", kill_on_drop: false }` [INFO] [stdout] b9ad27332f463fe9ea023f89c7a60cb0bfd691d55c2d94119fd3a0b513310a95 [INFO] running `Command { std: "docker" "start" "-a" "b9ad27332f463fe9ea023f89c7a60cb0bfd691d55c2d94119fd3a0b513310a95", kill_on_drop: false }` [INFO] [stderr] Compiling osr_ai_gm v0.1.0 (/opt/rustwide/workdir) [INFO] [stderr] Finished `test` profile [unoptimized + debuginfo] target(s) in 29.38s [INFO] running `Command { std: "docker" "inspect" "b9ad27332f463fe9ea023f89c7a60cb0bfd691d55c2d94119fd3a0b513310a95", kill_on_drop: false }` [INFO] running `Command { std: "docker" "rm" "-f" "b9ad27332f463fe9ea023f89c7a60cb0bfd691d55c2d94119fd3a0b513310a95", kill_on_drop: false }` [INFO] [stdout] b9ad27332f463fe9ea023f89c7a60cb0bfd691d55c2d94119fd3a0b513310a95 [INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-2-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+8da20828b6ea601dfd8e2448cb50ace88876bd78" "test" "--frozen", kill_on_drop: false }` [INFO] [stdout] b0e55e04db9028270a24e7691a7e8b9caf3d83b789ec53a25ee2f4a016fb1423 [INFO] running `Command { std: "docker" "start" "-a" "b0e55e04db9028270a24e7691a7e8b9caf3d83b789ec53a25ee2f4a016fb1423", kill_on_drop: false }` [INFO] [stderr] Finished `test` profile [unoptimized + debuginfo] target(s) in 0.15s [INFO] [stderr] Running unittests src/lib.rs (/opt/rustwide/target/debug/deps/osr_ai_gm-3988bcab9a50fe48) [INFO] [stdout] [INFO] [stdout] running 1411 tests [INFO] [stdout] test auth::tests::constant_time_eq_different ... ok [INFO] [stdout] test auth::tests::constant_time_eq_same ... ok [INFO] [stdout] test auth::tests::generate_token_unique ... ok [INFO] [stdout] test auth::tests::generate_token_length ... ok [INFO] [stdout] test auth::tests::token_store_revoke ... ok [INFO] [stdout] test auth::tests::token_store_create_duplicate_name_rejected ... ok [INFO] [stdout] test auth::tests::constant_time_eq_different_lengths ... ok [INFO] [stdout] test backend::tests::default_config_is_all_dsl ... ok [INFO] [stdout] test auth::tests::token_store_revoke_nonexistent ... ok [INFO] [stdout] test auth::tests::default_path_respects_osr_data_dir ... ok [INFO] [stdout] test auth::tests::token_store_create_and_validate ... ok [INFO] [stdout] test backend::tests::backend_config_get ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_dungeon_level_zero_error ... ok [INFO] [stdout] test auth::tests::token_store_create_after_revoke_allowed ... ok [INFO] [stdout] test backend::tests::mechanic_group_env_suffix ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_wilderness_no_state_error ... ok [INFO] [stdout] test auth::tests::token_store_load_missing_file ... ok [INFO] [stdout] test command::exploration_cmds::tests::open_moves_through_open_door ... ok [INFO] [stdout] test command::exploration_cmds::tests::open_locked_door_rejected ... ok [INFO] [stdout] test command::exploration_cmds::tests::pick_lock_no_args ... ok [INFO] [stdout] test auth::tests::token_store_roundtrip ... ok [INFO] [stdout] test command::gm_cmds::tests::add_gold_basic ... ok [INFO] [stdout] test command::exploration_cmds::tests::pick_lock_non_thief_rejected ... ok [INFO] [stdout] test command::gm_cmds::tests::add_gold_invalid_amount ... ok [INFO] [stdout] test command::exploration_cmds::tests::pick_lock_thief_attempts ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_idle_mode_error ... ok [INFO] [stdout] test command::gm_cmds::tests::add_gold_missing_args ... ok [INFO] [stdout] test command::exploration_cmds::tests::open_no_args ... ok [INFO] [stdout] test command::exploration_cmds::tests::open_closed_door_attempts_force ... ok [INFO] [stdout] test command::gm_cmds::tests::add_gold_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::add_rations_invalid_amount ... ok [INFO] [stdout] test command::gm_cmds::tests::add_rations_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_dead_character ... ok [INFO] [stdout] test command::gm_cmds::tests::add_rations_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::award_xp_applies_prime_req_modifier ... ok [INFO] [stdout] test command::gm_cmds::tests::award_xp_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_invalid_amount ... ok [INFO] [stdout] test command::gm_cmds::tests::award_xp_dead_character ... ok [INFO] [stdout] test command::gm_cmds::tests::award_xp_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::award_xp_shows_ready_to_train ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::award_treasure_xp_applies_modifier ... ok [INFO] [stdout] test command::gm_cmds::tests::damage_kills ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::damage_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::damage_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::damage_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::gm_commands_include_new ... ok [INFO] [stdout] test command::gm_cmds::tests::gm_commands_include_train ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_invalid_monster_index ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_unknown_weapon ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_non_thief_rejected ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_no_combat ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_default_weapon ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_multi_word_weapon ... ok [INFO] [stdout] test command::gm_cmds::tests::gm_commands_include_rations ... ok [INFO] [stdout] test command::gm_cmds::tests::backstab_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::heal_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::ruling_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::ruling_empty ... ok [INFO] [stdout] test command::gm_cmds::tests::set_hp_above_max_clamps_and_warns ... ok [INFO] [stdout] test command::gm_cmds::tests::set_hp_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::heal_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::set_hp_basic ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_dungeon_outputs_all_sections ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_wilderness_outputs_all_sections ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_all_dungeon_levels ... ok [INFO] [stdout] test command::gm_cmds::tests::heal_above_max_hp_does_not_reduce ... ok [INFO] [stdout] test command::gm_cmds::tests::heal_capped_at_max ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_all_wilderness_terrains ... ok [INFO] [stdout] test command::encounter_cmds::tests::encounter_dungeon_number_appearing_positive ... ok [INFO] [stdout] test command::gm_cmds::tests::gm_only_commands_list ... ok [INFO] [stdout] test command::gm_cmds::tests::heal_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::set_hp_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::set_hp_to_zero ... ok [INFO] [stdout] test command::gm_cmds::tests::set_rations_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::set_rations_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::set_rations_zero ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_missing_args ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_basic ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_no_character ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_unknown_skill ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_non_thief_rejected ... ok [INFO] [stdout] test command::gm_cmds::tests::train_dead_character ... ok [INFO] [stdout] test command::gm_cmds::tests::train_in_combat_blocked ... ok [INFO] [stdout] test command::gm_cmds::tests::train_insufficient_gold ... ok [INFO] [stdout] test command::gm_cmds::tests::train_insufficient_xp ... ok [INFO] [stdout] test command::gm_cmds::tests::train_no_args ... ok [INFO] [stdout] test command::gm_cmds::tests::train_max_level ... ok [INFO] [stdout] test command::gm_cmds::tests::train_success ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_gear ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_insufficient_gold ... ok [INFO] [stdout] test command::inventory_cmds::tests::drop_missing_item ... ok [INFO] [stdout] test command::inventory_cmds::tests::equip_already_equipped_shows_error ... ok [INFO] [stdout] test command::inventory_cmds::tests::equip_armour_and_shield ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_suggests_arrows ... ok [INFO] [stdout] test command::inventory_cmds::tests::equip_armour_updates_ac ... ok [INFO] [stdout] test command::inventory_cmds::tests::drop_item ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_suggests_chain_mail ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_suggests_rope ... ok [INFO] [stdout] test command::gm_cmds::tests::thief_check_multi_word_skill ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_sword ... ok [INFO] [stdout] test command::inventory_cmds::tests::equip_missing_item ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_unknown_item ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_adhoc_item_in_dungeon ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_adhoc_item_in_dungeon_no_value ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_unknown_character ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_already_taken_becomes_adhoc ... ok [INFO] [stdout] test command::inventory_cmds::tests::buy_ammunition ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_from_current_room ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_item ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_item_no_value ... ok [INFO] [stdout] test command::inventory_cmds::tests::loot_zero_value_item_from_room ... ok [INFO] [stdout] test command::inventory_cmds::tests::shop_filters_by_category ... ok [INFO] [stdout] test command::inventory_cmds::tests::shop_invalid_category ... ok [INFO] [stdout] test command::inventory_cmds::tests::shop_lists_all_categories ... ok [INFO] [stdout] test command::inventory_cmds::tests::unequip_armour_resets_ac ... ok [INFO] [stdout] test command::inventory_cmds::tests::unequip_not_equipped_shows_error ... ok [INFO] [stdout] test command::lookup_cmds::tests::item_lookup_missing_args ... ok [INFO] [stdout] test command::lookup_cmds::tests::search_items_missing_args ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_missing_args ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_a ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_invalid ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_h_dragon ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_individual_p ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_lowercase ... ok [INFO] [stdout] test command::lookup_cmds::tests::treasure_type_missing_args ... ok [INFO] [stdout] test command::module_cmds::tests::load_module_success ... ok [INFO] [stdout] test command::party::tests::party_command_hides_inventory_when_empty ... ok [INFO] [stdout] test command::party::tests::party_command_shows_encumbrance_tag ... ok [INFO] [stdout] test command::party::tests::party_command_shows_resources ... ok [INFO] [stdout] test command::module_cmds::tests::load_module_requires_path ... ok [INFO] [stdout] test command::retainer_cmds::tests::dismiss_case_insensitive ... ok [INFO] [stdout] test command::retainer_cmds::tests::dismiss_not_found ... ok [INFO] [stdout] test command::retainer_cmds::tests::dismiss_numbered_retainer ... ok [INFO] [stdout] test command::party::tests::party_command_shows_inventory_section ... ok [INFO] [stdout] test command::party::tests::party_command_shows_overloaded_tag ... ok [INFO] [stdout] test command::retainer_cmds::tests::dismiss_removes_retainer ... ok [INFO] [stdout] test command::retainer_cmds::tests::hire_max_retainers_enforced ... ok [INFO] [stdout] test command::retainer_cmds::tests::hire_requires_args ... ok [INFO] [stdout] test command::retainer_cmds::tests::hire_no_party ... ok [INFO] [stdout] test command::retainer_cmds::tests::hire_unknown_class ... ok [INFO] [stdout] test command::lookup_cmds::tests::item_lookup_case_insensitive ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_case_insensitive ... ok [INFO] [stdout] test command::retainer_cmds::tests::retainers_empty ... ok [INFO] [stdout] test command::retainer_cmds::tests::retainers_lists_members ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_different_names_no_conflict ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_case_insensitive ... ok [INFO] [stdout] test command::retainer_cmds::tests::morale_check_numbered_retainer ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_no_conflict ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_multiple_conflicts ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_one_conflict ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_no_args ... ok [INFO] [stdout] test command::lookup_cmds::tests::item_lookup_exact ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_show_no_table ... ok [INFO] [stdout] test command::lookup_cmds::tests::item_lookup_not_found ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_list ... ok [INFO] [stdout] test command::lookup_cmds::tests::item_lookup_partial ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_roll_case_insensitive ... ok [INFO] [stdout] test command::lookup_cmds::tests::search_items_finds_potions ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_roll_tavern ... ok [INFO] [stdout] test command::retainer_cmds::tests::unique_name_gap_in_numbering ... ok [INFO] [stdout] test command::lookup_cmds::tests::search_items_no_results ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_exact ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_with_mu_alias ... ok [INFO] [stdout] test command::lookup_cmds::tests::search_items_groups_by_category ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_not_found ... ok [INFO] [stdout] test command::lookup_cmds::tests::spell_lookup_with_list_filter ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_show_tavern ... ok [INFO] [stdout] test command::rumor_cmds::tests::rumor_command_unknown_table ... ok [INFO] [stdout] test command::system::tests::load_invalid_path_errors ... ok [INFO] [stdout] test command::system::tests::note_delete_no_args ... ok [INFO] [stdout] test command::system::tests::note_delete_not_a_number ... ok [INFO] [stdout] test command::system::tests::note_delete_out_of_range ... ok [INFO] [stdout] test command::system::tests::note_delete_zero ... ok [INFO] [stdout] test command::system::tests::note_add ... ok [INFO] [stdout] test command::system::tests::notes_lists_all ... ok [INFO] [stdout] test command::system::tests::note_empty_args ... ok [INFO] [stdout] test command::system::tests::roll_invalid_notation_errors ... ok [INFO] [stdout] test command::system::tests::notes_empty ... ok [INFO] [stdout] test command::tests::alias_go_resolves_wilderness ... ok [INFO] [stdout] test command::tests::alias_inventory_resolves ... ok [INFO] [stdout] test command::tests::alias_status_resolves_combat ... ok [INFO] [stdout] test command::tests::alias_look_resolves ... ok [INFO] [stdout] test command::tests::alias_status_resolves_exploration ... ok [INFO] [stdout] test command::system::tests::quit_sets_quit_flag ... ok [INFO] [stdout] test command::system::tests::save_invalid_path_errors ... ok [INFO] [stdout] test command::tests::alias_take_resolves ... ok [INFO] [stdout] test command::tests::alias_go_resolves_exploration ... ok [INFO] [stdout] test command::tests::alias_status_resolves_wilderness ... ok [INFO] [stdout] test command::tests::non_alias_passes_through ... ok [INFO] [stdout] test command::tests::registry_dispatch ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_list ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_no_args ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_individual_p ... ok [INFO] [stdout] test command::system::tests::note_delete_valid ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_unknown_type ... ok [INFO] [stdout] test dice::tests::parse_case_insensitive ... ok [INFO] [stdout] test dice::tests::parse_percentile ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_type_a ... ok [INFO] [stdout] test command::treasure_cmds::tests::treasure_command_lowercase ... ok [INFO] [stdout] test dice::tests::roll_with_modifier_bounds ... ok [INFO] [stdout] test dice::tests::roll_standard_bounds ... ok [INFO] [stdout] test command::tests::successful_command_has_success_true ... ok [INFO] [stdout] test dice::tests::parse_errors ... ok [INFO] [stdout] test dice::tests::parse_rejects_excessive_sides ... ok [INFO] [stdout] test engine::chargen::tests::character_sheet_contains_key_info ... ok [INFO] [stdout] test dice::tests::parse_standard_dice ... ok [INFO] [stdout] test dice::tests::parse_with_modifier ... ok [INFO] [stdout] test dice::tests::parse_x_in_6 ... ok [INFO] [stdout] test dice::tests::roll_display ... ok [INFO] [stdout] test dice::tests::parse_rejects_excessive_count ... ok [INFO] [stdout] test dice::tests::roll_x_in_6_bounds ... ok [INFO] [stdout] test engine::chargen::tests::backward_compat_old_json ... ok [INFO] [stdout] test dice::tests::roll_percentile_bounds ... ok [INFO] [stdout] test engine::chargen::tests::create_dwarf_with_racial_mods ... ok [INFO] [stdout] test engine::chargen::tests::create_fighter ... ok [INFO] [stdout] test engine::chargen::tests::chargen_full_pipeline ... ok [INFO] [stdout] test engine::chargen::tests::roll_hp_minimum_1 ... ok [INFO] [stdout] test engine::chargen::tests::thac0_martial_level_1 ... ok [INFO] [stdout] test engine::chargen::tests::roll_abilities_bounds ... ok [INFO] [stdout] test engine::chargen::tests::thac0_martial_progression ... ok [INFO] [stdout] test engine::chargen::tests::thac0_non_martial_progression ... ok [INFO] [stdout] test engine::chargen::tests::thac0_semi_martial_progression ... ok [INFO] [stdout] test engine::chargen::tests::create_thief_ac_with_dex ... ok [INFO] [stdout] test engine::chargen::tests::roll_gold_3d6x10 ... ok [INFO] [stdout] test engine::chargen::tests::create_magic_user ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_rejected_with_pure_missile_weapon ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_rejected_at_ranged_distance_with_melee_weapon ... ok [INFO] [stdout] test command::tests::unknown_command_is_error ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_with_dagger_at_ranged_distance_rejected ... ok [INFO] [stdout] test command::tests::unknown_command ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_cannot_cast_twice_per_round ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_fails_without_declaration ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_resolves_declared_spell ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_succeeds_at_melee_distance ... ok [INFO] [stdout] test engine::combat::actions::tests::attack_guard_is_case_insensitive ... ok [INFO] [stdout] test engine::chargen::tests::roll_hp_bounds ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_no_combat_error ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_marks_character_acted ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_clears_declaration ... ok [INFO] [stdout] test engine::chargen::tests::serialization_with_new_fields ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_unknown_character_error ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_damage_does_not_exceed_weapon_max_times_multiplier_plus_str ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_str_mod_not_multiplied ... ok [INFO] [stdout] test engine::combat::actions::tests::backstab_with_dagger_at_melee_range_succeeds ... ok [INFO] [stdout] test engine::combat::actions::tests::expiry_messages_in_combat_log ... ok [INFO] [stdout] test engine::combat::actions::tests::fighting_withdrawal_distance_moved_is_nonzero ... ok [INFO] [stdout] test engine::combat::actions::tests::character_can_attack_again_after_new_round ... ok [INFO] [stdout] test engine::combat::actions::tests::combat_status_returns_status_string ... ok [INFO] [stdout] test engine::combat::actions::tests::declare_spell_rejected_when_slots_exhausted ... ok [INFO] [stdout] test engine::combat::actions::tests::different_monsters_can_attack_same_round ... ok [INFO] [stdout] test engine::chargen::tests::roll_abilities_deterministic ... ok [INFO] [stdout] test engine::combat::actions::tests::combat_status_no_combat_error ... ok [INFO] [stdout] test engine::combat::actions::tests::end_combat_distributes_xp_to_survivors ... ok [INFO] [stdout] test engine::combat::actions::tests::end_combat_no_xp_when_no_kills ... ok [INFO] [stdout] test engine::combat::actions::tests::end_combat_xp_applies_prime_req_modifier ... ok [INFO] [stdout] test engine::combat::actions::tests::disrupted_spell_still_consumes_slot ... ok [INFO] [stdout] test engine::combat::actions::tests::cast_spell_reports_disruption ... ok [INFO] [stdout] test engine::combat::actions::tests::monster_attack_twice_same_round_is_rejected ... ok [INFO] [stdout] test engine::combat::actions::tests::monster_attack_allowed_after_new_round ... ok [INFO] [stdout] test engine::combat::actions::tests::end_combat_xp_excludes_dead_party_members ... ok [INFO] [stdout] test engine::combat::actions::tests::multi_attack_monster_can_attack_three_times ... ok [INFO] [stdout] test engine::combat::actions::tests::multi_attack_resets_on_new_round ... ok [INFO] [stdout] test engine::combat::actions::tests::multiple_slots_allow_multiple_casts ... ok [INFO] [stdout] test engine::combat::actions::tests::multiple_effects_across_characters_and_monsters ... ok [INFO] [stdout] test engine::combat::actions::tests::roll_initiative_allowed_after_attack ... ok [INFO] [stdout] test engine::combat::actions::tests::roll_initiative_twice_without_action_is_rejected ... ok [INFO] [stdout] test engine::combat::actions::tests::same_character_cannot_attack_twice_per_round ... ok [INFO] [stdout] test engine::combat::actions::tests::roll_initiative_allowed_after_morale_check ... ok [INFO] [stdout] test engine::combat::actions::tests::roll_initiative_allowed_after_monster_attack ... ok [INFO] [stdout] test engine::combat::actions::tests::set_helpless_marks_monster ... ok [INFO] [stdout] test engine::combat::actions::tests::set_helpless_unmarks_monster ... ok [INFO] [stdout] test engine::combat::actions::tests::same_character_cannot_declare_spell_twice_per_round ... ok [INFO] [stdout] test engine::combat::actions::tests::set_helpless_out_of_range_error ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_combat_active_error ... ok [INFO] [stdout] test engine::combat::actions::tests::single_attack_monster_still_blocked_after_one ... ok [INFO] [stdout] test engine::combat::actions::tests::set_helpless_dead_monster_error ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_module_monster ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_no_unspawned_error ... ok [INFO] [stdout] test engine::combat::actions::tests::spell_declaration_allowed_after_new_round ... ok [INFO] [stdout] test engine::combat::actions::tests::spell_declaration_guard_is_case_insensitive ... ok [INFO] [stdout] test engine::combat::actions::tests::turned_monster_cannot_attack ... ok [INFO] [stdout] test engine::combat::actions::tests::tick_rounds_effect_on_character_in_combat ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_no_dungeon_error ... ok [INFO] [stdout] test engine::combat::actions::tests::tick_rounds_effect_on_monster_decrements_and_expires ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_undead_from_placed_monster ... ok [INFO] [stdout] test engine::combat::actions::tests::turns_permanent_concentration_not_ticked_by_round ... ok [INFO] [stdout] test engine::combat::golden_tests::set_helpless_parity ... ok [INFO] [stdout] test engine::combat::golden_tests::combat_status_via_shared_action ... ok [INFO] [stdout] test engine::combat::golden_tests::set_helpless_no_combat_error_parity ... ok [INFO] [stdout] test engine::combat::tests::action_next_phase_includes_actor_order ... ok [INFO] [stdout] test engine::combat::tests::action_budget_clears_on_phase_advance ... ok [INFO] [stdout] test engine::combat::tests::close_already_at_zero ... ok [INFO] [stdout] test engine::combat::tests::close_capped_by_encounter_move ... ok [INFO] [stdout] test engine::combat::tests::close_logs_entry ... ok [INFO] [stdout] test engine::combat::tests::character_hp_goes_negative ... ok [INFO] [stdout] test engine::combat::tests::close_none_caps_at_encounter_move ... ok [INFO] [stdout] test engine::combat::tests::action_budget_consume_and_query ... ok [INFO] [stdout] test engine::combat::tests::close_to_melee ... ok [INFO] [stdout] test engine::combat::tests::combat_state_actor_order_for_simultaneous_phases ... ok [INFO] [stdout] test engine::combat::tests::close_specific_feet ... ok [INFO] [stdout] test engine::combat::actions::tests::set_helpless_no_combat_error ... ok [INFO] [stdout] test engine::combat::tests::combat_state_actor_order_uses_stored_initiative ... ok [INFO] [stdout] test engine::combat::tests::combat_state_initiative_order_clears_on_new_round ... ok [INFO] [stdout] test engine::combat::tests::close_none_reaches_zero_when_closer ... ok [INFO] [stdout] test engine::combat::tests::combat_state_creation ... ok [INFO] [stdout] test engine::combat::tests::combat_status_shows_individual_initiative ... ok [INFO] [stdout] test engine::combat::tests::combat_with_single_monster_morale ... ok [INFO] [stdout] test engine::combat::tests::combat_status_shows_group_initiative ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_clears_helpless_flag ... ok [INFO] [stdout] test engine::combat::tests::combat_status_shows_helpless ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_fails_on_dead_character ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_display ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_fails_on_dead_monster ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_fails_on_non_helpless ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_kills_helpless_monster ... ok [INFO] [stdout] test engine::combat::tests::coup_de_grace_logs_result ... ok [INFO] [stdout] test engine::combat::tests::distance_tracking_across_movements ... ok [INFO] [stdout] test engine::combat::tests::fighting_withdrawal_no_free_attacks ... ok [INFO] [stdout] test engine::combat::tests::fighting_withdrawal_speed ... ok [INFO] [stdout] test engine::combat::tests::full_combat_round_sequence ... ok [INFO] [stdout] test engine::combat::tests::combat_status_display ... ok [INFO] [stdout] test engine::combat::tests::hp_goes_negative_clamped_to_dead ... ok [INFO] [stdout] test engine::combat::tests::individual_initiative_populates_order ... ok [INFO] [stdout] test engine::combat::tests::distance_saturating_add ... ok [INFO] [stdout] test engine::combat::tests::initiative_clears_disruptions_but_preserves_declarations ... ok [INFO] [stdout] test engine::combat::tests::initiative_determines_action_order ... ok [INFO] [stdout] test engine::combat::tests::initiative_model_defaults_to_group ... ok [INFO] [stdout] test engine::combat::tests::initiative_result_includes_order_for_individual ... ok [INFO] [stdout] test engine::combat::tests::initiative_roll_advances_round ... ok [INFO] [stdout] test engine::combat::tests::initiative_tie_simultaneous ... ok [INFO] [stdout] test engine::combat::tests::last_monster_killed_mid_round ... ok [INFO] [stdout] test engine::combat::tests::living_monster_tracking ... ok [INFO] [stdout] test engine::combat::tests::melee_at_distance_error_suggests_close_and_missile_weapons ... ok [INFO] [stdout] test engine::combat::tests::melee_attack_damage_applied ... ok [INFO] [stdout] test engine::combat::tests::melee_attack_logs ... ok [INFO] [stdout] test engine::combat::tests::melee_attack_resolves ... ok [INFO] [stdout] test engine::combat::tests::melee_range_allows_10_feet ... ok [INFO] [stdout] test engine::combat::tests::missile_attack_dead_monster_returns_err ... ok [INFO] [stdout] test engine::combat::tests::melee_range_fails_beyond_10_feet ... ok [INFO] [stdout] test engine::combat::tests::missile_attack_melee_range_error ... ok [INFO] [stdout] test engine::combat::tests::missile_attack_nonexistent_monster_returns_err ... ok [INFO] [stdout] test engine::combat::tests::missile_attack_out_of_range ... ok [INFO] [stdout] test engine::combat::tests::monster_attack_ogre_damage ... ok [INFO] [stdout] test engine::combat::tests::monster_attack_disrupts_declared_spell ... ok [INFO] [stdout] test engine::combat::tests::monster_attack_resolves ... ok [INFO] [stdout] test engine::combat::tests::monster_multiple_attacks_same_round ... ok [INFO] [stdout] test engine::combat::tests::morale_check_bounds ... ok [INFO] [stdout] test engine::combat::tests::morale_check_per_type ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_unresolved_monster_error ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_marks_spawned ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_core_db_monster ... ok [INFO] [stdout] test engine::combat::tests::morale_trigger_first_death ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_partial_success_with_unresolved ... ok [INFO] [stdout] test engine::combat::tests::missile_attack_in_range ... ok [INFO] [stdout] test engine::combat::tests::morale_score_12_never_flees ... ok [INFO] [stdout] test engine::combat::actions::tests::spawn_placed_name_filter ... ok [INFO] [stdout] test engine::combat::tests::morale_trigger_half_killed ... ok [INFO] [stdout] test engine::combat::tests::morale_trigger_simultaneous_first_and_half ... ok [INFO] [stdout] test engine::combat::tests::morale_score_2_always_flees ... ok [INFO] [stdout] test engine::combat::tests::multi_round_all_phases ... ok [INFO] [stdout] test engine::combat::tests::non_caster_not_disrupted ... ok [INFO] [stdout] test engine::combat::tests::phase_advancement_full_cycle ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_initiative_ordered_monsters_first ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_simultaneous_phases ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_initiative_ordered_party_first ... ok [INFO] [stdout] test engine::combat::tests::retreat_turned_monsters_dont_attack ... ok [INFO] [stdout] test engine::combat::tests::set_helpless_fails_on_dead ... ok [INFO] [stdout] test engine::combat::tests::set_helpless_marks_monster ... ok [INFO] [stdout] test engine::combat::tests::set_helpless_unmarks_monster ... ok [INFO] [stdout] test engine::combat::tests::spell_declaration ... ok [INFO] [stdout] test engine::combat::tests::retreat_resolves_multiple_free_attacks ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_simultaneous_initiative ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_morale_monsters_only ... ok [INFO] [stdout] test engine::combat::tests::retreat_dead_monsters_dont_attack ... ok [INFO] [stdout] test engine::combat::tests::spell_disruption_multiple_casters ... ok [INFO] [stdout] test engine::combat::tests::spell_not_disrupted_if_missed ... ok [INFO] [stdout] test engine::combat::tests::spell_disruption_on_damage ... ok [INFO] [stdout] test engine::combat::tests::spell_disruption_cleared_on_new_round ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_destroy_kills_monsters ... ok [INFO] [stdout] test engine::combat::tests::retreat_grants_free_attacks ... ok [INFO] [stdout] test engine::combat::tests::phase_actor_order_end_of_round_system ... ok [INFO] [stdout] test engine::combat::tests::retreat_speed ... ok [INFO] [stdout] test engine::combat::tests::retreat_stops_if_character_dies ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_skeleton_level_3 ... ok [INFO] [stdout] test engine::combat::tests::tpk_detection ... ok [INFO] [stdout] test engine::encounter_engine::tests::begin_encounter_dungeon_sequence ... ok [INFO] [stdout] test engine::encounter_engine::tests::evasion_display ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_hd_exhaustion ... ok [INFO] [stdout] test engine::encounter_engine::tests::begin_encounter_wilderness_sequence ... ok [INFO] [stdout] test engine::encounter_engine::tests::evasion_faster_party_auto_success ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_display ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_skips_non_undead_in_mixed_encounter ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_impossible ... ok [INFO] [stdout] test engine::encounter_engine::tests::dungeon_distance_normal_bounds ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_friendly ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_skips_already_turned ... ok [INFO] [stdout] test engine::encounter_engine::tests::dungeon_distance_surprised_bounds ... ok [INFO] [stdout] test engine::encounter::golden_tests::encounter_command_parity_compatibility_gates ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_roll_with_low_cha ... ok [INFO] [stdout] test engine::combat::tests::turn_undead_mixed_types ... ok [INFO] [stdout] test engine::combat::golden_tests::combat_command_parity_golden_scaffold_captures_snapshots ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_roll_with_high_cha ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_hostile ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_indifferent ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_uncertain ... ok [INFO] [stdout] test engine::encounter_engine::tests::surprise_display ... ok [INFO] [stdout] test engine::encounter_engine::tests::reaction_unfriendly ... ok [INFO] [stdout] test engine::exploration::actions::tests::global_effects_tick_during_exploration ... ok [INFO] [stdout] test engine::exploration::actions::tests::advance_turn_ticks_turn_effects ... ok [INFO] [stdout] test engine::exploration::actions::tests::listen_at_door_ticks_turn_effects ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_advance ... ok [INFO] [stdout] test engine::exploration::actions::tests::rest_ticks_turn_effects ... ok [INFO] [stdout] test engine::exploration::actions::tests::search_room_ticks_turn_effects ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_listen ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_move ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_force ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_pick ... ok [INFO] [stdout] test engine::exploration::tests::advance_turn_tracks_time ... ok [INFO] [stdout] test engine::exploration::tests::action_phases_exp_search ... ok [INFO] [stdout] test engine::exploration::actions::tests::round_effects_not_ticked_by_exploration ... ok [INFO] [stdout] test engine::encounter_engine::tests::evasion_small_party_vs_more_monsters ... ok [INFO] [stdout] test engine::exploration::tests::darkness_blocks_exploration ... ok [INFO] [stdout] test engine::exploration::tests::action_trap_notifies_gm_on_entry ... ok [INFO] [stdout] test engine::exploration::tests::exploration_status_display ... ok [INFO] [stdout] test engine::encounter_engine::tests::evasion_small_party_vs_fewer_monsters ... ok [INFO] [stdout] test engine::exploration::tests::check_trap_can_trigger ... ok [INFO] [stdout] test engine::encounter_engine::tests::wilderness_distance_bounds ... ok [INFO] [stdout] test engine::exploration::tests::darkness_blocks_door_movement ... ok [INFO] [stdout] test engine::exploration::tests::advance_turn_marks_explored ... ok [INFO] [stdout] test engine::exploration::tests::entry_trap_still_triggers_on_room_entry ... ok [INFO] [stdout] test engine::exploration::tests::explore_no_torch_status_in_darkness ... ok [INFO] [stdout] test engine::exploration::tests::explore_output_includes_torch_status ... ok [INFO] [stdout] test engine::exploration::tests::encounter_result_includes_next_steps ... ok [INFO] [stdout] test engine::exploration::tests::door_auto_closes_after_passing ... ok [INFO] [stdout] test engine::exploration::tests::force_open_door_no_op ... ok [INFO] [stdout] test engine::exploration::tests::force_door_success ... ok [INFO] [stdout] test engine::exploration::tests::listen_at_door_consumes_turn ... ok [INFO] [stdout] test engine::exploration::tests::force_locked_door_refused ... ok [INFO] [stdout] test engine::exploration::tests::move_cross_level_updates_dungeon_level ... ok [INFO] [stdout] test engine::exploration::tests::move_into_cleared_room_does_not_spawn_monsters ... ok [INFO] [stdout] test engine::exploration::tests::module_open_door_does_not_auto_close ... ok [INFO] [stdout] test engine::exploration::tests::move_into_room_spawns_placed_monsters ... ok [INFO] [stdout] test engine::exploration::tests::listen_output_includes_torch_status ... ok [INFO] [stdout] test engine::exploration::tests::move_back_up_ascends_level ... ok [INFO] [stdout] test engine::exploration::tests::action_trap_does_not_trigger_on_room_entry ... ok [INFO] [stdout] test engine::exploration::tests::move_through_door_not_connected_to_current_room ... ok [INFO] [stdout] test engine::exploration::tests::move_output_includes_torch_status ... ok [INFO] [stdout] test engine::exploration::tests::move_through_closed_door_fails ... ok [INFO] [stdout] test engine::encounter_engine::tests::surprise_produces_valid_results ... ok [INFO] [stdout] test engine::exploration::tests::listen_at_door_basic ... ok [INFO] [stdout] test engine::exploration::tests::lantern_lasts_longer_than_torch ... ok [INFO] [stdout] test engine::exploration::tests::move_to_nonexistent_room_fails ... ok [INFO] [stdout] test engine::exploration::tests::no_encounter_means_no_next_steps ... ok [INFO] [stdout] test engine::exploration::tests::move_through_door_triggers_trap ... ok [INFO] [stdout] test engine::exploration::tests::move_through_open_door ... ok [INFO] [stdout] test engine::exploration::tests::no_level_keys_means_no_transition ... ok [INFO] [stdout] test engine::exploration::tests::pick_lock_failure ... ok [INFO] [stdout] test engine::exploration::tests::pick_lock_non_thief_rejected ... ok [INFO] [stdout] test engine::exploration::tests::pick_lock_not_locked_rejected ... ok [INFO] [stdout] test engine::exploration::tests::re_entering_room_after_spawn_does_not_spawn_again ... ok [INFO] [stdout] test engine::exploration::tests::room_with_no_placed_content_works_normally ... ok [INFO] [stdout] test engine::exploration::tests::placed_monsters_report_undead_tag ... ok [INFO] [stdout] test engine::exploration::tests::pick_lock_door_not_found ... ok [INFO] [stdout] test engine::exploration::tests::pick_lock_success ... ok [INFO] [stdout] test engine::exploration::tests::same_level_move_no_transition_message ... ok [INFO] [stdout] test engine::exploration::tests::search_consumes_a_turn ... ok [INFO] [stdout] test engine::exploration::tests::search_looted_room_finds_no_treasure ... ok [INFO] [stdout] test engine::exploration::tests::search_finds_secret_door ... ok [INFO] [stdout] test engine::exploration::tests::rest_requirement_message_after_5_turns ... ok [INFO] [stdout] test engine::exploration::tests::torch_expires_during_exploration ... ok [INFO] [stdout] test engine::exploration::tests::search_room_finds_placed_treasure ... ok [INFO] [stdout] test engine::exploration::tests::search_room_basic ... ok [INFO] [stdout] test engine::exploration::tests::search_room_twice_only_yields_treasure_once ... ok [INFO] [stdout] test engine::exploration::tests::skip_exploration_phase_check_rest_skipped_when_not_needed ... ok [INFO] [stdout] test engine::exploration::tests::skip_exploration_phase_check_light_never_skipped ... ok [INFO] [stdout] test engine::exploration::tests::search_output_includes_torch_status ... ok [INFO] [stdout] test engine::exploration::tests::skip_exploration_phase_darkness_blocks_all_after_check_light ... ok [INFO] [stdout] test engine::exploration::tests::skip_exploration_phase_no_skip_when_light_present ... ok [INFO] [stdout] test engine::exploration::tests::status_shows_level_key_after_transition ... ok [INFO] [stdout] test engine::exploration::tests::stuck_door_treated_as_closed_for_forcing ... ok [INFO] [stdout] test engine::exploration::tests::turn_phases_check_light_is_first ... ok [INFO] [stdout] test engine::exploration::tests::turn_phases_contains_six_expected_phases ... ok [INFO] [stdout] test engine::exploration::tests::wandering_monster_check_every_2_turns ... ok [INFO] [stdout] test engine::gm::actions::tests::add_note_empty_rejected ... ok [INFO] [stdout] test engine::gm::actions::tests::add_note_multiple ... ok [INFO] [stdout] test engine::gm::actions::tests::add_rations_normal_addition ... ok [INFO] [stdout] test engine::gm::actions::tests::add_rations_zero_rejected ... ok [INFO] [stdout] test engine::gm::actions::tests::award_treasure_xp_basic ... ok [INFO] [stdout] test engine::gm::actions::tests::award_treasure_xp_no_character ... ok [INFO] [stdout] test engine::gm::actions::tests::award_treasure_xp_zero_amounts ... ok [INFO] [stdout] test engine::gm::actions::tests::award_treasure_xp_ready_to_train ... ok [INFO] [stdout] test engine::gm::actions::tests::award_xp_near_max_no_overflow ... ok [INFO] [stdout] test engine::gm::actions::tests::delete_note_basic ... ok [INFO] [stdout] test engine::gm::actions::tests::add_note_basic ... ok [INFO] [stdout] test engine::gm::actions::tests::delete_note_out_of_range ... ok [INFO] [stdout] test engine::gm::actions::tests::delete_note_zero_rejected ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_insufficient_xp ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_hp_increases ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_max_level ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_no_character ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_no_gold_cost ... ok [INFO] [stdout] test engine::gm::actions::tests::award_xp_normal_addition ... ok [INFO] [stdout] test engine::exploration::tests::wandering_monster_never_on_odd_turns ... ok [INFO] [stdout] test engine::gm::actions::tests::add_rations_near_max_no_overflow ... ok [INFO] [stdout] test engine::gm::actions::tests::delete_note_empty_list ... ok [INFO] [stdout] test engine::gm::actions::tests::level_up_vs_train_cost_distinction ... ok [INFO] [stdout] test engine::gm::actions::tests::list_notes_empty ... ok [INFO] [stdout] test engine::gm::actions::tests::list_notes_returns_indexed ... ok [INFO] [stdout] test engine::gm::actions::tests::ruling_adds_prefixed_note ... ok [INFO] [stdout] test engine::gm::actions::tests::thief_skill_check_dead_character_rejected ... ok [INFO] [stdout] test engine::gm::actions::tests::train_dead_character ... ok [INFO] [stdout] test engine::gm::actions::tests::train_deducts_gold ... ok [INFO] [stdout] test engine::gm::actions::tests::train_in_combat_blocked ... ok [INFO] [stdout] test engine::gm::actions::tests::train_insufficient_gold ... ok [INFO] [stdout] test engine::gm::actions::tests::train_insufficient_xp ... ok [INFO] [stdout] test engine::gm::actions::tests::train_no_character ... ok [INFO] [stdout] test engine::gm::golden_tests::award_treasure_xp_error_parity ... ok [INFO] [stdout] test engine::gm::golden_tests::delete_note_error_parity ... ok [INFO] [stdout] test engine::gm::golden_tests::award_treasure_xp_parity ... ok [INFO] [stdout] test engine::gm::golden_tests::delete_note_parity ... ok [INFO] [stdout] test engine::gm::golden_tests::note_vs_ruling_intentional_divergence ... ok [INFO] [stdout] test engine::gm::golden_tests::list_notes_parity ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_chain_mail_with_space_resolves_to_chainmail ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_improvised_weapon_not_free ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_leather_armor_suggests_leather ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_plate_mail_with_extra_space_resolves ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_holy_water_costs_gp ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_war_hammer_without_space_resolves ... ok [INFO] [stdout] test engine::gm::golden_tests::treasure_module_command_parity_golden_scaffold_captures_snapshots ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_stores_weight_in_pounds ... ok [INFO] [stdout] test engine::inventory::actions::tests::drop_item ... ok [INFO] [stdout] test engine::encounter_engine::tests::evasion_large_party_low_chance ... ok [INFO] [stdout] test engine::exploration::tests::elf_has_better_secret_door_detection ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_suggests_chainmail ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_sword ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_thieves_tools_without_apostrophe ... ok [INFO] [stdout] test engine::inventory::actions::tests::buy_torch_costs_gp ... ok [INFO] [stdout] test engine::inventory::actions::tests::equip_updates_ac ... ok [INFO] [stdout] test engine::inventory::actions::tests::list_equipment_all_have_cost ... ok [INFO] [stdout] test engine::inventory::actions::tests::list_equipment_contains_sword ... ok [INFO] [stdout] test engine::inventory::actions::tests::list_equipment_has_items ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_adhoc_item_in_dungeon_no_value ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_adhoc_item_in_dungeon ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_from_current_room_marks_treasure_taken ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_invalid_character_does_not_consume_treasure ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_ambiguous_match_returns_error ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_no_match_still_creates_adhoc ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_normalized_match_strips_punctuation ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_case_insensitive_substring ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_substring_match_finds_brooch ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_substring_match_uses_canonical_name ... ok [INFO] [stdout] test engine::inventory::actions::tests::list_equipment_contains_chainmail ... ok [INFO] [stdout] test engine::inventory::actions::tests::loot_taken_items_not_matched ... ok [INFO] [stdout] test engine::lookup::actions::tests::action_lookup_item_exact_match ... ok [INFO] [stdout] test engine::lookup::actions::tests::action_lookup_spell_with_list ... ok [INFO] [stdout] test engine::lookup::actions::tests::action_lookup_treasure_type_returns_entries ... ok [INFO] [stdout] test engine::lookup::actions::tests::parse_spell_list_aliases ... ok [INFO] [stdout] test engine::lookup::actions::tests::action_roll_treasure_type_p_has_copper ... ok [INFO] [stdout] test engine::module::actions::tests::load_module_monsters_bare_array ... ok [INFO] [stdout] test engine::module::actions::tests::load_module_monsters_wrapped_format ... ok [INFO] [stdout] test engine::inventory::golden_tests::inventory_command_parity_golden_scaffold_captures_snapshots ... ok [INFO] [stdout] test engine::inventory::actions::tests::equip_second_body_armour_rejected ... ok [INFO] [stdout] test engine::lookup::golden_tests::lookup_empty_query_parity_restored ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_creates_rooms ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_creates_doors ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_entry_room_is_current ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_deterministic_room_ids ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_builds_level_map ... ok [INFO] [stdout] test engine::module::actions::tests::load_module_rejects_during_combat ... ok [INFO] [stdout] test engine::module::actions::tests::load_module_rejects_during_exploration ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_door_states ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_item_treasure_with_value_gp ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_loads_monsters ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_logs_load ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_no_levels_has_no_level_keys ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_propagates_rich_content ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_propagates_connection_type ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_propagates_undead ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_rich_content_defaults_empty ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_propagates_trap_trigger ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_room_descriptions ... ok [INFO] [stdout] test engine::lookup::actions::tests::action_search_items_finds_results ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_sets_level ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_open_doors_are_module_open ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_loads_treasure ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_sets_level_keys ... ok [INFO] [stdout] test engine::party::actions::tests::query_party_empty_inventory ... ok [INFO] [stdout] test engine::party::actions::tests::query_party_includes_inventory_summary ... ok [INFO] [stdout] test engine::result::tests::display_uses_wrapped_message ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_status_shows_level_key ... ok [INFO] [stdout] test engine::party::actions::tests::query_party_includes_rations_and_gold ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_sets_room_keys ... ok [INFO] [stdout] test engine::retainer::tests::hiring_reaction_accepts ... ok [INFO] [stdout] test engine::retainer::tests::hiring_reaction_eager ... ok [INFO] [stdout] test engine::retainer::tests::hiring_reaction_hostile ... ok [INFO] [stdout] test engine::party::golden_tests::party_command_parity_golden_scaffold_captures_snapshots ... ok [INFO] [stdout] test engine::module::actions::tests::module_to_dungeon_sets_current_level_key ... ok [INFO] [stdout] test engine::retainer::tests::hiring_reaction_reluctant ... ok [INFO] [stdout] test engine::retainer::tests::hiring_reaction_uncertain ... ok [INFO] [stdout] test engine::retainer::tests::loyalty_check_disloyal ... ok [INFO] [stdout] test engine::retainer::tests::hiring_with_rng ... ok [INFO] [stdout] test engine::retainer::tests::loyalty_check_loyal ... ok [INFO] [stdout] test engine::retainer::tests::loyalty_check_wavering ... ok [INFO] [stdout] test engine::retainer::tests::max_retainers_by_cha ... ok [INFO] [stdout] test engine::retainer::tests::retainer_creation ... ok [INFO] [stdout] test engine::party::actions::tests::query_party_overloaded_character ... ok [INFO] [stdout] test engine::retainer::tests::retainer_xp_half_share ... ok [INFO] [stdout] test engine::lookup::golden_tests::lookup_happy_path_cli_api_and_state_parity ... ok [INFO] [stdout] test engine::retainer::tests::standard_wages ... ok [INFO] [stdout] test engine::retainer::tests::base_loyalty_by_cha ... ok [INFO] [stdout] test engine::retainers::actions::tests::hire_assess_unknown_employer ... ok [INFO] [stdout] test engine::retainers::actions::tests::dismiss_case_insensitive ... ok [INFO] [stdout] test engine::retainers::actions::tests::hire_recruit_checks_max ... ok [INFO] [stdout] test engine::retainers::actions::tests::unique_name_multiple_conflicts ... ok [INFO] [stdout] test engine::retainers::actions::tests::unique_name_no_conflict ... ok [INFO] [stdout] test engine::rumor::actions::tests::list_rumor_tables ... ok [INFO] [stdout] test engine::rumor::actions::tests::lookup_rumor_table_unknown ... ok [INFO] [stdout] test engine::rumor::actions::tests::lookup_rumor_table_tavern ... ok [INFO] [stdout] test engine::rumor::actions::tests::roll_rumor_unknown_table ... ok [INFO] [stdout] test engine::spell_management::tests::long_rest_recharges_spell_points ... ok [INFO] [stdout] test engine::spell_management::tests::long_rest_recharges_slots ... ok [INFO] [stdout] test engine::rumor::actions::tests::roll_rumor_tavern ... ok [INFO] [stdout] test engine::rumor::actions::tests::roll_rumor_case_insensitive ... ok [INFO] [stdout] test engine::rumor::actions::tests::roll_rumor_has_truth_marker ... ok [INFO] [stdout] test engine::spell_management::tests::long_rest_skips_non_casters ... ok [INFO] [stdout] test engine::combat::tests::dead_monster_cannot_attack - should panic ... ok [INFO] [stdout] test engine::combat::tests::melee_attack_dead_monster_panics - should panic ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_happy_path ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_rejects_excess_slots ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_rejects_non_caster ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_rejects_too_high_level ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_rejects_unknown_spell ... ok [INFO] [stdout] test engine::spell_management::tests::prepare_spells_resets_slots_used ... ok [INFO] [stdout] test engine::system::actions::tests::action_load_game_rejects_path_like_input ... ok [INFO] [stdout] test engine::system::actions::tests::action_help_lists_commands ... ok [INFO] [stdout] test engine::system::actions::tests::action_roll_dice_invalid ... ok [INFO] [stdout] test engine::system::actions::tests::action_save_game_rejects_path_like_input ... ok [INFO] [stdout] test engine::system::actions::tests::action_roll_dice_valid ... ok [INFO] [stdout] test engine::treasure::actions::tests::action_list_treasure_types_contains_categories ... ok [INFO] [stdout] test engine::retainers::golden_tests::retainer_command_parity_golden_snapshots_capture_compatibility_gates ... ok [INFO] [stdout] test engine::treasure::actions::tests::format_haul_empty ... ok [INFO] [stdout] test engine::treasure::actions::tests::action_roll_treasure_type_a_cli_output ... ok [INFO] [stdout] test engine::treasure::actions::tests::action_roll_treasure_type_p_always_has_items ... ok [INFO] [stdout] test engine::treasure::actions::tests::action_lookup_treasure_type_a ... ok [INFO] [stdout] test engine::system::actions::tests::action_save_game_creates_missing_saves_dir ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_plain_number ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_from_downtime ... ok [INFO] [stdout] test engine::system::golden_tests::system_command_parity_golden_scaffold_captures_snapshots ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_simple_dice ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_number_with_multiplier ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_dice_with_multiplier ... ok [INFO] [stdout] test engine::system::actions::tests::action_quit_success ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_dice_with_asterisk ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_2d6_multiplier ... ok [INFO] [stdout] test engine::treasure::actions::tests::parse_dice_with_x_multiplier ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_from_idle ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_rejects_already_wilderness ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_rejects_combat ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_rejects_exploration ... ok [INFO] [stdout] test engine::wilderness_engine::tests::empty_party_consumes_no_rations ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_barren_terrain_fails ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_city_terrain_fails ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_adds_rations_to_party ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_consumes_rations_and_advances_day ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_starvation_during_forage ... ok [INFO] [stdout] test engine::wilderness::actions::tests::enter_wilderness_rejects_chargen ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_in_forest ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_returns_quantity_on_success ... ok [INFO] [stdout] test engine::wilderness_engine::tests::hunt_basic ... ok [INFO] [stdout] test engine::wilderness_engine::tests::hunt_adds_rations_to_party ... ok [INFO] [stdout] test engine::wilderness_engine::tests::multi_hex_travel_enforced ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_advances_travel_day ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_consumes_rations ... ok [INFO] [stdout] test engine::wilderness_engine::tests::hunt_returns_quantity_on_success ... ok [INFO] [stdout] test engine::wilderness_engine::tests::hunt_ocean_fails ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_failure_keeps_lost_status ... ok [INFO] [stdout] test engine::wilderness_engine::tests::hunt_consumes_rations_and_advances_day ... ok [INFO] [stdout] test engine::wilderness_engine::tests::forage_in_ocean_fails ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_logs_attempt ... ok [INFO] [stdout] test engine::wilderness_engine::tests::out_of_range_travel_no_day_advance ... ok [INFO] [stdout] test engine::wilderness_engine::tests::out_of_range_in_mountains_no_side_effects ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_when_not_lost_fails ... ok [INFO] [stdout] test engine::wilderness_engine::tests::out_of_range_travel_no_encounters ... ok [INFO] [stdout] test engine::wilderness_engine::tests::out_of_range_travel_no_rations_consumed ... ok [INFO] [stdout] test engine::wilderness_engine::tests::out_of_range_travel_no_position_change ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_can_kill ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_causes_hp_damage_after_3_days ... ok [INFO] [stdout] test engine::wilderness_engine::tests::slow_party_travels_fewer_hexes ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_penalty_calculation ... ok [INFO] [stdout] test engine::wilderness_engine::tests::terrain_movement_rates_vary ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_day_basic ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_no_hp_damage_first_two_days ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_death_excludes_already_dead ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_tracks_days_without_food ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_larger_party_consumes_more_rations ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_day_increments_day_counter ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_increments_day ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_consumes_rations ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_to_current_hex_is_noop ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_to_invalid_hex_reports_error ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_to_current_hex_after_move_is_noop ... ok [INFO] [stdout] test engine::wilderness_engine::tests::starvation_resets_when_fed ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_partial_rations_causes_starvation ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_no_rations_causes_starvation ... ok [INFO] [stdout] test engine::spell_management::tests::long_rest_skips_dead_characters ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_can_get_lost ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_when_lost_can_succeed ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_encounter_check ... ok [INFO] [stdout] test engine::wilderness_engine::tests::wilderness_status_shows_rations ... ok [INFO] [stdout] test engine::wilderness_engine::tests::wilderness_status_shows_hp_damage_warning ... ok [INFO] [stdout] test engine::wilderness_engine::tests::wilderness_status_shows_starvation ... ok [INFO] [stdout] test engine::xp::tests::apply_level_up_basic ... ok [INFO] [stdout] test engine::xp::tests::award_combined_xp ... ok [INFO] [stdout] test engine::xp::tests::award_treasure_xp ... ok [INFO] [stdout] test engine::xp::tests::award_monster_xp ... ok [INFO] [stdout] test engine::xp::tests::level_up_no_spell_change_for_fighter ... ok [INFO] [stdout] test engine::xp::tests::hp_gain_minimum_1 ... ok [INFO] [stdout] test engine::xp::tests::level_up_updates_saves ... ok [INFO] [stdout] test engine::xp::tests::not_ready_to_train_insufficient_xp ... ok [INFO] [stdout] test engine::xp::tests::thief_xp_with_dex_prime ... ok [INFO] [stdout] test gmapi::interface::tests::add_monster_no_combat_error ... ok [INFO] [stdout] test engine::xp::tests::level_up_updates_spell_slots_for_caster ... ok [INFO] [stdout] test engine::wilderness_engine::tests::wilderness_status_display ... ok [INFO] [stdout] test engine::xp::tests::ready_to_train_when_xp_sufficient ... ok [INFO] [stdout] test engine::xp::tests::low_prime_req_penalty ... ok [INFO] [stdout] test gmapi::interface::tests::add_room_no_dungeon ... ok [INFO] [stdout] test gmapi::interface::tests::award_xp_no_character ... ok [INFO] [stdout] test gmapi::interface::tests::close_command_integration ... ok [INFO] [stdout] test gmapi::interface::tests::add_monster_single_named_correctly ... ok [INFO] [stdout] test gmapi::interface::tests::add_monster_to_active_combat ... ok [INFO] [stdout] test gmapi::interface::tests::combat_already_active ... ok [INFO] [stdout] test gmapi::interface::tests::eligible_classes_invalid_score ... ok [INFO] [stdout] test gmapi::interface::tests::create_character_and_query ... ok [INFO] [stdout] test gmapi::interface::tests::end_combat_no_combat ... ok [INFO] [stdout] test gmapi::interface::tests::end_combat_marks_room_monsters_cleared ... ok [INFO] [stdout] test gmapi::interface::tests::end_combat_no_combat_preserves_mode ... ok [INFO] [stdout] test gmapi::interface::tests::eligible_classes_success ... ok [INFO] [stdout] test gmapi::interface::tests::enter_dungeon_level_zero ... ok [INFO] [stdout] test gmapi::interface::tests::enter_dungeon_and_advance ... ok [INFO] [stdout] test gmapi::interface::tests::enter_wilderness_and_add_hex ... ok [INFO] [stdout] test gmapi::interface::tests::enter_wilderness_invalid_terrain ... ok [INFO] [stdout] test gmapi::interface::tests::fighting_withdrawal_no_free_attacks ... ok [INFO] [stdout] test gmapi::interface::tests::fighting_withdrawal_without_character_auto_selects ... ok [INFO] [stdout] test gmapi::interface::tests::heal_dead_character_rejected ... ok [INFO] [stdout] test gmapi::interface::tests::full_combat_sequence ... ok [INFO] [stdout] test gmapi::interface::tests::initiative_no_combat ... ok [INFO] [stdout] test gmapi::interface::tests::initiative_twice_without_action_rejected ... ok [INFO] [stdout] test gmapi::interface::tests::light_invalid_source ... ok [INFO] [stdout] test gmapi::interface::tests::light_not_exploring ... ok [INFO] [stdout] test gmapi::interface::tests::list_classes_success ... ok [INFO] [stdout] test gmapi::interface::tests::list_equipment_invalid_category ... ok [INFO] [stdout] test gmapi::interface::tests::list_equipment_all ... ok [INFO] [stdout] test gmapi::interface::tests::list_equipment_weapons_only ... ok [INFO] [stdout] test gmapi::interface::tests::load_module_not_found ... ok [INFO] [stdout] test gmapi::interface::tests::look_not_exploring ... ok [INFO] [stdout] test gmapi::interface::tests::load_module_path_traversal_rejected ... ok [INFO] [stdout] test gmapi::interface::tests::load_module_success ... ok [INFO] [stdout] test gmapi::interface::tests::query_combat_no_combat ... ok [INFO] [stdout] test gmapi::interface::tests::look_shows_room_description ... ok [INFO] [stdout] test gmapi::interface::tests::query_exploration_not_exploring ... ok [INFO] [stdout] test gmapi::interface::tests::query_party_empty ... ok [INFO] [stdout] test gmapi::interface::tests::query_wilderness_not_in_wilderness ... ok [INFO] [stdout] test gmapi::interface::tests::query_mode ... ok [INFO] [stdout] test gmapi::interface::tests::query_state_empty ... ok [INFO] [stdout] test gmapi::interface::tests::lookup_treasure_type_invalid ... ok [INFO] [stdout] test gmapi::interface::tests::lookup_item_success ... ok [INFO] [stdout] test gmapi::interface::tests::lookup_treasure_type_success ... ok [INFO] [stdout] test gmapi::interface::tests::quit_response ... ok [INFO] [stdout] test gmapi::interface::tests::lookup_item_not_found ... ok [INFO] [stdout] test gmapi::interface::tests::look_shows_exits ... ok [INFO] [stdout] test gmapi::interface::tests::retreat_without_character_auto_selects_sole_member ... ok [INFO] [stdout] test gmapi::interface::tests::retreat_auto_resolves_free_attacks ... ok [INFO] [stdout] test gmapi::interface::tests::roll_treasure_invalid ... ok [INFO] [stdout] test gmapi::interface::tests::retreat_without_character_errors_with_multiple_members ... ok [INFO] [stdout] test gmapi::interface::tests::retreat_no_combat_error ... ok [INFO] [stdout] test gmapi::interface::tests::ruling_recorded ... ok [INFO] [stdout] test gmapi::interface::tests::spawn_encounter_invalid_morale ... ok [INFO] [stdout] test gmapi::interface::tests::roll_dice_valid ... ok [INFO] [stdout] test gmapi::interface::tests::spawn_encounter_and_query ... ok [INFO] [stdout] test gmapi::interface::tests::roll_dice_invalid ... ok [INFO] [stdout] test gmapi::interface::tests::surprise_roll ... ok [INFO] [stdout] test gmapi::protocol::tests::accept_valid_monster_count ... ok [INFO] [stdout] test gmapi::protocol::tests::all_query_commands_parse ... ok [INFO] [stdout] test gmapi::interface::tests::spawn_npc_party_basic ... ok [INFO] [stdout] test gmapi::protocol::tests::extract_id_from_invalid_command ... ok [INFO] [stdout] test gmapi::interface::tests::roll_treasure_success ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_award_xp ... ok [INFO] [stdout] test gmapi::protocol::tests::extract_id_from_json_without_id ... ok [INFO] [stdout] test gmapi::protocol::tests::extract_id_from_invalid_json ... ok [INFO] [stdout] test gmapi::interface::tests::spawn_npc_party_invalid_type ... ok [INFO] [stdout] test gmapi::protocol::tests::extract_id_from_numeric_id ... ok [INFO] [stdout] test gmapi::protocol::tests::all_system_commands_parse ... ok [INFO] [stdout] test gmapi::protocol::tests::extract_id_from_valid_json ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_add_monster ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_attack ... ok [INFO] [stdout] test gmapi::interface::tests::search_items_success ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_damage ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_close_with_feet ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_declare_spell ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_create_character_with_abilities ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_cast_spell ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_add_rations ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_delete_note ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_buy ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_dismiss_retainer ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_close ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_drop ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_eligible_classes ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_fighting_withdrawal_with_character ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_fighting_withdrawal_without_character ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_create_character_defaults ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_equip ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_force_door ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_heal ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_invalid_json ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_kill ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_list_classes ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_list_equipment ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_list_equipment_with_category ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_listen ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_listen_default ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_list_notes ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_lookup_treasure_type ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_loot ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_query_combat_log ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_rejects_empty_id ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_open_door ... ok [INFO] [stdout] test engine::wilderness_engine::tests::orient_harder_in_difficult_terrain ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_lookup_item ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_rest ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_loot_no_value ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_look ... ok [INFO] [stdout] test engine::wilderness_engine::tests::travel_three_encounter_checks_per_day ... ok [INFO] [stdout] test engine::wilderness_engine::tests::encounter_uses_post_move_terrain ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_query_state ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_list_retainers ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_retreat_with_character ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_retreat_without_character ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_load_module ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_roll ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_roll_treasure ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_ruling ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_search_items ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_set_helpless ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_set_helpless_default ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_spawn_npc_party ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_spawn_encounter ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_spawn_placed_defaults ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_set_rations ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_spawn_placed_with_params ... ok [INFO] [stdout] test gmapi::protocol::tests::reject_long_character_name ... ok [INFO] [stdout] test engine::wilderness_engine::tests::lost_chance_varies_by_terrain ... ok [INFO] [stdout] test gmapi::protocol::tests::parse_set_hp ... ok [INFO] [stdout] test gmapi::protocol::tests::reject_oversized_request ... ok [INFO] [stdout] test gmapi::protocol::tests::request_roundtrip ... ok [INFO] [stdout] test gmapi::protocol::tests::response_roundtrip ... ok [INFO] [stdout] test gmapi::protocol::tests::response_error ... ok [INFO] [stdout] test log_entry::tests::deref_contains ... ok [INFO] [stdout] test gmapi::protocol::tests::response_ok ... ok [INFO] [stdout] test log_entry::tests::deserialize_from_string ... ok [INFO] [stdout] test gmapi::protocol::tests::response_ok_with_data ... ok [INFO] [stdout] test gmapi::protocol::tests::reject_long_request_id ... ok [INFO] [stdout] test log_entry::tests::partial_eq_str ... ok [INFO] [stdout] test log_entry::tests::deserialize_vec_of_strings ... ok [INFO] [stdout] test log_entry::tests::serialize_roundtrip ... ok [INFO] [stdout] test log_entry::tests::display ... ok [INFO] [stdout] test gmapi::protocol::tests::serialize_response_compact ... ok [INFO] [stdout] test log_entry::tests::deserialize_from_object ... ok [INFO] [stdout] test gmapi::protocol::tests::reject_excessive_monster_count ... ok [INFO] [stdout] test manifest::tests::features_default ... ok [INFO] [stdout] test model::tests::character_creation ... ok [INFO] [stdout] test manifest::tests::path_resolution ... ok [INFO] [stdout] test manifest::tests::rules_files_resolution ... ok [INFO] [stdout] test model::tests::party_operations ... ok [INFO] [stdout] test pathutil::tests::normalize_removes_dot ... ok [INFO] [stdout] test pathutil::tests::normalize_relative_path ... ok [INFO] [stdout] test pathutil::tests::normalize_removes_dotdot ... ok [INFO] [stdout] test pathutil::tests::normalize_multiple_dotdot ... ok [INFO] [stdout] test manifest::tests::load_ose_manifest ... ok [INFO] [stdout] test model::tests::serialization_roundtrip ... ok [INFO] [stdout] test pathutil::tests::normalize_dotdot_at_root ... ok [INFO] [stdout] test pathutil::tests::normalize_simple_path ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_passes_for_idle ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_passes_for_exploration ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_passes_for_wilderness ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_passes_for_combat ... ok [INFO] [stdout] test persist::tests::data_dir_falls_back_to_home ... ok [INFO] [stdout] test model::tests::backward_compat_class_string ... ok [INFO] [stdout] test persist::tests::data_dir_uses_osr_data_dir_when_set ... ok [INFO] [stdout] test manifest::tests::parse_manifest ... ok [INFO] [stdout] test persist::tests::enter_combat_sets_mode_and_saves_pre_combat ... ok [INFO] [stdout] test manifest::tests::supports_mechanic ... ok [INFO] [stdout] test persist::tests::enter_exploration_sets_all_state ... ok [INFO] [stdout] test persist::tests::enter_wilderness_sets_state ... ok [INFO] [stdout] test persist::tests::exit_combat_falls_back_to_idle ... ok [INFO] [stdout] test persist::tests::exit_combat_no_combat_preserves_mode ... ok [INFO] [stdout] test persist::tests::exit_combat_restores_pre_combat_mode ... ok [INFO] [stdout] test persist::tests::exit_wilderness_clears_state ... ok [INFO] [stdout] test persist::tests::exit_wilderness_noop_when_not_in_wilderness ... ok [INFO] [stdout] test persist::tests::export_live_state_roundtrip ... ok [INFO] [stdout] test persist::tests::load_missing_file ... ok [INFO] [stdout] test persist::tests::live_state_path_respects_osr_data_dir ... ok [INFO] [stdout] test persist::tests::log_entries_carry_sequence_numbers ... ok [INFO] [stdout] test persist::tests::log_entry_backward_compat_deserialize ... ok [INFO] [stdout] test persist::tests::log_seq_propagates_through_combat_lifecycle ... ok [INFO] [stdout] test persist::tests::safe_save_path_allows_dashes_and_underscores ... ok [INFO] [stdout] test persist::tests::safe_save_path_allows_unicode_names ... ok [INFO] [stdout] test persist::tests::load_rejects_future_save_version ... ok [INFO] [stdout] test persist::tests::safe_save_path_already_has_json ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_absolute_unix ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_absolute_with_dotdot ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_backslash ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_dotdot ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_embedded_dotdot ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_empty ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_null_bytes ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_slash ... ok [INFO] [stdout] test persist::tests::safe_save_path_rejects_whitespace_only ... ok [INFO] [stdout] test persist::tests::safe_save_path_result_inside_saves_dir ... ok [INFO] [stdout] test persist::tests::safe_save_path_simple_name ... ok [INFO] [stdout] test persist::tests::safe_save_path_trims_and_validates ... ok [INFO] [stdout] test persist::tests::saves_dir_respects_osr_data_dir ... ok [INFO] [stdout] test persist::tests::save_cleans_up_temp_on_rename_failure ... ok [INFO] [stdout] test rules::ability::tests::cha_modifiers ... ok [INFO] [stdout] test persist::tests::save_creates_missing_directory ... ok [INFO] [stdout] test rules::ability::tests::dex_modifiers ... ok [INFO] [stdout] test rules::ability::tests::wis_modifiers ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_backward_compat ... ok [INFO] [stdout] test rules::ability::tests::prime_requisite ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_default ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_new_normalizes ... ok [INFO] [stdout] test rules::ability::tests::str_modifiers ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_serde_roundtrip ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_unknown_stored_as_is ... ok [INFO] [stdout] test rules::alignment::tests::parse_canonical ... ok [INFO] [stdout] test rules::ability::tests::con_modifiers ... ok [INFO] [stdout] test rules::ability::tests::int_modifiers ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_from_trait ... ok [INFO] [stdout] test rules::alignment::tests::parse_case_insensitive ... ok [INFO] [stdout] test rules::alignment::tests::alignment_id_from_enum ... ok [INFO] [stdout] test rules::alignment::tests::parse_invalid ... ok [INFO] [stdout] test rules::alignment::tests::parse_shortcuts ... ok [INFO] [stdout] test persist::tests::save_and_load_roundtrip ... ok [INFO] [stdout] test rules::alignment::tests::serde_alias ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_bonus_with_special ... ok [INFO] [stdout] test rules::alignment::tests::serde_roundtrip ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_double_special ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_fractional ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_range ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_fractional_decimal_with_special ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_serde_roundtrip ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_with_bonus ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_simple ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_with_penalty ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_with_special ... ok [INFO] [stdout] test rules::attack::tests::hit_with_negative_modifier ... ok [INFO] [stdout] test rules::attack::tests::hit_with_str_modifier ... ok [INFO] [stdout] test rules::attack::tests::hit_dice_fractional_decimal ... ok [INFO] [stdout] test rules::attack::tests::missile_long_range ... ok [INFO] [stdout] test rules::attack::tests::missile_medium_range ... ok [INFO] [stdout] test rules::attack::tests::missile_melee_only_weapon ... ok [INFO] [stdout] test rules::attack::tests::missile_medium_range_boundary ... ok [INFO] [stdout] test rules::attack::tests::missile_out_of_range ... ok [INFO] [stdout] test rules::attack::tests::missile_short_range ... ok [INFO] [stdout] test rules::attack::tests::missile_short_range_boundary ... ok [INFO] [stdout] test rules::attack::tests::missile_zero_distance ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_10hd ... ok [INFO] [stdout] test rules::attack::tests::hp_dice_count_respects_range ... ok [INFO] [stdout] test rules::attack::tests::missile_long_range_boundary ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_13hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_1hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_3hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_16hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_20hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_4hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_7hd ... ok [INFO] [stdout] test rules::attack::tests::monster_thac0_normal_human ... ok [INFO] [stdout] test rules::attack::tests::natural_1_always_misses ... ok [INFO] [stdout] test rules::attack::tests::natural_20_always_hits ... ok [INFO] [stdout] test rules::attack::tests::standard_hit_exact ... ok [INFO] [stdout] test rules::attack::tests::standard_hit_exceeds ... ok [INFO] [stdout] test rules::attack::tests::standard_miss ... ok [INFO] [stdout] test rules::attack::tests::target_number_ac_zero ... ok [INFO] [stdout] test rules::attack::tests::target_number_better_thac0 ... ok [INFO] [stdout] test rules::attack::tests::target_number_negative_ac ... ok [INFO] [stdout] test rules::class::tests::apply_dwarf_modifiers ... ok [INFO] [stdout] test rules::class::tests::apply_halfling_modifiers ... ok [INFO] [stdout] test rules::class::tests::apply_modifier_clamping ... ok [INFO] [stdout] test rules::class::tests::canonical_class_count ... ok [INFO] [stdout] test rules::class::tests::can_backstab_tags ... ok [INFO] [stdout] test rules::class::tests::class_id_display ... ok [INFO] [stdout] test rules::class::tests::can_turn_undead_tags ... ok [INFO] [stdout] test rules::class::tests::class_id_equality ... ok [INFO] [stdout] test rules::class::tests::class_id_from_trait ... ok [INFO] [stdout] test rules::attack::tests::target_number_chain ... ok [INFO] [stdout] test rules::attack::tests::target_number_unarmoured ... ok [INFO] [stdout] test rules::class::tests::class_id_new_normalizes ... ok [INFO] [stdout] test rules::class::tests::class_id_serde_unknown_class ... ok [INFO] [stdout] test rules::class::tests::class_id_serde_roundtrip ... ok [INFO] [stdout] test rules::class::tests::class_id_unknown_class_preserved ... ok [INFO] [stdout] test rules::class::tests::bx_equivalent_tags ... ok [INFO] [stdout] test rules::class::tests::fighter_def ... ok [INFO] [stdout] test rules::class::tests::combat_aptitude_groups ... ok [INFO] [stdout] test rules::class::tests::meets_barbarian_requirements ... ok [INFO] [stdout] test rules::class::tests::class_id_hash_consistent ... ok [INFO] [stdout] test rules::class::tests::has_thief_skills_tags ... ok [INFO] [stdout] test rules::class::tests::meets_dwarf_requirements ... ok [INFO] [stdout] test rules::class::tests::magic_user_def ... ok [INFO] [stdout] test rules::class::tests::eligible_classes_low_stats ... ok [INFO] [stdout] test rules::class::tests::eligible_classes_average ... ok [INFO] [stdout] test rules::class::tests::meets_fighter_requirements ... ok [INFO] [stdout] test rules::class::tests::dwarf_def ... ok [INFO] [stdout] test rules::class::tests::registry_covers_all_classes ... ok [INFO] [stdout] test rules::class::tests::normalize_class_names ... ok [INFO] [stdout] test rules::class::tests::registry_parity_with_native ... ok [INFO] [stdout] test rules::class::tests::registry_lookup_by_name ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_catches_wilderness_without_state - should panic ... ok [INFO] [stdout] test rules::class::tests::registry_lookup_by_class_id ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_catches_combat_without_state - should panic ... ok [INFO] [stdout] test rules::encounter::tests::all_dungeon_levels_populated ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_d40_roll_1 ... ok [INFO] [stdout] test rules::encounter::tests::all_wilderness_terrains_have_codes ... ok [INFO] [stdout] test persist::tests::assert_mode_invariants_catches_exploration_without_dungeon - should panic ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_level_8_has_vampires ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_roll_1_0 ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_roll_4_9 ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_with_hd_variant ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_level_1_has_40_entries ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_level_8_has_40_entries ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_full_encounter_desert ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_categories_forest ... ok [INFO] [stdout] test rules::encounter::tests::dungeon_encounter_d40_roll_40 ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_full_encounter_forest ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_full_encounter_ocean ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_subtable_code_forest ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_subtable_lookup_forest_animal ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_subtable_lookup_dragon ... ok [INFO] [stdout] test rules::encumbrance::tests::armour_weights ... ok [INFO] [stdout] test rules::encumbrance::tests::thief_in_leather ... ok [INFO] [stdout] test rules::encumbrance::tests::total_weight_calculation ... ok [INFO] [stdout] test rules::encumbrance::tests::light_encumbrance ... ok [INFO] [stdout] test rules::encounter::tests::wilderness_subtable_code_forest_dragon ... ok [INFO] [stdout] test rules::encumbrance::tests::fighter_in_plate_with_loot ... ok [INFO] [stdout] test rules::encumbrance::tests::encumbrance_level_names ... ok [INFO] [stdout] test rules::encumbrance::tests::heavy_encumbrance ... ok [INFO] [stdout] test rules::encumbrance::tests::severe_encumbrance ... ok [INFO] [stdout] test rules::encumbrance::tests::overloaded ... ok [INFO] [stdout] test rules::encumbrance::tests::total_weight_with_gold ... ok [INFO] [stdout] test rules::encumbrance::tests::unencumbered ... ok [INFO] [stdout] test rules::equipment::tests::ac_plate_shield_dex ... ok [INFO] [stdout] test rules::equipment::tests::ac_unarmoured ... ok [INFO] [stdout] test rules::equipment::tests::blunt_weapons ... ok [INFO] [stdout] test rules::equipment::tests::crossbow_has_reload ... ok [INFO] [stdout] test rules::equipment::tests::find_leather ... ok [INFO] [stdout] test rules::equipment::tests::find_dagger ... ok [INFO] [stdout] test rules::equipment::tests::find_plate ... ok [INFO] [stdout] test rules::equipment::tests::find_sword ... ok [INFO] [stdout] test rules::equipment::tests::find_weapon_fuzzy_magic_variant ... ok [INFO] [stdout] test rules::equipment::tests::is_magical_weapon_detection ... ok [INFO] [stdout] test rules::equipment::tests::gear_count ... ok [INFO] [stdout] test rules::equipment::tests::mounts_loaded ... ok [INFO] [stdout] test rules::equipment::tests::registry_loads ... ok [INFO] [stdout] test rules::equipment::tests::staff_qualities ... ok [INFO] [stdout] test rules::equipment::tests::poisons_loaded ... ok [INFO] [stdout] test rules::equipment::tests::armour_count ... ok [INFO] [stdout] test rules::equipment::tests::ac_leather_no_shield_low_dex ... ok [INFO] [stdout] test rules::equipment::tests::water_vessels_loaded ... ok [INFO] [stdout] test rules::equipment::tests::weapon_count ... ok [INFO] [stdout] test rules::magic_item::tests::cursed_item_detection ... ok [INFO] [stdout] test rules::magic_item::tests::find_bag_of_holding ... ok [INFO] [stdout] test rules::magic_item::tests::find_item_case_insensitive ... ok [INFO] [stdout] test rules::magic_item::tests::item_has_properties ... ok [INFO] [stdout] test rules::magic_item::tests::items_by_category_potion ... ok [INFO] [stdout] test rules::magic_item::tests::partial_match_multiple ... ok [INFO] [stdout] test rules::magic_item::tests::registry_loads ... ok [INFO] [stdout] test rules::magic_item::tests::partial_match_single ... ok [INFO] [stdout] test rules::module::tests::load_module_from_absolute_dir ... ok [INFO] [stdout] test rules::magic_item::tests::search_no_results ... ok [INFO] [stdout] test rules::module::tests::connection_type_display ... ok [INFO] [stdout] test rules::module::tests::default_connection_type_is_door ... ok [INFO] [stdout] test rules::module::tests::expand_tilde_alone ... ok [INFO] [stdout] test rules::module::tests::expand_tilde_no_tilde ... ok [INFO] [stdout] test rules::module::tests::expand_tilde_with_subpath ... ok [INFO] [stdout] test rules::module::tests::levels_default_to_empty ... ok [INFO] [stdout] test rules::module::tests::default_monster_count_is_one ... ok [INFO] [stdout] test rules::module::tests::load_gotfn_morkaals_tomb ... ok [INFO] [stdout] test rules::module::tests::default_door_state_is_closed ... ok [INFO] [stdout] test rules::magic_item::tests::items_by_category_sword ... ok [INFO] [stdout] test rules::magic_item::tests::search_by_name ... ok [INFO] [stdout] test rules::module::tests::module_defaults_empty_new_fields ... ok [INFO] [stdout] test rules::module::tests::load_module_valid_path ... ok [INFO] [stdout] test rules::module::tests::parse_all_connection_types ... ok [INFO] [stdout] test rules::module::tests::parse_exit_with_connection_type_and_description ... ok [INFO] [stdout] test rules::module::tests::parse_custom_rules_and_tables ... ok [INFO] [stdout] test rules::module::tests::parse_item_treasure_with_value_gp ... ok [INFO] [stdout] test rules::module::tests::parse_exits_with_door_state ... ok [INFO] [stdout] test rules::module::tests::parse_item_treasure_without_value_gp_defaults_zero ... ok [INFO] [stdout] test rules::module::tests::parse_module_json ... ok [INFO] [stdout] test rules::module::tests::parse_module_with_levels ... ok [INFO] [stdout] test rules::module::tests::parse_module_with_sections ... ok [INFO] [stdout] test rules::module::tests::parse_room_with_monsters ... ok [INFO] [stdout] test rules::module::tests::load_module_traversal_blocked ... ok [INFO] [stdout] test rules::module::tests::parse_room_with_rich_content ... ok [INFO] [stdout] test rules::module::tests::rich_content_defaults_to_empty ... ok [INFO] [stdout] test rules::module::tests::parse_room_with_treasure ... ok [INFO] [stdout] test rules::module::tests::room_defaults ... ok [INFO] [stdout] test rules::module::tests::parse_wandering_monster_table ... ok [INFO] [stdout] test rules::module::tests::room_trap_trigger_defaults_to_entry ... ok [INFO] [stdout] test rules::module::tests::room_with_action_trap_trigger ... ok [INFO] [stdout] test rules::module::tests::room_with_trap ... ok [INFO] [stdout] test rules::module::tests::validate_absolute_path_outside_modules_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_bad_level_range ... ok [INFO] [stdout] test rules::module::tests::validate_bad_exit_reference ... ok [INFO] [stdout] test rules::module::tests::validate_deeply_nested_traversal_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_conflicting_bidirectional_door_states ... ok [INFO] [stdout] test rules::module::tests::validate_empty_path_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_level_references_nonexistent_room ... ok [INFO] [stdout] test rules::module::tests::validate_matching_bidirectional_door_states ... ok [INFO] [stdout] test rules::module::tests::validate_good_module ... ok [INFO] [stdout] test rules::module::tests::validate_missing_entry_room ... ok [INFO] [stdout] test rules::module::tests::validate_null_byte_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_nonexistent_file_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_module_with_valid_levels ... ok [INFO] [stdout] test rules::module::tests::validate_path_traversal_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_room_in_multiple_levels ... ok [INFO] [stdout] test rules::module::tests::validate_dot_only_path_rejected ... ok [INFO] [stdout] test rules::module::tests::sections_default_to_empty ... ok [INFO] [stdout] test rules::module::tests::validate_path_traversal_from_absolute_dir_rejected ... ok [INFO] [stdout] test rules::module::tests::validate_room_not_assigned_to_level ... ok [INFO] [stdout] test rules::monster::tests::all_monsters_accessible ... ok [INFO] [stdout] test rules::module::tests::wandering_monster_table_defaults ... ok [INFO] [stdout] test rules::monster::tests::find_case_insensitive ... ok [INFO] [stdout] test rules::module::tests::validate_path_within_modules_dir ... ok [INFO] [stdout] test rules::monster::tests::immune_to_normal_weapons_detection ... ok [INFO] [stdout] test rules::monster::tests::find_nonexistent ... ok [INFO] [stdout] test rules::module::tests::validate_tilde_traversal_rejected ... ok [INFO] [stdout] test rules::monster::tests::monster_has_required_fields ... ok [INFO] [stdout] test rules::monster::tests::registry_initializes ... ok [INFO] [stdout] test rules::monster::tests::is_undead_detection ... ok [INFO] [stdout] test rules::npc_party::tests::dice_expr_parsing ... ok [INFO] [stdout] test rules::monster::tests::special_compatibility ... ok [INFO] [stdout] test rules::npc_party::tests::all_alignments_appear_in_npc_parties ... ok [INFO] [stdout] test rules::npc_party::tests::roll_alignment_returns_valid ... ok [INFO] [stdout] test rules::monster::tests::damage_compatibility ... ok [INFO] [stdout] test rules::npc_party::tests::basic_party_has_correct_size ... ok [INFO] [stdout] test rules::npc_party::tests::expert_party_has_correct_size ... ok [INFO] [stdout] test rules::npc_party::tests::high_level_cleric_party_has_leader ... ok [INFO] [stdout] test rules::npc_party::tests::high_level_magic_user_party_has_apprentices ... ok [INFO] [stdout] test rules::npc_party::tests::high_level_fighter_party_has_leader ... ok [INFO] [stdout] test rules::npc_party::tests::npc_member_to_monster_fighter ... ok [INFO] [stdout] test rules::npc_party::tests::npc_member_to_monster_magic_user ... ok [INFO] [stdout] test rules::npc_party::tests::npc_party_members_have_individual_alignments ... ok [INFO] [stdout] test rules::npc_party::tests::roll_class_returns_valid_class ... ok [INFO] [stdout] test rules::npc_party::tests::patrol_generation_works ... ok [INFO] [stdout] test rules::rumor::tests::find_case_insensitive ... ok [INFO] [stdout] test rules::rumor::tests::docks_table_exists ... ok [INFO] [stdout] test rules::rumor::tests::find_nonexistent_table ... ok [INFO] [stdout] test rules::rumor::tests::find_tavern_table ... ok [INFO] [stdout] test rules::rumor::tests::market_table_exists ... ok [INFO] [stdout] test rules::rumor::tests::rumor_entries_have_truth_values ... ok [INFO] [stdout] test rules::rumor::tests::registry_loads ... ok [INFO] [stdout] test rules::save::tests::barbarian_saves_level_7 ... ok [INFO] [stdout] test rules::rumor::tests::rumor_entries_have_text ... ok [INFO] [stdout] test rules::save::tests::cleric_saves_level_4 ... ok [INFO] [stdout] test rules::save::tests::cleric_saves_level_5 ... ok [INFO] [stdout] test rules::save::tests::dwarf_saves_level_1 ... ok [INFO] [stdout] test rules::save::tests::dynamic_map_access ... ok [INFO] [stdout] test rules::save::tests::convenience_accessors_match_map ... ok [INFO] [stdout] test rules::save::tests::drow_saves_level_10 ... ok [INFO] [stdout] test rules::save::tests::fighter_saves_level_13 ... ok [INFO] [stdout] test rules::save::tests::fighter_saves_level_1 ... ok [INFO] [stdout] test rules::save::tests::magic_user_saves_level_1 ... ok [INFO] [stdout] test rules::save::tests::magic_user_saves_level_6 ... ok [INFO] [stdout] test rules::save::tests::save_category_id_dsl_name ... ok [INFO] [stdout] test rules::save::tests::level_0_gets_worst_saves ... ok [INFO] [stdout] test rules::save::tests::save_category_id_from_enum ... ok [INFO] [stdout] test rules::save::tests::save_category_id_from_trait ... ok [INFO] [stdout] test rules::save::tests::save_category_id_hyphenated ... ok [INFO] [stdout] test rules::save::tests::save_category_id_new_normalizes ... ok [INFO] [stdout] test rules::save::tests::missing_save_defaults_to_20 ... ok [INFO] [stdout] test rules::save::tests::paladin_saves_level_13 ... ok [INFO] [stdout] test rules::save::tests::save_category_id_serde_roundtrip ... ok [INFO] [stdout] test rules::save::tests::thief_saves_level_1 ... ok [INFO] [stdout] test rules::save::tests::thief_saves_level_5 ... ok [INFO] [stdout] test rules::spell::tests::bard_level_14 ... ok [INFO] [stdout] test rules::spell::tests::bard_level_2 ... ok [INFO] [stdout] test rules::save::tests::save_category_id_unknown_stored_as_is ... ok [INFO] [stdout] test rules::save::tests::svirfneblin_saves_level_7 ... ok [INFO] [stdout] test rules::spell::tests::can_cast_spell_with_slots_available ... ok [INFO] [stdout] test rules::spell::tests::can_cast_spell_all_slots_used ... ok [INFO] [stdout] test rules::spell::tests::can_cast_spell_partial_usage ... ok [INFO] [stdout] test rules::spell::tests::casting_resource_type_is_vancian ... ok [INFO] [stdout] test rules::spell::tests::cast_cost_is_one ... ok [INFO] [stdout] test rules::spell::tests::cleric_gets_spells_level_2 ... ok [INFO] [stdout] test rules::spell::tests::cleric_level_14 ... ok [INFO] [stdout] test rules::spell::tests::cleric_no_spells_level_1 ... ok [INFO] [stdout] test rules::spell::tests::drow_level_10 ... ok [INFO] [stdout] test rules::spell::tests::druid_level_7 ... ok [INFO] [stdout] test rules::spell::tests::half_elf_level_8 ... ok [INFO] [stdout] test rules::spell::tests::drow_level_1 ... ok [INFO] [stdout] test rules::spell::tests::paladin_no_spells_level_8 ... ok [INFO] [stdout] test rules::spell::tests::non_caster ... ok [INFO] [stdout] test rules::spell::tests::ranger_level_10 ... ok [INFO] [stdout] test rules::spell::tests::spell_point_costs ... ok [INFO] [stdout] test rules::spell::tests::total_slots_magic_user_5 ... ok [INFO] [stdout] test rules::spell::tests::rest_recovery_always_true ... ok [INFO] [stdout] test rules::spell_data::tests::cleric_level_1_spells ... ok [INFO] [stdout] test rules::spell::tests::magic_user_level_1 ... ok [INFO] [stdout] test rules::spell::tests::paladin_gets_spells_level_9 ... ok [INFO] [stdout] test rules::spell::tests::magic_user_level_14 ... ok [INFO] [stdout] test rules::spell_data::tests::find_magic_missile ... ok [INFO] [stdout] test rules::spell_data::tests::find_spell_case_insensitive ... ok [INFO] [stdout] test rules::spell_data::tests::find_spell_with_list_filter ... ok [INFO] [stdout] test rules::spell_data::tests::magic_user_level_3_has_fireball ... ok [INFO] [stdout] test rules::spell_data::tests::registry_loads ... ok [INFO] [stdout] test rules::spell_data::tests::reversible_spells_exist ... ok [INFO] [stdout] test rules::spell_data::tests::spell_damage_dice_no_damage_default ... ok [INFO] [stdout] test rules::spell_data::tests::spell_damage_dice_returns_value ... ok [INFO] [stdout] test rules::spell_data::tests::spell_save_type_no_save_default ... ok [INFO] [stdout] test rules::spell_data::tests::spell_save_type_returns_value ... ok [INFO] [stdout] test rules::thief::tests::backstab_multiplier_level_1 ... ok [INFO] [stdout] test rules::thief::tests::backstab_multiplier_level_13 ... ok [INFO] [stdout] test rules::thief::tests::backstab_multiplier_level_9 ... ok [INFO] [stdout] test rules::thief::tests::backstab_multiplier_level_5 ... ok [INFO] [stdout] test rules::thief::tests::climb_walls_progression ... ok [INFO] [stdout] test rules::thief::tests::find_traps_progression ... ok [INFO] [stdout] test rules::thief::tests::hear_noise_d6_check ... ok [INFO] [stdout] test rules::thief::tests::level_clamping ... ok [INFO] [stdout] test rules::thief::tests::open_locks_progression ... ok [INFO] [stdout] test rules::thief::tests::read_languages_unavailable_low_level ... ok [INFO] [stdout] test rules::treasure::tests::coin_type_detection ... ok [INFO] [stdout] test rules::treasure::tests::damaged_jewellery_halves_value ... ok [INFO] [stdout] test rules::treasure::tests::average_values_are_reasonable ... ok [INFO] [stdout] test rules::treasure::tests::gem_value_distribution ... ok [INFO] [stdout] test rules::treasure::tests::gem_value_table_coverage ... ok [INFO] [stdout] test rules::thief::tests::thief_has_skills ... ok [INFO] [stdout] test rules::thief::tests::skill_check_exact ... ok [INFO] [stdout] test rules::thief::tests::thief_can_backstab ... ok [INFO] [stdout] test rules::thief::tests::skill_check_failure ... ok [INFO] [stdout] test rules::thief::tests::hear_noise_d6 ... ok [INFO] [stdout] test rules::treasure::tests::find_type_a ... ok [INFO] [stdout] test rules::treasure::tests::find_type_case_sensitive ... ok [INFO] [stdout] test rules::treasure::tests::gem_value_boundaries ... ok [INFO] [stdout] test rules::treasure::tests::group_treasure_u ... ok [INFO] [stdout] test rules::treasure::tests::group_types_count ... ok [INFO] [stdout] test rules::treasure::tests::gems_jewellery_loads_from_file ... ok [INFO] [stdout] test rules::treasure::tests::individual_treasure_p ... ok [INFO] [stdout] test rules::thief::tests::skill_check_success ... ok [INFO] [stdout] test rules::treasure::tests::individual_types_count ... ok [INFO] [stdout] test rules::npc_party::tests::all_classes_reachable ... ok [INFO] [stdout] test rules::treasure::tests::magic_type_detection ... ok [INFO] [stdout] test rules::turn::tests::ghoul_level_2 ... ok [INFO] [stdout] test rules::turn::tests::ghoul_level_3 ... ok [INFO] [stdout] test rules::turn::tests::infernal_level_11 ... ok [INFO] [stdout] test rules::treasure::tests::registry_loads ... ok [INFO] [stdout] test rules::turn::tests::infernal_level_12 ... ok [INFO] [stdout] test rules::turn::tests::infernal_level_6 ... ok [INFO] [stdout] test rules::treasure::tests::roll_multiple_jewellery ... ok [INFO] [stdout] test rules::treasure::tests::type_a_has_magic_items ... ok [INFO] [stdout] test rules::treasure::tests::hoard_types_count ... ok [INFO] [stdout] test rules::treasure::tests::type_h_has_high_value ... ok [INFO] [stdout] test rules::turn::tests::ghoul_level_1 ... ok [INFO] [stdout] test rules::treasure::tests::roll_multiple_gems ... ok [INFO] [stdout] test rules::treasure::tests::jewellery_value_range ... ok [INFO] [stdout] test rules::turn::tests::infernal_level_7 ... ok [INFO] [stdout] test rules::turn::tests::infernal_level_9 ... ok [INFO] [stdout] test rules::turn::tests::rank_clamps_high ... ok [INFO] [stdout] test rules::turn::tests::rank_clamps_low ... ok [INFO] [stdout] test rules::turn::tests::rank_direct_mapping ... ok [INFO] [stdout] test rules::turn::tests::skeleton_level_1 ... ok [INFO] [stdout] test rules::turn::tests::skeleton_level_2 ... ok [INFO] [stdout] test rules::turn::tests::skeleton_level_3 ... ok [INFO] [stdout] test rules::turn::tests::skeleton_level_14 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_10 ... ok [INFO] [stdout] test rules::turn::tests::skeleton_level_4 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_6 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_11 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_7 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_9 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_8 ... ok [INFO] [stdout] test rules::turn::tests::zombie_level_1 ... ok [INFO] [stdout] test rules::turn::tests::wight_level_2 ... ok [INFO] [stdout] test rules::turn::tests::vampire_level_5 ... ok [INFO] [stdout] test rules::turn::tests::wight_level_1 ... ok [INFO] [stdout] test rules::turn::tests::zombie_level_2 ... ok [INFO] [stdout] test rules::xp::tests::adjust_xp_with_bonus ... ok [INFO] [stdout] test rules::turn::tests::zombie_level_3 ... ok [INFO] [stdout] test rules::turn::tests::zombie_level_5 ... ok [INFO] [stdout] test rules::xp::tests::check_level_up_ready ... ok [INFO] [stdout] test rules::xp::tests::adjust_xp_zero_modifier ... ok [INFO] [stdout] test rules::xp::tests::cleric_xp_table ... ok [INFO] [stdout] test rules::xp::tests::check_level_up_at_max ... ok [INFO] [stdout] test rules::xp::tests::duergar_cannot_exceed_max_level ... ok [INFO] [stdout] test rules::xp::tests::beyond_max_level ... ok [INFO] [stdout] test rules::xp::tests::dwarf_xp_table ... ok [INFO] [stdout] test rules::xp::tests::prime_req_modifier_fighter_low_str ... ok [INFO] [stdout] test rules::xp::tests::fighter_xp_table ... ok [INFO] [stdout] test rules::xp::tests::thief_xp_table ... ok [INFO] [stdout] test rules::xp::tests::adjust_xp_with_penalty ... ok [INFO] [stdout] test rules::xp::tests::prime_req_modifier_elf_dual ... ok [INFO] [stdout] test session::state::tests::find_player ... ok [INFO] [stdout] test session::state::tests::is_gm_check ... ok [INFO] [stdout] test session::state::tests::find_gm ... ok [INFO] [stdout] test session::io::tests::json_pipe_construction ... ok [INFO] [stdout] test session::state::tests::permission_gm_only ... ok [INFO] [stdout] test session::state::tests::session_creation ... ok [INFO] [stdout] test rules::xp::tests::check_level_up_not_ready ... ok [INFO] [stdout] test session::state::tests::serialization_roundtrip ... ok [INFO] [stdout] test rules::xp::tests::prime_req_modifier_fighter_high_str ... ok [INFO] [stdout] test rules::xp::tests::magic_user_xp_table ... ok [INFO] [stdout] test session::player::tests::ai_gm ... ok [INFO] [stdout] test session::player::tests::serialization_roundtrip ... ok [INFO] [stdout] test session::state::tests::turn_order ... ok [INFO] [stdout] test state::dungeon::tests::duplicate_room_id_rejected ... ok [INFO] [stdout] test state::dungeon::tests::empty_dungeon_has_no_current_room ... ok [INFO] [stdout] test state::dungeon::tests::explore_marks_room ... ok [INFO] [stdout] test session::player::tests::human_player ... ok [INFO] [stdout] test state::dungeon::tests::add_door_rejects_nonexistent_rooms ... ok [INFO] [stdout] test state::dungeon::tests::door_default_connection_type_is_door ... ok [INFO] [stdout] test state::dungeon::tests::door_connection_type_serializes_round_trip ... ok [INFO] [stdout] test state::dungeon::tests::door_passable_when_open ... ok [INFO] [stdout] test state::dungeon::tests::door_self_connection_rejected ... ok [INFO] [stdout] test state::dungeon::tests::first_room_becomes_current ... ok [INFO] [stdout] test state::dungeon::tests::doors_from_current_excludes_secret ... ok [INFO] [stdout] test state::dungeon::tests::move_to_cross_level_returns_transition ... ok [INFO] [stdout] test state::dungeon::tests::move_to_nonadjacent_fails ... ok [INFO] [stdout] test state::dungeon::tests::dungeon_level_fields_round_trip ... ok [INFO] [stdout] test state::dungeon::tests::move_to_room_through_open_door ... ok [INFO] [stdout] test state::dungeon::tests::move_to_nonexistent_fails ... ok [INFO] [stdout] test state::dungeon::tests::move_to_without_level_keys_returns_none ... ok [INFO] [stdout] test state::dungeon::tests::move_to_same_level_returns_none ... ok [INFO] [stdout] test state::dungeon::tests::duplicate_door_id_rejected ... ok [INFO] [stdout] test state::dungeon::tests::placed_monster_instance_defaults ... ok [INFO] [stdout] test state::dungeon::tests::placed_treasure_instance_defaults ... ok [INFO] [stdout] test state::dungeon::tests::old_room_json_loads_with_defaults ... ok [INFO] [stdout] test state::dungeon::tests::room_trap ... ok [INFO] [stdout] test state::dungeon::tests::room_with_action_trap ... ok [INFO] [stdout] test state::dungeon::tests::move_to_without_open_door_fails ... ok [INFO] [stdout] test state::dungeon::tests::old_dungeon_json_loads_without_level_fields ... ok [INFO] [stdout] test state::dungeon::tests::secret_door_discovered ... ok [INFO] [stdout] test state::dungeon::tests::status_display ... ok [INFO] [stdout] test state::dungeon::tests::status_shows_connection_type_label ... ok [INFO] [stdout] test state::dungeon::tests::status_without_level_key ... ok [INFO] [stdout] test state::dungeon::tests::status_shows_level_key ... ok [INFO] [stdout] test state::effect::tests::backward_compat_no_modifiers_no_notes ... ok [INFO] [stdout] test state::dungeon::tests::trap_trigger_serializes_round_trip ... ok [INFO] [stdout] test state::dungeon::tests::old_door_json_loads_with_default_connection_type ... ok [INFO] [stdout] test state::effect::tests::duration_display ... ok [INFO] [stdout] test state::effect::tests::next_effect_id_increments ... ok [INFO] [stdout] test state::effect::tests::effect_detail_lines ... ok [INFO] [stdout] test state::effect::tests::duration_expired ... ok [INFO] [stdout] test state::effect::tests::tick_round_does_not_affect_permanent ... ok [INFO] [stdout] test state::effect::tests::serialization_roundtrip ... ok [INFO] [stdout] test state::effect::tests::tick_round_does_not_affect_concentration ... ok [INFO] [stdout] test state::effect::tests::modifier_display ... ok [INFO] [stdout] test state::effect::tests::tick_round_does_not_affect_turns ... ok [INFO] [stdout] test state::effect::tests::tick_round_effects_includes_notes_in_expiry_message ... ok [INFO] [stdout] test state::effect::tests::display_formatting ... ok [INFO] [stdout] test state::effect::tests::next_effect_id_empty ... ok [INFO] [stdout] test state::effect::tests::effect_summary_line ... ok [INFO] [stdout] test state::effect::tests::tick_round_effects_removes_expired ... ok [INFO] [stdout] test state::effect::tests::tick_turn_does_not_affect_rounds ... ok [INFO] [stdout] test state::game::tests::default_mode_is_idle ... ok [INFO] [stdout] test state::effect::tests::tick_turn_decrements_turns ... ok [INFO] [stdout] test state::game::tests::display_modes ... ok [INFO] [stdout] test state::game::tests::serialization_roundtrip ... ok [INFO] [stdout] test state::time::tests::advance_turn_decrements_light ... ok [INFO] [stdout] test state::time::tests::light_summary_single_lantern ... ok [INFO] [stdout] test state::dungeon::tests::new_room_fields_serialize ... ok [INFO] [stdout] test state::time::tests::no_light_status ... ok [INFO] [stdout] test state::time::tests::light_summary_multiple_sources ... ok [INFO] [stdout] test state::time::tests::light_summary_singular_turn ... ok [INFO] [stdout] test state::time::tests::light_summary_single_torch ... ok [INFO] [stdout] test state::time::tests::rest_requirement_after_5_turns ... ok [INFO] [stdout] test state::time::tests::light_summary_single_torch_after_advance ... ok [INFO] [stdout] test state::time::tests::rest_resets_counter ... ok [INFO] [stdout] test state::time::tests::light_summary_none_when_no_lights ... ok [INFO] [stdout] test state::time::tests::sputtering_warning_at_1_turn ... ok [INFO] [stdout] test state::time::tests::torch_duration ... ok [INFO] [stdout] test state::wilderness::tests::status_display ... ok [INFO] [stdout] test state::wilderness::tests::duplicate_hex_rejected ... ok [INFO] [stdout] test state::wilderness::tests::hex_movement ... ok [INFO] [stdout] test state::wilderness::tests::terrain_foraging ... ok [INFO] [stdout] test state::wilderness::tests::hex_movement_invalid ... ok [INFO] [stdout] test state::time::tests::torch_expires_after_6_turns ... ok [INFO] [stdout] test state::time::tests::duplicate_light_replaces_not_stacks ... ok [INFO] [stdout] test state::dungeon::tests::room_with_module_fields ... ok [INFO] [stdout] test telemetry::tests::log_to_path_writes_jsonl ... ok [INFO] [stdout] test state::time::tests::lantern_duration ... ok [INFO] [stdout] test state::time::tests::lantern_lasts_24_turns ... ok [INFO] [stdout] test state::wilderness::tests::hex_movement_nonadjacent_fails ... ok [INFO] [stdout] test state::wilderness::tests::terrain_movement_costs ... ok [INFO] [stdout] test state::wilderness::tests::travel_speed_clear ... ok [INFO] [stdout] test state::wilderness::tests::travel_speed_forest ... ok [INFO] [stdout] test state::wilderness::tests::travel_speed_mountains ... ok [INFO] [stdout] test telemetry::tests::failed_command_serializes_to_json ... ok [INFO] [stdout] test state::wilderness::tests::travel_speed_slow_party ... ok [INFO] [stdout] test state::time::tests::day_calculation ... ok [INFO] [stdout] test state::time::tests::rest_penalty_applied_when_overdue ... ok [INFO] [stdout] test state::wilderness::tests::terrain_lost_chances ... ok [INFO] [stdout] test state::effect::tests::tick_round_decrements_rounds ... ok [INFO] [stdout] test telemetry::tests::log_does_not_panic_on_missing_home ... ok [INFO] [stdout] test telemetry::tests::reconstruct_input_no_args ... ok [INFO] [stdout] test telemetry::tests::reconstruct_input_with_args ... ok [INFO] [stdout] test telemetry::tests::telemetry_dir_respects_osr_data_dir ... ok [INFO] [stdout] test rules::npc_party::tests::ruler_reaction_varies_by_type ... ok [INFO] [stdout] [INFO] [stdout] test result: ok. 1411 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.40s [INFO] [stdout] [INFO] [stderr] Running unittests src/bin/gmrepl.rs (/opt/rustwide/target/debug/deps/gmrepl-64b2f9b861193fd4) [INFO] [stdout] [INFO] [stdout] running 0 tests [INFO] [stdout] [INFO] [stdout] test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s [INFO] [stdout] [INFO] [stderr] Running unittests src/main.rs (/opt/rustwide/target/debug/deps/osr_ai_gm-be8ac5821b729048) [INFO] [stdout] [INFO] [stdout] running 10 tests [INFO] [stdout] test tests::parse_args_adjacent_to_quotes ... ok [INFO] [stdout] test tests::parse_args_empty ... ok [INFO] [stdout] test tests::parse_args_empty_quotes ... ok [INFO] [stdout] test tests::parse_args_double_quotes ... ok [INFO] [stdout] test tests::parse_args_escaped_quote ... ok [INFO] [stdout] test tests::parse_args_extra_whitespace ... ok [INFO] [stdout] test tests::parse_args_mixed_quotes ... ok [INFO] [stdout] test tests::parse_args_simple ... ok [INFO] [stdout] test tests::parse_args_single_quotes ... ok [INFO] [stdout] test tests::parse_args_whitespace_only ... ok [INFO] [stdout] [INFO] [stderr] Running tests/gmapi_protocol_qa.rs (/opt/rustwide/target/debug/deps/gmapi_protocol_qa-4e3fda16574cd990) [INFO] [stdout] test result: ok. 10 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s [INFO] [stdout] [INFO] [stdout] [INFO] [stdout] running 315 tests [INFO] [stdout] test add_door_happy_path ... ok [INFO] [stdout] test add_door_all_valid_states ... ok [INFO] [stdout] test add_door_no_dungeon ... ok [INFO] [stdout] test add_door_invalid_state ... ok [INFO] [stdout] test add_hex_happy_path ... ok [INFO] [stdout] test add_hex_duplicate ... ok [INFO] [stdout] test add_hex_invalid_terrain ... ok [INFO] [stdout] test add_hex_not_in_wilderness ... ok [INFO] [stdout] test add_rations_invalid_amount ... ok [INFO] [stdout] test add_room_happy_path ... ok [INFO] [stdout] test add_room_no_dungeon ... ok [INFO] [stdout] test advance_turn_not_exploring ... ok [INFO] [stdout] test advance_turn_happy_path ... ok [INFO] [stdout] test advance_turn_outside_exploration ... ok [INFO] [stdout] test advance_turn_rejected_in_wilderness ... ok [INFO] [stdout] test add_rations_happy_path ... ok [INFO] [stdout] test add_room_duplicate_id ... ok [INFO] [stdout] test award_treasure_xp_happy_path ... ok [INFO] [stdout] test award_treasure_xp_unknown_character ... ok [INFO] [stdout] test award_xp_cumulative ... ok [INFO] [stdout] test award_xp_happy_path ... ok [INFO] [stdout] test award_xp_unknown_character ... ok [INFO] [stdout] test attack_dead_monster ... ok [INFO] [stdout] test attack_monster_idx_out_of_range ... ok [INFO] [stdout] test attack_melee_at_distance ... ok [INFO] [stdout] test attack_unknown_character ... ok [INFO] [stdout] test attack_no_combat ... ok [INFO] [stdout] test attack_dead_character ... ok [INFO] [stdout] test attack_unknown_weapon ... ok [INFO] [stdout] test backstab_unknown_character ... ok [INFO] [stdout] test attack_outside_combat ... ok [INFO] [stdout] test backstab_unknown_weapon ... ok [INFO] [stdout] test attack_happy_path ... ok [INFO] [stdout] test backstab_no_combat ... ok [INFO] [stdout] test backstab_dead_monster ... ok [INFO] [stdout] test backstab_non_thief ... ok [INFO] [stdout] test buy_happy_path ... ok [INFO] [stdout] test check_morale_no_combat ... ok [INFO] [stdout] test check_morale_happy_path ... ok [INFO] [stdout] test create_character_abilities_out_of_range ... ok [INFO] [stdout] test create_character_alignment_abbreviations ... ok [INFO] [stdout] test create_character_invalid_class ... ok [INFO] [stdout] test create_character_unknown_alignment_accepted ... ok [INFO] [stdout] test buy_unknown_item ... ok [INFO] [stdout] test create_character_with_abilities ... ok [INFO] [stdout] test create_character_happy_path ... ok [INFO] [stdout] test buy_suggests_similar ... ok [INFO] [stdout] test buy_json_parse ... ok [INFO] [stdout] test backstab_happy_path ... ok [INFO] [stdout] test backstab_idx_out_of_range ... ok [INFO] [stdout] test buy_unknown_character ... ok [INFO] [stdout] test buy_insufficient_gold ... ok [INFO] [stdout] test check_morale_no_living_monsters ... ok [INFO] [stdout] test damage_invalid_amount ... ok [INFO] [stdout] test damage_happy_path ... ok [INFO] [stdout] test damage_kills_character ... ok [INFO] [stdout] test damage_no_character ... ok [INFO] [stdout] test declare_spell_unknown_character ... ok [INFO] [stdout] test delete_note_happy_path ... ok [INFO] [stdout] test delete_note_out_of_range ... ok [INFO] [stdout] test dismiss_retainer_case_insensitive ... ok [INFO] [stdout] test declare_spell_non_caster_rejected ... ok [INFO] [stdout] test dismiss_retainer_happy_path ... ok [INFO] [stdout] test delete_note_empty ... ok [INFO] [stdout] test drop_unknown_character ... ok [INFO] [stdout] test double_quit ... ok [INFO] [stdout] test eligible_classes_invalid_score_too_high ... ok [INFO] [stdout] test double_query_state ... ok [INFO] [stdout] test eligible_classes_invalid_score_too_low ... ok [INFO] [stdout] test eligible_classes_abilities_in_response ... ok [INFO] [stdout] test eligible_classes_all_high_scores ... ok [INFO] [stdout] test drop_happy_path ... ok [INFO] [stdout] test eligible_classes_minimum_scores ... ok [INFO] [stdout] test enter_dungeon_happy_path ... ok [INFO] [stdout] test enter_dungeon_level_zero ... ok [INFO] [stdout] test double_save ... ok [INFO] [stdout] test dismiss_retainer_not_found ... ok [INFO] [stdout] test drop_missing_item ... ok [INFO] [stdout] test enter_dungeon_rejected_in_combat ... ok [INFO] [stdout] test eligible_classes_mode_unchanged ... ok [INFO] [stdout] test drop_json_parse ... ok [INFO] [stdout] test end_combat_happy_path ... ok [INFO] [stdout] test enter_dungeon_rejected_in_wilderness_mode ... ok [INFO] [stdout] test enter_dungeon_rejected_when_already_exploring ... ok [INFO] [stdout] test enter_wilderness_happy_path ... ok [INFO] [stdout] test enter_wilderness_all_terrain_types ... ok [INFO] [stdout] test enter_wilderness_while_already_in_wilderness_rejected ... ok [INFO] [stdout] test enter_wilderness_invalid_terrain ... ok [INFO] [stdout] test equip_already_equipped_errors ... ok [INFO] [stdout] test equip_happy_path ... ok [INFO] [stdout] test equip_json_parse ... ok [INFO] [stdout] test equip_missing_item ... ok [INFO] [stdout] test equip_unknown_character ... ok [INFO] [stdout] test error_response_serializes_correctly ... ok [INFO] [stdout] test evade_json_parse ... ok [INFO] [stdout] test evade_happy_path ... ok [INFO] [stdout] test end_combat_no_combat ... ok [INFO] [stdout] test end_combat_xp_counts_dead_only ... ok [INFO] [stdout] test evade_no_party_members ... ok [INFO] [stdout] test forage_in_dungeon_mode ... ok [INFO] [stdout] test forage_happy_path ... ok [INFO] [stdout] test forage_json_parse ... ok [INFO] [stdout] test forage_not_in_wilderness ... ok [INFO] [stdout] test force_door_no_character ... ok [INFO] [stdout] test force_door_happy_path ... ok [INFO] [stdout] test heal_above_max_hp_does_not_reduce ... ok [INFO] [stdout] test heal_happy_path ... ok [INFO] [stdout] test heal_capped_at_max ... ok [INFO] [stdout] test heal_invalid_amount ... ok [INFO] [stdout] test force_door_no_dungeon ... ok [INFO] [stdout] test heal_no_character ... ok [INFO] [stdout] test hire_retainer_happy_path ... ok [INFO] [stdout] test hire_retainer_unknown_employer ... ok [INFO] [stdout] test hunt_happy_path ... ok [INFO] [stdout] test hunt_not_in_wilderness ... ok [INFO] [stdout] test hunt_json_parse ... ok [INFO] [stdout] test hunt_in_dungeon_mode ... ok [INFO] [stdout] test kill_happy_path ... ok [INFO] [stdout] test kill_no_character ... ok [INFO] [stdout] test kill_no_combat ... ok [INFO] [stdout] test leave_wilderness_happy_path ... ok [INFO] [stdout] test kill_not_helpless ... ok [INFO] [stdout] test leave_wilderness_during_exploration ... ok [INFO] [stdout] test declare_spell_no_combat ... ok [INFO] [stdout] test leave_wilderness_not_in_wilderness ... ok [INFO] [stdout] test leave_wilderness_parses_from_json ... ok [INFO] [stdout] test leave_wilderness_then_enter_dungeon ... ok [INFO] [stdout] test level_up_not_enough_xp ... ok [INFO] [stdout] test level_up_double ... ok [INFO] [stdout] test light_duplicate_carrier_rejected ... ok [INFO] [stdout] test light_not_exploring ... ok [INFO] [stdout] test level_up_happy_path ... ok [INFO] [stdout] test level_up_unknown_character ... ok [INFO] [stdout] test light_torch_happy_path ... ok [INFO] [stdout] test light_invalid_source ... ok [INFO] [stdout] test light_lantern_happy_path ... ok [INFO] [stdout] test list_notes_empty ... ok [INFO] [stdout] test list_notes_with_entries ... ok [INFO] [stdout] test list_classes_mode_unchanged ... ok [INFO] [stdout] test list_classes_includes_fighter ... ok [INFO] [stdout] test list_classes_returns_all ... ok [INFO] [stdout] test list_retainers_dead_retainer ... ok [INFO] [stdout] test list_retainers_empty ... ok [INFO] [stdout] test list_retainers_with_entries ... ok [INFO] [stdout] test list_rumor_tables_parses_from_json ... ok [INFO] [stdout] test listen_as_demihuman ... ok [INFO] [stdout] test listen_happy_path ... ok [INFO] [stdout] test listen_not_exploring ... ok [INFO] [stdout] test load_path_traversal_rejected ... ok [INFO] [stdout] test list_rumor_tables_success ... ok [INFO] [stdout] test lookup_rumor_table_unknown ... ok [INFO] [stdout] test lookup_spell_filter_by_cleric ... ok [INFO] [stdout] test lookup_rumor_table_success ... ok [INFO] [stdout] test lookup_spell_happy_path ... ok [INFO] [stdout] test lookup_spell_list_aliases ... ok [INFO] [stdout] test lookup_spell_not_found ... ok [INFO] [stdout] test load_invalid_path ... ok [INFO] [stdout] test lookup_spell_unknown_list ... ok [INFO] [stdout] test load_happy_path ... ok [INFO] [stdout] test lookup_rumor_table_parses_from_json ... ok [INFO] [stdout] test lookup_treasure_type_individual ... ok [INFO] [stdout] test lookup_treasure_type_a ... ok [INFO] [stdout] test lookup_treasure_type_invalid ... ok [INFO] [stdout] test lookup_treasure_type_mode_unchanged ... ok [INFO] [stdout] test loot_adhoc_item_in_dungeon ... ok [INFO] [stdout] test loot_from_dungeon_room ... ok [INFO] [stdout] test loot_happy_path_no_dungeon ... ok [INFO] [stdout] test loot_json_parse_no_value ... ok [INFO] [stdout] test loot_json_parse ... ok [INFO] [stdout] test loot_no_value ... ok [INFO] [stdout] test loot_unknown_character ... ok [INFO] [stdout] test monster_attack_dead_character ... ok [INFO] [stdout] test monster_attack_idx_out_of_range ... ok [INFO] [stdout] test declare_spell_happy_path ... ok [INFO] [stdout] test modifier_formatting_in_party_query ... ok [INFO] [stdout] test mode_transitions ... ok [INFO] [stdout] test monster_attack_no_combat ... ok [INFO] [stdout] test monster_attack_happy_path ... ok [INFO] [stdout] test loyalty_check_happy_path ... ok [INFO] [stdout] test lookup_treasure_type_lowercase ... ok [INFO] [stdout] test monster_attack_dead_monster ... ok [INFO] [stdout] test open_door_closed_attempts_force ... ok [INFO] [stdout] test open_door_happy_path ... ok [INFO] [stdout] test open_door_locked_rejected ... ok [INFO] [stdout] test monster_attack_unknown_character ... ok [INFO] [stdout] test move_room_happy_path ... ok [INFO] [stdout] test move_room_not_exploring ... ok [INFO] [stdout] test open_door_force_fail_returns_success_false ... ok [INFO] [stdout] test open_door_nonexistent ... ok [INFO] [stdout] test move_room_outside_exploration ... ok [INFO] [stdout] test orient_not_in_wilderness ... ok [INFO] [stdout] test orient_advances_travel_day ... ok [INFO] [stdout] test orient_when_not_lost ... ok [INFO] [stdout] test orient_when_lost_happy_path ... ok [INFO] [stdout] test query_combat_log_no_combat ... ok [INFO] [stdout] test query_combat_active ... ok [INFO] [stdout] test query_combat_log_after_attack ... ok [INFO] [stdout] test query_encumbrance_unknown_character ... ok [INFO] [stdout] test query_combat_with_effects_on_characters_and_monsters ... ok [INFO] [stdout] test open_door_not_exploring ... ok [INFO] [stdout] test query_encumbrance_happy_path ... ok [INFO] [stdout] test query_combat_with_global_area_effects ... ok [INFO] [stdout] test query_combat_log_empty ... ok [INFO] [stdout] test query_combat_no_combat ... ok [INFO] [stdout] test query_exploration_active ... ok [INFO] [stdout] test query_combat_no_effects_omits_effect_fields ... ok [INFO] [stdout] test query_exploration_no_effects_omits_section ... ok [INFO] [stdout] test query_combat_monster_effect_with_helpless_tag ... ok [INFO] [stdout] test query_exploration_not_exploring ... ok [INFO] [stdout] test query_mode_idle ... ok [INFO] [stdout] test query_mode_exploration ... ok [INFO] [stdout] test query_mode_wilderness ... ok [INFO] [stdout] test query_exploration_with_effects_shows_summary ... ok [INFO] [stdout] test query_state_during_combat ... ok [INFO] [stdout] test query_party_effects_show_in_message ... ok [INFO] [stdout] test lookup_item_case_insensitive ... ok [INFO] [stdout] test lookup_item_mode_unchanged ... ok [INFO] [stdout] test lookup_item_exact_match ... ok [INFO] [stdout] test lookup_item_not_found ... ok [INFO] [stdout] test query_party_empty ... ok [INFO] [stdout] test lookup_item_partial_match ... ok [INFO] [stdout] test query_party_with_effects_shows_in_data ... ok [INFO] [stdout] test query_party_with_members ... ok [INFO] [stdout] test query_party_without_effects_omits_effects_field ... ok [INFO] [stdout] test query_wilderness_not_in_wilderness ... ok [INFO] [stdout] test query_mode_combat ... ok [INFO] [stdout] test query_state_during_exploration ... ok [INFO] [stdout] test quit_happy_path ... ok [INFO] [stdout] test query_state_happy_path ... ok [INFO] [stdout] test query_wilderness_active ... ok [INFO] [stdout] test rest_happy_path ... ok [INFO] [stdout] test rest_not_exploring ... ok [INFO] [stdout] test roll_encounter_combat_mode_error ... ok [INFO] [stdout] test roll_invalid_notation ... ok [INFO] [stdout] test response_id_matches_request ... ok [INFO] [stdout] test roll_encounter_idle_mode_error ... ok [INFO] [stdout] test roll_initiative_happy_path ... ok [INFO] [stdout] test roll_encounter_json_parse ... ok [INFO] [stdout] test roll_rumor_case_insensitive ... ok [INFO] [stdout] test roll_reaction_unknown_character ... ok [INFO] [stdout] test roll_initiative_no_combat ... ok [INFO] [stdout] test response_serializes_correctly ... ok [INFO] [stdout] test roll_rumor_parses_from_json ... ok [INFO] [stdout] test rapid_exploration_sequence ... ok [INFO] [stdout] test rapid_combat_sequence ... ok [INFO] [stdout] test roll_reaction_happy_path ... ok [INFO] [stdout] test roll_treasure_invalid_type ... ok [INFO] [stdout] test roll_treasure_has_structured_items ... ok [INFO] [stdout] test roll_rumor_success ... ok [INFO] [stdout] test roll_treasure_lowercase ... ok [INFO] [stdout] test roll_treasure_mode_unchanged ... ok [INFO] [stdout] test roll_treasure_type_p ... ok [INFO] [stdout] test roll_with_modifier ... ok [INFO] [stdout] test roll_valid ... ok [INFO] [stdout] test ruling_happy_path ... ok [INFO] [stdout] test roll_rumor_unknown_table ... ok [INFO] [stdout] test roll_surprise_happy_path ... ok [INFO] [stdout] test save_invalid_path ... ok [INFO] [stdout] test save_path_traversal_rejected ... ok [INFO] [stdout] test search_as_elf ... ok [INFO] [stdout] test search_happy_path ... ok [INFO] [stdout] test search_not_exploring ... ok [INFO] [stdout] test set_helpless_happy_path ... ok [INFO] [stdout] test ruling_multiple ... ok [INFO] [stdout] test search_outside_exploration ... ok [INFO] [stdout] test set_helpless_out_of_range ... ok [INFO] [stdout] test set_hp_no_character ... ok [INFO] [stdout] test set_hp_happy_path ... ok [INFO] [stdout] test set_helpless_no_combat ... ok [INFO] [stdout] test save_happy_path ... ok [INFO] [stdout] test search_items_mode_unchanged ... ok [INFO] [stdout] test search_items_sword ... ok [INFO] [stdout] test set_rations_happy_path ... ok [INFO] [stdout] test roll_encounter_wilderness_happy_path ... ok [INFO] [stdout] test roll_encounter_dungeon_happy_path ... ok [INFO] [stdout] test set_hp_above_max_clamps_and_warns ... ok [INFO] [stdout] test set_hp_to_zero_kills ... ok [INFO] [stdout] test spawn_encounter_combat_already_active ... ok [INFO] [stdout] test spawn_encounter_explicit_xp_value ... ok [INFO] [stdout] test spawn_encounter_happy_path ... ok [INFO] [stdout] test search_items_finds_results ... ok [INFO] [stdout] test search_items_no_results ... ok [INFO] [stdout] test spawn_encounter_invalid_morale_high ... ok [INFO] [stdout] test spawn_encounter_invalid_morale_low ... ok [INFO] [stdout] test set_rations_to_zero ... ok [INFO] [stdout] test set_helpless_remove ... ok [INFO] [stdout] test spawn_encounter_morale_boundary_valid ... ok [INFO] [stdout] test spawn_monster_combat_already_active ... ok [INFO] [stdout] test spawn_encounter_single_monster_no_numbering ... ok [INFO] [stdout] test spawn_monster_unknown ... ok [INFO] [stdout] test spawn_npc_party_rejects_during_combat ... ok [INFO] [stdout] test spell_info_happy_path ... ok [INFO] [stdout] test spawn_monster_happy_path ... ok [INFO] [stdout] test spell_info_not_found ... ok [INFO] [stdout] test spell_info_healing_spell ... ok [INFO] [stdout] test thief_skill_check_aliases ... ok [INFO] [stdout] test thief_skill_check_all_skills ... ok [INFO] [stdout] test travel_not_in_wilderness ... ok [INFO] [stdout] test spawn_monster_rejects_during_combat ... ok [INFO] [stdout] test thief_skill_check_happy_path ... ok [INFO] [stdout] test spell_info_no_damage_spell ... ok [INFO] [stdout] test thief_skill_check_non_thief ... ok [INFO] [stdout] test turn_undead_cleric_happy_path ... ok [INFO] [stdout] test travel_happy_path ... ok [INFO] [stdout] test thief_skill_check_unknown_character ... ok [INFO] [stdout] test thief_skill_check_unknown_skill ... ok [INFO] [stdout] test turn_undead_dead_monster ... ok [INFO] [stdout] test turn_undead_no_combat ... ok [INFO] [stdout] test turn_undead_non_undead_monster ... ok [INFO] [stdout] test unequip_not_equipped_errors ... ok [INFO] [stdout] test turn_undead_non_cleric ... ok [INFO] [stdout] test turn_undead_idx_out_of_range ... ok [INFO] [stdout] test unequip_via_unequip_command ... ok [INFO] [stdout] test turn_undead_unknown_character ... ok [INFO] [stderr] Running tests/integration.rs (/opt/rustwide/target/debug/deps/integration-252fbb99266aa605) [INFO] [stdout] test travel_outside_wilderness ... ok [INFO] [stdout] [INFO] [stdout] test result: ok. 315 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s [INFO] [stdout] [INFO] [stdout] [INFO] [stdout] running 68 tests [INFO] [stdout] test backstab_no_combat_rejected ... ok [INFO] [stdout] test encumbrance_query ... ok [INFO] [stdout] test level_up_command ... ok [INFO] [stdout] test loyalty_check_via_api ... ok [INFO] [stdout] test level_up_from_treasure ... ok [INFO] [stdout] test morkaals_tomb_all_rooms_reachable ... ok [INFO] [stdout] test morkaals_tomb_module_monsters_loaded ... ok [INFO] [stdout] test morkaals_tomb_monster_spawning ... ok [INFO] [stdout] test morkaals_tomb_rich_content ... ok [INFO] [stdout] test morkaals_tomb_load_and_dungeon_state ... ok [INFO] [stdout] test morkaals_tomb_traps_and_treasure ... ok [INFO] [stdout] test playtest2c_add_hex_duplicate_coordinates ... ok [INFO] [stdout] test playtest2c_dungeon_cmds_in_wilderness ... ok [INFO] [stdout] test playtest2c_enter_dungeon_from_wilderness_blocked ... ok [INFO] [stdout] test playtest2c_enter_wilderness_while_in_wilderness ... ok [INFO] [stdout] test playtest2c_evade_mechanics ... ok [INFO] [stdout] test playtest2c_forage_consumes_day_and_rations ... ok [INFO] [stdout] test dungeon_exploration_flow ... ok [INFO] [stdout] test playtest2c_hunt_consumes_day_and_rations ... ok [INFO] [stdout] test playtest2c_forage_terrain_variation ... ok [INFO] [stdout] test playtest2c_large_hex_coordinates ... ok [INFO] [stdout] test playtest2c_idle_mode_rejects_exploration_and_wilderness ... ok [INFO] [stdout] test playtest2c_hex_map_persistence ... ok [INFO] [stdout] test playtest2c_orient_behavior ... ok [INFO] [stdout] test playtest2c_rapid_roll_encounters ... ok [INFO] [stdout] test playtest2c_npc_party_bx_classes ... ok [INFO] [stdout] test playtest2c_reaction_high_charisma ... ok [INFO] [stdout] test playtest2c_roll_encounter_mode_gating ... ok [INFO] [stdout] test playtest2c_roll_encounter_mountains ... ok [INFO] [stdout] test playtest2c_roll_encounter_wilderness ... ok [INFO] [stdout] test playtest2c_surprise_in_wilderness ... ok [INFO] [stdout] test playtest2c_starvation_at_zero_rations ... ok [INFO] [stdout] test playtest2c_travel_all_terrain_types ... ok [INFO] [stdout] test playtest2c_travel_out_of_range_no_resource_consumption ... ok [INFO] [stdout] test playtest2c_travel_to_current_hex ... ok [INFO] [stdout] test playtest2c_travel_rations_consumption ... ok [INFO] [stdout] test playtest2c_wilderness_cmds_in_dungeon ... ok [INFO] [stdout] test backstab_non_thief_rejected ... ok [INFO] [stdout] test backstab_multiplier_level_9_x4 ... ok [INFO] [stdout] test backstab_multiplier_level_5_x3 ... ok [INFO] [stdout] test backstab_multiplier_level_1_x2 ... ok [INFO] [stdout] test monster_attack_api_damages_character ... ok [INFO] [stdout] test mode_transition_idle_wilderness_combat_wilderness ... ok [INFO] [stdout] test backstab_dead_monster_rejected ... ok [INFO] [stdout] test full_dungeon_session ... ok [INFO] [stdout] test monster_database_spawn ... ok [INFO] [stdout] test playtest2c_spawn_encounter_in_wilderness ... ok [INFO] [stdout] test retainer_hiring ... ok [INFO] [stdout] test playtest2c_wilderness_combat_distance_yards ... ok [INFO] [stdout] test playtest2c_wilderness_combat_roundtrip ... ok [INFO] [stdout] test sample_crypt_backward_compatibility ... ok [INFO] [stdout] test multi_round_combat_api ... ok [INFO] [stdout] test mode_transition_idle_exploration_combat_exploration ... ok [INFO] [stdout] test character_progression_multi_level ... ok [INFO] [stdout] test playtest2c_wilderness_retreat ... ok [INFO] [stdout] test save_load_complex_state ... ok [INFO] [stdout] test session_c_retainers ... ok [INFO] [stdout] test session_b_wilderness_travel ... ok [INFO] [stdout] test save_load_roundtrip ... ok [INFO] [stdout] test thief_skill_checks ... ok [INFO] [stdout] test session_a_dungeon_crawl ... ok [INFO] [stdout] test wilderness_commands_rejected_in_dungeon_mode ... ok [INFO] [stdout] test wilderness_multi_day_travel ... ok [INFO] [stdout] test xp_and_level_advancement ... ok [INFO] [stdout] test wilderness_encounter ... ok [INFO] [stdout] test turn_undead_via_api ... ok [INFO] [stdout] test spell_lookup ... ok [INFO] [stdout] test complete_ose_session ... ok [INFO] [stderr] Running tests/playtest_pass2_combat_spells.rs (/opt/rustwide/target/debug/deps/playtest_pass2_combat_spells-04419866bd986bac) [INFO] [stdout] [INFO] [stdout] test result: ok. 68 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s [INFO] [stdout] [INFO] [stdout] [INFO] [stdout] running 39 tests [INFO] [stdout] test create_character_via_gmapi ... ok [INFO] [stdout] test phase2_dead_char_thief_skill_check ... ok [INFO] [stdout] test phase2_end_combat_preserves_exploration_mode ... ok [INFO] [stdout] test phase2_dead_char_xp_award ... ok [INFO] [stdout] test phase2_declare_spell_non_caster ... ok [INFO] [stdout] test phase2_monster_attack_rejected_at_range ... ok [INFO] [stdout] test phase2_roll_initiative_spam ... ok [INFO] [stdout] test phase2_morale_check ... ok [INFO] [stdout] test phase2_same_monster_double_attack ... ok [INFO] [stdout] test phase3_cast_without_declare ... ok [INFO] [stdout] test phase2_turn_undead_non_undead ... ok [INFO] [stdout] test phase3_dwarf_cannot_cast ... ok [INFO] [stdout] test phase2_turned_monsters_cannot_attack ... ok [INFO] [stdout] test phase3_level1_cleric_cannot_cast ... ok [INFO] [stdout] test phase4_retreat_no_free_attacks_at_range ... ok [INFO] [stdout] test phase4_fighting_withdrawal_no_free_attacks ... ok [INFO] [stdout] test phase2_backstab_distance_check ... ok [INFO] [stdout] test phase2_coup_de_grace_rejected_at_range ... ok [INFO] [stdout] test phase2_backstab_damage_cap ... ok [INFO] [stdout] test phase3_thief_cannot_cast ... ok [INFO] [stdout] test phase4_turned_monsters_no_free_attacks_on_retreat ... ok [INFO] [stdout] test phase4_retreat_triggers_free_attacks ... ok [INFO] [stdout] test phase5_pick_lock_with_fighter_rejected ... ok [INFO] [stdout] test phase5_pick_lock_on_closed_door ... ok [INFO] [stdout] test phase5_pick_lock_with_thief ... ok [INFO] [stdout] test phase6_save_load_preserves_turned_status ... ok [INFO] [stdout] test set_helpless_and_kill_flow ... ok [INFO] [stdout] test turn_undead_on_skeletons ... ok [INFO] [stdout] test phase2_multiple_spells_same_char ... ok [INFO] [stdout] test phase3_two_casters_same_round ... ok [INFO] [stdout] test phase2_declare_spell_invalid_spell ... ok [INFO] [stdout] test phase3_elf_spell_cast ... ok [INFO] [stdout] test phase3_magic_user_sleep_cast ... ok [INFO] [stdout] test phase3_cleric_declare_spell ... ok [INFO] [stdout] test phase3_spell_disruption ... ok [INFO] [stdout] test phase6_save_load_preserves_spell_state ... ok [INFO] [stdout] test phase6_save_load_combat_round_trip ... ok [INFO] [stdout] test spawn_monster_from_database ... ok [INFO] [stdout] test end_to_end_dungeon_combat_cycle ... ok [INFO] [stderr] Doc-tests osr_ai_gm [INFO] [stdout] [INFO] [stdout] test result: ok. 39 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s [INFO] [stdout] [INFO] [stdout] [INFO] [stdout] running 0 tests [INFO] [stdout] [INFO] [stdout] test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s [INFO] [stdout] [INFO] running `Command { std: "docker" "inspect" "b0e55e04db9028270a24e7691a7e8b9caf3d83b789ec53a25ee2f4a016fb1423", kill_on_drop: false }` [INFO] running `Command { std: "docker" "rm" "-f" "b0e55e04db9028270a24e7691a7e8b9caf3d83b789ec53a25ee2f4a016fb1423", kill_on_drop: false }` [INFO] [stdout] b0e55e04db9028270a24e7691a7e8b9caf3d83b789ec53a25ee2f4a016fb1423