From 151c61ad088764b8fce7e6490d964fe4ab221e66 Mon Sep 17 00:00:00 2001 From: Linghong Date: Tue, 15 Sep 2026 07:00:00 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E9=80=80=E5=BD=B9=E7=AD=96?= =?UTF-8?q?=E5=88=92=E6=B5=8B=E8=AF=95=E5=A4=B9=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除策划 V2 与批准 GDD 的旧测试数据和调用模拟 保留现役设计 Agent 与 DirectCodex 的界面测试 移除测试中对退役规划命令的断言 --- apps/ai-game-creator-shell/src/App.tsx | 1 - .../tests/appSurface/harness.ts | 194 ------------------ .../tests/appSurface/home.suite.ts | 117 ----------- 3 files changed, 312 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index f8463c9e3..604816870 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -11388,7 +11388,6 @@ export function App({ !directCodexProductRuntime && orchestrationMode === 'professional-dag' } workspaceStatus={workspaceStatus} - planningLane={planningLaneActive} designView={useDesignAgentSurface ? designAgentView : null} onDesignApprove={ useDesignAgentSurface diff --git a/apps/ai-game-creator-shell/tests/appSurface/harness.ts b/apps/ai-game-creator-shell/tests/appSurface/harness.ts index 5dbedafbf..e42c88ea8 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/harness.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/harness.ts @@ -13,7 +13,6 @@ import { import React from 'react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import type { PlanGddStateViewV1 } from '../../src/app/types'; import * as clientApi from '../../src/services/clientApi'; import { resetLlmModelCatalogCacheForTest } from '../../src/services/llmModelCatalog'; import { useLauncherHomeDraftStore } from '../../src/view/home/useHomeDraftStore'; @@ -483,150 +482,6 @@ function agentRuntimeUserInputRequest({ }; } -function createPlanGddStateView( - overrides: Partial = {}, -): PlanGddStateViewV1 { - const gddRef = { - gddId: 'gdd-plan-0001', - version: 1, - fingerprint: 'sha256-serde-json-v2:1111111111111111', - }; - return { - schemaVersion: 'plan-gdd-state-view.v1', - projectId: 'local-project-draft', - gddId: gddRef.gddId, - state: 'ready_for_approval', - session: { - sessionId: 'plan-session-0001', - sessionRevision: 3, - sessionFingerprint: 'sha256-serde-json-v2:2222222222222222', - phase: 'awaiting_gdd_approval', - clarificationRound: 2, - repairDepth: 0, - accumulatedAgentMillis: 42_000, - activeRunId: null, - awaitingAnswerFor: null, - decisionStateCounts: { - confirmed: 2, - defaultPending: 1, - prototypePending: 0, - }, - }, - versions: [ - { - gddRef, - status: 'ready_for_approval', - approvalRequestId: 'gdd-approval-0001', - createdAtUtc: '2026-08-18T00:00:00Z', - decision: null, - }, - ], - displayGdd: { - schemaVersion: 'plan-gdd.v1', - projectId: 'local-project-draft', - gddId: gddRef.gddId, - version: gddRef.version, - submissionId: 'action-0123456789abcdef01234567', - approvalRequestId: 'gdd-approval-0001', - actionFingerprint: 'a'.repeat(64), - agentId: 'project-planning', - source: 'agent-delegate', - runProfile: 'standard', - runProfileBindingFingerprint: 'b'.repeat(64), - rootAgentId: 'project-supervisor', - rootRunId: 'run-plan-root-0001', - delegationId: 'delegation-0001', - sessionId: 'plan-session-0001', - sourceSessionRevision: 2, - sourceSessionFingerprint: 'sha256-serde-json-v2:3333333333333333', - createdByRunId: 'run-plan-child-0001', - createdAtUtc: '2026-08-18T00:00:00Z', - fingerprint: gddRef.fingerprint, - game: { - title: '灯塔守夜人', - oneLiner: '在潮汐涨落之间调度光束,护送迷航的船只回港。', - genre: { primary: '策略', fusion: null }, - artStyle: { - visualType: '像素', - keywords: ['夜色', '海雾'], - moodAndColor: '冷蓝为主,暖黄光束作为唯一高光。', - mvpArtBoundary: '只做灯塔与三类船只的静帧。', - }, - pillars: [ - { - name: '光束调度', - playerFeel: '在有限视野里做取舍。', - mechanism: '每回合只能照亮一个扇区。', - decisionState: 'confirmed', - basis: null, - }, - ], - coreLoop: ['观察潮汐', '分配光束', '结算返港'], - targetUsers: { - coreUsers: '喜欢短局策略的玩家', - preferences: '偏好可预测的规则', - sessionLength: '单局 5 分钟', - referenceGames: ['灯塔物语'], - }, - platformFacts: { - runtime: 'web', - viewports: ['desktop', 'mobile'], - inputs: ['pointer'], - preview: '本地预览', - }, - mvpSystems: [ - { - system: '潮汐时钟', - minimalFunction: '固定三段潮汐循环。', - whyRequired: '没有它就没有节奏压力。', - verifyMethod: '观察一局内三段是否各触发一次。', - decisionState: 'confirmed', - basis: null, - }, - ], - outOfScope: ['多人对战'], - creatorTips: { - doFirst: '先做潮汐时钟。', - deferForNow: '暂缓天气系统。', - howToVerify: '单局跑满三段潮汐。', - expandWhen: '核心循环稳定后再加船种。', - }, - }, - decisions: [ - { - id: 'decision-0001', - topic: '光束是否可分裂', - state: 'confirmed', - answerSource: 'user_option', - round: 1, - answerSummary: '不可分裂,保持取舍压力。', - basis: null, - }, - ], - prototypeValidationItems: [ - { - id: 'proto-0001', - question: '单扇区照明是否足够做出取舍?', - microPrototype: '纸面推演三回合。', - observation: '玩家是否出现犹豫。', - passCriterion: '三回合内至少一次改变计划。', - }, - ], - }, - pendingApproval: { - gddRef, - pendingActionId: 'action-0123456789abcdef01234567', - actionFingerprint: 'a'.repeat(64), - approvalRequestId: 'gdd-approval-0001', - sessionId: 'plan-session-0001', - runId: 'run-plan-root-0001', - }, - approvedGddRef: null, - recoveryPending: false, - ...overrides, - }; -} - function createProjectSupervisorRuntimeHarness({ projectPath = '/tmp/authorized-game', sessionId = 'supervisor-session-active', @@ -638,8 +493,6 @@ function createProjectSupervisorRuntimeHarness({ initialProjectRevision = 0, runtimeMapLoader, expectedRunProfile = 'autonomous-game-build', - planningV2Result = null, - planningV2StartResult = null, designAgentView = null, designAgentContinueView = null, designWorkspaceFiles = [], @@ -654,8 +507,6 @@ function createProjectSupervisorRuntimeHarness({ initialProjectRevision?: number; runtimeMapLoader?: () => Promise>>; expectedRunProfile?: 'standard' | 'autonomous-game-build'; - planningV2Result?: Record | null; - planningV2StartResult?: Record | null; designAgentView?: Record | null; designAgentContinueView?: Record | null; designWorkspaceFiles?: Array>; @@ -703,14 +554,9 @@ function createProjectSupervisorRuntimeHarness({ let rejectRuntime: Record | null = null; let answerRuntime: Record | null = null; let answerFailuresRemaining = 0; - // 默认不配置策划状态:hydrate 与接入本 harness 之前一样抛出,既有用例行为不变。 - let currentPlanningV2Result = planningV2Result; - let currentPlanningV2StartResult = planningV2StartResult; let currentDesignAgentView = designAgentView; const currentDesignContinueView = designAgentContinueView; const currentDesignWorkspaceFiles = [...designWorkspaceFiles]; - let planningV2DecisionError: string | null = null; - const planningV2DecisionCalls: Array> = []; let runtimeUpdateHandler: | ((event: { payload: { @@ -1060,35 +906,6 @@ function createProjectSupervisorRuntimeHarness({ if (command === 'read_design_workspace_file') { return ''; } - if (command === 'hydrate_planning_session_v2') { - return currentPlanningV2Result; - } - if ( - command === 'start_planning_session_v2' || - command === 'continue_planning_session_v2' - ) { - const nextResult = - command === 'start_planning_session_v2' - ? (currentPlanningV2StartResult ?? currentPlanningV2Result) - : currentPlanningV2Result; - if (!nextResult) { - throw new Error('PLANNING_V2_RESULT_NOT_CONFIGURED'); - } - currentPlanningV2Result = nextResult; - return nextResult; - } - if (command === 'decide_planning_artifact_v2') { - planningV2DecisionCalls.push({ ...(args ?? {}) }); - if (planningV2DecisionError) { - const failure = planningV2DecisionError; - planningV2DecisionError = null; - throw new Error(failure); - } - if (!currentPlanningV2Result) { - throw new Error('PLANNING_V2_RESULT_NOT_CONFIGURED'); - } - return currentPlanningV2Result; - } throw new Error(`unexpected invoke ${command}`); }, ); @@ -1156,19 +973,9 @@ function createProjectSupervisorRuntimeHarness({ failNextAnswers(count = 1) { answerFailuresRemaining = count; }, - setPlanningV2Result(state: Record | null) { - currentPlanningV2Result = state; - }, emitDesignAgentEvent(payload: Record) { designAgentUpdateHandler?.({ payload }); }, - setPlanningV2StartResult(state: Record | null) { - currentPlanningV2StartResult = state; - }, - failNextPlanningV2Decision(message: string) { - planningV2DecisionError = message; - }, - planningV2DecisionCalls, appendSupervisorMessage(message: Record) { currentSupervisorMessages.push(message); }, @@ -1377,7 +1184,6 @@ export { composerValue, createGameCreationAppManifest, createGameCreationAppSeedTasks, - createPlanGddStateView, createProjectSupervisorRuntimeHarness, deriveAgentStatusCards, describe, diff --git a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts index af621b7b5..048d4b058 100644 --- a/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts +++ b/apps/ai-game-creator-shell/tests/appSurface/home.suite.ts @@ -1,7 +1,5 @@ import type { ProjectSupervisorComponentProps } from '../../src/features/app-shell/model'; -import { useHomeProjectCreation } from '../../src/features/app-shell/useHomeProjectCreation'; import { WorkspaceLauncherShell } from '../../src/features/app-shell/WorkspaceLauncher'; -import type { LauncherView } from '../../src/view/layout'; import { act, App, @@ -63,38 +61,6 @@ function homeDesignContinueView({ }; } -function ApprovedGddStartHarness() { - const [, setLauncherView] = React.useState( - 'project-development', - ); - const [, setStatus] = React.useState(''); - const [, setAgentChatProjectPath] = React.useState(''); - const controller = useHomeProjectCreation({ - setStatus, - setLauncherView, - setAgentChatProjectPath, - rememberRecentWorkspace: () => undefined, - }); - - if (controller.currentProjectContext) { - return React.createElement( - 'p', - { 'aria-label': '已进入自动游戏项目' }, - controller.currentProjectContext.initialPrompt, - ); - } - - return React.createElement( - 'button', - { - type: 'button', - onClick: () => - void controller.startGameFromApprovedGdd('/tmp/planning-project'), - }, - '直接用已批准 GDD 开始建造', - ); -} - async function openResourceBookCategory(label: string) { const categoryByLabel: Record = { 'UI 交互': 'ui-interaction', @@ -1704,73 +1670,6 @@ export function registerHomeProjectCreationTests() { expect(followUpPayload).not.toHaveProperty('attachments'); }); - it('starts an automatic game project from the approved GDD', async () => { - const automaticProjectPath = '/tmp/approved-gdd-game'; - const manifest = createGameCreationAppManifest( - 'approved-gdd-game', - '已批准 GDD 游戏', - ); - const gddContent = '# Fast GDD\n\n批准后的方案内容'; - const invoke = vi.fn(async (command: string) => { - if (command === 'read_local_project_file') { - return { - path: 'game/fast_gdd.md', - absolutePath: '/tmp/planning-project/game/fast_gdd.md', - content: gddContent, - }; - } - if (command === 'create_automatic_local_game_project') { - return { - projectPath: automaticProjectPath, - manifestPath: `${automaticProjectPath}/.agent/manifest.json`, - manifest, - }; - } - if (command === 'upload_local_asset') { - return { - id: 'approved-gdd-asset', - localPath: 'assets/uploads/fast_gdd.md', - absolutePath: `${automaticProjectPath}/assets/uploads/fast_gdd.md`, - manifestPath: `${automaticProjectPath}/.agent/manifest.json`, - }; - } - throw new Error(`unexpected invoke ${command}`); - }); - window.__TAURI__ = { core: { invoke } }; - render(React.createElement(ApprovedGddStartHarness)); - - fireEvent.click( - screen.getByRole('button', { name: '直接用已批准 GDD 开始建造' }), - ); - fireEvent.click( - screen.getByRole('button', { name: '直接用已批准 GDD 开始建造' }), - ); - - await waitFor(() => { - expect( - invoke.mock.calls.filter( - ([command]) => command === 'create_automatic_local_game_project', - ), - ).toHaveLength(1); - }); - expect(screen.getByLabelText('已进入自动游戏项目').textContent).toContain( - '请按照附件中的已批准 GDD 开始建造这款游戏。', - ); - expect(invoke).toHaveBeenCalledWith('read_local_project_file', { - projectPath: '/tmp/planning-project', - relativePath: 'game/fast_gdd.md', - commandId: 'file.read', - }); - await waitFor(() => { - expect(invoke).toHaveBeenCalledWith('upload_local_asset', { - projectPath: automaticProjectPath, - fileName: 'fast_gdd.md', - mediaType: 'text/markdown', - bytes: Array.from(new TextEncoder().encode(gddContent)), - }); - }); - }); - it('keeps the home composer out of chat mode while automatic project creation is pending', async () => { let rejectAutomaticProject: ((error: Error) => void) | null = null; const automaticProject = new Promise((_resolve, reject) => { @@ -2054,11 +1953,6 @@ export function registerHomeProjectCreationTests() { expect(JSON.stringify(startCall?.[1] ?? {})).not.toContain( '本轮用户附件', ); - expect( - invoke.mock.calls.some( - ([command]) => command === 'start_planning_session_v2', - ), - ).toBe(false); expect(invoke).not.toHaveBeenCalledWith( 'chat_with_game_creator_direct_codex', expect.anything(), @@ -2163,11 +2057,6 @@ export function registerHomeProjectCreationTests() { expect(JSON.stringify(startCall?.[1] ?? {})).not.toContain( 'assets/uploads/reference.png', ); - expect( - invoke.mock.calls.some( - ([command]) => command === 'start_planning_session_v2', - ), - ).toBe(false); expect(invoke).not.toHaveBeenCalledWith( 'chat_with_game_creator_direct_codex', expect.anything(), @@ -2245,12 +2134,6 @@ export function registerHomeProjectCreationTests() { }), ); }); - expect( - invoke.mock.calls.some( - ([command]) => command === 'start_planning_session_v2', - ), - ).toBe(false); - await screen.findByText('首版角色规范图采用哪种美术方向?'); expect(screen.getByRole('button', { name: '像素' })).not.toBeNull(); });