test(aigc-3b-B): 派发面 e2e 真证安全面+全自动管线闭合(HMAC双向),P5 生成质量转 L1
3b-B e2e(mini-desktop 真跑·证据 wg1/gen-worker/evidence-3bB/): ✅ P0-P4 安全面+全自动管线=真证闭合(铁证 backend-callback-hmac.log + p4*.txt): - HMAC 双向证:缺签名头→HTTP 401 / 错签(deadbeef≠482147b5)→HTTP 401 / 正签→过门(走到下游"任务不存在"非401) =关死 /dify/callback-internal 裸 @PermitAll 缺口 - 全自动派发链真通:执行器认领 taskId→dispatchGeneric 投 §6.1 job→worker 真生成(真烧模型)→ HMAC 签名回调→验签通过→handleCallback 落库(gen-9303/9304/9305 三轮齐全) ❌ P5 一句话真生成=未达终局:三款全 nine_gate_failed。但截图(gen-9303-after-play.png)证生成 真出 on-theme 可渲可动的「点击小怪物」游戏(Score/3s 倒计时/多彩怪物 monsters/targetScore=12), 仅点击→计分坏(Score 仍 0)→九门确定性地板正确拦截「看着像但玩不了」=质量门正确履职、拒发不可玩。 判:L0 交付(管线+安全+质量门)已完成且证;缺=便宜模型把「点击命中→计分」写对=L1 生成域 (prompt 点击坑+模型档+player/calibration,run_studio 自修 max_repairs 未救回)→转 L1 v3 迭代。 附带:serve-and-play.sh 跨平台 Chrome 探测(CHROME_BIN 覆盖>Linux /usr/bin>macOS>PATH 兜底, Linux 在前因 mini-desktop x86 是权威 e2e 机);p3bB_*.sql 发布四态/翻 feed 桩。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d59093f84c
commit
c99014c243
47
game-cloud/scripts/p3bB_publish_flip_9303.sql
Normal file
47
game-cloud/scripts/p3bB_publish_flip_9303.sql
Normal file
@ -0,0 +1,47 @@
|
||||
-- ============================================================================
|
||||
-- P3·3b-B 派发面终局 e2e·发布翻转(把 gameId=9303 的 feed 卡翻到【回调链新建的真生成 version】)
|
||||
-- 缘由:回调链 handleCallback 建【新】version(N)+runtime_package(engineBundle=worker 真生成 bundle),但
|
||||
-- 新 runtime_package 落库 status=0(未发布),且 project.current_version_id/feed_rank 仍指占位 93030。
|
||||
-- 本脚本把三处翻到回调新版本 N,使 feed 服务【回调链产物】(=真生成游戏),完成终局闭环。
|
||||
-- 自动选 N:gameId=9303 下 gen_task_id 非空(=回调建的,占位 93030 的 gen_task_id 为 NULL)的最新 version。
|
||||
-- 幂等:纯 UPDATE 翻指针,可重复执行(再跑选同一 N)。
|
||||
-- 用法:docker exec -i game-staging-mysql mysql --default-character-set=utf8mb4 -uroot -p"$MYSQL_ROOT_PASSWORD" < 本文件
|
||||
-- ============================================================================
|
||||
USE `ruoyi-vue-pro`;
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- 选回调新建的最新 version N(gen_task_id 非空 = 回调链建的;占位 93030 gen_task_id 为 NULL 被排除)
|
||||
SET @vid := (SELECT id FROM game_version
|
||||
WHERE game_id = 9303 AND gen_task_id IS NOT NULL AND deleted = b'0'
|
||||
ORDER BY id DESC LIMIT 1);
|
||||
|
||||
-- ① 把回调新版本对应的 runtime_package 发布(status 0→1);占位 93030 包仍在但不再被 feed 指
|
||||
UPDATE game_runtime_package SET status = 1, updater = '0', update_time = NOW()
|
||||
WHERE game_id = 9303 AND version_id = @vid AND @vid IS NOT NULL;
|
||||
|
||||
-- ② project.current_version_id 指向回调新版本 N
|
||||
UPDATE game_project SET current_version_id = @vid, updater = '0', update_time = NOW()
|
||||
WHERE id = 9303 AND @vid IS NOT NULL;
|
||||
|
||||
-- ③ feed_rank.version_id 指向回调新版本 N(feed 卡 /play 取此 version 的包 = 回调真生成产物)
|
||||
UPDATE game_feed_rank SET version_id = @vid, updater = '0', update_time = NOW()
|
||||
WHERE game_id = 9303 AND @vid IS NOT NULL;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- 回读:翻转后的指针 + 新版本运行包态(@vid 即 feed 现服务的 versionId,供 CDP driver 用)
|
||||
SELECT @vid AS flipped_version_id;
|
||||
SELECT 'project.current_version' k, current_version_id v FROM game_project WHERE id=9303
|
||||
UNION ALL SELECT 'feed_rank.version', version_id FROM game_feed_rank WHERE game_id=9303
|
||||
UNION ALL SELECT 'new_pkg.status', status FROM game_runtime_package WHERE game_id=9303 AND version_id=@vid
|
||||
UNION ALL SELECT 'new_pkg.bundleSize', bundle_size FROM game_runtime_package WHERE game_id=9303 AND version_id=@vid;
|
||||
-- 校验 engineBundle 真入包(LENGTH>0 = 回调把真生成 bundle 落进 package_json)
|
||||
SELECT 'engineBundle_in_pkg_len' k,
|
||||
CHAR_LENGTH(JSON_UNQUOTE(JSON_EXTRACT(package_json, '$.engineBundle'))) v
|
||||
FROM game_runtime_package WHERE game_id=9303 AND version_id=@vid;
|
||||
-- 校验 checksum 自洽(列值 == 对所存 package_json 重算的 sha256)——宿主完整性校验链不变量
|
||||
SELECT 'checksum_selfconsistent' k,
|
||||
(checksum = LOWER(SHA2(package_json, 256))) v
|
||||
FROM game_runtime_package WHERE game_id=9303 AND version_id=@vid;
|
||||
89
game-cloud/scripts/p3bB_scaffold_gen9303.sql
Normal file
89
game-cloud/scripts/p3bB_scaffold_gen9303.sql
Normal file
@ -0,0 +1,89 @@
|
||||
-- ============================================================================
|
||||
-- P3·3b-B 派发面终局 e2e·四态脚手架 + generic 生成任务(gameId=9303,一句话真生成)
|
||||
-- 缘由:3b-B 证「提交 generic 任务 → 执行器轮询 CAS 认领 → dispatchGeneric 投递真 worker →
|
||||
-- worker 真烧便宜模型 design+九门生成 GameHostFactory → 回调携 engineBundle 经 HMAC 验签落包入 feed」。
|
||||
-- 与 3b-A(9302·stub 回 pong) 的差异:本款 engineBundle 是【真生成】(brief=限时点击小怪物得分),非固定 pong。
|
||||
-- 本脚本建:① 已发布 project(gameId=9303)+占位 version(93030)+占位 pkg+feed_rank(供组包/入 feed 四态成立);
|
||||
-- ② game_aigc_task 一行(status=0 queued, template_id=generic, game_id=9303, prompt=一句话创意),
|
||||
-- 供执行器 @Scheduled 扫到 → CAS 认领(0→1) → dispatchGeneric 投 worker :9401。
|
||||
-- 回调链会另建【新】version(N)+runtime_package(engineBundle=worker 真生成 bundle);随后跑 p3bB_publish_flip.sql 翻 feed。
|
||||
-- ID:gameId=9303 / 占位 versionId=93030 / pkgId=93030 / feedRankId=93030 / taskId 自增(高位区,与 9201/9301/9302 零碰撞)
|
||||
-- trace_id:'wg1-3bB-gen9303-001'(贯穿全链;worker 回调 reqVO.traceId 须与此一致,handleCallback 据此定位任务)
|
||||
-- 手工 seed 行 creator/updater 填 '0'(DefaultDBFieldHandler 无登录态取不到 userId 的同根因兜底)
|
||||
-- tenant:staging tenant.enable=false → tenant_id=0
|
||||
-- 幂等:先 DELETE 同 gameId/占位 ID 行 + 同 trace_id 任务再 INSERT(纯重建,可重复执行)。
|
||||
-- 用法:docker exec -i game-staging-mysql mysql --default-character-set=utf8mb4 -uroot -p"$MYSQL_ROOT_PASSWORD" < 本文件
|
||||
-- ============================================================================
|
||||
USE `ruoyi-vue-pro`;
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- 清旧(幂等重建;删该 gameId 全部 version/package/feed_rank + 同 trace_id 任务,重跑前清场)
|
||||
DELETE FROM game_aigc_task WHERE trace_id = 'wg1-3bB-gen9303-001';
|
||||
DELETE FROM game_feed_rank WHERE game_id = 9303;
|
||||
DELETE FROM game_runtime_package WHERE game_id = 9303;
|
||||
DELETE FROM game_version WHERE game_id = 9303;
|
||||
DELETE FROM game_project WHERE id = 9303;
|
||||
|
||||
-- ① project:已发布(status=4),current_version_id 先指占位 93030(flip 后改指回调新版本 N)
|
||||
INSERT INTO game_project
|
||||
(id, creator_user_id, title, summary, cover_url, tags, template_id, age_rating,
|
||||
status, current_version_id, launch_zone_id, featured, play_count, like_count,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(9303, 1, '打地鼠(generic 真生成·回调入feed)', 'P3 3b-B 派发面终局 e2e:一句话创意经 worker 真生成 GameHostFactory 过九门,回调携 engineBundle 入 feed',
|
||||
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
|
||||
'P3,3b-B,dispatch,generic,real-gen', 'generic', 'all',
|
||||
4, 93030, NULL, b'0', 0, 0,
|
||||
'0', NOW(), '0', NOW(), b'0', 0);
|
||||
|
||||
-- ② 占位 version:已发布(status=3),仅供脚手架四态成立;回调会另建新 version(N)
|
||||
INSERT INTO game_version
|
||||
(id, game_id, version_no, gen_task_id, package_url, bundle_size, checksum,
|
||||
status, creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(93030, 9303, 1, NULL, '', 0, '',
|
||||
3, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
|
||||
-- ③ 占位 runtime_package:status=1 + 空 package_json(占位包;flip 前 feed 卡指它,flip 后指回调新包)
|
||||
INSERT INTO game_runtime_package
|
||||
(id, game_id, version_id, template_id, package_url, entry, runtime_version, preload_policy,
|
||||
bundle_size, checksum, sandbox_attr, allow_origins, status,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id, package_json)
|
||||
VALUES
|
||||
(93030, 9303, 93030, 'generic', '', 'index.html', '1.0.0', 'eager',
|
||||
0, '', 'allow-scripts', '', 1,
|
||||
'0', NOW(), '0', NOW(), b'0', 0, NULL);
|
||||
|
||||
-- ④ feed_rank:zone_id=0(混合流) + status=1 入流(flip 后把 version_id 改指回调新版本 N)
|
||||
INSERT INTO game_feed_rank
|
||||
(id, game_id, version_id, zone_id, quality_score, boost, sort_score, pinned, status,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(93030, 9303, 93030, 0, 0.0000, 0.0000, 0.0000, 0, 1,
|
||||
'0', NOW(), '0', NOW(), b'0', 0);
|
||||
|
||||
-- ⑤ generic 生成任务:status=0 queued → 执行器 @Scheduled 扫到 CAS 认领 → dispatchGeneric 投 worker
|
||||
-- prompt=一句话创意(whack/点击得分型,避开 4 短板:文本HUD/网格/CCD/拖拽);
|
||||
-- prompt_hash 给占位非空值(NOT NULL char(64);缓存键,本端到端不依赖命中);
|
||||
-- failure_reason/result_package_url 占位空串(NOT NULL)。
|
||||
INSERT INTO game_aigc_task
|
||||
(creator_user_id, game_id, version_id, template_id, prompt, prompt_hash,
|
||||
status, progress, quality_score, failure_reason, result_package_url, retry_of, trace_id,
|
||||
creator, create_time, updater, update_time, finish_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(1, 9303, NULL, 'generic', '限时点击不断冒出的小怪物得分',
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
0, 0, NULL, '', '', NULL, 'wg1-3bB-gen9303-001',
|
||||
'0', NOW(), '0', NOW(), NULL, b'0', 0);
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- 回读四态 + 任务
|
||||
SELECT 'project' k, id, status, current_version_id FROM game_project WHERE id=9303
|
||||
UNION ALL SELECT 'version', id, status, game_id FROM game_version WHERE id=93030
|
||||
UNION ALL SELECT 'runtime_pkg', id, status, version_id FROM game_runtime_package WHERE id=93030
|
||||
UNION ALL SELECT 'feed_rank', id, status, version_id FROM game_feed_rank WHERE id=93030;
|
||||
SELECT 'aigc_task' k, id, status, game_id, template_id, prompt, trace_id
|
||||
FROM game_aigc_task WHERE trace_id='wg1-3bB-gen9303-001';
|
||||
43
game-cloud/scripts/p3bB_scaffold_gen9304.sql
Normal file
43
game-cloud/scripts/p3bB_scaffold_gen9304.sql
Normal file
@ -0,0 +1,43 @@
|
||||
USE `ruoyi-vue-pro`;
|
||||
SET NAMES utf8mb4;
|
||||
START TRANSACTION;
|
||||
DELETE FROM game_aigc_task WHERE trace_id = 'wg1-3bB-gen9304-001';
|
||||
DELETE FROM game_feed_rank WHERE game_id = 9304;
|
||||
DELETE FROM game_runtime_package WHERE game_id = 9304;
|
||||
DELETE FROM game_version WHERE game_id = 9304;
|
||||
DELETE FROM game_project WHERE id = 9304;
|
||||
INSERT INTO game_project
|
||||
(id, creator_user_id, title, summary, cover_url, tags, template_id, age_rating,
|
||||
status, current_version_id, launch_zone_id, featured, play_count, like_count,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(9304, 1, '接球弹球(generic 真生成·回调入feed)', 'P3 3b-B 派发面终局 e2e:一句话创意经 worker 真生成过九门,回调携 engineBundle 入 feed',
|
||||
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
|
||||
'P3,3b-B,dispatch,generic,real-gen', 'generic', 'all',
|
||||
4, 93040, NULL, b'0', 0, 0, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_version
|
||||
(id, game_id, version_no, gen_task_id, package_url, bundle_size, checksum,
|
||||
status, creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES (93040, 9304, 1, NULL, '', 0, '', 3, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_runtime_package
|
||||
(id, game_id, version_id, template_id, package_url, entry, runtime_version, preload_policy,
|
||||
bundle_size, checksum, sandbox_attr, allow_origins, status,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id, package_json)
|
||||
VALUES (93040, 9304, 93040, 'generic', '', 'index.html', '1.0.0', 'eager',
|
||||
0, '', 'allow-scripts', '', 1, '0', NOW(), '0', NOW(), b'0', 0, NULL);
|
||||
INSERT INTO game_feed_rank
|
||||
(id, game_id, version_id, zone_id, quality_score, boost, sort_score, pinned, status,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES (93040, 9304, 93040, 0, 0.0000, 0.0000, 0.0000, 0, 1, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_aigc_task
|
||||
(creator_user_id, game_id, version_id, template_id, prompt, prompt_hash,
|
||||
status, progress, quality_score, failure_reason, result_package_url, retry_of, trace_id,
|
||||
creator, create_time, updater, update_time, finish_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(1, 9304, NULL, 'generic', '左右移动挡板接住不断下落的小球,接住得分,漏球则游戏结束',
|
||||
'0000000000000000000000000000000000000000000000000000000000000001',
|
||||
0, 0, NULL, '', '', NULL, 'wg1-3bB-gen9304-001',
|
||||
'0', NOW(), '0', NOW(), NULL, b'0', 0);
|
||||
COMMIT;
|
||||
SELECT 'aigc_task' k, id, status, game_id, template_id, prompt, trace_id
|
||||
FROM game_aigc_task WHERE trace_id='wg1-3bB-gen9304-001';
|
||||
34
game-cloud/scripts/p3bB_scaffold_gen9305.sql
Normal file
34
game-cloud/scripts/p3bB_scaffold_gen9305.sql
Normal file
@ -0,0 +1,34 @@
|
||||
USE `ruoyi-vue-pro`;
|
||||
SET NAMES utf8mb4;
|
||||
START TRANSACTION;
|
||||
DELETE FROM game_aigc_task WHERE trace_id = 'wg1-3bB-gen9305-001';
|
||||
DELETE FROM game_feed_rank WHERE game_id = 9305;
|
||||
DELETE FROM game_runtime_package WHERE game_id = 9305;
|
||||
DELETE FROM game_version WHERE game_id = 9305;
|
||||
DELETE FROM game_project WHERE id = 9305;
|
||||
INSERT INTO game_project
|
||||
(id, creator_user_id, title, summary, cover_url, tags, template_id, age_rating,
|
||||
status, current_version_id, launch_zone_id, featured, play_count, like_count,
|
||||
creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(9305, 1, '记忆翻牌(generic 真生成·回调入feed)', 'P3 3b-B 派发面终局 e2e:一句话创意经 worker 真生成过九门,回调携 engineBundle 入 feed',
|
||||
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==',
|
||||
'P3,3b-B,dispatch,generic,real-gen', 'generic', 'all',
|
||||
4, 93050, NULL, b'0', 0, 0, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_version
|
||||
(id, game_id, version_no, gen_task_id, package_url, bundle_size, checksum, status, creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES (93050, 9305, 1, NULL, '', 0, '', 3, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_runtime_package
|
||||
(id, game_id, version_id, template_id, package_url, entry, runtime_version, preload_policy, bundle_size, checksum, sandbox_attr, allow_origins, status, creator, create_time, updater, update_time, deleted, tenant_id, package_json)
|
||||
VALUES (93050, 9305, 93050, 'generic', '', 'index.html', '1.0.0', 'eager', 0, '', 'allow-scripts', '', 1, '0', NOW(), '0', NOW(), b'0', 0, NULL);
|
||||
INSERT INTO game_feed_rank
|
||||
(id, game_id, version_id, zone_id, quality_score, boost, sort_score, pinned, status, creator, create_time, updater, update_time, deleted, tenant_id)
|
||||
VALUES (93050, 9305, 93050, 0, 0.0000, 0.0000, 0.0000, 0, 1, '0', NOW(), '0', NOW(), b'0', 0);
|
||||
INSERT INTO game_aigc_task
|
||||
(creator_user_id, game_id, version_id, template_id, prompt, prompt_hash, status, progress, quality_score, failure_reason, result_package_url, retry_of, trace_id, creator, create_time, updater, update_time, finish_time, deleted, tenant_id)
|
||||
VALUES
|
||||
(1, 9305, NULL, 'generic', '记住并按顺序点亮闪烁的彩色按钮序列,每过一关序列加长',
|
||||
'0000000000000000000000000000000000000000000000000000000000000002',
|
||||
0, 0, NULL, '', '', NULL, 'wg1-3bB-gen9305-001', '0', NOW(), '0', NOW(), NULL, b'0', 0);
|
||||
COMMIT;
|
||||
SELECT 'aigc_task' k, id, status, game_id, prompt, trace_id FROM game_aigc_task WHERE trace_id='wg1-3bB-gen9305-001';
|
||||
@ -8,14 +8,23 @@ GAME_ID="${1:?用法: serve-and-play.sh <gameId> [port] [cdpPort]}"
|
||||
PORT="${2:-4320}"
|
||||
CDP_PORT="${3:-9222}"
|
||||
|
||||
# Chrome 路径探测(macOS)。
|
||||
# Chrome 路径探测(跨平台:CHROME_BIN 显式覆盖 > Linux(mini-desktop x86 e2e门) > macOS(lili-mac 快走查))。
|
||||
# mini-desktop 是权威 e2e 验收机(Linux),Chrome 在 /usr/bin;lili-mac 是 macOS 快走查;故两套路径都探,Linux 在前。
|
||||
CHROME=""
|
||||
for p in "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
|
||||
"/Applications/Chromium.app/Contents/MacOS/Chromium" \
|
||||
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"; do
|
||||
[ -x "$p" ] && CHROME="$p" && break
|
||||
done
|
||||
[ -z "$CHROME" ] && { echo "❌ 未找到 Chrome(/Applications/Google Chrome.app)"; exit 3; }
|
||||
if [ -n "${CHROME_BIN:-}" ] && [ -x "${CHROME_BIN}" ]; then
|
||||
CHROME="${CHROME_BIN}" # 显式覆盖优先(CI/特殊安装位)
|
||||
else
|
||||
for p in "/usr/bin/google-chrome" "/usr/bin/google-chrome-stable" \
|
||||
"/usr/bin/chromium" "/usr/bin/chromium-browser" "/opt/google/chrome/chrome" \
|
||||
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
|
||||
"/Applications/Chromium.app/Contents/MacOS/Chromium" \
|
||||
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"; do
|
||||
[ -x "$p" ] && CHROME="$p" && break
|
||||
done
|
||||
# 兜底:PATH 中的 google-chrome / chromium(command -v 解析符号链接)
|
||||
[ -z "$CHROME" ] && CHROME="$(command -v google-chrome chromium chromium-browser 2>/dev/null | head -1)"
|
||||
fi
|
||||
[ -z "$CHROME" ] && { echo "❌ 未找到 Chrome(探测 /usr/bin/google-chrome、/Applications、PATH、CHROME_BIN 均无)"; exit 3; }
|
||||
|
||||
USER_DATA_DIR="$(mktemp -d -t wg1-chrome-XXXX)"
|
||||
SERVE_PID=""; CHROME_PID=""
|
||||
|
||||
40
wg1/gen-worker/evidence-3bB/factory-head-gen9303.js
Normal file
40
wg1/gen-worker/evidence-3bB/factory-head-gen9303.js
Normal file
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
export default function createGame(opts) {
|
||||
const o = opts || {};
|
||||
let ctx = null;
|
||||
let nowMs = 0;
|
||||
let seed = o.seed || 0;
|
||||
|
||||
// 游戏状态
|
||||
let phase = 'booting';
|
||||
let score = 0;
|
||||
let timeLeft = 30; // 剩余秒数
|
||||
let targetScore = 12;
|
||||
let gameoverReason = '';
|
||||
let monsters = []; // {x,y,vx,vy,radius,color,isBomb,ttl}
|
||||
let spawnTimer = 0; // 距离下次生成怪物的时间(秒)
|
||||
let bombTimer = 0; // 距离下次生成炸弹的时间(秒)
|
||||
let elapsed = 0; // 游戏已运行时间(秒)
|
||||
let explosionEnd = 0; // 炸弹爆炸闪烁结束时间戳
|
||||
let inputSub = null;
|
||||
|
||||
// 用于 last 5 秒闪烁
|
||||
let flashAlpha = 0;
|
||||
|
||||
function init(boot) {
|
||||
ctx = boot.ctx;
|
||||
const random = ctx.random;
|
||||
if (seed !== undefined) {
|
||||
random.reseed(seed);
|
||||
}
|
||||
phase = 'playing';
|
||||
score = 0;
|
||||
timeLeft = 30;
|
||||
monsters = [];
|
||||
spawnTimer = 1.0; // 第一个怪物在 1.0 秒后
|
||||
bombTimer = random.range(8, 10);
|
||||
elapsed = 0;
|
||||
explosionEnd = 0;
|
||||
gameoverReason = '';
|
||||
|
||||
// 订阅点击
|
||||
40
wg1/gen-worker/evidence-3bB/factory-head-gen9304.js
Normal file
40
wg1/gen-worker/evidence-3bB/factory-head-gen9304.js
Normal file
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
export default function createCatchGame(opts) {
|
||||
const o = opts || {};
|
||||
let ctx = null; // boot.ctx
|
||||
let nowMs = 0;
|
||||
let subMove = null; // pointermove subscription
|
||||
let subDown = null; // pointerdown subscription (optional)
|
||||
let phase = 'booting';
|
||||
let score = 0;
|
||||
let currentBall = null; // {x, y, speed} 或 null
|
||||
let nextSpawnTime = 0; // 毫秒
|
||||
let paddleX = 195; // 挡板中心 x
|
||||
const paddleY = 814;
|
||||
const paddleW = 120;
|
||||
const paddleH = 20;
|
||||
const ballR = 10;
|
||||
const baseSpeed = 150; // px/s
|
||||
let gameoverReason = '';
|
||||
let lastSpawnTime = 0; // 用于 debug
|
||||
|
||||
// 动画计时器(用于HUD脉冲)
|
||||
let hudPulse = 0;
|
||||
|
||||
function init(boot) {
|
||||
ctx = boot.ctx;
|
||||
// 订阅输入
|
||||
subMove = ctx.getInput().on('pointermove', onPointerMove);
|
||||
subDown = ctx.getInput().on('pointerdown', onPointerDown);
|
||||
// 初始状态
|
||||
score = 0;
|
||||
phase = 'playing';
|
||||
gameoverReason = '';
|
||||
currentBall = null;
|
||||
paddleX = 195;
|
||||
nowMs = ctx.time.nowMs();
|
||||
nextSpawnTime = nowMs + ctx.random.range(500, 1500);
|
||||
hudPulse = 0;
|
||||
|
||||
// 开局尝试演示引擎能力:持续粒子发射(常驻)
|
||||
40
wg1/gen-worker/evidence-3bB/factory-head-gen9305.js
Normal file
40
wg1/gen-worker/evidence-3bB/factory-head-gen9305.js
Normal file
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
export default function createGame(opts) {
|
||||
const o = opts || {};
|
||||
let ctx = null;
|
||||
const W = 390, H = 844;
|
||||
const BUTTON_RADIUS = 60;
|
||||
const COLORS = ['#FF4136', '#2ECC40', '#0074D9', '#FFDC00'];
|
||||
const BRIGHT_COLORS = ['#FF6B6B', '#5FDC6F', '#4A9EF5', '#FFE54C'];
|
||||
const TONES = [262, 330, 392, 494]; // C4 E4 G4 B4
|
||||
const HIGHLIGHT_DURATION = 500; // ms
|
||||
const GAP_DURATION = 200; // ms
|
||||
const BUTTON_Y = 550;
|
||||
const totalButtonWidth = 4 * BUTTON_RADIUS * 2 + 3 * 30;
|
||||
const startX = (W - totalButtonWidth) / 2 + BUTTON_RADIUS;
|
||||
|
||||
const buttonPositions = COLORS.map((_, i) => ({
|
||||
x: startX + i * (BUTTON_RADIUS * 2 + 30),
|
||||
y: BUTTON_Y,
|
||||
color: COLORS[i],
|
||||
brightColor: BRIGHT_COLORS[i]
|
||||
}));
|
||||
|
||||
let phase = 'playing';
|
||||
let score = 0; // 已完成的关卡数
|
||||
let sequence = [];
|
||||
let userStep = 0;
|
||||
let remaining = 0;
|
||||
let gameoverReason = '';
|
||||
let inputSub = null;
|
||||
|
||||
// 动画状态
|
||||
let showState = 'idle'; // 'showing' | 'waiting' | 'idle'
|
||||
let showStartTime = -1;
|
||||
let activeIndex = -1;
|
||||
let isLight = false;
|
||||
let lastPlayedIndex = -1;
|
||||
|
||||
// 按钮缩放动画
|
||||
let popTimers = [0, 0, 0, 0]; // 剩余秒数
|
||||
|
||||
BIN
wg1/gen-worker/evidence-3bB/gen-9303-after-play.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9303-after-play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
BIN
wg1/gen-worker/evidence-3bB/gen-9303-first-paint.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9303-first-paint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
wg1/gen-worker/evidence-3bB/gen-9304-after-play.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9304-after-play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
wg1/gen-worker/evidence-3bB/gen-9304-first-paint.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9304-first-paint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
wg1/gen-worker/evidence-3bB/gen-9305-after-play.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9305-after-play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
wg1/gen-worker/evidence-3bB/gen-9305-first-paint.png
Normal file
BIN
wg1/gen-worker/evidence-3bB/gen-9305-first-paint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
2
wg1/gen-worker/evidence-3bB/p4a-nosig.txt
Normal file
2
wg1/gen-worker/evidence-3bB/p4a-nosig.txt
Normal file
@ -0,0 +1,2 @@
|
||||
{"code":401,"msg":"回调签名校验未过","data":null}
|
||||
HTTP_CODE=401
|
||||
2
wg1/gen-worker/evidence-3bB/p4b-wrongsig.txt
Normal file
2
wg1/gen-worker/evidence-3bB/p4b-wrongsig.txt
Normal file
@ -0,0 +1,2 @@
|
||||
{"code":401,"msg":"回调签名校验未过","data":null}
|
||||
HTTP_CODE=401
|
||||
2
wg1/gen-worker/evidence-3bB/p4c-goodsig.txt
Normal file
2
wg1/gen-worker/evidence-3bB/p4c-goodsig.txt
Normal file
@ -0,0 +1,2 @@
|
||||
{"code":1101000000,"msg":"生成任务不存在","data":null}
|
||||
HTTP_CODE=200
|
||||
133
wg1/gen-worker/evidence-3bB/result-gen9303.json
Normal file
133
wg1/gen-worker/evidence-3bB/result-gen9303.json
Normal file
@ -0,0 +1,133 @@
|
||||
{
|
||||
"game_id": "gen-9303",
|
||||
"stage": "stage1",
|
||||
"pass": false,
|
||||
"repairs": 5,
|
||||
"player_rounds_used": 0,
|
||||
"design_text": "你是轻量 H5 小游戏的【设计 agent】。输入是“限时点击不断冒出的小怪物得分”,输出设计稿。\n\n---\n\n## 设计稿\n\n1. **核心机制**:每 1.2~1.8 秒从屏幕顶部或两侧随机刷出一只小怪物(大小约 80×80),怪物缓慢下落或横向飘移。玩家需在 30 秒内点击怪物得分,点击空白处或不点击不会惩罚,但得分过少则输。\n2. **胜负条件**:\n - **赢**:倒计时结束时,得分 ≥ 目标分 12。\n - **输**:倒计时结束得分 < 12;或点击到随机出现的炸弹怪物(每 8~10 秒混入一只)立即输。\n3. **操作**:触摸点击怪物身体区域(检测点击位置与怪物矩形中心 ≤ 40px)。无连续操控。\n4. **关键数值**:\n - 怪物出现间隔:1.2~1.8 秒(随机),首个怪物在 1.0 秒后出现。\n - 怪物移动速度:垂直下落 40~60 px/s,或水平飘移 30~50 px/s(方向随机)。\n - 炸弹怪物出现概率:每 8~10 秒一次,点击即游戏结束。\n - 倒计时:30 秒,显示在右上角。\n - 目标分:12 分。\n5. **Juice 反馈**:\n - 点击普通怪物 → 粒子爆发(8~12 个彩色碎片向外扩散 20px)+ 轻快叮声(必要)。\n - 点击炸弹 → 全屏红色闪烁 + 短时震动(200ms)+ 低音爆炸音效。\n - 倒计时最后 5 秒:加速跳动提示。\n6. **画面要点**:\n - 背景:浅绿色渐变(#D4E9D5 → #A8D8A8),全屏铺满。\n - 怪物:圆形/椭圆形,随机颜色(橙/紫/蓝/粉),眼睛是两个小黑点,简单可爱。\n - 炸弹:黑白圆形,直径 70,带引线图案。\n - HUD:左上角分数(白色粗体 36px),右上角倒计时(红色 32px,最后 5 秒变大)。\n7. **可观测进展**:\n - 分数实时增加(点击屏幕左上角数字上升)。\n - 倒计时数字递减,最后 5 秒闪烁。\n - 怪物被点击后消失(粒子动画证明击中)。\n - 炸弹出现时屏幕边缘出现红色闪烁提示。\n - 胜负切换:倒计时归零 → 切换至结算界面(显示得分+胜/败字样),点击任意处可重玩。\n\n```gatespec\n{\n \"exportState\": [\"phase\", \"score\", \"timeLeft\", \"monsters\"],\n \"driver\": {\"type\": \"none\"},\n \"controlCheck\": null,\n \"assertAfterPlay\": [\n {\"path\": \"score\", \"op\": \">=\", \"why\": \"点击怪物后得分增加\"}\n ],\n \"expectLatch\": true\n}\n```",
|
||||
"gatespec": {
|
||||
"exportState": [
|
||||
"phase",
|
||||
"score",
|
||||
"timeLeft",
|
||||
"monsters"
|
||||
],
|
||||
"driver": {
|
||||
"type": "none"
|
||||
},
|
||||
"controlCheck": null,
|
||||
"assertAfterPlay": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": ">=",
|
||||
"why": "点击怪物后得分增加"
|
||||
}
|
||||
],
|
||||
"expectLatch": true
|
||||
},
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 0,
|
||||
"role": "code",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4206,
|
||||
"out": 5531
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
},
|
||||
{
|
||||
"attempt": 1,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4249,
|
||||
"out": 6241
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
},
|
||||
{
|
||||
"attempt": 2,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4249,
|
||||
"out": 5585
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
},
|
||||
{
|
||||
"attempt": 3,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4249,
|
||||
"out": 5575
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
},
|
||||
{
|
||||
"attempt": 4,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4249,
|
||||
"out": 6523
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
},
|
||||
{
|
||||
"attempt": 5,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4249,
|
||||
"out": 5490
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {}
|
||||
}
|
||||
],
|
||||
"seven_gate_verdict": null,
|
||||
"player": null,
|
||||
"tokens": {
|
||||
"prompt": 26160,
|
||||
"completion": 36307
|
||||
},
|
||||
"tokens_by_model": {
|
||||
"deepseek-v4-flash": [
|
||||
26160,
|
||||
36307
|
||||
]
|
||||
},
|
||||
"cost": {
|
||||
"by_model": {
|
||||
"deepseek-v4-flash": {
|
||||
"in": 26160,
|
||||
"out": 36307,
|
||||
"rmb": 0.07857
|
||||
}
|
||||
},
|
||||
"total_rmb": 0.07857,
|
||||
"gate_rmb": 0.15
|
||||
},
|
||||
"wall_s": 388.4,
|
||||
"models": {
|
||||
"design": "deepseek-v4-flash",
|
||||
"code": "deepseek-v4-flash",
|
||||
"fix": "deepseek-v4-flash",
|
||||
"player_vision": "MiniMax-M3",
|
||||
"player_text": "deepseek-v4-flash"
|
||||
}
|
||||
}
|
||||
317
wg1/gen-worker/evidence-3bB/result-gen9304.json
Normal file
317
wg1/gen-worker/evidence-3bB/result-gen9304.json
Normal file
@ -0,0 +1,317 @@
|
||||
{
|
||||
"game_id": "gen-9304",
|
||||
"stage": "stage1",
|
||||
"pass": false,
|
||||
"repairs": 5,
|
||||
"player_rounds_used": 0,
|
||||
"design_text": "【轻量接球游戏·设计稿】\n\n1. **核心机制**:手指左右滑动,控制底部挡板接住从顶部随机位置下落的小球。每接住一颗得1分,漏掉则立即结束游戏,追求最高分。\n\n2. **胜负条件**: \n - 输:漏掉任意一颗小球,游戏结束(失败态)。 \n - 赢:无限模式,分数可不断累积,目标为获得更高分数(无固定胜利,仅追求高分)。\n\n3. **操作**:触摸滑动手指,挡板 x 坐标平滑跟随手指 x,限制在屏幕左右边缘(0~390px 内)。无其他按键。\n\n4. **关键数值**(逻辑像素 390×844): \n - 挡板:宽 120px,高 20px,底部 y = 814(距离底边 30px)。 \n - 小球:半径 10px;初始下落速度 150px/s;每得 5 分速度提升 10%。 \n - 生成间隔:随机 0.5~1.5s;x 范围 [20,370]。\n\n5. **juice 反馈**: \n - 接住小球:播放“叮”声效(引擎音频),小球缩小的动画。 \n - 漏球:引擎震动(shake 0.2s),短暂红屏,低沉失败音。\n\n6. **画面要点**: \n - 背景:从上到下渐变色(深蓝→浅蓝),铺满。 \n - 挡板:白色半透明圆角矩形。 \n - 小球:随机亮色(红/黄/青)。 \n - HUD:顶部分数显示(白色大字号,带轻微的缩放脉冲动画)。\n\n7. **可观测进展**:分数实时增加(每接住一次 +1)。漏球后 phase 从 \"playing\" 切换为 \"gameover\",分数锁定并显示“最终分数”及重玩按钮。\n\n```gatespec\n{\n \"exportState\": [\"phase\",\"score\",\"ballPosX\",\"paddleX\"],\n \"driver\": {\"type\":\"paddle-intercept\",\"ballPath\":\"ballPosX\",\"paddleY\":814},\n \"controlCheck\": {\"paddlePath\":\"paddleX\",\"tapXs\":[50,340]},\n \"assertAfterPlay\": [{\"path\":\"score\",\"op\":\"increased\",\"why\":\"接住小球得分\"}],\n \"expectLatch\": true\n}\n```",
|
||||
"gatespec": {
|
||||
"exportState": [
|
||||
"phase",
|
||||
"score",
|
||||
"ballPosX",
|
||||
"paddleX"
|
||||
],
|
||||
"driver": {
|
||||
"type": "paddle-intercept",
|
||||
"ballPath": "ballPosX",
|
||||
"paddleY": 814
|
||||
},
|
||||
"controlCheck": {
|
||||
"paddlePath": "paddleX",
|
||||
"tapXs": [
|
||||
50,
|
||||
340
|
||||
]
|
||||
},
|
||||
"assertAfterPlay": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": "increased",
|
||||
"why": "接住小球得分"
|
||||
}
|
||||
],
|
||||
"expectLatch": true
|
||||
},
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 0,
|
||||
"role": "code",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4060,
|
||||
"out": 6004
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": false,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 1,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4278,
|
||||
"out": 5191
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 2,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4189,
|
||||
"out": 9126
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 3,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4189,
|
||||
"out": 7909
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": false,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 4,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4187,
|
||||
"out": 6430
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 5,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4189,
|
||||
"out": 6097
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": false,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"seven_gate_verdict": {
|
||||
"gameId": "gen-9304",
|
||||
"url": "http://localhost:4320/games/_wg1-gen/gen-9304/index.html",
|
||||
"ts": null,
|
||||
"guards": {
|
||||
"A_boot": {
|
||||
"pass": true
|
||||
},
|
||||
"C_frame": {
|
||||
"pass": true,
|
||||
"f0": 60,
|
||||
"f1": 90,
|
||||
"delta": 30
|
||||
},
|
||||
"I_control": {
|
||||
"pass": false,
|
||||
"paddlePath": "paddleX",
|
||||
"results": [
|
||||
{
|
||||
"tapX": 50,
|
||||
"before": 195,
|
||||
"after": 195,
|
||||
"moved": 0,
|
||||
"distToTarget": 145,
|
||||
"pass": false
|
||||
},
|
||||
{
|
||||
"tapX": 340,
|
||||
"before": 195,
|
||||
"after": 195,
|
||||
"moved": 0,
|
||||
"distToTarget": 145,
|
||||
"pass": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"D_render": {
|
||||
"pass": true,
|
||||
"bright": 1091360,
|
||||
"maxCh": 255
|
||||
},
|
||||
"E_live": {
|
||||
"pass": true,
|
||||
"distinctStates": 31,
|
||||
"samples": 31
|
||||
},
|
||||
"B_uncaught": {
|
||||
"pass": true,
|
||||
"uncaught": []
|
||||
},
|
||||
"F_wiring": {
|
||||
"pass": true,
|
||||
"callCount": 89,
|
||||
"sample": [
|
||||
"particles.spawnEmitter",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter"
|
||||
],
|
||||
"expected": []
|
||||
},
|
||||
"G_input": {
|
||||
"pass": true,
|
||||
"inputHash": "2f4267bc",
|
||||
"controlHash": "1ceee3f7",
|
||||
"atFrame": 1176,
|
||||
"ctrlFrame": 1181
|
||||
},
|
||||
"H_progress": {
|
||||
"pass": true,
|
||||
"checks": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": "increased",
|
||||
"before": 0,
|
||||
"after": 2,
|
||||
"pass": true,
|
||||
"why": "接住小球得分"
|
||||
}
|
||||
],
|
||||
"latch": {
|
||||
"pass": true,
|
||||
"dwelledMs": 600,
|
||||
"after": "gameover",
|
||||
"reason": ""
|
||||
},
|
||||
"state0": {
|
||||
"phase": "playing",
|
||||
"score": 0,
|
||||
"remaining": 1,
|
||||
"progress": null,
|
||||
"gameoverReason": "",
|
||||
"ballPosX": 210.06992567097768,
|
||||
"paddleX": 195
|
||||
},
|
||||
"state1": {
|
||||
"phase": "gameover",
|
||||
"score": 2,
|
||||
"remaining": 0,
|
||||
"progress": null,
|
||||
"gameoverReason": "ball_lost",
|
||||
"ballPosX": -1,
|
||||
"paddleX": 195
|
||||
}
|
||||
}
|
||||
},
|
||||
"pass": false,
|
||||
"notes": []
|
||||
},
|
||||
"player": null,
|
||||
"tokens": {
|
||||
"prompt": 25813,
|
||||
"completion": 42252
|
||||
},
|
||||
"tokens_by_model": {
|
||||
"deepseek-v4-flash": [
|
||||
25813,
|
||||
42252
|
||||
]
|
||||
},
|
||||
"cost": {
|
||||
"by_model": {
|
||||
"deepseek-v4-flash": {
|
||||
"in": 25813,
|
||||
"out": 42252,
|
||||
"rmb": 0.08738
|
||||
}
|
||||
},
|
||||
"total_rmb": 0.08738,
|
||||
"gate_rmb": 0.15
|
||||
},
|
||||
"wall_s": 785.7,
|
||||
"models": {
|
||||
"design": "deepseek-v4-flash",
|
||||
"code": "deepseek-v4-flash",
|
||||
"fix": "deepseek-v4-flash",
|
||||
"player_vision": "MiniMax-M3",
|
||||
"player_text": "deepseek-v4-flash"
|
||||
}
|
||||
}
|
||||
256
wg1/gen-worker/evidence-3bB/result-gen9305.json
Normal file
256
wg1/gen-worker/evidence-3bB/result-gen9305.json
Normal file
@ -0,0 +1,256 @@
|
||||
{
|
||||
"game_id": "gen-9305",
|
||||
"stage": "stage1",
|
||||
"pass": false,
|
||||
"repairs": 5,
|
||||
"player_rounds_used": 0,
|
||||
"design_text": "## 设计稿:Simon Says(记忆序列)\n\n**1. 核心机制** \n电脑随机生成一组颜色序列并逐个闪烁提示,玩家需按相同顺序点击对应彩色按钮。每轮正确复现后,序列长度 +1,进入下一关。错误点击则游戏结束。\n\n**2. 胜负条件** \n- 胜:完成当前关(全部正确点击)→ 进入下一关(序列加长),无最终胜利,分数无限递增。 \n- 负:点击顺序与电脑序列不匹配 → 立即 gameover(失败态),驻留界面,分数固定。\n\n**3. 操作** \n触摸点击按钮(逻辑像素 390×844 竖屏)。按钮为 4 个等大圆形,均匀分布在屏幕下半区(半径约 60,间距 30),分别渲染红/绿/蓝/黄色。\n\n**4. 关键数值** \n- 初始序列长度:3 \n- 每次提示单个按钮闪烁时间:0.5s,间隔 0.2s \n- 玩家点击超时容限:无(不设倒计时,未点击不算错,但不推进) \n- 难度梯度:每关序列长度 +1,连续正确累加(最大 20+)\n\n**5. Juice 反馈** \n- 提示阶段:按钮高亮 + 同时播放对应短促音高(C/E/G/B4) \n- 玩家点击正确:按钮瞬间放大 1.1 倍 + 点击音效(短嘀声) \n- 点击错误:屏幕震动 0.1s + 低沉错误音(引擎必备)\n\n**6. 画面要点** \n- 背景:纯黑色,#000000 \n- 按钮圆形,描边白色、半径 60,填充分别:#FF4136, #2ECC40, #0074D9, #FFDC00 \n- HUD:顶部居中显示当前关卡数(\"Level 5\" 白色 24pt 字体),左下显示最高分(当前连续关卡数)\n\n**7. 可观测进展** \n- 每关正确完成 → 右上角分数(关卡数)+1 → 序列长度 +1(下次提示变长) \n- 失败瞬时:phase 从 \"playing\" → \"lose\",分数冻结,按钮变灰不可点击 \n- 进度量化:玩家每次点击后 `remaining` = 当前关剩余待点击步骤数(初始 = 序列长度,点击正确递减)\n\n```gatespec\n{\n \"exportState\": [\"phase\",\"score\",\"sequenceLength\",\"remaining\",\"userStep\"],\n \"driver\": {\"type\":\"none\"},\n \"controlCheck\": null,\n \"assertAfterPlay\": [\n {\"path\":\"score\",\"op\":\"increased\",\"why\":\"正确复现后关卡数上升\"}\n ],\n \"expectLatch\": true\n}\n```",
|
||||
"gatespec": {
|
||||
"exportState": [
|
||||
"phase",
|
||||
"score",
|
||||
"sequenceLength",
|
||||
"remaining",
|
||||
"userStep"
|
||||
],
|
||||
"driver": {
|
||||
"type": "none"
|
||||
},
|
||||
"controlCheck": null,
|
||||
"assertAfterPlay": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": "increased",
|
||||
"why": "正确复现后关卡数上升"
|
||||
}
|
||||
],
|
||||
"expectLatch": true
|
||||
},
|
||||
"attempts": [
|
||||
{
|
||||
"attempt": 0,
|
||||
"role": "code",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "validate",
|
||||
"usage": {
|
||||
"in": 4136,
|
||||
"out": 5211
|
||||
},
|
||||
"errors": [
|
||||
"违禁:禁 Math.random(用 ctx.random)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attempt": 1,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4181,
|
||||
"out": 5627
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": false,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": false,
|
||||
"G_input": false,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 2,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4337,
|
||||
"out": 9020
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 3,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "validate",
|
||||
"usage": {
|
||||
"in": 4264,
|
||||
"out": 5089
|
||||
},
|
||||
"errors": [
|
||||
"违禁:禁 Math.random(用 ctx.random)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attempt": 4,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "seven_gate",
|
||||
"usage": {
|
||||
"in": 4181,
|
||||
"out": 7544
|
||||
},
|
||||
"seven_gate_pass": false,
|
||||
"guards": {
|
||||
"A_boot": true,
|
||||
"C_frame": true,
|
||||
"I_control": true,
|
||||
"D_render": true,
|
||||
"E_live": true,
|
||||
"B_uncaught": true,
|
||||
"F_wiring": true,
|
||||
"G_input": true,
|
||||
"H_progress": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"attempt": 5,
|
||||
"role": "fix",
|
||||
"model": "deepseek-v4-flash",
|
||||
"stage_fail": "validate",
|
||||
"usage": {
|
||||
"in": 4264,
|
||||
"out": 4875
|
||||
},
|
||||
"errors": [
|
||||
"违禁:禁 Math.random(用 ctx.random)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"seven_gate_verdict": {
|
||||
"gameId": "gen-9305",
|
||||
"url": "http://localhost:4320/games/_wg1-gen/gen-9305/index.html",
|
||||
"ts": null,
|
||||
"guards": {
|
||||
"A_boot": {
|
||||
"pass": true
|
||||
},
|
||||
"C_frame": {
|
||||
"pass": true,
|
||||
"f0": 60,
|
||||
"f1": 90,
|
||||
"delta": 30
|
||||
},
|
||||
"I_control": {
|
||||
"pass": true,
|
||||
"skipped": "未声明 controlCheck(向后兼容)"
|
||||
},
|
||||
"D_render": {
|
||||
"pass": true,
|
||||
"bright": 117266,
|
||||
"maxCh": 255
|
||||
},
|
||||
"E_live": {
|
||||
"pass": true,
|
||||
"distinctStates": 62,
|
||||
"samples": 62
|
||||
},
|
||||
"B_uncaught": {
|
||||
"pass": true,
|
||||
"uncaught": []
|
||||
},
|
||||
"F_wiring": {
|
||||
"pass": true,
|
||||
"callCount": 4,
|
||||
"sample": [
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"audio.synth.synthSfx",
|
||||
"audio.synth.synthSfx"
|
||||
],
|
||||
"expected": []
|
||||
},
|
||||
"G_input": {
|
||||
"pass": true,
|
||||
"inputHash": "ce332c9b",
|
||||
"controlHash": "10545f53",
|
||||
"atFrame": 1664,
|
||||
"ctrlFrame": -1
|
||||
},
|
||||
"H_progress": {
|
||||
"pass": false,
|
||||
"checks": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": "increased",
|
||||
"before": 0,
|
||||
"after": 0,
|
||||
"pass": false,
|
||||
"why": "正确复现后关卡数上升"
|
||||
}
|
||||
],
|
||||
"latch": {
|
||||
"pass": false,
|
||||
"reason": "真玩未到达 gameover 终态(终态不可达/无失败态/play-spec 未驱动到结束)",
|
||||
"phaseNow": "playing"
|
||||
},
|
||||
"state0": {
|
||||
"phase": "playing",
|
||||
"score": 0,
|
||||
"remaining": 3,
|
||||
"progress": null,
|
||||
"gameoverReason": "",
|
||||
"sequenceLength": 3,
|
||||
"userStep": 0
|
||||
},
|
||||
"state1": {
|
||||
"phase": "playing",
|
||||
"score": 0,
|
||||
"remaining": 3,
|
||||
"progress": null,
|
||||
"gameoverReason": "",
|
||||
"sequenceLength": 3,
|
||||
"userStep": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"pass": false,
|
||||
"notes": []
|
||||
},
|
||||
"player": null,
|
||||
"tokens": {
|
||||
"prompt": 26081,
|
||||
"completion": 38590
|
||||
},
|
||||
"tokens_by_model": {
|
||||
"deepseek-v4-flash": [
|
||||
26081,
|
||||
38590
|
||||
]
|
||||
},
|
||||
"cost": {
|
||||
"by_model": {
|
||||
"deepseek-v4-flash": {
|
||||
"in": 26081,
|
||||
"out": 38590,
|
||||
"rmb": 0.08201
|
||||
}
|
||||
},
|
||||
"total_rmb": 0.08201,
|
||||
"gate_rmb": 0.15
|
||||
},
|
||||
"wall_s": 564.2,
|
||||
"models": {
|
||||
"design": "deepseek-v4-flash",
|
||||
"code": "deepseek-v4-flash",
|
||||
"fix": "deepseek-v4-flash",
|
||||
"player_vision": "MiniMax-M3",
|
||||
"player_text": "deepseek-v4-flash"
|
||||
}
|
||||
}
|
||||
117
wg1/gen-worker/evidence-3bB/verdict-gen9304.json
Normal file
117
wg1/gen-worker/evidence-3bB/verdict-gen9304.json
Normal file
@ -0,0 +1,117 @@
|
||||
{
|
||||
"gameId": "gen-9304",
|
||||
"url": "http://localhost:4320/games/_wg1-gen/gen-9304/index.html",
|
||||
"ts": null,
|
||||
"guards": {
|
||||
"A_boot": {
|
||||
"pass": true
|
||||
},
|
||||
"C_frame": {
|
||||
"pass": true,
|
||||
"f0": 60,
|
||||
"f1": 90,
|
||||
"delta": 30
|
||||
},
|
||||
"I_control": {
|
||||
"pass": false,
|
||||
"paddlePath": "paddleX",
|
||||
"results": [
|
||||
{
|
||||
"tapX": 50,
|
||||
"before": 195,
|
||||
"after": 195,
|
||||
"moved": 0,
|
||||
"distToTarget": 145,
|
||||
"pass": false
|
||||
},
|
||||
{
|
||||
"tapX": 340,
|
||||
"before": 195,
|
||||
"after": 195,
|
||||
"moved": 0,
|
||||
"distToTarget": 145,
|
||||
"pass": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"D_render": {
|
||||
"pass": true,
|
||||
"bright": 1091360,
|
||||
"maxCh": 255
|
||||
},
|
||||
"E_live": {
|
||||
"pass": true,
|
||||
"distinctStates": 31,
|
||||
"samples": 31
|
||||
},
|
||||
"B_uncaught": {
|
||||
"pass": true,
|
||||
"uncaught": []
|
||||
},
|
||||
"F_wiring": {
|
||||
"pass": true,
|
||||
"callCount": 89,
|
||||
"sample": [
|
||||
"particles.spawnEmitter",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter",
|
||||
"audio.synth.synthSfx",
|
||||
"particles.spawnEmitter"
|
||||
],
|
||||
"expected": []
|
||||
},
|
||||
"G_input": {
|
||||
"pass": true,
|
||||
"inputHash": "2f4267bc",
|
||||
"controlHash": "1ceee3f7",
|
||||
"atFrame": 1176,
|
||||
"ctrlFrame": 1181
|
||||
},
|
||||
"H_progress": {
|
||||
"pass": true,
|
||||
"checks": [
|
||||
{
|
||||
"path": "score",
|
||||
"op": "increased",
|
||||
"before": 0,
|
||||
"after": 2,
|
||||
"pass": true,
|
||||
"why": "接住小球得分"
|
||||
}
|
||||
],
|
||||
"latch": {
|
||||
"pass": true,
|
||||
"dwelledMs": 600,
|
||||
"after": "gameover",
|
||||
"reason": ""
|
||||
},
|
||||
"state0": {
|
||||
"phase": "playing",
|
||||
"score": 0,
|
||||
"remaining": 1,
|
||||
"progress": null,
|
||||
"gameoverReason": "",
|
||||
"ballPosX": 210.06992567097768,
|
||||
"paddleX": 195
|
||||
},
|
||||
"state1": {
|
||||
"phase": "gameover",
|
||||
"score": 2,
|
||||
"remaining": 0,
|
||||
"progress": null,
|
||||
"gameoverReason": "ball_lost",
|
||||
"ballPosX": -1,
|
||||
"paddleX": 195
|
||||
}
|
||||
}
|
||||
},
|
||||
"pass": false,
|
||||
"notes": []
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user