完成M1D-2入口分流与阶段进度
游戏新项目默认进入立项策划并保留直接开建路径 项目总控页面挂载GDD审批卡与阶段进度 同步策划展示名称、定向测试与开发日志
This commit is contained in:
@@ -33,6 +33,7 @@ import {
|
|||||||
CONVERSATION_INITIAL_VISIBLE_COUNT,
|
CONVERSATION_INITIAL_VISIBLE_COUNT,
|
||||||
CONVERSATION_VISIBLE_STEP,
|
CONVERSATION_VISIBLE_STEP,
|
||||||
PROJECT_SUPERVISOR_AGENT_ID,
|
PROJECT_SUPERVISOR_AGENT_ID,
|
||||||
|
PROJECT_SUPERVISOR_PLAN_SOURCE,
|
||||||
seedManifest,
|
seedManifest,
|
||||||
} from './app/constants';
|
} from './app/constants';
|
||||||
import { useEscapeToClose } from './app/dialogs';
|
import { useEscapeToClose } from './app/dialogs';
|
||||||
@@ -6008,12 +6009,31 @@ export function App({
|
|||||||
if (!sessionId || localProjectPathRef.current !== nextProjectPath) {
|
if (!sessionId || localProjectPathRef.current !== nextProjectPath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const submissionRunProfile =
|
const runtimeAtSubmission = projectSupervisorRuntimeRef.current;
|
||||||
workspaceProjectKind === 'godot' ||
|
const planningEntry =
|
||||||
(supervisorChatOnly && !gameChatOnly)
|
!gameChatOnly &&
|
||||||
|
workspaceProjectKind === 'web' &&
|
||||||
|
runtimeAtSubmission?.source === PROJECT_SUPERVISOR_PLAN_SOURCE;
|
||||||
|
const submissionRunProfile = planningEntry
|
||||||
|
? 'standard'
|
||||||
|
: workspaceProjectKind === 'godot' ||
|
||||||
|
(supervisorChatOnly && !gameChatOnly)
|
||||||
? 'standard'
|
? 'standard'
|
||||||
: 'autonomous-game-build';
|
: 'autonomous-game-build';
|
||||||
const runtimeAtSubmission = projectSupervisorRuntimeRef.current;
|
const submissionSource = planningEntry
|
||||||
|
? PROJECT_SUPERVISOR_PLAN_SOURCE
|
||||||
|
: gameChatOnly
|
||||||
|
? 'project-supervisor-game-chat'
|
||||||
|
: 'project-supervisor-gui';
|
||||||
|
if (
|
||||||
|
planningEntry &&
|
||||||
|
runtimeAtSubmission &&
|
||||||
|
runtimeAtSubmission.source === PROJECT_SUPERVISOR_PLAN_SOURCE &&
|
||||||
|
!isAgentRuntimeTerminalState(runtimeAtSubmission)
|
||||||
|
) {
|
||||||
|
setProjectSupervisorRuntimeError('请先完成当前立项策划步骤');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const steerRuntime = gameChatOnly
|
const steerRuntime = gameChatOnly
|
||||||
? matchingAgentRuntimeForSteer(
|
? matchingAgentRuntimeForSteer(
|
||||||
[runtimeAtSubmission],
|
[runtimeAtSubmission],
|
||||||
@@ -6077,9 +6097,7 @@ export function App({
|
|||||||
prompt,
|
prompt,
|
||||||
runtime: runtimeAtSubmission,
|
runtime: runtimeAtSubmission,
|
||||||
runProfile: submissionRunProfile,
|
runProfile: submissionRunProfile,
|
||||||
source: gameChatOnly
|
source: submissionSource,
|
||||||
? 'project-supervisor-game-chat'
|
|
||||||
: 'project-supervisor-gui',
|
|
||||||
});
|
});
|
||||||
const runtimeResult = submission.runtimeResult;
|
const runtimeResult = submission.runtimeResult;
|
||||||
const acceptedRunId = submission.acceptedRunId.trim();
|
const acceptedRunId = submission.acceptedRunId.trim();
|
||||||
@@ -11324,6 +11342,11 @@ export function App({
|
|||||||
visibleMessages={visibleMessages}
|
visibleMessages={visibleMessages}
|
||||||
visibleProfessionalAgentCards={visibleProfessionalAgentCards}
|
visibleProfessionalAgentCards={visibleProfessionalAgentCards}
|
||||||
workspaceStatus={workspaceStatus}
|
workspaceStatus={workspaceStatus}
|
||||||
|
planGddState={planGddState}
|
||||||
|
planGddHydrateBusy={planGddHydrateBusy || planGddDecisionBusy}
|
||||||
|
planGddError={planGddError}
|
||||||
|
onPlanGddRefresh={() => void hydratePlanGddState()}
|
||||||
|
onPlanGddDecision={decidePlanGdd}
|
||||||
runtime={projectSupervisorRuntime}
|
runtime={projectSupervisorRuntime}
|
||||||
error={projectSupervisorRuntimeError}
|
error={projectSupervisorRuntimeError}
|
||||||
runtimeByAgentId={agentRuntimeById}
|
runtimeByAgentId={agentRuntimeById}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const CONVERSATION_INITIAL_VISIBLE_COUNT = 20;
|
|||||||
export const CONVERSATION_VISIBLE_STEP = 20;
|
export const CONVERSATION_VISIBLE_STEP = 20;
|
||||||
export const AGENT_CHAT_SCROLL_BOTTOM_THRESHOLD = 48;
|
export const AGENT_CHAT_SCROLL_BOTTOM_THRESHOLD = 48;
|
||||||
export const PROJECT_SUPERVISOR_AGENT_ID = 'project-supervisor';
|
export const PROJECT_SUPERVISOR_AGENT_ID = 'project-supervisor';
|
||||||
|
export const PROJECT_SUPERVISOR_PLAN_SOURCE = 'project-supervisor-plan';
|
||||||
export const launcherNotifications: Array<{
|
export const launcherNotifications: Array<{
|
||||||
label: string;
|
label: string;
|
||||||
detail: string;
|
detail: string;
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export type LauncherImportedAttachment = {
|
|||||||
|
|
||||||
export type LocalProjectKind = 'web' | 'godot';
|
export type LocalProjectKind = 'web' | 'godot';
|
||||||
|
|
||||||
|
export type ProjectStartMode = 'planning' | 'direct-build';
|
||||||
|
|
||||||
export type LauncherProjectContext = {
|
export type LauncherProjectContext = {
|
||||||
projectPath: string;
|
projectPath: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
@@ -76,6 +78,7 @@ export type PendingNonEmptyProject =
|
|||||||
kind: 'home-create';
|
kind: 'home-create';
|
||||||
projectPath: string;
|
projectPath: string;
|
||||||
mode: HomeAgentMode;
|
mode: HomeAgentMode;
|
||||||
|
startMode: ProjectStartMode;
|
||||||
prompt: string;
|
prompt: string;
|
||||||
attachments: HomeAttachmentDraft[];
|
attachments: HomeAttachmentDraft[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1537,6 +1537,9 @@ export function projectSupervisorCollaboratingAgentRuntimes(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function projectProfessionalAgentLabel(agentId: string) {
|
export function projectProfessionalAgentLabel(agentId: string) {
|
||||||
|
if (agentId === 'project-planning') {
|
||||||
|
return '立项策划 Agent';
|
||||||
|
}
|
||||||
if (agentId === 'design-foundation') {
|
if (agentId === 'design-foundation') {
|
||||||
return '玩法策划 Agent';
|
return '玩法策划 Agent';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ export function WorkspaceLauncherShell({
|
|||||||
setAgentResults: setActiveProjectAgentResults,
|
setAgentResults: setActiveProjectAgentResults,
|
||||||
resetLauncherHomeDraft,
|
resetLauncherHomeDraft,
|
||||||
createHomeDraft,
|
createHomeDraft,
|
||||||
|
createHomeDraftDirectBuild,
|
||||||
createHomeDraftAutomatically,
|
createHomeDraftAutomatically,
|
||||||
openProject,
|
openProject,
|
||||||
} = homeProject;
|
} = homeProject;
|
||||||
@@ -260,6 +261,7 @@ export function WorkspaceLauncherShell({
|
|||||||
homeAgentModeItems={homeAgentModeItems}
|
homeAgentModeItems={homeAgentModeItems}
|
||||||
recentProjectRows={recentProjectRows}
|
recentProjectRows={recentProjectRows}
|
||||||
onCreateDraft={createHomeDraft}
|
onCreateDraft={createHomeDraft}
|
||||||
|
onCreateDraftDirectBuild={createHomeDraftDirectBuild}
|
||||||
onCreateDraftAutomatically={createHomeDraftAutomatically}
|
onCreateDraftAutomatically={createHomeDraftAutomatically}
|
||||||
onProjectsOpen={() => setLauncherView('projects')}
|
onProjectsOpen={() => setLauncherView('projects')}
|
||||||
onProjectOpen={(path) => {
|
onProjectOpen={(path) => {
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import type {
|
|||||||
GameCreationAppManifest,
|
GameCreationAppManifest,
|
||||||
GameCreationAppPreviewState,
|
GameCreationAppPreviewState,
|
||||||
} from '../../../../../packages/shared/src/contracts/gameCreationApp';
|
} from '../../../../../packages/shared/src/contracts/gameCreationApp';
|
||||||
import { seedManifest } from '../../app/constants';
|
import {
|
||||||
|
PROJECT_SUPERVISOR_PLAN_SOURCE,
|
||||||
|
seedManifest,
|
||||||
|
} from '../../app/constants';
|
||||||
import { useEscapeToClose } from '../../app/dialogs';
|
import { useEscapeToClose } from '../../app/dialogs';
|
||||||
import { resolveTauriInvoke } from '../../app/tauri';
|
import { resolveTauriInvoke } from '../../app/tauri';
|
||||||
import type {
|
import type {
|
||||||
@@ -20,6 +23,7 @@ import type {
|
|||||||
LocalGameProjectRevisionStatus,
|
LocalGameProjectRevisionStatus,
|
||||||
LocalProjectDirectoryStatus,
|
LocalProjectDirectoryStatus,
|
||||||
PendingNonEmptyProject,
|
PendingNonEmptyProject,
|
||||||
|
ProjectStartMode,
|
||||||
TauriInvoke,
|
TauriInvoke,
|
||||||
UploadLocalAssetResult,
|
UploadLocalAssetResult,
|
||||||
} from '../../app/types';
|
} from '../../app/types';
|
||||||
@@ -168,6 +172,7 @@ export function useHomeProjectCreation({
|
|||||||
mode: HomeAgentMode,
|
mode: HomeAgentMode,
|
||||||
prompt: string,
|
prompt: string,
|
||||||
attachments: HomeAttachmentDraft[],
|
attachments: HomeAttachmentDraft[],
|
||||||
|
startMode: ProjectStartMode,
|
||||||
) {
|
) {
|
||||||
const importedAttachments = await importHomeAttachments(
|
const importedAttachments = await importHomeAttachments(
|
||||||
invoke,
|
invoke,
|
||||||
@@ -187,7 +192,10 @@ export function useHomeProjectCreation({
|
|||||||
sessionId,
|
sessionId,
|
||||||
prompt: buildHomeConversationContent(mode, prompt, attachments),
|
prompt: buildHomeConversationContent(mode, prompt, attachments),
|
||||||
runtime: null,
|
runtime: null,
|
||||||
runProfile: 'autonomous-game-build',
|
runProfile:
|
||||||
|
startMode === 'planning' ? 'standard' : 'autonomous-game-build',
|
||||||
|
source:
|
||||||
|
startMode === 'planning' ? PROJECT_SUPERVISOR_PLAN_SOURCE : undefined,
|
||||||
});
|
});
|
||||||
enterProjectDevelopment({
|
enterProjectDevelopment({
|
||||||
projectPath: result.projectPath,
|
projectPath: result.projectPath,
|
||||||
@@ -218,6 +226,7 @@ export function useHomeProjectCreation({
|
|||||||
mode: HomeAgentMode,
|
mode: HomeAgentMode,
|
||||||
prompt: string,
|
prompt: string,
|
||||||
attachments: HomeAttachmentDraft[],
|
attachments: HomeAttachmentDraft[],
|
||||||
|
startMode: ProjectStartMode,
|
||||||
skipNonEmptyCheck = false,
|
skipNonEmptyCheck = false,
|
||||||
) {
|
) {
|
||||||
const trimmedProjectPath = validateProjectPath(nextProjectPath);
|
const trimmedProjectPath = validateProjectPath(nextProjectPath);
|
||||||
@@ -241,6 +250,7 @@ export function useHomeProjectCreation({
|
|||||||
kind: 'home-create',
|
kind: 'home-create',
|
||||||
projectPath: trimmedProjectPath,
|
projectPath: trimmedProjectPath,
|
||||||
mode,
|
mode,
|
||||||
|
startMode,
|
||||||
prompt,
|
prompt,
|
||||||
attachments,
|
attachments,
|
||||||
});
|
});
|
||||||
@@ -263,6 +273,7 @@ export function useHomeProjectCreation({
|
|||||||
mode,
|
mode,
|
||||||
prompt,
|
prompt,
|
||||||
attachments,
|
attachments,
|
||||||
|
startMode,
|
||||||
);
|
);
|
||||||
setStatus('已创建项目并交给项目总控 Agent');
|
setStatus('已创建项目并交给项目总控 Agent');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -285,6 +296,7 @@ export function useHomeProjectCreation({
|
|||||||
mode: HomeAgentMode,
|
mode: HomeAgentMode,
|
||||||
prompt: string,
|
prompt: string,
|
||||||
attachments: HomeAttachmentDraft[],
|
attachments: HomeAttachmentDraft[],
|
||||||
|
startMode: ProjectStartMode,
|
||||||
) {
|
) {
|
||||||
const invoke = resolveTauriInvoke();
|
const invoke = resolveTauriInvoke();
|
||||||
if (!invoke) {
|
if (!invoke) {
|
||||||
@@ -292,7 +304,14 @@ export function useHomeProjectCreation({
|
|||||||
}
|
}
|
||||||
setStatus('正在启动项目总控 Agent');
|
setStatus('正在启动项目总控 Agent');
|
||||||
try {
|
try {
|
||||||
await enterCreatedHomeProject(invoke, result, mode, prompt, attachments);
|
await enterCreatedHomeProject(
|
||||||
|
invoke,
|
||||||
|
result,
|
||||||
|
mode,
|
||||||
|
prompt,
|
||||||
|
attachments,
|
||||||
|
startMode,
|
||||||
|
);
|
||||||
setStatus('已自动创建工作区并开始工作');
|
setStatus('已自动创建工作区并开始工作');
|
||||||
return '已自动创建工作区并开始工作';
|
return '已自动创建工作区并开始工作';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -476,6 +495,7 @@ export function useHomeProjectCreation({
|
|||||||
pendingProject.mode,
|
pendingProject.mode,
|
||||||
pendingProject.prompt,
|
pendingProject.prompt,
|
||||||
pendingProject.attachments,
|
pendingProject.attachments,
|
||||||
|
pendingProject.startMode,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -513,6 +533,28 @@ export function useHomeProjectCreation({
|
|||||||
draft.mode,
|
draft.mode,
|
||||||
draft.prompt,
|
draft.prompt,
|
||||||
draft.attachments,
|
draft.attachments,
|
||||||
|
draft.mode === 'game' ? 'planning' : 'direct-build',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createHomeDraftDirectBuild(draft: HomeDraft) {
|
||||||
|
const invoke = resolveTauriInvoke();
|
||||||
|
if (!invoke) {
|
||||||
|
throw new Error('需要在 Tauri App 内运行');
|
||||||
|
}
|
||||||
|
const selectedPath = await invoke<string | null>(
|
||||||
|
'pick_local_project_directory',
|
||||||
|
projectPath.trim() ? { initialPath: projectPath.trim() } : undefined,
|
||||||
|
);
|
||||||
|
if (!selectedPath) {
|
||||||
|
return '已取消';
|
||||||
|
}
|
||||||
|
return createHomeProjectFromDirectory(
|
||||||
|
selectedPath,
|
||||||
|
draft.mode,
|
||||||
|
draft.prompt,
|
||||||
|
draft.attachments,
|
||||||
|
'direct-build',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,6 +572,7 @@ export function useHomeProjectCreation({
|
|||||||
draft.mode,
|
draft.mode,
|
||||||
draft.prompt,
|
draft.prompt,
|
||||||
draft.attachments,
|
draft.attachments,
|
||||||
|
draft.mode === 'game' ? 'planning' : 'direct-build',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,6 +662,7 @@ export function useHomeProjectCreation({
|
|||||||
pendingNonEmptyProject,
|
pendingNonEmptyProject,
|
||||||
resetLauncherHomeDraft,
|
resetLauncherHomeDraft,
|
||||||
createHomeDraft,
|
createHomeDraft,
|
||||||
|
createHomeDraftDirectBuild,
|
||||||
createHomeDraftAutomatically,
|
createHomeDraftAutomatically,
|
||||||
openProject,
|
openProject,
|
||||||
pickAndOpenProject,
|
pickAndOpenProject,
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export const commonProjectInternalReadDrafts = [
|
|||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const taskGroupLabels: Record<GameCreationAppAgentGroup, string> = {
|
export const taskGroupLabels: Record<GameCreationAppAgentGroup, string> = {
|
||||||
design: '策划组',
|
design: '设计实现组',
|
||||||
art: '美术组',
|
art: '美术组',
|
||||||
code: '程序组',
|
code: '程序组',
|
||||||
balance: '数值组',
|
balance: '数值组',
|
||||||
|
|||||||
@@ -25,6 +25,39 @@ const stateLabels: Record<PlanGddStateViewV1['state'], string> = {
|
|||||||
rejected: '已退回',
|
rejected: '已退回',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function PlanGddStageProgress({
|
||||||
|
state,
|
||||||
|
active = false,
|
||||||
|
}: {
|
||||||
|
state: PlanGddStateViewV1 | null;
|
||||||
|
active?: boolean;
|
||||||
|
}) {
|
||||||
|
if (!state || (!active && state.state === 'not_started')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const latestVersion =
|
||||||
|
state.displayGdd?.version ??
|
||||||
|
state.versions[state.versions.length - 1]?.gddRef.version ??
|
||||||
|
null;
|
||||||
|
const clarificationRound = state.session?.clarificationRound ?? 0;
|
||||||
|
return (
|
||||||
|
<section className="plan-gdd-stage-progress" aria-label="立项策划阶段进度">
|
||||||
|
<div className="plan-gdd-stage-progress__header">
|
||||||
|
<strong>立项策划</strong>
|
||||||
|
<span>{stateLabels[state.state]}</span>
|
||||||
|
</div>
|
||||||
|
<div className="plan-gdd-stage-progress__meta">
|
||||||
|
<span>{`轮次 ${clarificationRound}/3`}</span>
|
||||||
|
<span>
|
||||||
|
{latestVersion === null
|
||||||
|
? '当前版本:草稿'
|
||||||
|
: `当前版本:v${latestVersion}`}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const decisionStateLabels = {
|
const decisionStateLabels = {
|
||||||
confirmed: '已确认',
|
confirmed: '已确认',
|
||||||
default_pending: '待确认默认项',
|
default_pending: '待确认默认项',
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import type {
|
|||||||
AgentStatusCard,
|
AgentStatusCard,
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
PendingUiConfirmation,
|
PendingUiConfirmation,
|
||||||
|
PlanGddDecisionAction,
|
||||||
|
PlanGddStateViewV1,
|
||||||
} from '../../app/types';
|
} from '../../app/types';
|
||||||
import {
|
import {
|
||||||
projectProfessionalAgentLabel,
|
projectProfessionalAgentLabel,
|
||||||
@@ -21,6 +23,7 @@ import {
|
|||||||
} from '../agent-runtime';
|
} from '../agent-runtime';
|
||||||
import { formatAgentCardRuntimeStatus } from '../project-summary/agentPresentation';
|
import { formatAgentCardRuntimeStatus } from '../project-summary/agentPresentation';
|
||||||
import { taskStatusLabels } from '../project-summary/projectSummary';
|
import { taskStatusLabels } from '../project-summary/projectSummary';
|
||||||
|
import { GddApprovalCard, PlanGddStageProgress } from './GddApprovalCard';
|
||||||
|
|
||||||
type RuntimePanelProps = ComponentProps<typeof ProjectSupervisorRuntimePanel>;
|
type RuntimePanelProps = ComponentProps<typeof ProjectSupervisorRuntimePanel>;
|
||||||
|
|
||||||
@@ -39,6 +42,14 @@ type ProjectSupervisorViewProps = RuntimePanelProps & {
|
|||||||
visibleMessages: ChatMessage[];
|
visibleMessages: ChatMessage[];
|
||||||
visibleProfessionalAgentCards: AgentStatusCard[];
|
visibleProfessionalAgentCards: AgentStatusCard[];
|
||||||
workspaceStatus: string;
|
workspaceStatus: string;
|
||||||
|
planGddState: PlanGddStateViewV1 | null;
|
||||||
|
planGddHydrateBusy: boolean;
|
||||||
|
planGddError: string | null;
|
||||||
|
onPlanGddRefresh: () => void;
|
||||||
|
onPlanGddDecision: (
|
||||||
|
action: PlanGddDecisionAction,
|
||||||
|
comment: string | null,
|
||||||
|
) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ProjectSupervisorView({
|
export function ProjectSupervisorView({
|
||||||
@@ -56,11 +67,29 @@ export function ProjectSupervisorView({
|
|||||||
visibleMessages,
|
visibleMessages,
|
||||||
visibleProfessionalAgentCards,
|
visibleProfessionalAgentCards,
|
||||||
workspaceStatus,
|
workspaceStatus,
|
||||||
|
planGddState,
|
||||||
|
planGddHydrateBusy,
|
||||||
|
planGddError,
|
||||||
|
onPlanGddRefresh,
|
||||||
|
onPlanGddDecision,
|
||||||
...runtimePanelProps
|
...runtimePanelProps
|
||||||
}: ProjectSupervisorViewProps) {
|
}: ProjectSupervisorViewProps) {
|
||||||
return (
|
return (
|
||||||
<section className="project-supervisor-surface" aria-label="项目总控对话">
|
<section className="project-supervisor-surface" aria-label="项目总控对话">
|
||||||
<div className="project-supervisor-conversation">
|
<div className="project-supervisor-conversation">
|
||||||
|
<PlanGddStageProgress
|
||||||
|
state={planGddState}
|
||||||
|
active={
|
||||||
|
runtimePanelProps.runtime?.source === 'project-supervisor-plan'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<GddApprovalCard
|
||||||
|
state={planGddState}
|
||||||
|
busy={planGddHydrateBusy}
|
||||||
|
error={planGddError}
|
||||||
|
onRefresh={onPlanGddRefresh}
|
||||||
|
onDecision={onPlanGddDecision}
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
className="message-list project-supervisor-message-list"
|
className="message-list project-supervisor-message-list"
|
||||||
aria-label="项目总控消息"
|
aria-label="项目总控消息"
|
||||||
|
|||||||
+7
-1
@@ -47,7 +47,7 @@ import {
|
|||||||
taskGroupLabels,
|
taskGroupLabels,
|
||||||
taskStatusLabels,
|
taskStatusLabels,
|
||||||
} from '../project-summary/projectSummary';
|
} from '../project-summary/projectSummary';
|
||||||
import { GddApprovalCard } from './GddApprovalCard';
|
import { GddApprovalCard, PlanGddStageProgress } from './GddApprovalCard';
|
||||||
import {
|
import {
|
||||||
pendingCommandDetail,
|
pendingCommandDetail,
|
||||||
pendingCommandTitle,
|
pendingCommandTitle,
|
||||||
@@ -363,6 +363,12 @@ export function ProjectWorkspaceChatPane({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<PlanGddStageProgress
|
||||||
|
state={planGddState}
|
||||||
|
active={
|
||||||
|
projectSupervisorRuntime?.source === 'project-supervisor-plan'
|
||||||
|
}
|
||||||
|
/>
|
||||||
<GddApprovalCard
|
<GddApprovalCard
|
||||||
state={planGddState}
|
state={planGddState}
|
||||||
busy={planGddHydrateBusy}
|
busy={planGddHydrateBusy}
|
||||||
|
|||||||
@@ -3272,6 +3272,59 @@ textarea {
|
|||||||
background: #f8fbff;
|
background: #f8fbff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plan-gdd-stage-progress {
|
||||||
|
display: grid;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #dbe4f1;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
color: #526173;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-gdd-stage-progress__header,
|
||||||
|
.plan-gdd-stage-progress__meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-gdd-stage-progress__header strong {
|
||||||
|
color: #27364a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-gdd-stage-progress__header span {
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: #eef6ff;
|
||||||
|
color: #1f6feb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-creation-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-direct-build-button {
|
||||||
|
min-height: 28px;
|
||||||
|
padding: 0 9px;
|
||||||
|
border: 1px solid var(--platform-surface-border);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: var(--platform-button-secondary-fill);
|
||||||
|
color: var(--platform-button-secondary-text);
|
||||||
|
font-size: 11px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-direct-build-button:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
|
||||||
.gdd-approval-card__header {
|
.gdd-approval-card__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ type HomeViewProps = {
|
|||||||
homeAgentModeItems: readonly HomeAgentModeItem[];
|
homeAgentModeItems: readonly HomeAgentModeItem[];
|
||||||
recentProjectRows: readonly HomeProjectRow[];
|
recentProjectRows: readonly HomeProjectRow[];
|
||||||
onCreateDraft: (draft: HomeDraft) => Promise<string>;
|
onCreateDraft: (draft: HomeDraft) => Promise<string>;
|
||||||
|
onCreateDraftDirectBuild: (draft: HomeDraft) => Promise<string>;
|
||||||
onCreateDraftAutomatically: (draft: HomeDraft) => Promise<string>;
|
onCreateDraftAutomatically: (draft: HomeDraft) => Promise<string>;
|
||||||
onProjectsOpen: () => void;
|
onProjectsOpen: () => void;
|
||||||
onProjectOpen: (path: string) => void;
|
onProjectOpen: (path: string) => void;
|
||||||
@@ -60,6 +61,7 @@ export default function HomeView({
|
|||||||
homeAgentModeItems,
|
homeAgentModeItems,
|
||||||
recentProjectRows,
|
recentProjectRows,
|
||||||
onCreateDraft,
|
onCreateDraft,
|
||||||
|
onCreateDraftDirectBuild,
|
||||||
onCreateDraftAutomatically,
|
onCreateDraftAutomatically,
|
||||||
onProjectsOpen,
|
onProjectsOpen,
|
||||||
onProjectOpen,
|
onProjectOpen,
|
||||||
@@ -183,14 +185,33 @@ export default function HomeView({
|
|||||||
>
|
>
|
||||||
<div className="grid grid-cols-[1fr_auto] items-center gap-2.5 text-[12px] text-(--platform-text-soft)">
|
<div className="grid grid-cols-[1fr_auto] items-center gap-2.5 text-[12px] text-(--platform-text-soft)">
|
||||||
<UploadButton />
|
<UploadButton />
|
||||||
<button
|
<div className="home-creation-actions">
|
||||||
className="grid size-6 cursor-pointer place-items-center rounded-full border-0 bg-(image:--platform-button-primary-fill) p-0 text-(--platform-button-primary-text) shadow-(--platform-profile-action-shadow) disabled:cursor-not-allowed disabled:opacity-55"
|
{homeAgentMode === 'game' ? (
|
||||||
type="submit"
|
<button
|
||||||
aria-label="开启创作"
|
className="home-direct-build-button"
|
||||||
disabled={homeCreationBusy}
|
type="button"
|
||||||
>
|
disabled={homeCreationBusy}
|
||||||
<Plus size={16} aria-hidden="true" />
|
onClick={() =>
|
||||||
</button>
|
void createFromHome(
|
||||||
|
onCreateDraftDirectBuild,
|
||||||
|
'正在创建工作区',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
直接开建
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
<button
|
||||||
|
className="grid size-6 cursor-pointer place-items-center rounded-full border-0 bg-(image:--platform-button-primary-fill) p-0 text-(--platform-button-primary-text) shadow-(--platform-profile-action-shadow) disabled:cursor-not-allowed disabled:opacity-55"
|
||||||
|
type="submit"
|
||||||
|
aria-label={
|
||||||
|
homeAgentMode === 'game' ? '进入立项策划' : '开启创作'
|
||||||
|
}
|
||||||
|
disabled={homeCreationBusy}
|
||||||
|
>
|
||||||
|
<Plus size={16} aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</RichInputArea>
|
</RichInputArea>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, expect, test, vi } from 'vitest';
|
import { describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
import { createGameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp';
|
import { createGameCreationAppManifest } from '../../../packages/shared/src/contracts/gameCreationApp';
|
||||||
|
import { PROJECT_SUPERVISOR_PLAN_SOURCE } from '../src/app/constants';
|
||||||
import type {
|
import type {
|
||||||
AgentRuntimeEventRecord,
|
AgentRuntimeEventRecord,
|
||||||
AgentRuntimeResponseStream,
|
AgentRuntimeResponseStream,
|
||||||
@@ -618,6 +619,51 @@ describe('Game Chat stream identity and source', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('planning entry forwards the exact standard profile and trusted plan source', async () => {
|
||||||
|
const runtimeResult = {
|
||||||
|
state: {
|
||||||
|
schemaVersion: 'game-creator-agent-runtime.v1',
|
||||||
|
agentId: 'project-supervisor',
|
||||||
|
taskId: 'project-supervisor',
|
||||||
|
sessionId: 'session-plan-entry',
|
||||||
|
runId: 'plan-run',
|
||||||
|
source: PROJECT_SUPERVISOR_PLAN_SOURCE,
|
||||||
|
runProfile: 'standard' as const,
|
||||||
|
status: 'running',
|
||||||
|
phase: 'planning',
|
||||||
|
currentTask: '整理游戏立项需求',
|
||||||
|
currentAction: '',
|
||||||
|
plan: [],
|
||||||
|
observations: [],
|
||||||
|
allowedTools: [],
|
||||||
|
lastResponse: null,
|
||||||
|
error: null,
|
||||||
|
updatedAt: 1,
|
||||||
|
},
|
||||||
|
sessionPath: 'session.json',
|
||||||
|
eventPath: 'events.jsonl',
|
||||||
|
} satisfies AgentRuntimeResult;
|
||||||
|
const invoke = vi.fn(async () => runtimeResult);
|
||||||
|
|
||||||
|
await submitProjectSupervisorRuntimeTask({
|
||||||
|
invoke,
|
||||||
|
projectPath: '/tmp/plan-entry',
|
||||||
|
sessionId: 'session-plan-entry',
|
||||||
|
prompt: '做一个双摇杆动作游戏',
|
||||||
|
runtime: null,
|
||||||
|
runProfile: 'standard',
|
||||||
|
source: PROJECT_SUPERVISOR_PLAN_SOURCE,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(invoke).toHaveBeenCalledWith(
|
||||||
|
'start_game_creator_supervisor_runtime_task',
|
||||||
|
expect.objectContaining({
|
||||||
|
runProfile: 'standard',
|
||||||
|
source: PROJECT_SUPERVISOR_PLAN_SOURCE,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('game-chat hydration keeps identical text from a different runtime response identity', () => {
|
test('game-chat hydration keeps identical text from a different runtime response identity', () => {
|
||||||
const history = [
|
const history = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# 决策记录
|
# 决策记录
|
||||||
|
|
||||||
|
## 2026-08-18 M1D-2 隔离工作树实现:入口分流与阶段进度
|
||||||
|
|
||||||
|
- **隔离范围**:在 `codex/genarrative-isolated`、基线 `5b11a0530` 上开工;只接入口分流、阶段进度和实际项目总控页面的现有审批卡挂载,不接 M2 `approvedGddRef` 构建绑定、完整构建按钮或 M1E 端到端故障注入。
|
||||||
|
- **入口合同**:游戏新项目默认以 `standard + project-supervisor-plan` 启动;“直接开建”显式走既有 `autonomous-game-build` 路径。做素材/做方案入口保持原有自动构建行为;空目录确认会携带同一 start mode,不因二次确认改变路径。项目打开/项目页新建不注入 start mode,保持老项目行为。
|
||||||
|
- **页面接线**:`ProjectSupervisorView` 现在复用 M1D-1 的 hydrate、GDD 审批卡和阶段进度;阶段进度只消费 `plan-gdd-state-view.v1`,显示 `轮次 x/3`、当前版本与状态徽章。`project-planning` 显示为“立项策划 Agent”,设计组展示名改为“设计实现组”。
|
||||||
|
- **Runtime 路由**:项目总控聊天提交在规划入口或已读到 `project-supervisor-plan` 时继续使用 `standard + project-supervisor-plan`;规划 Run 尚未终态时不另起通用聊天 Run,要求先完成当前策划步骤。直接开建及非规划入口保留原提交 profile/source。
|
||||||
|
- **自审边界与验证**:只接受有完整触发链路的问题;本包不改变 Runtime source 门禁、审批命令、构建准入或老项目 direct-build 语义。改动文件 ESLint、Shell TypeScript 两套 typecheck、`agentRuntimeModel.test.ts`(29 passed)、编码检查与 `git diff --check` 通过;appSurface UI suite 受仓库现有缺失 Tauri plugin 依赖阻断,未把该基线失败归因于本包。自审未发现测试失败或修复边界明确的 M1D-2 之外缺陷;M2 approved-GDD 构建绑定与 M1E 跨层故障注入保留。
|
||||||
|
|
||||||
## 2026-08-18 M1D-1 隔离工作树实现:hydrate/read model 与 GDD 审批卡
|
## 2026-08-18 M1D-1 隔离工作树实现:hydrate/read model 与 GDD 审批卡
|
||||||
|
|
||||||
- **隔离基线与范围**:在 `codex/genarrative-isolated`、基线 `14c00017c` 上开工;只实现 M1D-1 的前端 hydrate/read model 与 GDD 审批卡,不接 M1D-2 入口分流、完整构建按钮、构建准入或 M1E 下游链路。
|
- **隔离基线与范围**:在 `codex/genarrative-isolated`、基线 `14c00017c` 上开工;只实现 M1D-1 的前端 hydrate/read model 与 GDD 审批卡,不接 M1D-2 入口分流、完整构建按钮、构建准入或 M1E 下游链路。
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
- 日期:2026-08-10
|
- 日期:2026-08-10
|
||||||
- 状态:2026-08-12 **M0 代码工作包全部完成**(`M0A-2`、`M0B-1`、`M0B-2` 已合入 M0 集成分支并通过各自门禁,见第 23.4 节);同日 **D6 作废、拓扑改变**,`M0A-1` 交付的文档基线随之失效,需以工作包 `M0A-3` 修订,**修订完成前 M0 不计完整完成**(见第 1.1 节)。2026-08-13 **D9 二次作废、D10 作废,由 D11 取代**:立项策划节点改为 Project Supervisor 通过 `agent.delegate` 发起的静态委派子 Agent,问询复用 PR #165 中转链路(见第 1.1 节「D11 新拓扑」);D11 依赖 WP1(静态委派澄清轮次与返工深度拆分)为强制前置,**该前置已于 2026-08-13 落地并合入**(`WP1` 生产代码 + `WP2` 回归,完成状态与门禁见第 23.5 节),澄清轮次上限现为 3(game-chat source 仍为 1)。随后 `M1A-1`、`M1A-2`、`M1A-3`、`M1A-4` 已分别落地:`M1A-2` 仅收口两层工具面、`project-planning` role brief 注入和 fail-closed 拒绝边界,`M1A-4` 收窄 plan 根 run 的子 Agent 创建面。**2026-08-14 `M1B-1` 已通过门禁并合入本分支**:已落地 `.agent/planning` storage module、strict schema/typed 指纹/canonical parser、GDD 版本链、session 原子恢复、Runtime 写入身份及只挡写门禁;golden vector 与 11 个定向 storage 测试通过,writer/index/recovery 门禁已完成。**2026-08-15 `M1B-2` 工作包已通过本包门禁并以 `27c3eb847` 合入本分支**:已落地 `plan.submit_gdd`、exact planning Provider binding/structured injection、专用提交点与崩溃恢复;本包不包含 `gdd-approval` planning pending、审批等待、receipt、审批命令或 UI。**2026-08-14 `M1C-0` 已合回本分支**:仅新增用户修订状态及 lineage 分类,不包含审批写入方。**2026-08-15 `M1C-0b` 已通过定向门禁并完成**:只改静态委派 durable status 的前向兼容读路径,未知字符串显式保留为 `Unknown(raw)` 并最大化阻塞;不含审批写入方。`M1C-1` 与 `M1C-2a` 已提供审批核心、固定 Goal Contract、完整分页 `file.read` evidence、claim 后三态 acceptance gate、审批 pending 恢复及 completion/finalization 门。**`M1C-2b` 已完成本包实现并通过门禁,现已快进合回 `feat/five_min_design`**:planning 澄清中转、确定性 continuation/session 投影、审批后用户修订谱系、Provider 活跃时间预算与末次 submit usage fold 已实现,11 条 `planning_clarification_*` 回归及关联 Rust 门禁通过。审批 UI、hydrate、构建准入与下游完整构建仍后置,M1 整体不可交付(见第 23.6、23.8 节)。
|
- 状态:2026-08-12 **M0 代码工作包全部完成**(`M0A-2`、`M0B-1`、`M0B-2` 已合入 M0 集成分支并通过各自门禁,见第 23.4 节);同日 **D6 作废、拓扑改变**,`M0A-1` 交付的文档基线随之失效,需以工作包 `M0A-3` 修订,**修订完成前 M0 不计完整完成**(见第 1.1 节)。2026-08-13 **D9 二次作废、D10 作废,由 D11 取代**:立项策划节点改为 Project Supervisor 通过 `agent.delegate` 发起的静态委派子 Agent,问询复用 PR #165 中转链路(见第 1.1 节「D11 新拓扑」);D11 依赖 WP1(静态委派澄清轮次与返工深度拆分)为强制前置,**该前置已于 2026-08-13 落地并合入**(`WP1` 生产代码 + `WP2` 回归,完成状态与门禁见第 23.5 节),澄清轮次上限现为 3(game-chat source 仍为 1)。随后 `M1A-1`、`M1A-2`、`M1A-3`、`M1A-4` 已分别落地:`M1A-2` 仅收口两层工具面、`project-planning` role brief 注入和 fail-closed 拒绝边界,`M1A-4` 收窄 plan 根 run 的子 Agent 创建面。**2026-08-14 `M1B-1` 已通过门禁并合入本分支**:已落地 `.agent/planning` storage module、strict schema/typed 指纹/canonical parser、GDD 版本链、session 原子恢复、Runtime 写入身份及只挡写门禁;golden vector 与 11 个定向 storage 测试通过,writer/index/recovery 门禁已完成。**2026-08-15 `M1B-2` 工作包已通过本包门禁并以 `27c3eb847` 合入本分支**:已落地 `plan.submit_gdd`、exact planning Provider binding/structured injection、专用提交点与崩溃恢复;本包不包含 `gdd-approval` planning pending、审批等待、receipt、审批命令或 UI。**2026-08-14 `M1C-0` 已合回本分支**:仅新增用户修订状态及 lineage 分类,不包含审批写入方。**2026-08-15 `M1C-0b` 已通过定向门禁并完成**:只改静态委派 durable status 的前向兼容读路径,未知字符串显式保留为 `Unknown(raw)` 并最大化阻塞;不含审批写入方。`M1C-1` 与 `M1C-2a` 已提供审批核心、固定 Goal Contract、完整分页 `file.read` evidence、claim 后三态 acceptance gate、审批 pending 恢复及 completion/finalization 门。**`M1C-2b` 已完成本包实现并通过门禁,现已快进合回 `feat/five_min_design`**:planning 澄清中转、确定性 continuation/session 投影、审批后用户修订谱系、Provider 活跃时间预算与末次 submit usage fold 已实现,11 条 `planning_clarification_*` 回归及关联 Rust 门禁通过。审批 UI、hydrate、构建准入与下游完整构建仍后置,M1 整体不可交付(见第 23.6、23.8 节)。
|
||||||
- 适用范围:AI 游戏创作独立 App、Project Supervisor、Agent Runtime、本地项目策划 sidecar 与后续完整构建准入
|
- 适用范围:AI 游戏创作独立 App、Project Supervisor、Agent Runtime、本地项目策划 sidecar 与后续完整构建准入
|
||||||
- 当前实现边界:本文件是后续详细设计与实现的仓库内阶段基线;M0 工作包冻结 Fast GDD 合同并修复现有 owner 验证、game-chat retry 与前端投影边界,`M1A-1`~`M1A-4` 已提供 plan source、两层工具面、角色 brief 与子 Agent 创建面收窄的 Runtime 基础,`M1C-0` 已提供用户修订 lineage 分类,已合入的 `M1B-1` 提供 storage 基础与写入隔离;`M1B-2` 已提供提交点与恢复,`M1C-0b` 已补齐静态委派未知 durable status 的前向兼容读路径,`M1C-1` 已提供 receipt/审批核心、投影恢复和 plan 根完成门,`M1C-2a` 已补齐固定 Goal Contract、验收图证据与生产 acceptance gate。`M1C-2b` 已实现 planning 澄清中转、三轮确定性 session/continuation 投影、审批后修订谱系和 Provider 活跃时间预算,并已合回 `feat/five_min_design`;审批 UI、hydrate、构建绑定和正式入口仍不可用
|
- 当前实现边界:本文件是后续详细设计与实现的仓库内阶段基线;M0 工作包冻结 Fast GDD 合同并修复现有 owner 验证、game-chat retry 与前端投影边界,`M1A-1`~`M1A-4` 已提供 plan source、两层工具面、角色 brief 与子 Agent 创建面收窄的 Runtime 基础,`M1C-0` 已提供用户修订 lineage 分类,已合入的 `M1B-1` 提供 storage 基础与写入隔离;`M1B-2` 已提供提交点与恢复,`M1C-0b` 已补齐静态委派未知 durable status 的前向兼容读路径,`M1C-1` 已提供 receipt/审批核心、投影恢复和 plan 根完成门,`M1C-2a` 已补齐固定 Goal Contract、验收图证据与生产 acceptance gate。`M1C-2b` 已实现 planning 澄清中转、三轮确定性 session/continuation 投影、审批后修订谱系和 Provider 活跃时间预算,并已合回 `feat/five_min_design`;`M1D-1` 已提供 hydrate/read model 与审批卡,`M1D-2` 已接入新项目入口分流、阶段进度和实际项目总控页面挂载;approved GDD 构建绑定与完整下游仍留给 M2/M1E
|
||||||
|
|
||||||
## 1. 背景与目标
|
## 1. 背景与目标
|
||||||
|
|
||||||
@@ -483,7 +483,7 @@ exact plan source 的 `user.input_request` 仍是四个 action tool 之一,不
|
|||||||
|
|
||||||
**轮次计数。** 本轮是第几轮由委派链上的 `clarification_round` 派生值决定(沿 `repair_of_delegation_id` 上溯推断,语义见第 23.5 节),上限 3;session 不再自累加 `roundsUsed`。达到上限后 Runtime 在下一轮子 run 的上下文里注入「必须出稿」,若子 Agent 仍输出信封则拒绝该信封并要求改为 `plan.submit_gdd`。
|
**轮次计数。** 本轮是第几轮由委派链上的 `clarification_round` 派生值决定(沿 `repair_of_delegation_id` 上溯推断,语义见第 23.5 节),上限 3;session 不再自累加 `roundsUsed`。达到上限后 Runtime 在下一轮子 run 的上下文里注入「必须出稿」,若子 Agent 仍输出信封则拒绝该信封并要求改为 `plan.submit_gdd`。
|
||||||
|
|
||||||
当前实现边界:第四轮违规信封已能在建立 Supervisor pending 前失败关闭,但失败后目前进入 reconciliation,尚未形成“同一子 run 被强制改为 `plan.submit_gdd`”的自动闭环。该差距不影响三轮、重放、身份、锁序与预算门禁,但涉及更宽的 Provider/终态状态机,留待后续单列,不将 M1C-2b 的“第四轮不建 pending”回归夸大为已完成强制 submit。
|
当前实现边界:第四轮澄清委派在 `agent.delegate` 工具边界按持久化血缘上限被硬拒,并以普通 failed observation 返回 Supervisor;正常路径不进入 reconciliation,Supervisor 可据此改走 `plan.submit_gdd`。`planning_coordinator` 的超三轮 reconciliation 分支仅用于损坏或篡改血缘的纵深防御;本包不把它扩展成自动 submit 状态机。
|
||||||
|
|
||||||
**Provider batch 规则。** exact planning 子 Agent 的普通 tool-plan 只要产生 action,即使仅一项也必须强制 durable 写 v4 batch,不走现役「少于两项则 NotNeeded」的优化,`plan.submit_gdd` 因此是唯一 v4 member。Supervisor 侧的澄清 `user.input_request` 由 Runtime parent-wake 从 delivery 直接投影,不是 Supervisor Provider action、也不创建 v4 batch;该 pending 的 exactly-once 由 delivery/request/answer 指纹、pending identity 与 planning session revision 共同保证。exact planning 的 `final-reply`、`context-compaction`、`final-reply-context-compaction` 均无 action batch但仍写 v3 lifecycle/binding,planning idle compaction 不支持。非 plan source 的 input wire、数量和校验保持现状,任何额外 plan metadata 都因 unknown field 失败。
|
**Provider batch 规则。** exact planning 子 Agent 的普通 tool-plan 只要产生 action,即使仅一项也必须强制 durable 写 v4 batch,不走现役「少于两项则 NotNeeded」的优化,`plan.submit_gdd` 因此是唯一 v4 member。Supervisor 侧的澄清 `user.input_request` 由 Runtime parent-wake 从 delivery 直接投影,不是 Supervisor Provider action、也不创建 v4 batch;该 pending 的 exactly-once 由 delivery/request/answer 指纹、pending identity 与 planning session revision 共同保证。exact planning 的 `final-reply`、`context-compaction`、`final-reply-context-compaction` 均无 action batch但仍写 v3 lifecycle/binding,planning idle compaction 不支持。非 plan source 的 input wire、数量和校验保持现状,任何额外 plan metadata 都因 unknown field 失败。
|
||||||
|
|
||||||
@@ -2023,8 +2023,8 @@ M0 完成不表示完整策划闭环已经上线。`M1A-1`~`M1A-4`、`M1B-1`
|
|||||||
| `M1C-2a` | Goal Contract 接线:turn 1 冻结、固定验收图、审批前置门取证 | `M1C-1`、`M1A-3` | **当前隔离 worktree 已完成并通过本包门禁,尚未合回**:turn 1 的 request-scoped schema 与格式修复都只允许一个固定 `agent.goal_contract`;按项目变化的四项之外,`preferences=[]`、唯一验收节点及证据工具均冻结。Fast GDD evidence 只接受当前 Supervisor 根 run 对 `game/fast_gdd.md` 从第 1 行到 EOF 的同 hash 完整分页;无/旧证据先继续读取,显式 failed 才给原 delivery 的 `repairOfDelegationId`,passed 且 delivery 已认领才建 pending。pending/recovery/completion/finalization 均按同 identity 幂等,审批后 Markdown 改写不损坏 Graph。格式、Provider 强判据、M1C-2a、Acceptance Graph、planning submit/approval、finalization、all-targets、编码与 diff 门禁均通过;扩展 autonomous completion 整组的无关 game-chat 并行超时及精确复跑结果见 decision-log 同日条,不改该路径。不包含 `M1C-2b`、UI 或构建准入 |
|
| `M1C-2a` | Goal Contract 接线:turn 1 冻结、固定验收图、审批前置门取证 | `M1C-1`、`M1A-3` | **当前隔离 worktree 已完成并通过本包门禁,尚未合回**:turn 1 的 request-scoped schema 与格式修复都只允许一个固定 `agent.goal_contract`;按项目变化的四项之外,`preferences=[]`、唯一验收节点及证据工具均冻结。Fast GDD evidence 只接受当前 Supervisor 根 run 对 `game/fast_gdd.md` 从第 1 行到 EOF 的同 hash 完整分页;无/旧证据先继续读取,显式 failed 才给原 delivery 的 `repairOfDelegationId`,passed 且 delivery 已认领才建 pending。pending/recovery/completion/finalization 均按同 identity 幂等,审批后 Markdown 改写不损坏 Graph。格式、Provider 强判据、M1C-2a、Acceptance Graph、planning submit/approval、finalization、all-targets、编码与 diff 门禁均通过;扩展 autonomous completion 整组的无关 game-chat 并行超时及精确复跑结果见 decision-log 同日条,不改该路径。不包含 `M1C-2b`、UI 或构建准入 |
|
||||||
| `M1C-2b` | 澄清中转接线、轮次派生、预算注入 | `M1C-2a` | **实现与本包门禁已完成并已快进合回 `feat/five_min_design`**:首 child 的 revision 1 session、`NeedsUserInput → awaiting_user_input`、回答绑定后 continuation 的确定性 session 投影、审批后 `revise/reject` 用户修订谱系及 Provider 活跃时间 usage fact/fold 已接线;末次 `plan.submit_gdd` usage 在 receipt/session successor 落盘且 standalone/v4 anchors 精确消费后于同一项目锁内折叠,真实 receipt 回归证明累计值恰好推进一次,重复审批与 recovery reconcile 不二次推进。`planning_clarification_*` **13 passed / 0 failed**(M1C-2c 语义回归另见本包),另有 static deliveries 44、planning storage 13、planning submit 53、Provider usage 4、末次 usage receipt 1、barrier detail 3 条定向回归通过;格式、offline all-targets、编码与 diff 门禁通过。锁序承诺只适用于 **M1C-2b 新增的 planning 澄清写投影路径**;`main_loop` 既有通用 completion blocker 的 execution→project 路径不在本包。第 4 轮信封在正常路径不可达:`agent.delegate` 已在工具边界按血缘上限硬拒并返回 failed observation;coordinator 的超三轮 reconciliation 仅用于损坏血缘纵深防御。审批 UI、hydrate、构建准入和下游完整构建不在本包范围 |
|
| `M1C-2b` | 澄清中转接线、轮次派生、预算注入 | `M1C-2a` | **实现与本包门禁已完成并已快进合回 `feat/five_min_design`**:首 child 的 revision 1 session、`NeedsUserInput → awaiting_user_input`、回答绑定后 continuation 的确定性 session 投影、审批后 `revise/reject` 用户修订谱系及 Provider 活跃时间 usage fact/fold 已接线;末次 `plan.submit_gdd` usage 在 receipt/session successor 落盘且 standalone/v4 anchors 精确消费后于同一项目锁内折叠,真实 receipt 回归证明累计值恰好推进一次,重复审批与 recovery reconcile 不二次推进。`planning_clarification_*` **13 passed / 0 failed**(M1C-2c 语义回归另见本包),另有 static deliveries 44、planning storage 13、planning submit 53、Provider usage 4、末次 usage receipt 1、barrier detail 3 条定向回归通过;格式、offline all-targets、编码与 diff 门禁通过。锁序承诺只适用于 **M1C-2b 新增的 planning 澄清写投影路径**;`main_loop` 既有通用 completion blocker 的 execution→project 路径不在本包。第 4 轮信封在正常路径不可达:`agent.delegate` 已在工具边界按血缘上限硬拒并返回 failed observation;coordinator 的超三轮 reconciliation 仅用于损坏血缘纵深防御。审批 UI、hydrate、构建准入和下游完整构建不在本包范围 |
|
||||||
| `M1C-2c` | 决策卡 A/B 语义(第 23.9 节,2026-08-18 实现完成并合回):选项 → 台账映射改为 A/B 均 `confirmed/user_option`、信封 label 形状校验、planning role brief 与 Supervisor playbook/final-reply 文案(B 必须是真实岔路、第 3 项恒定且 description 须给出可执行验证方式、改口转述规则、提问纪律) | `M1C-2b` | **实现与门禁完成,已由 `6e4bd9703` 合回 `feat/five_min_design`**:Runtime 已实现 A/B/固定第三项校验、B 不再生成 `default_pending`、`answerSummary` 逐字保真;非法 C/缺项 fail-closed,A/B/自由填写回归已通过。`planning_clarification_*` 13、`project_planning` prompt 5、`planning_submit` 定向回归、prompt bundle、格式、编码、diff、offline all-targets 均通过;不含 M1D-1 前端、hydrate、构建准入或下游完整构建 |
|
| `M1C-2c` | 决策卡 A/B 语义(第 23.9 节,2026-08-18 实现完成并合回):选项 → 台账映射改为 A/B 均 `confirmed/user_option`、信封 label 形状校验、planning role brief 与 Supervisor playbook/final-reply 文案(B 必须是真实岔路、第 3 项恒定且 description 须给出可执行验证方式、改口转述规则、提问纪律) | `M1C-2b` | **实现与门禁完成,已由 `6e4bd9703` 合回 `feat/five_min_design`**:Runtime 已实现 A/B/固定第三项校验、B 不再生成 `default_pending`、`answerSummary` 逐字保真;非法 C/缺项 fail-closed,A/B/自由填写回归已通过。`planning_clarification_*` 13、`project_planning` prompt 5、`planning_submit` 定向回归、prompt bundle、格式、编码、diff、offline all-targets 均通过;不含 M1D-1 前端、hydrate、构建准入或下游完整构建 |
|
||||||
| `M1D-1` | 前端 hydrate 与 GDD 审批卡;决策卡按第 23.9 节实现(label 动态渲染、默认焦点 A、Other 槽不变) | `M1C-2b` | **隔离工作树实现完成,待提交/合回**:新增严格 `{projectPath}` hydrate command、`plan-gdd-state-view.v1` Rust read model、审批卡与独立 GDD 正文详情弹层;页面只消费 hydrate,决定 responseId 按审批请求/动作复用,`recoveryPending` 仅提供恢复重试。已修正“仅 session awaiting 即露出审批动作”及未审批 GDD 缺 session 的 fail-closed 边界;定向 hydrate 空项目回归、offline all-targets cargo check、格式、编码与 diff 门禁通过。未接 M1D-2 入口分流、完整构建按钮或 M1E 下游链路 |
|
| `M1D-1` | 前端 hydrate 与 GDD 审批卡;决策卡按第 23.9 节实现(label 动态渲染、默认焦点 A、Other 槽不变) | `M1C-2b` | **已完成并合入 `feat/five_min_design`(`5b11a0530`)**:新增严格 `{projectPath}` hydrate command、`plan-gdd-state-view.v1` Rust read model、审批卡与独立 GDD 正文详情弹层;页面只消费 hydrate,决定 responseId 按审批请求/动作复用,`recoveryPending` 仅提供恢复重试;审批前置 pending 与错绑 session 继续 fail-closed。 |
|
||||||
| `M1D-2` | 入口分流与阶段进度 | `M1D-1` | 「直接开建」跳过路径与现状零差异 |
|
| `M1D-2` | 入口分流与阶段进度 | `M1D-1` | **隔离工作树实现完成,待提交**:游戏新项目默认 `standard + project-supervisor-plan`,显式“直接开建”保持 `autonomous-game-build`;阶段进度显示轮次 x/3、当前版本和状态徽章;实际项目总控页面挂载 hydrate/审批卡,并将 `project-planning` / 设计组展示名收口。未接 M2 approved-GDD 构建绑定或完整构建按钮。 |
|
||||||
| `M1E` | 端到端与故障注入收口 | `M1D-2` | 第 21 节测试矩阵中跨层场景 |
|
| `M1E` | 端到端与故障注入收口 | `M1D-2` | 第 21 节测试矩阵中跨层场景 |
|
||||||
|
|
||||||
**2026-08-14 `M1B-1` 合入验收快照**:已合入实现集中在 `apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_storage.rs`,并由 `runtime_protocol.rs` 注册。已具备 `plan-gdd.v1`、`plan-gdd-index.v1`、`plan-session.v1` 及 `plan.submit_gdd` input 的 strict serde 形状校验、文本/ID/时间/枚举边界、typed serde fingerprint、canonical JSON(重复键、BOM、尾空白、字段顺序)解析、GDD 连续版本链、session `revision + 1` / `previousFingerprint` 链、create-only durable writer、session 原子替换与受限 recovery,以及 `project-planning / agent-delegate / standard / project-supervisor` writer identity。通用 `file.write`、`file.patch`、`file.delete`、`project.patchset` 与 checkpoint restore 对 `.agent/planning/**` 和 `game/fast_gdd.md` 只挡写,planning 的 `file.read` / `file.list` 仍可读;M1B-1 合入时没有注册或执行 `plan.submit_gdd`,也没有实现 approval pending、receipt、UI 或构建准入。
|
**2026-08-14 `M1B-1` 合入验收快照**:已合入实现集中在 `apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/planning_storage.rs`,并由 `runtime_protocol.rs` 注册。已具备 `plan-gdd.v1`、`plan-gdd-index.v1`、`plan-session.v1` 及 `plan.submit_gdd` input 的 strict serde 形状校验、文本/ID/时间/枚举边界、typed serde fingerprint、canonical JSON(重复键、BOM、尾空白、字段顺序)解析、GDD 连续版本链、session `revision + 1` / `previousFingerprint` 链、create-only durable writer、session 原子替换与受限 recovery,以及 `project-planning / agent-delegate / standard / project-supervisor` writer identity。通用 `file.write`、`file.patch`、`file.delete`、`project.patchset` 与 checkpoint restore 对 `.agent/planning/**` 和 `game/fast_gdd.md` 只挡写,planning 的 `file.read` / `file.list` 仍可读;M1B-1 合入时没有注册或执行 `plan.submit_gdd`,也没有实现 approval pending、receipt、UI 或构建准入。
|
||||||
|
|||||||
Reference in New Issue
Block a user