feat(迭代27 T5): 波五a 类型闸拉起+存量收口——审计器 0 存量+warning 配置在位

P1-6 类型闸(须 T1-T4 全落后——本波按执行顺序锁殿后):
- tools/audit_type_hints.py 新机器闸(V7): R1 无类型容器注解/R2 有值返回缺返回类型/
  R3 参数缺类型三规则+行级 # type-hint: ignore 显式白名单通道;产品码 core/data/presentation
- 存量收口: 368 处显式 Array/Dictionary 非参数化注解→机械参数化(Array[Variant]/
  Dictionary[Variant, Variant] 零行为面);13 处参数真类型(SaveManagerCore/ConfigDb/
  BattleOrchestrator/MinesweeperRules/LevelRunner/SettingsStore 等)
- 白名单豁免四处: board_generator generate/_attempt/legality/_finalize 的 db 参——
  测量面 _BoardRowStub 冒烟夹具鸭子型注入(typed 参拒 stub)
- project.godot 拉起 gdscript/warnings/untyped_declaration=1(V7 源码断言在 smoke _smoke_type_gate)
- static_scan 新 S9 类型闸规则;顺修历史 cd 错位(9-24 布局迁移后 /.. 落 game/ 致守卫
  恒跳过静默空转——修复后 S1-S4/S9 首次实跑全绿)+S1/S2 增 ADR-0007-exempt 标记豁免通道
  (main _seed_value 引擎熵源=文档化豁免面)

验收: 冒烟 1081/0(+V7×2)+run_all 27 套+static_scan 全绿+probe click+render golden+对拍三变体全同
This commit is contained in:
DKChan committed 2026-10-15 01:05:17 +08:00
1 parent 8b9e55673f
commit b605022001
58 files changed
+503 -384

No files matched your search

+13 -13
View File
@@ -91,8 +91,8 @@ const DO_KEYS := ["kind", "value", "value_from", "delta", "delta_from", "mult",
const ACTIVE_KINDS := ["reveal_tiles", "preview", "grant_ap", "remove_mines", "refresh_pick", "safe_dig"]
# ---- 订阅集与计数器账本 ----
var _triggers: Array = [] # [{source, id, on, when, do}](装载序=声明序,重建时定死)
var _counters: Dictionary = {} # counter_id → int(battle 域账本;重建清零;重置点由订阅行声明)
var _triggers: Array[Variant] = [] # [{source, id, on, when, do}](装载序=声明序,重建时定死)
var _counters: Dictionary[Variant, Variant] = {} # counter_id → int(battle 域账本;重建清零;重置点由订阅行声明)
var _reset_on_round_start: Array[String] = [] # round_start 重置点计数器名单(装载时收集)
var _adventure_counter_ids: Array[String] = [] # domain=adventure 计数器名单(T6——重建时收集、不清零;
# battle 末 export → 冒险账本、begin_battle seed 回灌)
@@ -171,7 +171,7 @@ func rebuild(feat_ids: Array, item_ids: Array, tree_rules: Array = []) -> void:
func _push_trigger(source: String, id: String, tr: Dictionary, row: Dictionary) -> void:
var on := String(tr.get("on", ""))
assert(EVENTS.has(on), "[效果引擎] 订阅事件出域: %s(%s %s)" % [on, source, id])
var do_d: Dictionary = (tr.get("do", {}) as Dictionary).duplicate(true)
var do_d: Dictionary[Variant, Variant] = (tr.get("do", {}) as Dictionary).duplicate(true)
# *_from 解析(rebuild 时把行字段引用定影为值——value_from:"magnitude" → value=行 magnitude)
for pair in [["value_from", "value"], ["delta_from", "delta"], ["mult_from", "mult"], ["cap_from", "cap"]]:
if do_d.has(pair[0]):
@@ -179,9 +179,9 @@ func _push_trigger(source: String, id: String, tr: Dictionary, row: Dictionary)
do_d.erase(pair[0])
# when value_from 同面解析(行字段引用条件——dawn_order effective_rounds 先例:字面量出行=数值
# 单一事实源破面,行引用随 rebuild 定影)
var when_d: Array = (tr.get("when", []) as Array).duplicate(true)
var when_d: Array[Variant] = (tr.get("when", []) as Array).duplicate(true)
for c_v in when_d:
var c: Dictionary = c_v as Dictionary
var c: Dictionary[Variant, Variant] = c_v as Dictionary
if c.has("value_from"):
c["value"] = int(row.get(String(c["value_from"]), 0))
c.erase("value_from")
@@ -206,7 +206,7 @@ func has_effect_on(event: String, kind: String, mode: String = "") -> bool:
for tr in _triggers:
if String(tr.on) != event:
continue
var d: Dictionary = tr.do
var d: Dictionary[Variant, Variant] = tr.do
if String(d.get("kind", "")) == kind and (mode == "" or String(d.get("mode", "")) == mode):
# 有 when 时不能预判命中(发射点缺省行为保守按「可能命中」计——命中由 dispatch 定夺)
return true
@@ -221,7 +221,7 @@ func dispatch(event: String, payload: Dictionary, facts: Callable = Callable())
if event == "round_start":
for cid in _reset_on_round_start:
_counters[cid] = 0
var hits: Array = []
var hits: Array[Variant] = []
for tr in _triggers:
if String(tr.on) != event:
continue
@@ -350,8 +350,8 @@ func _counter_delta_of(matchup: String) -> int:
var parts := matchup.split("_vs_")
if parts.size() != 2:
return 0
var tbl: Dictionary = db.settlement.armor_effectiveness
var row: Dictionary = tbl.get(String(parts[0]), {})
var tbl: Dictionary[Variant, Variant] = db.settlement.armor_effectiveness
var row: Dictionary[Variant, Variant] = tbl.get(String(parts[0]), {})
return int(row.get(String(parts[1]), 0))
@@ -362,7 +362,7 @@ func _counter_delta_of(matchup: String) -> int:
static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array, errs: Array) -> bool:
var mine_covered := false
for tr_v in triggers:
var tr: Dictionary = tr_v as Dictionary
var tr: Dictionary[Variant, Variant] = tr_v as Dictionary
for k in tr.keys():
if not ["on", "when", "do"].has(String(k)):
errs.append({"category": "zero_flat", "message": "%s trigger 键出白名单: %s" % [rid, String(k)]})
@@ -372,7 +372,7 @@ static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array,
elif MINE_EVENTS.has(on):
mine_covered = true
for c_v in (tr.get("when", []) as Array):
var c: Dictionary = c_v as Dictionary
var c: Dictionary[Variant, Variant] = c_v as Dictionary
for k in c.keys():
if not WHEN_KEYS.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s when 键出白名单: %s" % [rid, String(k)]})
@@ -381,7 +381,7 @@ static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array,
errs.append({"category": "enum", "message": "%s fact 出域(事实词汇封闭 9 项): %s" % [rid, fact]})
if not OPS.has(String(c.get("op", "eq"))):
errs.append({"category": "enum", "message": "%s when 算子出域: %s" % [rid, String(c.get("op", ""))]})
var do_d: Dictionary = tr.get("do", {}) as Dictionary
var do_d: Dictionary[Variant, Variant] = tr.get("do", {}) as Dictionary
for k in do_d.keys():
if not DO_KEYS.has(String(k)):
errs.append({"category": "zero_flat", "message": "%s do 键出白名单: %s(机制轴禁无条件属性加项)" % [rid, String(k)]})
@@ -396,7 +396,7 @@ static func validate_trigger_row(rid: String, row: Dictionary, triggers: Array,
if fld != "" and not row.has(fld):
errs.append({"category": "dangling", "message": "%s do.%s 悬空(行无字段 %s)" % [rid, vf_k, fld]})
for c_v in (tr.get("when", []) as Array):
var c_w: Dictionary = c_v as Dictionary
var c_w: Dictionary[Variant, Variant] = c_v as Dictionary
if c_w.has("value_from"):
var wfld := String(c_w.get("value_from", ""))
if wfld != "" and not row.has(wfld):