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

+2 -2
View File
@@ -130,8 +130,8 @@ func _flush_pending_agg() -> void:
if _pending_agg.is_empty():
return
for key in _pending_agg:
var item: Dictionary = _pending_agg[key]
var row: Dictionary = item["row"]
var item: Dictionary[Variant, Variant] = _pending_agg[key]
var row: Dictionary[Variant, Variant] = item["row"]
var count: int = item["count"]
var bb := _format_row(row, count)
_round_rows.append(bb)
+5 -5
View File
@@ -275,7 +275,7 @@ func _refresh_slab() -> void:
# 战斗启动/换板:按板尺寸重建格单元(minesweeper 引用随之更新)
func rebuild(board: BoardData, minesweeper) -> void:
func rebuild(board: BoardData, minesweeper: MinesweeperRules) -> void:
_board = board
_minesweeper = minesweeper
for child in _world.get_children():
@@ -630,7 +630,7 @@ func _show_path_preview(c: Vector2i) -> void:
# D3 合法性指示:悬停已开格 → BFS 路径蓝细线点迹(compute_move_path 只读面)
if _minesweeper == null:
return
var path: Array = _minesweeper.compute_move_path(c)
var path: Array[Variant] = _minesweeper.compute_move_path(c)
for pc in path:
if _cells.has(pc):
_cells[pc].dot_visible = true
@@ -648,7 +648,7 @@ func _update_badge(c: Vector2i) -> String:
return ""
if _r0.has(c):
return "" # R₀ 初始展开格无奖励身份(地图战斗资源 资格域 = S∖R₀)
var rec: Dictionary = _minesweeper.reveal_record(c) # E2 收口:已开记录经查询面(禁直读 排雷玩法 状态字典)
var rec: Dictionary[Variant, Variant] = _minesweeper.reveal_record(c) # E2 收口:已开记录经查询面(禁直读 排雷玩法 状态字典)
if rec.get("kind", "") != "safe":
return ""
var ident = _identity_cb.call(c)
@@ -704,7 +704,7 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
flag = false
u.tex_flag = null
if revealed:
var rec: Dictionary = _minesweeper.reveal_record(c) # E2 收口:已开记录经查询面
var rec: Dictionary[Variant, Variant] = _minesweeper.reveal_record(c) # E2 收口:已开记录经查询面
if rec.get("kind", "") == "mine":
bg = COL_FLOOR
glyph = "雷"
@@ -910,7 +910,7 @@ func _load_board_tiles(board_type: String = "dungeon") -> void:
# 方向稿 _v3_darken_floors 同式移植;现行瓦片 L≈0.036 低于带下沿故实为提亮;素材重产归资产批,
# 本归一为程序代役(逐批装载时对 freshly-loaded 原图测光,幂等)。归一后逐像素明度顺路采集,
# 驱动数字墨族按板自适应(_digit_ink_mode——均值分位同源同像素,禁二次解码)
var lumas: Array = []
var lumas: Array[Variant] = []
for i in range(floors.size()):
floors[i] = _normalize_floor_luma(floors[i], 0.10, lumas)
var ink_mode := _digit_ink_mode(lumas)
+9 -9
View File
@@ -238,8 +238,8 @@ func _rebuild_tree(data: Dictionary) -> void:
c.queue_free()
_tree_buy_btns.clear()
_tree_fork_btns.clear()
var tree: Array = data.get("tree", []) as Array
var forks: Array = data.get("fork_groups", []) as Array
var tree: Array[Variant] = data.get("tree", []) as Array
var forks: Array[Variant] = data.get("fork_groups", []) as Array
var vein_names := {"spine": "·脊柱淬炼·", "forge": "·锻造脉·", "keystone": "·钥石脉·", "attune": "·同调脉·"}
var last_vein := ""
for row in tree:
@@ -407,7 +407,7 @@ func refresh_camp(data: Dictionary) -> void:
for row in data.get("workshop", []):
ws_by_id[String(row.get("item_id", ""))] = row
for card in _workshop_rows:
var row: Dictionary = ws_by_id.get(String(card.item_id), {})
var row: Dictionary[Variant, Variant] = ws_by_id.get(String(card.item_id), {})
if row.is_empty():
continue
var unlocked := bool(row.get("unlocked", false))
@@ -422,7 +422,7 @@ func refresh_camp(data: Dictionary) -> void:
elif mode == "condition":
var parts: Array[String] = []
for req_v in (row.get("reqs", []) as Array):
var req: Dictionary = req_v as Dictionary
var req: Dictionary[Variant, Variant] = req_v as Dictionary
var lbl := String(UiKit.TREASURE_REQ_LABELS.get(String(req.get("key", "")), "条件"))
parts.append("%s %d/%d" % [lbl, int(req.get("progress", 0)), int(req.get("threshold", 0))])
prog_text = "、".join(parts)
@@ -440,10 +440,10 @@ func refresh_camp(data: Dictionary) -> void:
if card.get("buy_btn") != null:
card.buy_btn.disabled = balance < int(card.get("price", 0))
# 同调装配段状态就地刷(迭代 11 第①批 T4——Slots 点亮/满位禁选/Y 升级行余额联动)
var att: Dictionary = data.get("attune", {})
var att: Dictionary[Variant, Variant] = data.get("attune", {})
if _attune_header_l != null:
var slots_n := int(att.get("slots", 0))
var eq: Array = att.get("equipped", [])
var eq: Array[Variant] = att.get("equipped", [])
_attune_header_l.text = "── 同调装配 Slots %d/%d ──" % [eq.size(), slots_n]
var eq_set := {}
for v in eq:
@@ -454,7 +454,7 @@ func refresh_camp(data: Dictionary) -> void:
# 满位禁选+未解锁禁装(迭代 22 T4——已装件恒可卸下;unlocked 快照随 rebuild 刷新)
card2.btn.disabled = (not on and eq.size() >= slots_n) or (not on and not bool(card2.get("unlocked", false)))
if _refresh_l != null:
var rf: Dictionary = att.get("refresh", {})
var rf: Dictionary[Variant, Variant] = att.get("refresh", {})
_refresh_l.text = "三选一刷新 +%d 次/冒险 · Lv%d" % [int(rf.get("charges", 0)), int(rf.get("level", 0))]
_refresh_btn.text = "已满级" if bool(rf.get("maxed", false)) else "升级 %d 钥石" % int(rf.get("price", 0))
_refresh_btn.disabled = bool(rf.get("maxed", false)) or balance < int(rf.get("price", 0))
@@ -508,7 +508,7 @@ func _rebuild_workshop(data: Dictionary) -> void:
# 同调装配段重建(迭代 11 第①批 T4——秘宝匣柜台尾部段〔迭代 21 T6 随柜台迁入〕;Slots 点亮+
# 九件行板+Y 升级行,程序占位面)
func _rebuild_attune(data: Dictionary) -> void:
var att: Dictionary = data.get("attune", {})
var att: Dictionary[Variant, Variant] = data.get("attune", {})
_attune_header_l = UiKit.label("",UiKit.FS_HINT, true, UiKit.INK)
_workshop_holder.add_child(_attune_header_l)
_attune_nodes.append(_attune_header_l)
@@ -548,7 +548,7 @@ func _rebuild_attune(data: Dictionary) -> void:
func _rebuild_recent(data: Dictionary) -> void:
var lines: Array[String] = []
var recent: Array = data.get("recent", [])
var recent: Array[Variant] = data.get("recent", [])
if recent.is_empty():
lines.append(" 最近冒险:(暂无记录——完成或结束一次冒险后入账)")
for s in recent:
+1 -1
View File
@@ -28,7 +28,7 @@ var _keystone_badge: UiKit.KeystoneBadge # 钥石余额(badge 工厂件—
func _init() -> void:
# 全屏页壳(T6/T7 对齐批先例——暖亮底+石纹弱质感+暗角+56px 通栏顶条+内容列)
var page: Dictionary = UiKit.page_shell(self, true)
var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, true)
var top: HBoxContainer = page.top_row
top.add_child(UiKit.label("生 涯",UiKit.FS_TITLE, true, UiKit.WARM))
var top_sp := Control.new()
@@ -24,8 +24,8 @@ var _refresh_allowance := 0 # 组合根投喂免费余量(X/Y
var _refresh_gp_cost := 0 # 组合根投喂 GP 刷新价(免费位用尽后的付费档读数)
var _selected := "" # 点选暂存(确认前可改选)
var _header := "" # 停点头部文案(选择态保持显示)
var _card_meta: Array = [] # open_pick 缓存 [{id, text}]——高亮还原读面
var _bcards: Array = [] # M7 bcard 引用列(select 高亮=set_selected)
var _card_meta: Array[Variant] = [] # open_pick 缓存 [{id, text}]——高亮还原读面
var _bcards: Array[Variant] = [] # M7 bcard 引用列(select 高亮=set_selected)
func _init() -> void:
@@ -33,7 +33,7 @@ func _init() -> void:
# 根底暗档)——56px 通栏顶条(标题+刷新图标钮/角标)+ 居中入账信息行(GP 汇总行承载)+
# bcard 三竖卡(D1 232×352)+ 底部确认主钮与免费选择注记。差异白名单=免费选择/✓章/无价签。
# 状态机不变:pick→result。M7 同构裁决遗产保留。
var page: Dictionary = UiKit.page_shell(self, false)
var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, false)
var top: HBoxContainer = page.top_row
top.add_child(UiKit.label("战利品三选一",UiKit.FS_TITLE, true, UiKit.WARM))
var top_sp := Control.new()
@@ -137,7 +137,7 @@ func _select_card(id: String) -> void:
_selected = id
# 选中态=木描边+✓章(demo ⑥;set_selected 逐卡置真值防改选残留)
for i in _bcards.size():
var meta: Dictionary = _card_meta[i] if i < _card_meta.size() else {}
var meta: Dictionary[Variant, Variant] = _card_meta[i] if i < _card_meta.size() else {}
(_bcards[i] as UiKit.BCard).set_selected(String(meta.get("id", "")) == id)
_confirm_btn.visible = true
+1 -1
View File
@@ -158,7 +158,7 @@ func effective_max_hp() -> int:
# ---- 内部构建(标题/关闭固定于浮窗骨架,可扩展列表区居中滚动)----
func _build() -> void:
var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_OVERLAY, Vector2(640, 0), 8)
var shell: Dictionary[Variant, Variant] = UiKit.modal_shell(self, UiKit.BG_OVERLAY, Vector2(640, 0), 8)
var box: VBoxContainer = shell.box
var title := UiKit.label("调试",UiKit.FS_TITLE, true, UiKit.WARM)
@@ -16,9 +16,9 @@ var _atk_label: Label
var _armor_label: Label
signal treasure_slot_clicked(handle: int) # 迭代 7 T4——槽点击(组合根消费:AP 类即用/空间类进选中态)
var item_slots: HBoxContainer # 秘宝槽(迭代 7 T4 接线——库存条常读+两步交互第一步)
var _slot_panels: Array = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷)
var _slot_panels: Array[Variant] = [] # 槽 PanelContainer 引用(选中高亮/置灰重刷)
var _selected_handle := 0 # 选中态(0=无;组合根回写维持单源)
var _slot_handles: Array = [] # 槽位→handle 映射(set_treasure_inventory 刷新)
var _slot_handles: Array[Variant] = [] # 槽位→handle 映射(set_treasure_inventory 刷新)
var _curio_section: VBoxContainer # 特性(预留——空态隐藏,接线归大奖励/锻造呈现批)
var _curio_list: VBoxContainer
var _feat_section: VBoxContainer # 特性持有段(迭代 12 呈现补齐——空态隐藏)
@@ -180,7 +180,7 @@ func set_treasure_inventory(items: Array, selected_handle: int) -> void:
slot.add_theme_stylebox_override("panel",
UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, 0, 1, Vector4(4, 4, 4, 4)))
continue
var rec: Dictionary = items[i]
var rec: Dictionary[Variant, Variant] = items[i]
_slot_handles.append(int(rec.get("handle", 0)))
var used := bool(rec.get("used", false))
var usable := bool(rec.get("usable", true))
+7 -7
View File
@@ -282,7 +282,7 @@ func _process(delta: float) -> void:
# 打开选路口(cands = 候选节点引用数组;runner 只读用于整图渲染与状态栏刷新)
func open_choices(cands: Array, runner) -> void:
func open_choices(cands: Array, runner: LevelRunner) -> void:
var was_visible := visible # 进入转场判据(就地刷新/模态栈恢复不重放淡入)
_runner = runner
_hover_id = -1
@@ -400,7 +400,7 @@ func _on_canvas_input(ev: InputEvent) -> void:
func _candidate_at(local_pos: Vector2) -> int:
if _runner == null:
return -1
var nodes: Array = _runner.nodes()
var nodes: Array[Variant] = _runner.nodes()
var pos := _layout(nodes, _canvas)
for nid in _cand_ids:
var node := _node_by_id(nid, nodes)
@@ -427,7 +427,7 @@ func _submit_choice(nid: int) -> void:
func press_candidate(index: int) -> void:
if index < 0 or index >= _cand_ids.size() or _runner == null:
return
var nodes: Array = _runner.nodes()
var nodes: Array[Variant] = _runner.nodes()
var node := _node_by_id(int(_cand_ids[index]), nodes)
if node.is_empty():
return
@@ -447,12 +447,12 @@ func _id_of(node: Dictionary) -> int:
func _draw_graph(canvas: Control) -> void:
if _runner == null or not visible:
return
var nodes: Array = _runner.nodes()
var nodes: Array[Variant] = _runner.nodes()
var pos := _layout(nodes, canvas)
var current_id: int = _runner.current_node_id()
# 当前节点 id(单链=下标 / 图=编号)——visited_ids() 已按编号空间解析
var visited: Array = _runner.visited_ids()
var cand_ids: Array = _runner.next_candidate_ids()
var visited: Array[Variant] = _runner.visited_ids()
var cand_ids: Array[Variant] = _runner.next_candidate_ids()
# 连线(通道)先行画(方块覆盖其上);悬停预承诺 = 所属通道再增亮(加粗)
# T17 修复:选路停点(候选非空)非候选通道降透明——金岔路从结构网分离(干线共线重叠缺陷的
# 视觉主因:不同源通道共用同一垂直干线,金边与石色边焊接成「整列可走」假象)
@@ -549,7 +549,7 @@ func _assign_layers(nodes: Array, layer: Dictionary, slot: Dictionary) -> void:
queue.append(entry)
layer[entry] = 0
while not queue.is_empty():
var cur: Dictionary = queue.pop_front()
var cur: Dictionary[Variant, Variant] = queue.pop_front()
var l: int = int(layer[cur])
layer_counts[l] = int(layer_counts.get(l, 0)) + 1
slot[cur] = int(layer_counts[l]) - 1
+1 -1
View File
@@ -13,7 +13,7 @@ var _btn: Button
func _init() -> void:
# M5(UI 落码批):rest 兑付面板 plate9 石板化+暖金头带字(demo ④休息弹层;暗字上亮板 §7.2)
var shell: Dictionary = UiKit.modal_shell(self, Color(0, 0, 0, 0.6), Vector2.ZERO, 14, true,
var shell: Dictionary[Variant, Variant] = UiKit.modal_shell(self, Color(0, 0, 0, 0.6), Vector2.ZERO, 14, true,
UiKit.panel_skinned(Vector4(26, 18, 26, 18)))
var box: VBoxContainer = shell.box
_label = UiKit.label("",UiKit.FS_SUB, true, UiKit.INK_TITLE)
+2 -2
View File
@@ -26,7 +26,7 @@ func _init(store) -> void:
# 探针隔离换注(冒烟/探针禁碰真实 user://settings.cfg——换注后按新 store 重挂控件态)
func retarget(store) -> void:
func retarget(store: SettingsStore) -> void:
_store = store
_sync()
@@ -37,7 +37,7 @@ func _build() -> void:
# 减动效与结算演出动画=同一设置(语义命名批合并),一行承载。
# T8(UI 设计对齐批 2026-10-06):两列对齐(label 列定宽 140——demo .setrow label/控制两列)+
# 后果说明内联随行(demo .why 同排)+返回钮紧凑化(demo .btn9 紧凑——原 216 宽砖)。
var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_BRIGHT, Vector2(560, 0), 8, true,
var shell: Dictionary[Variant, Variant] = UiKit.modal_shell(self, UiKit.BG_BRIGHT, Vector2(560, 0), 8, true,
UiKit.panel_skinned(Vector4(20, 16, 20, 16)))
var box: VBoxContainer = shell.box
+2 -2
View File
@@ -33,7 +33,7 @@ func _init() -> void:
# 角标+GP 框)+ 爬价规则行 + bcard 三竖卡居中 + 底部离开钮与池源注记。
# M6 遗产:库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 投喂)。
# legacy 面(open_shop)行卡同壳呈现(shop=off 对照承载原样)。高内聚边界不变:纯视图 setter 面。
var page: Dictionary = UiKit.page_shell(self, true)
var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, true)
var top: HBoxContainer = page.top_row
top.add_child(UiKit.label("商 店",UiKit.FS_TITLE, true, UiKit.WARM))
var top_sp := Control.new()
@@ -110,7 +110,7 @@ func refresh_state(products: Array, gp: int) -> void:
for p in products:
by_id[String(p.product_id)] = p
for card in _card_rows:
var p: Dictionary = by_id.get(String(card.product_id), {})
var p: Dictionary[Variant, Variant] = by_id.get(String(card.product_id), {})
if p.is_empty():
continue
card.price.text = "现价 %d 金币" % int(p.price)
+2 -2
View File
@@ -21,7 +21,7 @@ var _tree_label: Label
func _init() -> void:
var shell: Dictionary = UiKit.modal_shell(self, Color(UiKit.DIM, 0.55), Vector2(560, 0), 10, true,
var shell: Dictionary[Variant, Variant] = UiKit.modal_shell(self, Color(UiKit.DIM, 0.55), Vector2(560, 0), 10, true,
UiKit.panel_skinned(Vector4(20, 16, 20, 16))) # 石板皮(缺位回退数据板——同设置面先例)
var box: VBoxContainer = shell.box
@@ -103,7 +103,7 @@ func _rebuild_workshop(data: Dictionary) -> void:
else:
var parts: Array[String] = []
for req_v in (row.get("reqs", []) as Array):
var req: Dictionary = req_v as Dictionary
var req: Dictionary[Variant, Variant] = req_v as Dictionary
var lbl := String(UiKit.TREASURE_REQ_LABELS.get(String(req.get("key", "")), "条件"))
parts.append("%s %d/%d" % [lbl, int(req.get("progress", 0)), int(req.get("threshold", 0))])
prog_text = "、".join(parts)
+1 -1
View File
@@ -165,7 +165,7 @@ func _on_slot_hover(slot: Control) -> void:
# tooltip:来源 + 语义 + 剩余(≥13px;悬停只读反馈通道——无点击无写)
if not slot.has_meta("eff"):
return
var eff: Dictionary = slot.get_meta("eff")
var eff: Dictionary[Variant, Variant] = slot.get_meta("eff")
var eid := String(eff.effect_id)
var src: String = String(SOURCE_NAMES.get(String(eff.get("source_class", "")), String(eff.get("source_class", ""))))
var semantic: String = String(EFFECT_SEMANTIC.get(eid, String(eff.get("display_name", ""))))