Files
Genarrative/apps/ai-game-creator-shell/tests/agentRuntimeUserInputCard.test.tsx
T
lhk229 f2245fb23d 策划澄清链路按原型拉齐:header 带主题、放开提问面、统一选项形状
对照 local-scripts/deisgn_agent 原型逐条比对后拉回五处分歧。原型 38 条 run 里
22 条走满 3 轮澄清,本仓库 GUI 实测一次都没到过第 3 轮。

1. header 从固定 8 字的轮号计数器「第N轮·关键决定」改回带主题的
   「第N轮·当前要决定:<主题>」,决定台账的 topic 改从 header 取。12 字上限是
   三条泳道共用的通用 user.input_request 常量,按 header 形状开策划分支——通用
   问询今天能过的明天逐字照过,做游戏 / 做素材拿到的仍是 12 字。

2. 提问名额判据恢复原型三分法:「且影响首个可玩闭环」从「空白」的定义挪回提问
   优先级,并恢复「空白或存疑」。此前的定义把「无从判断但不影响闭环」的字段整个
   排除在空白之外,可问集合被闭合成 pillars + coreLoop 两项。

3. 有默认建议的字段从「一律先用默认建议,不占轮次」改回「优先用默认建议而不是
   提问」——有默认不等于不能问。

4. 默认建议清单换回原型那五条(局长偏好、美术、成长、探索、构建)。摘掉
   genre.fusion / targetUsers.coreUsers|preferences|referenceGames / outOfScope:
   它们进清单等于把第三顺位「制作边界与 MVP」整条轴默认掉,出稿触发器③「剩余
   空白都能由默认建议覆盖」随之在第 3 轮恒真。反幻觉那句按原型结构移到「低幻觉
   与 GDD 约束」段,outOfScope 的兜底内容与该段已有的 MVP 范围句逐字重复。

5. 选项数 brief 写「2~3 个」(照通用常量生成)、Runtime 硬校验恰好 3、brief 下文
   又写「固定三个选项」,三方打架。统一为恰好 3,裸 3 提成
   PLAN_CLARIFICATION_OPTION_COUNT 让 brief 与解析器同源。label 分隔符集合按原型
   ^A\s*[·•・::..\-] 从 4 个扩到 8 个,两处都只放宽不收紧。

守门两条:策划 header 的放宽只对「第N轮·」形状生效、同长度的通用 header 仍被 12 字
挡下;分隔符集合对着一份逐字来自原型正则的显式清单断言——遍历集合本身是空转的,
删一个就少测一个。

未动分歧 5/6/7(轴级封锁、内容级禁问、oneLiner 禁问)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 03:36:29 +00:00

77 lines
2.2 KiB
TypeScript

// @vitest-environment jsdom
import { fireEvent, render, screen } from '@testing-library/react';
import { StrictMode } from 'react';
import { describe, expect, it } from 'vitest';
import type { AgentRuntimeUserInputRequest } from '../src/app/types';
import { AgentRuntimeUserInputCard } from '../src/features/agent-runtime/panels';
function clarificationRequest(): AgentRuntimeUserInputRequest {
return {
schemaVersion: 'agc.user_input_request.v1',
requestId: 'req-1',
agentId: 'project-supervisor',
taskId: 'task-1',
sessionId: 'session-1',
runId: 'run-1',
actionId: 'action-1',
status: 'pending',
questions: [
{
id: 'q1',
header: '第1轮·当前要决定:首版路线',
question: '这局游戏的重玩动力是什么?',
options: [
{ label: '分数驱动', description: '刷新纪录后重开' },
{ label: '成长驱动', description: '解锁新能力后重开' },
],
},
],
allowFreeform: true,
responseId: null,
requestedAt: 1,
updatedAt: 1,
};
}
describe('AgentRuntimeUserInputCard 澄清输入', () => {
it('手动输入自由回答不会让页面崩溃', () => {
render(
<StrictMode>
<AgentRuntimeUserInputCard
request={clarificationRequest()}
controlBusy={false}
/>
</StrictMode>,
);
const textarea = screen.getByLabelText(
'第1轮·当前要决定:首版路线 其他回答',
);
fireEvent.change(textarea, { target: { value: '玩家自己写的答案' } });
expect((textarea as HTMLTextAreaElement).value).toBe('玩家自己写的答案');
});
it('先选中选项再清空填充文本不会让页面崩溃', () => {
render(
<StrictMode>
<AgentRuntimeUserInputCard
request={clarificationRequest()}
controlBusy={false}
/>
</StrictMode>,
);
fireEvent.click(screen.getByText('分数驱动'));
const textarea = screen.getByLabelText(
'第1轮·当前要决定:首版路线 其他回答',
) as HTMLTextAreaElement;
expect(textarea.value).toBe('分数驱动');
fireEvent.change(textarea, { target: { value: '' } });
expect(textarea.value).toBe('');
});
});