diff --git a/tier2/gen-worker/worker/run.py b/tier2/gen-worker/worker/run.py index 9c8febf6..df0d31fa 100644 --- a/tier2/gen-worker/worker/run.py +++ b/tier2/gen-worker/worker/run.py @@ -364,7 +364,27 @@ def validate_datatable(game_id: str) -> dict: unreachable.append(f"{o.get('id')}→{item_id}") if unreachable: errs.append(f"以下订单物品不可达(既非合成产出、又不在开局库存):{unreachable}。" - "每个订单 requires 的物品必须能被某条 mergeChain 产出(to),或在 currencies.ingredients.initial 里。") + "每个订单 requires 的物品必须能被某条 mergeChain 产出(到 to),或在 currencies.ingredients.initial 里。") + + # ── ④ 经济线可达性:patience 太长会让破产路在有界 driver run 里耗不尽(spike feie-005 实证)── + # 破产路 driver 跑约 bankruptSteps×stepMs ≈ 16.8s,需 consecutiveOrderFails 单连续流失才判 lose。 + # 若订单 patience 远大于这点墙钟,破产路永远跑不到 lose → 经济门 bankruptPathLose/bothReachedTerminal、 + # H_progress、latch hostReadsTerminal 全挂(feie-005 用了 45~65s patience 正是栽在此;金标用 16~20s)。 + # 这里给一个明确的上界提示(不是死规则,留余量):patience 应让破产路在有界 run 内能连续流失。 + BANKRUPT_BUDGET_S = 16.8 # bankruptSteps(60)×stepMs(280ms);与 run_engine default_business_sim_spec 同源 + streak = int((g.get("loseCondition") or {}).get("consecutiveOrderFails") or 3) + patiences = [o.get("patience") for o in orders if isinstance(o.get("patience"), (int, float))] + if patiences: + # 破产路里订单并发倒计时、约同时耗尽(非排队累加),故判据 = 最小 streak 个订单的【最大】patience + # 要落在有界 run 墙钟内(留较宽余量 1.5×,金标 16~20s 应通过、feie-005 的 45~65s 应拦下)。 + smallest = sorted(patiences)[:max(1, streak)] + worst = max(smallest) + if worst > BANKRUPT_BUDGET_S * 1.5: # 留 50% 余量(金标 ~18s < 25.2s 通过) + errs.append( + f"订单 patience 偏大(最小 {len(smallest)} 单耐心={smallest},单位秒;最大 {worst}s)," + f"破产路在有界真玩 run(约 {BANKRUPT_BUDGET_S:.0f}s,连续 {streak} 单流失才判输)里耗不尽 → " + "经济门 bankruptPathLose / H_progress / latch 会挂。把 patience 调小(参考金标 16~20s 量级)," + "让破产路能在有界 run 内连续流失。") return {"ok": not errs, "errors": errs, "expectedSchemaHint": schema_hint if errs else ""}