fix(tier2): 焊死平台锁定文件——write_source 拒改装载胶水/三系统(根因3)
spike feie-002 实证:loop 自纠(commit b43d59c)已让 M3 续修、数据表 schema 也修对了
(mergeChains/currencies/requires:{id:qty} 全对,三联动门 requiresReachable/dagAcyclic 转绿),
但 F_wiring/G_input/H_progress/callsAddCoins 仍连环挂。diff 出真因:M3 重写了平台锁定的
src/main.js(装载胶水,130 行差异)——丢了 recHook 透传 → 资源系统 addCoins/consumeIngredient
不再记进 window.__engineCalls → F 门 calls=0、合成不记调用、G/H 门跟着挂。
fixture-spec 预建分工本就规定平台预建文件「写死不动」,但只是 prompt advisory、没机器门。
现把它焊成硬约束:write_source 对 9 个平台锁定文件(main.js/game-core.js/systems/*/layout.js/
tables.js/util/*)的真实修改直接拒(幂等回写放行),并提示「只改 play-scene.js + 数据表」。
agent 可写域 = src/scenes/play-scene.js + data/datatable.gold.json + src/scenes/ 新增表现文件。
单测:9 锁定文件命中、play-scene/datatable/新 scene 放行。prompt 同步加固铁律⑦。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b43d59cc9a
commit
f8ec30c875
@ -67,7 +67,12 @@ def writer_system(brief: str, design_text: str = "", *, fixture_hint: str = "")
|
||||
"据失败门 write_source 针对性修,再 build→run_gates,一轮轮逼到门绿。** 门没绿时调 finish 会被拒。\n"
|
||||
"⑥ 数据表是头号雷区:平台 tables.js 按固定 key 读 data/datatable.gold.json——**就地填 sentinel 的值,"
|
||||
"别改 key、别自创 schema**(详见下方品类约定)。填完先 validate_datatable 确认结构对,再 build。\n"
|
||||
"⑦ 收敛即 finish:门全绿才调 finish 交付;别无谓地反复刷探索,也别没绿就想 finish。\n",
|
||||
"⑦ 平台文件写死、绝不许改:**你只能改 src/scenes/play-scene.js(表现层)+ data/datatable.gold.json(数据表),"
|
||||
"或在 src/scenes/ 下新增表现文件**。src/main.js(装载胶水)、src/game-core.js、src/systems/*、src/layout.js、"
|
||||
"src/data/tables.js、src/util/* 全是平台锁定的——它们已把引擎接线(recHook 记 addCoins/consumeIngredient)、"
|
||||
"状态机、结算、latch、readState 导出、命中映射坐标都写好了。**改它们 = 破坏接线**(实测:重写 main.js 丢了 "
|
||||
"recHook → F 门 calls=0、合成不记引擎调用、G/H 门连环挂)。write_source 会拒绝改这些文件。\n"
|
||||
"⑧ 收敛即 finish:门全绿才调 finish 交付;别无谓地反复刷探索,也别没绿就想 finish。\n",
|
||||
"【典型循环节奏】scaffold_init(开局一次)→ write_source 填表现层 → build →(失败则据日志改源再 build)"
|
||||
"→ headless_check 快筛 → run_gates 真玩 → read_verdict 看哪门没过 → write_source 针对性修 →"
|
||||
" 再 run_gates …… 直到门全绿 → finish。\n",
|
||||
|
||||
@ -26,6 +26,28 @@ from agentscope.tool import Toolkit, FunctionTool
|
||||
|
||||
from . import run
|
||||
|
||||
# ── 平台锁定文件(写死、agent 不许改;spike feie-002 实证根因 3)──
|
||||
# fixture-spec 预建分工:平台预建(装载胶水 + 三系统纯逻辑 + 状态机 + 结算 + latch + readState 导出 +
|
||||
# 输入路由/命中映射约定)写死不动;agent 只写表现层 play-scene.js + 数据表 + 新增表现文件。
|
||||
# 实证:M3 重写了 main.js(装载胶水)→ 丢了 recHook 透传 → F 门 calls=0、合成不记引擎调用、G/H 门连环挂。
|
||||
# 故把 fixture 平台预建文件焊成只读:write_source 改它直接拒,并提示「只改 play-scene.js + 数据表」。
|
||||
LOCKED_PLATFORM_FILES = frozenset({
|
||||
"src/main.js", # entry · PhaserGameFactory 装载胶水(recHook/caps/scene 接线在此)
|
||||
"src/game-core.js", # 三系统编排 + 状态机 + 结算 + latch + _forensicsView/readState 导出
|
||||
"src/layout.js", # 棋盘/订单面板布局常量单一源(命中映射 + driver tap 同源坐标)
|
||||
"src/data/tables.js", # 数据表适配层(按固定 key 读 datatable.gold.json)
|
||||
"src/util/seeded-random.js", # 受控随机源(确定性铁律)
|
||||
"src/systems/resource-system.js", # 资源系统纯逻辑(addCoins/consumeIngredient 经 recHook 记调用)
|
||||
"src/systems/merge-system.js", # 合成系统纯逻辑(tapCell 两次点同物品合成)
|
||||
"src/systems/order-system.js", # 订单系统纯逻辑
|
||||
"src/systems/reachability.js", # 可达性纯逻辑
|
||||
})
|
||||
|
||||
|
||||
def is_locked_platform_file(rel: str) -> bool:
|
||||
"""该工程内相对路径是否平台锁定(写死、agent 不许改)。"""
|
||||
return rel in LOCKED_PLATFORM_FILES
|
||||
|
||||
|
||||
def _content_hash(files: list[dict]) -> str:
|
||||
"""整工程内容指纹 = sha256(各文件 path+content 规范化拼接)。对齐 A3 contentHash 语义。"""
|
||||
@ -130,7 +152,7 @@ def build_toolkit(session: Tier2Session) -> Toolkit:
|
||||
files: 文件数组,每项 {path: 工程内相对路径(如 'src/scenes/PlayScene.js',禁 '..'),
|
||||
content: 文件全文 UTF-8, role?: 文件角色(entry/scene/system/ui/config/lib/other)}。
|
||||
"""
|
||||
written, errors = [], []
|
||||
written, errors, locked = [], [], []
|
||||
for f in files or []:
|
||||
rel = (f or {}).get("path") or ""
|
||||
content = (f or {}).get("content")
|
||||
@ -140,6 +162,17 @@ def build_toolkit(session: Tier2Session) -> Toolkit:
|
||||
if not isinstance(content, str):
|
||||
errors.append({"path": rel, "reason": "content 必须是字符串"})
|
||||
continue
|
||||
# 平台锁定文件保护(根因 3):若改的是写死的平台文件且内容真变了,拒绝并提示。
|
||||
# 允许「内容完全相同」的无操作重写(幂等;不阻断 agent 把整树回写)。
|
||||
if is_locked_platform_file(rel) and session.files.get(rel) != content:
|
||||
locked.append({
|
||||
"path": rel,
|
||||
"reason": "这是平台锁定文件(装载胶水/三系统纯逻辑/状态机/结算/latch/readState/布局),"
|
||||
"写死不许改——改它会破坏引擎接线(如丢 recHook → F 门 calls=0、合成不记调用)。"
|
||||
"你只该改 src/scenes/play-scene.js(表现层)+ data/datatable.gold.json(数据表),"
|
||||
"或在 src/scenes/ 下新增表现文件。请把这个文件的改动撤回。",
|
||||
})
|
||||
continue
|
||||
session.files[rel] = content
|
||||
if (f or {}).get("role"):
|
||||
session.roles[rel] = f["role"]
|
||||
@ -148,8 +181,10 @@ def build_toolkit(session: Tier2Session) -> Toolkit:
|
||||
written.append(rel)
|
||||
# 同步落盘(供后续 build/headless_check 子进程读)。
|
||||
run.scaffold(session.game_id, session.file_list())
|
||||
return json.dumps({"ok": len(errors) == 0, "written": written, "errors": errors},
|
||||
ensure_ascii=False)
|
||||
return json.dumps(
|
||||
{"ok": len(errors) == 0 and len(locked) == 0,
|
||||
"written": written, "errors": errors, "lockedRejected": locked},
|
||||
ensure_ascii=False)
|
||||
|
||||
# ── 核心环:validate_datatable(数据表 schema/可达性预检)──
|
||||
async def validate_datatable() -> str:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user