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:
zizi 2026-06-14 16:20:28 +00:00
parent d59093f84c
commit c99014c243
21 changed files with 1178 additions and 7 deletions

View 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 服务【回调链产物】(=真生成游戏),完成终局闭环。
-- 自动选 NgameId=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 Ngen_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 指向回调新版本 Nfeed 卡 /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;

View 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。
-- IDgameId=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 的同根因兜底)
-- tenantstaging 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 先指占位 93030flip 后改指回调新版本 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_packagestatus=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_rankzone_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';

View 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';

View 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';

View File

@ -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/binlili-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 / chromiumcommand -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=""

View 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 = '';
// 订阅点击

View 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;
// 开局尝试演示引擎能力:持续粒子发射(常驻)

View 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]; // 剩余秒数

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,2 @@
{"code":401,"msg":"回调签名校验未过","data":null}
HTTP_CODE=401

View File

@ -0,0 +1,2 @@
{"code":401,"msg":"回调签名校验未过","data":null}
HTTP_CODE=401

View File

@ -0,0 +1,2 @@
{"code":1101000000,"msg":"生成任务不存在","data":null}
HTTP_CODE=200

View 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"
}
}

View 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.5sx 范围 [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"
}
}

View 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"
}
}

View 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": []
}