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:
1 parent
8b9e55673f
commit
b605022001
58 files changed
+503
-384
No files matched your search
@@ -88,7 +88,7 @@ func validate() -> Array:
|
||||
# 池模板(敌人技能池批——单表结构校验;跨表构成纪律在 ConfigDB):
|
||||
# 非空池 + 条目 {skill_id 非空, weight > 0} + 池内 skill_id 不重复。
|
||||
# 普攻冷却恒 0(SkillTable schema 锁死)→ 可摇集合恒非空,"空池不可能"由此结构保证。
|
||||
var pool: Array = row.get("pool", [])
|
||||
var pool: Array[Variant] = row.get("pool", [])
|
||||
if pool.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s pool 空池(禁——技能池行必带池模板)" % eid})
|
||||
var pool_ids := {}
|
||||
@@ -96,7 +96,7 @@ func validate() -> Array:
|
||||
if not (entry_v is Dictionary):
|
||||
errs.append({"category": "domain", "message": "%s pool 条目非字典: %s" % [eid, str(entry_v)]})
|
||||
continue
|
||||
var entry: Dictionary = entry_v
|
||||
var entry: Dictionary[Variant, Variant] = entry_v
|
||||
var sid: String = String(entry.get("skill_id", ""))
|
||||
if sid == "":
|
||||
errs.append({"category": "domain", "message": "%s pool 条目 skill_id 空" % eid})
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
class_name FeatTable
|
||||
extends Resource
|
||||
|
||||
@export var rows: Array = [] # Array[Dictionary] 键 feat_id
|
||||
@export var rows: Array[Variant] = [] # Array[Dictionary] 键 feat_id
|
||||
|
||||
## 稀有度词表(四级——与令牌池 TIERS 同名词族;令牌档 = rarity 直映射)
|
||||
const RARITIES := ["common", "excellent", "rare", "legendary"]
|
||||
@@ -37,7 +37,7 @@ const TRIGGER_KEYS := ["on", "when", "do"]
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array = []
|
||||
var errs: Array[Variant] = []
|
||||
if rows.is_empty():
|
||||
return errs # 空表合法态(T1 基建先行——逐件填行)
|
||||
var seen := {}
|
||||
|
||||
@@ -62,7 +62,7 @@ func validate() -> Array:
|
||||
continue
|
||||
# 类型轴:武器=attack_type 域、甲=armor_type 域;每型恰一路线(三武器三甲各一)
|
||||
var axis := String(row.get("type_axis", ""))
|
||||
var domain: Array = ATTACK_TYPES if kind == "weapon" else ARMOR_TYPES
|
||||
var domain: Array[Variant] = ATTACK_TYPES if kind == "weapon" else ARMOR_TYPES
|
||||
if not domain.has(axis):
|
||||
errs.append({"category": "enum", "message": "%s type_axis 出域 %s: %s" % [rid, domain, axis]})
|
||||
var type_key := "%s|%s" % [kind, axis]
|
||||
|
||||
@@ -49,7 +49,7 @@ func validate() -> Array:
|
||||
# 模板池(关卡节点图生成 v0.4——M-3 迭代 5 T5):row.templates 非空 = 池形态,池内全模板加载期校验
|
||||
# (违规致命——不只抽中的那张);空 = 旧单图形态(row.nodes 直读,向后兼容零迁移)。
|
||||
var node_lists: Array[Array] = [] # [ [上下文标签, nodes 数组], ... ]
|
||||
var templates: Array = row.get("templates", [])
|
||||
var templates: Array[Variant] = row.get("templates", [])
|
||||
if templates.is_empty():
|
||||
node_lists.append(["", row.get("nodes", [])])
|
||||
else:
|
||||
@@ -115,7 +115,7 @@ func _validate_graph(L: int, nodes: Array, is_graph: bool, tag: String = "") ->
|
||||
var nexts: Array[Array] = [] # 每节点出边 id 数组
|
||||
var id_to_idx := {}
|
||||
for i in nodes.size():
|
||||
var node: Dictionary = nodes[i]
|
||||
var node: Dictionary[Variant, Variant] = nodes[i]
|
||||
var nid: int = int(node.get("node_depth", i)) if is_graph else i
|
||||
if is_graph and not node.has("node_depth"):
|
||||
errs.append({"category": "structural", "message": "level %d%s 图形态节点[%d] 缺 node_depth(全节点须编号化)" % [L, tag, i]})
|
||||
@@ -190,7 +190,7 @@ func _validate_graph(L: int, nodes: Array, is_graph: bool, tag: String = "") ->
|
||||
errs.append({"category": "structural", "message": "level %d 节点 %d 沿连线不可达 Boss" % [L, ids[i]]})
|
||||
# ⑧ U2 目检新规则(迭代 5 返工批 2026-09-29):BFS 同深度层节点数上限 5(分支宽度天花板)
|
||||
var layer_of := {}
|
||||
var bfs: Array = [entries[0]]
|
||||
var bfs: Array[Variant] = [entries[0]]
|
||||
layer_of[entries[0]] = 0
|
||||
while not bfs.is_empty():
|
||||
var cur: int = bfs.pop_front()
|
||||
@@ -214,7 +214,7 @@ func _reachable(start: int, adj: Array, n: int) -> Dictionary:
|
||||
var seen := {}
|
||||
if start < 0 or start >= n:
|
||||
return seen
|
||||
var queue: Array = [start]
|
||||
var queue: Array[Variant] = [start]
|
||||
seen[start] = true
|
||||
while not queue.is_empty():
|
||||
var cur: int = queue.pop_front()
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
class_name MetaTreeTable
|
||||
extends Resource
|
||||
|
||||
@export var rows: Array = [] # Array[Dictionary] 键 node_id
|
||||
@export var rows: Array[Variant] = [] # Array[Dictionary] 键 node_id
|
||||
|
||||
const VEINS := ["spine", "forge", "keystone", "attune"]
|
||||
const KINDS := ["stat", "rule", "unlock", "socket", "fork", "easter"]
|
||||
@@ -47,7 +47,7 @@ const FORK_GROUPS := ["fg_posture", "fg_sense", "fg_economy"]
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array = []
|
||||
var errs: Array[Variant] = []
|
||||
if rows.is_empty():
|
||||
return errs # 空表合法态(建表先行——内容随换代批落)
|
||||
var seen := {}
|
||||
@@ -81,7 +81,7 @@ func validate() -> Array:
|
||||
var price := int(row.get("price", 0))
|
||||
if price < 0 or price > 9999:
|
||||
errs.append({"category": "domain", "message": "%s price 越域 [0,9999]: %d" % [nid, price]})
|
||||
var fx: Dictionary = row.get("effects", {}) as Dictionary
|
||||
var fx: Dictionary[Variant, Variant] = row.get("effects", {}) as Dictionary
|
||||
for ek in fx.keys():
|
||||
if not (STAT_KEYS.has(String(ek)) or RULE_KEYS.has(String(ek))):
|
||||
errs.append({"category": "zero_flat", "message": "%s effects 键出域(stat 线/rule 词表封闭): %s" % [nid, String(ek)]})
|
||||
@@ -100,7 +100,7 @@ func validate() -> Array:
|
||||
if not fx.is_empty():
|
||||
errs.append({"category": "cross_field", "message": "%s fork 行主 effects 须空(效果只放 a/b 双键)" % nid})
|
||||
for skey in ["effects_a", "effects_b"]:
|
||||
var sd: Dictionary = row.get(skey, {}) as Dictionary
|
||||
var sd: Dictionary[Variant, Variant] = row.get(skey, {}) as Dictionary
|
||||
if sd.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s %s 缺失或空(双态节点须双侧效果)" % [nid, skey]})
|
||||
for k in sd.keys():
|
||||
|
||||
@@ -83,7 +83,7 @@ func validate() -> Array:
|
||||
if d < 1 or d > 99 or (i > 0 and d >= int(roll_tier_discounts[i - 1])):
|
||||
errs.append({"category": "cross_field", "message": "roll_tier_discounts[%d] 越域/非降序(档位不设零档): %d" % [i, d]})
|
||||
for atk_type in ATTACK_TYPE_KEYS:
|
||||
var row: Dictionary = armor_effectiveness.get(atk_type, {})
|
||||
var row: Dictionary[Variant, Variant] = armor_effectiveness.get(atk_type, {})
|
||||
for armor in ARMOR_KEYS:
|
||||
var pct: int = int(row.get(armor, -99))
|
||||
if pct < -3 or pct > 3:
|
||||
|
||||
@@ -57,7 +57,7 @@ func validate() -> Array:
|
||||
errs.append({"category": "cross_field", "message": "gp_drops %s 违反 roll_min(%d) ≤ mean(%d) ≤ roll_max(%d)——均值恒等期望锚" % [tier, rmin, mean, rmax]})
|
||||
# level_gp_bonus / price_level_bonus:level_index 连续从 1 递增 + 加值域
|
||||
for family in ["level_gp_bonus", "price_level_bonus"]:
|
||||
var arr: Array = get(family)
|
||||
var arr: Array[Variant] = get(family)
|
||||
var seen := {}
|
||||
for row in arr:
|
||||
var li: int = int(row.get("level_index", 0))
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
class_name TreasureItemTable
|
||||
extends Resource
|
||||
|
||||
@export var rows: Array = [] # Array[Dictionary] 键 item_id
|
||||
@export var rows: Array[Variant] = [] # Array[Dictionary] 键 item_id
|
||||
|
||||
# 计数键封闭枚举(原 AttunementGrowthTable.COUNTER_KEYS——迭代 21 T5 谓词表退役后就地内联;
|
||||
# 迭代 22 T1 换代:clear_count(旧工坊按关累计渠道)与 C6 通关口径(通关=打通整局冒险)不符,
|
||||
@@ -85,7 +85,7 @@ const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kin
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array = []
|
||||
var errs: Array[Variant] = []
|
||||
if rows.is_empty():
|
||||
# 空表合法态(2026-09-17 用户拍板——切片期无道具内容;F2 覆盖检查仅对非空清单执行)
|
||||
return errs
|
||||
@@ -104,13 +104,13 @@ func validate() -> Array:
|
||||
var retired: bool = bool(row.get("retired", false))
|
||||
var deferred: bool = bool(row.get("deferred", false))
|
||||
# dimension_tags:五维词表 + 非空(退役/失义行仍须登记维度——语义面保留)
|
||||
var tags: Array = row.get("dimension_tags", [])
|
||||
var tags: Array[Variant] = row.get("dimension_tags", [])
|
||||
if tags.is_empty():
|
||||
errs.append({"category": "domain", "message": "%s dimension_tags 空" % iid})
|
||||
for tag in tags:
|
||||
if not DIMENSIONS.has(String(tag)):
|
||||
errs.append({"category": "enum", "message": "%s dimension_tag 出域 %s: %s" % [iid, str(DIMENSIONS), str(tag)]})
|
||||
var kinds: Array = row.get("effect_kinds", [])
|
||||
var kinds: Array[Variant] = row.get("effect_kinds", [])
|
||||
var target: String = String(row.get("target", "none"))
|
||||
if not TARGETS.has(target):
|
||||
errs.append({"category": "enum", "message": "%s target 出域 %s: %s" % [iid, str(TARGETS), target]})
|
||||
@@ -217,7 +217,7 @@ func validate() -> Array:
|
||||
if not kind_seen.has("ap_charge_safe") and charge_n != 0:
|
||||
errs.append({"category": "cross_field", "message": "%s 非 ap_charge_safe 行 charge_n 应 0,实得 %d" % [iid, charge_n]})
|
||||
# unlock_requires 谓词行:空 = 已解锁(首批全解锁合法态,底稿 §2.2);非空键 ∈ 计数键封闭枚举
|
||||
var ureqs: Array = row.get("unlock_requires", [])
|
||||
var ureqs: Array[Variant] = row.get("unlock_requires", [])
|
||||
var ukeys := {}
|
||||
for req in ureqs:
|
||||
var ukey: String = String(req.get("key", ""))
|
||||
@@ -234,7 +234,7 @@ func validate() -> Array:
|
||||
|
||||
# 同调行词表(form 非空)——装配覆盖层/效果接线/同调位上限的唯一取数口径(迭代 11 第①批 T1)
|
||||
func attunement_rows() -> Array:
|
||||
var out: Array = []
|
||||
var out: Array[Variant] = []
|
||||
for row in rows:
|
||||
if String(row.get("form", "")) != "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
@@ -244,7 +244,7 @@ func attunement_rows() -> Array:
|
||||
# 过渡行词表(form 空 = 切片期过渡形态活行)——掉落投放/停点池/过渡覆盖面的取数口径;
|
||||
# 同调行永不入过渡渠道。T7 退役面切换后本口径随渠道消亡。
|
||||
func transitional_rows() -> Array:
|
||||
var out: Array = []
|
||||
var out: Array[Variant] = []
|
||||
for row in rows:
|
||||
if String(row.get("form", "")) == "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
@@ -253,7 +253,7 @@ func transitional_rows() -> Array:
|
||||
|
||||
# 活行词表(非 retired 非 deferred)——投放校验/奖励节点池/F2 覆盖面的唯一取数口径
|
||||
func active_rows() -> Array:
|
||||
var out: Array = []
|
||||
var out: Array[Variant] = []
|
||||
for row in rows:
|
||||
if not bool(row.get("retired", false)) and not bool(row.get("deferred", false)):
|
||||
out.append(row)
|
||||
|
||||
Reference in new issue
Block a user