lili ad22be9b3a feat(saa): Phase 2 Template-First gamedef 骨架机制(flag 旁挂默认关;A/B 负面=不迁移到便宜 thinking-off)
机制(OpenGame +10.1 杠杆试落):
- SaaSkeletons 加载器:archetype→3 金标准过门纯净骨架(gd-breakout/tictactoe/simon,verdict.pass=true+rt纯净+过 Phase3 坑门),按 (tick/input) profile 映射;经济类(merge/idle/tycoon)无近似骨架不登记=走无骨架,绝不喂低质骨架。
- 注入:SaaPrompts buildGameDefMessages(openai 首生成)/historyFirstUser(anthropic 首轮) 追加骨架段(结构参照、非照抄,题面不符以题面为准);救场轮不注。
- pom 拷 contracts/agent-loop/skeletons/*.json 进 classpath。flag -Dsaa.gen.skeletonFirst=1 开,默认关=生成字节零变、零回归。

A/B 实测(thinking-off + skeleton conc=12 vs A 基线):
- 7/12(58.3%) ≤ A 8/12(67%),失败仍 E_live 哑火(#4,5,9,11,12) → 骨架没把基线拉向 91.7%。
- 结论:+10.1 骨架杠杆【不迁移到便宜模型+thinking-off】——哑火是推理缺口(thinking 补)、非结构样例缺口(骨架补不了)。thinking-ON(anthropic 91.7%)仍是唯一真杠杆。
- 处置(创始人定 A):保留机制 flag 关、可逆——换更强模型/配合 thinking 时或有用;默认不启用。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:53:02 -07:00

1 line
5.1 KiB
JSON

{"components": [{"id": "bg", "kind": "render", "shape": "fill", "color": "#0e1116"}, {"id": "rhud", "kind": "render", "shape": "rect", "color": "#ffffff", "w": 1, "h": 1}, {"id": "rb0", "kind": "render", "shape": "rect", "color": "#801a1a", "w": 130, "h": 130}, {"id": "rb1", "kind": "render", "shape": "rect", "color": "#1a8033", "w": 130, "h": 130}, {"id": "rb2", "kind": "render", "shape": "rect", "color": "#1a3d80", "w": 130, "h": 130}, {"id": "rb3", "kind": "render", "shape": "rect", "color": "#80701a", "w": 130, "h": 130}, {"id": "mb0", "kind": "clickable", "score": 1, "mark": {"shape": "rect", "color": "#ff3344", "w": 130, "h": 130}, "hit": {"x": 65, "y": 65, "w": 130, "h": 130}}, {"id": "mb1", "kind": "clickable", "score": 1, "mark": {"shape": "rect", "color": "#33ff66", "w": 130, "h": 130}, "hit": {"x": 65, "y": 65, "w": 130, "h": 130}}, {"id": "mb2", "kind": "clickable", "score": 1, "mark": {"shape": "rect", "color": "#3366ff", "w": 130, "h": 130}, "hit": {"x": 65, "y": 65, "w": 130, "h": 130}}, {"id": "mb3", "kind": "clickable", "score": 1, "mark": {"shape": "rect", "color": "#ffdd33", "w": 130, "h": 130}, "hit": {"x": 65, "y": 65, "w": 130, "h": 130}}], "entities": [{"id": "world", "transform": {"position": {"x": 0, "y": 0}}, "components": ["bg"]}, {"id": "hud0", "transform": {"position": {"x": 0, "y": 0}}, "components": ["rhud"]}, {"id": "b0", "transform": {"position": {"x": 65, "y": 280}}, "tags": ["target"], "idx": 0, "components": ["rb0", "mb0"], "occupied": false}, {"id": "b1", "transform": {"position": {"x": 215, "y": 280}}, "tags": ["target"], "idx": 1, "components": ["rb1", "mb1"], "occupied": false}, {"id": "b2", "transform": {"position": {"x": 65, "y": 430}}, "tags": ["target"], "idx": 2, "components": ["rb2", "mb2"], "occupied": false}, {"id": "b3", "transform": {"position": {"x": 215, "y": 430}}, "tags": ["target"], "idx": 3, "components": ["rb3", "mb3"], "occupied": false}], "behaviors": [{"id": "init", "trigger": "init", "code": "self.phase='show'; self.round=1; self.progress=0; self.seq=[rt.randInt(0,3)]; self.idx=0; self.lit=-1; self.litT=0; self.gapT=0; self.failT=0; self.score=0; rt.setScore(0); for(const b of rt.query('target')){ b.occupied=false; b._lit=0; } rt.spawn({x:195,y:60,tags:['hud'],components:[{kind:'render',shape:'rect',color:'#ffffff',w:1,h:1}]});"}, {"id": "engine", "trigger": "update", "code": "self.gapT=(self.gapT||0)-dt; self.litT=(self.litT||0)-dt; self.failT=(self.failT||0)-dt; if(self.phase==='show'){ if(self.lit>=0){ const b=rt.getEntity('b'+self.lit); if(b){ b._lit=Math.max(0,self.litT/0.42); const s=1+0.08*Math.sin(Math.min(1,self.litT/0.42)*Math.PI); b._sx=s; b._sy=s; } if(self.litT<=0){ if(b){ b._lit=0; b._sx=1; b._sy=1; } self.lit=-1; self.gapT=0.16; } } else if(self.gapT<=0){ if(self.idx<self.seq.length){ const c=self.seq[self.idx]; self.lit=c; self.litT=0.42; const b=rt.getEntity('b'+c); if(b){ b._lit=1; b._sx=1.08; b._sy=1.08; rt.fx.beep(c===0?'red':c===1?'green':c===2?'blue':'yellow'); } self.idx++; } else { self.phase='input'; self.progress=0; for(const b of rt.query('target')){ b.occupied=false; } } } } else if(self.phase==='input'){ for(const b of rt.query('target')){ b._lit=Math.max(0,(b._lit||0)-dt/0.24); b._sx=1+(b._lit||0)*0.08; b._sy=b._sx; } } else if(self.phase==='fail'){ self.idx=0; self.progress=0; if(self.failT<=0){ self.phase='show'; self.round=1; self.seq=[rt.randInt(0,3)]; self.lit=-1; self.gapT=0.6; for(const b of rt.query('target')){ b.occupied=false; b._lit=0; b._sx=1; b._sy=1; } } } else if(self.phase==='win'){ self.idx=0; if(self.failT<=0){ self.phase='show'; self.round=1; self.seq=[rt.randInt(0,3)]; self.lit=-1; self.gapT=0.6; for(const b of rt.query('target')){ b.occupied=false; b._lit=0; b._sx=1; b._sy=1; } } }"}, {"id": "tap", "trigger": "update", "code": "if(self.phase!=='input'){ for(const b of rt.query('target')){ b.occupied=true; } return; } for(const b of rt.query('target')){ b.occupied=false; } if(!rt.input.justTapped()) return; const p=rt.input.pointer; let hit=null; for(const b of rt.query('target')){ if(p.x>=b.x && p.x<=b.x+130 && p.y>=b.y && p.y<=b.y+130){ hit=b; break; } } if(!hit) return; const expected=self.seq[self.progress]; rt.fx.burst(hit.x+65", "hit.idx===0?'#ff3344'": "hit.idx===1?'#33ff66':hit.idx===2?'#3366ff':'#ffdd33'); rt.fx.beep(hit.idx===0?'red':hit.idx===1?'green':hit.idx===2?'blue':'yellow'); hit._lit=1; hit._sx=1.08; hit._sy=1.08; if(hit.idx===expected){ self.progress++; hit.occupied=true; if(self.progress>=self.seq.length){ self.score++; rt.addScore(1); rt.fx.burst(195,420,'#ffdd33'); self.round++; if(self.round>8){ self.phase='win'; self.failT=1.6; rt.fx.burst(195,422,'#ffdd33'); rt.win(); } else { self.phase='show'; self.idx=0; self.lit=-1; self.gapT=0.8; self.seq.push(rt.randInt(0,3)); for(const b of rt.query('target')){ b.occupied=true; b._lit=0; } } } } else { self.phase='fail'; self.failT=1.6; self.progress=0; rt.fx.burst(195,422,'#ff3344'); rt.fx.burst(195,422,'#ff3344'); for(const b of rt.query('target')){ b.occupied=true; } self.idx=0; }"}], "scenes": [{"id": "main", "entityRefs": ["world", "hud0", "b0", "b1", "b2", "b3"]}], "rules": [{"id": "winrule", "condition": "rt.score >= 1", "outcome": "win"}]}