Files
gplan-2/game/tests/mutation/mutation_plan.gd
T

160 lines
9.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tests/mutation/mutation_plan.gd — 变异验证引擎的计划配置(数据件,无逻辑)
# 宿主×套×变异策略一览:套→守的生产模块(账本 §二末列)+武器优先序+运行参数。
# src 指「被变换编译的宿主源码」:稳定宿主直接读工作区文件;迁移中的宿主(如 seal)
# 用驱动命令物化的快照(user:// 下,仓库外)——物化命令见套配置旁注与台账头部。
# 武器代号:table=表/资源改写(内存字段写读还原)· inject=注入编译(生产源码内存变换
# reload 原地替换·零触盘)· state=状态篡改(静态变量/成员初值/autoload 实例与树状态)。
# budget=每套改坏点试跑上限(轮)· cap_ms=每套墙钟上限 · count=静态断言点数(对账用)。
extends RefCounted
const GLOBAL_WATCHDOG_MS := 14400000 # 引擎全局看门狗(防挂死占闸;外层 bash 超时为最终兜底——4h,慢套全程靠它)
const SUITE_CAP_MS_DEFAULT := 600000 # 单套墙钟上限缺省(宿主级 cap_ms 可覆盖)
const BUDGET_DEFAULT := 160 # 单套试跑轮数缺省
static func hosts() -> Array:
return [
{
"id": "system_test",
"src": "res://tests/system_test.gd",
"channel": "self", # 断言通道 = 宿主自有 check(cond, label)
"async": true, # 套函数为协程(await process_frame)
"budget": 240,
"cap_ms": 2400000, # 慢套墙钟上限(boot 链/活战斗驱动单轮 20–60s)
"state_autoloads": ["ConfigDB", "SaveManager"],
"suites": {
"_split_tail": {"count": 1, "weapons": ["state"], "modules": [], "tables": [],
"strip_siblings": true, "funcs": {}},
"_smoke_scene_split": {"count": 11, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://presentation/scenes/menu_screen.gd", "res://presentation/scenes/camp_screen.gd",
"res://presentation/scenes/adventure_screen.gd", "res://presentation/main.gd"],
"funcs": {"menu_screen.gd": ["_ready", "_build_ui"], "camp_screen.gd": ["_ready", "_build_ui"],
"adventure_screen.gd": ["_ready", "_build_ui"], "main.gd": ["_apply_layer_contract", "_build_ui", "_ready"]}},
"_smoke_boot_chain": {"count": 15, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://presentation/settings_store.gd", "res://core/save_manager.gd",
"res://presentation/main.gd", "res://presentation/views/ui_kit.gd", "res://core/config_db.gd"],
"funcs": {"settings_store.gd": ["*"], "save_manager.gd": ["active_slot", "keystone_balance",
"write_to_disk", "has_breakpoint", "set_breakpoint", "clear_breakpoint", "slot_path", "adventure_total", "has_write_target"],
"main.gd": ["_ready", "_build_ui", "_refresh_resume_button", "_begin_session"]}},
"_smoke_run_lifecycle": {"count": 11, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://presentation/run_scope.gd", "res://presentation/views/battle_end_overlay.gd",
"res://presentation/main.gd", "res://core/adventure_runner.gd"],
"funcs": {"run_scope.gd": ["*"], "battle_end_overlay.gd": ["is_open", "open", "close"],
"main.gd": ["_start_adventure_from_menu", "_begin_session", "_on_battle_end_continue", "_refresh_resume_button"],
"adventure_runner.gd": ["abandon", "clear_breakpoint"]}},
"_smoke_lifecycle_matrix": {"count": 10, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://presentation/scenes/menu_screen.gd", "res://core/battle_orchestrator.gd",
"res://presentation/views/battle_end_overlay.gd", "res://presentation/main.gd", "res://core/adventure_runner.gd"],
"funcs": {"menu_screen.gd": ["_build_ui"], "battle_orchestrator.gd": ["is_battle_live", "begin_battle"],
"battle_end_overlay.gd": ["is_open"], "main.gd": ["_begin_session", "_on_battle_end_continue",
"_resume_from_menu", "_open_settings", "_open_career", "_show_debug_overlay"],
"adventure_runner.gd": ["abandon", "clear_breakpoint"]}},
"_stage_faces": {"count": 1, "run_fn": "_smoke_lifecycle_matrix", "weapons": ["inject", "state"],
"tables": [], "modules": ["res://presentation/modal_flow.gd", "res://presentation/main.gd"],
"funcs": {"modal_flow.gd": ["*"], "main.gd": ["_setup_modal_flow", "_build_ui"]}},
},
},
{
"id": "table_structure_guard",
"src": "res://tests/unit/data_config/table_structure_guard_test.gd",
"channel": "kit",
"async": false,
"budget": 3000,
"cap_ms": 1200000,
"state_autoloads": [],
"suites": {
"_smoke_ac_swap_guard": {"count": 12, "weapons": ["table", "inject"],
"tables": ["enemy", "status_effects", "reward", "settlement", "hero"],
"modules": ["res://core/unit_container.gd", "res://core/config_db_resolver.gd"], "funcs": {}},
"_smoke_enemy_bands": {"count": 4, "weapons": ["table", "inject"],
"tables": ["enemy"], "modules": ["res://core/config_db_resolver.gd"], "funcs": {}},
"_smoke_variation_framework": {"count": 9, "weapons": ["table", "inject"],
"tables": ["variation"], "modules": ["res://data/schemas/variation_table.gd"], "funcs": {}},
"_smoke_difficulty_table": {"count": 8, "weapons": ["table", "inject"],
"tables": ["difficulty"], "modules": ["res://core/unit_container.gd", "res://core/config_db_resolver.gd"], "funcs": {}},
"_smoke_nine_types_gp_stream": {"count": 6, "weapons": ["table", "inject"],
"tables": ["reward"], "modules": ["res://data/schemas/reward_table.gd", "res://core/rng_service.gd"], "funcs": {}},
"_smoke_adventure_table": {"count": 17, "weapons": ["table", "inject"],
"tables": ["adventure", "treasure_items", "meta"],
"modules": ["res://data/schemas/adventure_table.gd", "res://core/attunement.gd",
"res://data/schemas/treasure_item_table.gd", "res://core/battle_orchestrator.gd", "res://core/meta_progression.gd",
"res://core/config_db.gd"], "funcs": {}},
"_smoke_meta": {"count": 4, "weapons": ["table", "inject"],
"tables": ["meta"], "modules": ["res://core/meta_progression.gd"], "funcs": {}},
},
},
{
"id": "board_gen_reward",
"src": "res://tests/unit/core/board_gen_reward_test.gd",
"channel": "kit",
"async": false,
"budget": 800,
"state_autoloads": [],
"suites": {
"_smoke_layout_cell_formula": {"count": 2, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://presentation/views/board_view.gd"], "funcs": {}},
"_smoke_reward_identity_unit": {"count": 10, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://core/reward_economy.gd"], "funcs": {}},
"_smoke_board_generator": {"count": 22, "weapons": ["inject", "table"],
"tables": ["board_gen"],
"modules": ["res://core/board_generator.gd", "res://core/config_db_resolver.gd"], "funcs": {}},
"_smoke_power_interval": {"count": 5, "weapons": ["table", "inject"], "tables": ["reward"],
"modules": ["res://core/reward_economy.gd"], "funcs": {}},
},
},
{
"id": "roll_multiplier",
"src": "res://tests/unit/battle_settlement/roll_multiplier_test.gd",
"channel": "kit",
"async": false,
"budget": 400,
"cap_ms": 1800000,
"state_autoloads": [],
"suites": {
"_smoke_enemy_attack_type": {"count": 4, "weapons": ["table", "inject"],
"tables": ["enemy"], "modules": ["res://core/unit_container.gd", "res://core/damage_controller.gd"], "funcs": {}},
"_smoke_armor_roll": {"count": 15, "weapons": ["table", "inject"], "tables": ["settlement"],
"modules": ["res://core/damage_math.gd", "res://core/damage_controller.gd", "res://core/status_container.gd"], "funcs": {}},
"_smoke_pool_wiring": {"count": 4, "weapons": ["table", "inject"], "tables": ["status_effects"],
"modules": ["res://core/damage_controller.gd"], "funcs": {}},
"_smoke_damage_types": {"count": 10, "weapons": ["table", "inject"], "tables": ["enemy", "settlement"],
"modules": ["res://core/settlement/grant_segment.gd", "res://core/damage_controller.gd"], "funcs": {}},
"_smoke_attack_chain_fresh_pool": {"count": 3, "weapons": ["inject", "state"], "tables": [],
"modules": ["res://core/battle_orchestrator.gd", "res://core/damage_controller.gd"], "funcs": {}},
},
},
{
"id": "seal_polarity",
# 迁移中宿主:读驱动命令物化的提交快照(5ed1ec99 版=套1 五条在册形态),不读 WIP 工作区
"src": "user://mutation_work/seal_polarity_test.gd",
"channel": "kit",
"async": false,
"budget": 600,
"state_autoloads": [],
"suites": {
"_smoke_seal_ap_exhausted": {"count": 5, "weapons": ["state", "table", "inject"],
"tables": ["action_economy"],
"modules": ["res://core/battle_orchestrator.gd", "res://core/action_economy.gd", "res://core/minesweeper_rules.gd"],
# funcs 提示=账本 §九 G5 套1 旧法变异点所在函数(只作试跑排序,不作唯一改坏面)
"funcs": {"battle_orchestrator.gd": ["begin_battle"],
"minesweeper_rules.gd": ["revealed_cells", "settle_batch"],
"action_economy.gd": ["_cost", "try_spend", "_spend_cost_and_arbitrate", "_spend_and_arbitrate"]}},
},
},
]
static func host_by_id(id: String) -> Dictionary:
for h in hosts():
if h["id"] == id:
return h
return {}
static func total_static_checks() -> int:
var n := 0
for h in hosts():
for s in h["suites"].values():
n += int(s["count"])
return n