清理九条旧包装与失效门禁编译警告

删除无调用的素材生成、Goal 与用户修订查询包装
清理恒假视觉门禁、专属提示词及不可达等待分支
移除 manifest 初始化未用参数并更新全部调用
以循环返回值替代 Direct 回合的冗余初始化,保持重试语义
同步现行行为文档、警告处理记录及未编译验证边界
This commit is contained in:
2026-09-23 16:41:43 +00:00
parent 00984be228
commit b39cd555ae
13 changed files with 61 additions and 364 deletions
@@ -15,7 +15,6 @@
"owner.task": "{base}\n\n这是 正式 owner 写入任务。必须实际生成并写入非空正式产物:{paths};JSON 文件必须是可解析 JSONcode-prototype 的 game/index.html 不能沿用初始化占位。{publish_package_requirement}{visual_usage_requirement}{visual_requirement}{verification_requirement}不要调用 task.update。",
"background.previewReadiness": "{base}\n\n这是 只读静态验证任务,不要修改项目文件。固定核心动作是且只能是 command.run_limited(commandId=game.static_smoke);通过后直接交付验证结论,不要调用其它命令、项目 mutation 或 task.update。",
"background.previewPlaytest": "{base}\n\n这是 只读试玩验收任务,不要修改项目文件。固定核心动作是且只能是 preview.validate;完成当前 revision 的桌面与移动试玩后直接交付验收结论,不要调用项目 mutation、其它预览动作或 task.update。",
"background.artDirection": "{base}\n\n这是 视觉方向任务。根据项目需求决定是否调用 canvas.asset_generate,并选择图片名称、数量、素材类别和布局;生成成功后直接交付结论。",
"background.artDirectionWithoutCredentials": "{base}\n\n这是 无生图凭据只读协调任务。当前未配置 External Editor 生图凭据,上述 seed task 中 assets/art-spec.png 图片产物与生成验收条款在本轮不适用;只交付正式视觉方向结论,不要修改项目文件,不调用 canvas.asset_generate、game.static_smoke、project.verify、command.run_limited、preview 或 task.update。",
"background.coordination": "{base}\n\n这是 只读协调任务,不要修改项目文件,也不要为了 manifest 内部回执路径写入 memory/、game/、assets/ 或 exports/。只读取当前项目事实,完成方向协调、审查或验收并直接交付结论;不要调用 task.update。",
"background.relaxed": "处理 manifest ready 任务:{}\n\n任务 ID{}\n专业组:{}\n角色:{}\n依赖(仅供参考):{}\n\n这是并行自主执行任务。请在当前项目根内按你的职责自行规划和调用可用工具,可以与其它任务同时进行。完成后直接回复实际完成情况。",
@@ -5256,9 +5256,8 @@ async fn run_direct_game_creator_turn_inner(
} else {
let mut feedback_prompt = prompt.to_string();
let mut turn_kind = DirectCodexTurnKind::User;
let mut response = None;
let mut attempt = 1;
loop {
let response = loop {
let result = direct_game_creator_codex_chat_at_with_optional_observer(
root,
system_prompt.clone(),
@@ -5273,15 +5272,15 @@ async fn run_direct_game_creator_turn_inner(
match result {
Ok(value) => {
match super::direct_delivery::review_reply(root,&execution_session).await {
Ok(Some(report)) => { response = Some(report); break; }
Ok(None) => { response = Some(value); break; }
Ok(Some(report)) => break Some(report),
Ok(None) => break Some(value),
Err(detail) if detail.starts_with("delivery-review-required:") => {
feedback_prompt = format!(prompt_text!("direct.deliveryFeedback"),detail=detail);
}
Err(error) => return Err(DirectCodexTurnFailure::new(DirectCodexFailureStage::CodeGeneration,error)),
}
}
Err(_) if super::direct_delivery::terminal_report(&execution_session).is_some() => { response = super::direct_delivery::terminal_report(&execution_session); break; }
Err(_) if super::direct_delivery::terminal_report(&execution_session).is_some() => break super::direct_delivery::terminal_report(&execution_session),
Err(error)
if attempt < DIRECT_CODEX_ERROR_FEEDBACK_MAX_ATTEMPTS
&& direct_codex_error_should_feedback(&error) =>
@@ -5297,7 +5296,7 @@ async fn run_direct_game_creator_turn_inner(
));
}
}
}
};
response.ok_or_else(|| "陶泥儿错误反馈回合未返回结果".to_string())
}
.map_err(|error| DirectCodexTurnFailure::new(DirectCodexFailureStage::CodeGeneration, error))?;
@@ -63,8 +63,7 @@ pub(crate) use canvas_generation::request_platform_art_asset_with_options_for_te
#[allow(unused_imports)]
pub(crate) use canvas_generation::{
build_platform_art_asset_prompt, editor_api_key_is_configured, generate_platform_art_asset_at,
generate_platform_art_asset_with_options_at,
generate_platform_art_asset_with_required_slices_at, maybe_generate_platform_art_asset_step,
generate_platform_art_asset_with_options_at, maybe_generate_platform_art_asset_step,
needs_platform_art_asset_generation, normalize_platform_art_asset_generation_kind,
normalize_platform_art_reference_asset_ids, normalize_platform_art_target_category,
platform_art_asset_art_spec, platform_art_asset_output_extension_matches,
@@ -2579,33 +2579,6 @@ pub(crate) async fn generate_platform_art_asset_with_options_at(
.await
}
/// Generates the canonical game spritesheet together with the four durable
/// core slices. Callers that promise a playable game must use this instead
/// of the permissive asset path: a bare spritesheet is not enough evidence
/// that player, target, obstacle, and feedback visuals are available.
pub(crate) async fn generate_platform_art_asset_with_required_slices_at(
root: &Path,
prompt: &str,
briefs: &[AgentGroupBrief],
options: &PlatformArtAssetGenerationOptions,
) -> Result<GeneratedPlatformArtAsset, String> {
if options.asset_kind != GameCreationAppAssetKind::IconSpritesheet {
return Err("严格游戏切片生成只允许 icon-spritesheet 资产类型".to_string());
}
let generation_prompt = build_platform_art_asset_prompt(prompt, options);
let runtime_context =
standalone_platform_art_generation_runtime_context(&generation_prompt, options, false)?;
generate_platform_art_asset_with_runtime_options_at(
root,
prompt,
briefs,
options,
false,
&runtime_context,
)
.await
}
/// standalone 图片生成的**精确动作身份材料**。
///
/// 这份材料既是动作指纹(`actionFingerprint`)的来源,也是 durable 输出槽身份
@@ -1102,184 +1102,6 @@ pub(in crate::agent) fn agent_runtime_non_verification_completion_blocker_at_loc
.or_else(|| process_session_completion_blocker_at_locked(root, agent_id, run_id))
.or_else(|| isolated_join_completion_blocker_at_locked(root, agent_id, run_id))
.or_else(|| static_delegate_completion_blocker_at_locked(root, agent_id, run_id))
.or_else(|| visual_asset_completion_blocker_at_locked(root, agent_id, Some(run_id)))
}
pub(in crate::agent) fn ui_prototype_visual_inspection_blocker_detail_at_locked(
root: &Path,
agent_id: &str,
required_run_id: Option<&str>,
expected_path: &str,
) -> Result<Option<String>, String> {
let inspection_run_id = required_run_id.unwrap_or("task_update_current_image");
let mut images = load_agent_runtime_inspection_images(
root,
agent_id,
inspection_run_id,
&[expected_path.to_string()],
)?;
let image = images
.pop()
.ok_or_else(|| "UI 原型图片读取结果为空".to_string())?;
// 摘要缺失必须失败关闭:视觉检查审计按摘要证明「检查过的就是当前这张图」,
// 不能退化成空摘要比较,否则一条 sha256 为空的记录就能通过复核。
let image_sha256 = image.sha256_digest()?.to_string();
let (records, scan_truncated) =
read_agent_db_records_bounded(root, AGENT_RUNTIME_ACTION_HISTORY_MAX_DB_BYTES)?;
let matching = records.iter().rev().find(|record| {
record.get("recordType").and_then(serde_json::Value::as_str)
== Some("agent.runtime.image.inspect")
&& record.get("agentId").and_then(serde_json::Value::as_str) == Some(agent_id)
&& required_run_id.is_none_or(|run_id| {
record.get("runId").and_then(serde_json::Value::as_str) == Some(run_id)
})
&& record
.get("inspectionKind")
.and_then(serde_json::Value::as_str)
== Some(AGENT_RUNTIME_UI_DESIGN_INSPECTION_KIND)
&& record
.get("validationProfile")
.and_then(serde_json::Value::as_str)
== Some(AGENT_RUNTIME_UI_PROTOTYPE_VALIDATION_PROFILE)
&& record
.get("images")
.and_then(serde_json::Value::as_array)
.is_some_and(|items| {
items.len() == 1
&& items[0].get("path").and_then(serde_json::Value::as_str)
== Some(expected_path)
&& items[0].get("sha256").and_then(serde_json::Value::as_str)
== Some(image_sha256.as_str())
})
});
let Some(record) = matching else {
return Ok(Some(format!(
"expectedPath={expected_path} · currentSha256={} · requiredInspection=image.inspect · inspectionRunId={} · scanTruncated={scan_truncated}",
image_sha256,
required_run_id.unwrap_or("latest-current-image")
)));
};
let checks = serde_json::from_value::<AgentRuntimeUiPrototypeChecks>(
record
.get("checks")
.cloned()
.ok_or_else(|| "UI 原型视觉检查审计缺少 checks".to_string())?,
)
.map_err(|error| format!("解析 UI 原型视觉检查 checks 失败:{error}"))?;
let issues = serde_json::from_value::<Vec<String>>(
record
.get("issues")
.cloned()
.ok_or_else(|| "UI 原型视觉检查审计缺少 issues".to_string())?,
)
.map_err(|error| format!("解析 UI 原型视觉检查 issues 失败:{error}"))?;
let assessment = AgentRuntimeUiPrototypeAssessment {
checks,
issues,
summary: "结构化 UI 视觉检查审计".to_string(),
}
.validate()?;
let recorded_passed = record
.get("passed")
.and_then(serde_json::Value::as_bool)
.ok_or_else(|| "UI 原型视觉检查审计缺少 passed".to_string())?;
if recorded_passed != assessment.passed() {
return Err("UI 原型视觉检查审计的 passed 与结构化字段冲突".to_string());
}
if recorded_passed {
return Ok(None);
}
Ok(Some(format!(
"expectedPath={expected_path} · informationHud={} · gameplaySurface={} · objectiveEntities={} · primaryControls={} · failureRestartFlow={} · responsiveLayout={} · implementationClarity={} · originalTheme={} · issues={}",
assessment.checks.information_hud,
assessment.checks.gameplay_surface,
assessment.checks.objective_entities,
assessment.checks.primary_controls,
assessment.checks.failure_restart_flow,
assessment.checks.responsive_layout,
assessment.checks.implementation_clarity,
assessment.checks.original_theme,
assessment.issues.join(""),
)))
}
pub(in crate::agent) fn visual_asset_completion_blocker_at_locked(
root: &Path,
agent_id: &str,
required_run_id: Option<&str>,
) -> Option<AgentRuntimeToolObservation> {
// 图片产物由 Codex 按项目需求选择,不再存在固定视觉资产完成门禁。
return None;
#[allow(unreachable_code)]
{
if !editor_api_key_is_configured() {
return None;
}
let (expected_path, expected_kind, label) = match agent_id {
"art-director" => (
AGENT_RUNTIME_ART_SPEC_PATH,
GameCreationAppAssetKind::IconSpec,
"统一视觉规范图",
),
"design-foundation" => (
"assets/ui-prototype.png",
GameCreationAppAssetKind::UiDesign,
"策划界面原型图",
),
"art-asset-plan" => (
"assets/art-spritesheet.png",
GameCreationAppAssetKind::IconSpritesheet,
"首版美术素材图",
),
_ => return None,
};
let manifest = match read_manifest_for_project(root) {
Ok(manifest) => manifest,
Err(error) => {
return Some(AgentRuntimeToolObservation {
tool: "runtime.visual_asset".to_string(),
status: "blocked".to_string(),
summary: format!("无法核对{label},不能完成任务"),
detail: Some(redact_agent_runtime_project_paths(root, &error, 500)),
});
}
};
if let Err(error) = validate_manifest_required_visual_asset(root, &manifest, agent_id) {
return Some(AgentRuntimeToolObservation {
tool: "runtime.visual_asset".to_string(),
status: "blocked".to_string(),
summary: format!("{label}尚未按正式视觉流程生成并登记,不能完成任务"),
detail: Some(format!(
"expectedPath={expected_path} · expectedKind={expected_kind} · editorApiKeyConfigured={} · reason={}",
editor_api_key_is_configured(),
redact_agent_runtime_project_paths(root, &error, 300),
)),
});
}
if agent_id != "design-foundation" {
return None;
}
match ui_prototype_visual_inspection_blocker_detail_at_locked(
root,
agent_id,
required_run_id,
expected_path,
) {
Ok(None) => None,
Ok(Some(detail)) => Some(AgentRuntimeToolObservation {
tool: "runtime.visual_asset".to_string(),
status: "blocked".to_string(),
summary: "策划界面原型图尚未通过结构化 UI 视觉检查,不能完成任务".to_string(),
detail: Some(detail),
}),
Err(error) => Some(AgentRuntimeToolObservation {
tool: "runtime.visual_asset".to_string(),
status: "blocked".to_string(),
summary: "无法核对策划界面原型图的结构化 UI 视觉证据,不能完成任务".to_string(),
detail: Some(redact_agent_runtime_project_paths(root, &error, 500)),
}),
}
}
}
pub(in crate::agent) fn provider_retry_completion_blocker_at_locked(
@@ -544,30 +544,30 @@ async fn run_game_creator_agent_background_task_pass_without_deadline(
// impossible for a relaxed run to read the DAG and accidentally
// re-enter `waiting-for-manifest-tasks`.
if !relaxed_autonomous {
let autonomous_root_goal_contract_persisted = if agent_id
let autonomous_root_parent_identity_valid = if agent_id
== GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID
&& runtime.run_profile == AGENT_RUNTIME_RUN_PROFILE_AUTONOMOUS_GAME_BUILD
{
match autonomous_root_goal_contract_persisted_at(
match validate_autonomous_game_build_ready_task_parent_identity_at(
&root,
&agent_id,
&runtime.run_id,
) {
Ok(value) => value,
Ok(_) => true,
Err(error) => {
return fail_game_creator_agent_background_context_at(
&root,
&agent_id,
&session_id,
runtime,
&format!("读取自主构建根 Goal Contract 门失败:{error}"),
&format!("校验自主构建根任务身份失败:{error}"),
);
}
}
} else {
false
};
let autonomous_manifest_parent_can_wait = autonomous_root_goal_contract_persisted
let autonomous_manifest_parent_can_wait = autonomous_root_parent_identity_valid
&& agent_id == GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID
&& runtime.run_profile == AGENT_RUNTIME_RUN_PROFILE_AUTONOMOUS_GAME_BUILD
&& !game_creator_agent_runtime_provider_action_batch_exists(
@@ -1471,13 +1471,6 @@ async fn run_game_creator_agent_background_task_pass_without_deadline(
.or_else(|| {
static_delegate_completion_blocker_at(&root, &agent_id, &runtime.run_id)
})
.or_else(|| {
visual_asset_completion_blocker_at_locked(
&root,
&agent_id,
Some(&runtime.run_id),
)
})
.or_else(|| {
project_verification_completion_blocker_at(
&root,
@@ -1648,19 +1641,6 @@ async fn run_game_creator_agent_background_task_pass_without_deadline(
runtime.next_step =
"调用 agent.run_status 取得 readyDelegateReceipts".to_string();
}
} else if blocker.tool == "runtime.visual_asset" {
runtime.status = "running".to_string();
runtime.phase = "waiting-for-visual-asset".to_string();
if agent_id == "design-foundation" {
runtime.current_action = "等待可验收的 UI 原型图".to_string();
runtime.waiting_on =
"图片生成、manifest 登记与 ui-prototype.v2 结构化视觉检查".to_string();
runtime.next_step = "缺图时调用 canvas.asset_generate;已有候选时对 assets/ui-prototype.png 调用 image.inspect;未通过时如实返回 needs-repair,由 Supervisor 认领后发起唯一 repair 原位替换,禁止先删除正式图片".to_string();
} else {
runtime.current_action = "等待实际图片产物".to_string();
runtime.waiting_on = "图片生成确认、配置与本地 manifest 登记".to_string();
runtime.next_step = "调用 canvas.asset_generate 生成确定路径图片,并用 asset.list 核对登记结果".to_string();
}
} else if blocker.tool == "runtime.autonomous_completion" {
runtime.status = "running".to_string();
runtime.phase = "planning".to_string();
@@ -669,7 +669,7 @@ pub(crate) fn schedule_game_creator_agent_ready_tasks_at(
Ok(results)
}
fn validate_autonomous_game_build_ready_task_parent_identity_at(
pub(super) fn validate_autonomous_game_build_ready_task_parent_identity_at(
root: &Path,
parent_agent_id: &str,
parent_run_id: &str,
@@ -691,33 +691,6 @@ fn validate_autonomous_game_build_ready_task_parent_identity_at(
Ok(binding)
}
fn autonomous_root_goal_contract_persisted_for_binding_at(
root: &Path,
binding: &AgentRuntimeRunProfileBinding,
) -> Result<bool, String> {
Ok(
read_game_creator_agent_runtime_goal_contract_at(root, &binding.agent_id, &binding.run_id)?
.is_some(),
)
}
/// Return whether the trusted autonomous root has a valid, persisted Goal
/// Contract. The scheduler uses the `false` result as a safe no-op when the
/// sidecar has not landed yet; malformed or identity-conflicting sidecars are
/// deliberately propagated by `read_game_creator_agent_runtime_goal_contract_at`.
pub(crate) fn autonomous_root_goal_contract_persisted_at(
root: &Path,
parent_agent_id: &str,
parent_run_id: &str,
) -> Result<bool, String> {
validate_autonomous_game_build_ready_task_parent_identity_at(
root,
parent_agent_id,
parent_run_id,
)?;
Ok(true)
}
fn validate_autonomous_game_build_ready_task_parent_at(
root: &Path,
parent_agent_id: &str,
@@ -1500,7 +1473,7 @@ pub(in crate::agent) fn project_autonomous_manifest_ready_task_terminal_at_locke
else {
return Ok(false);
};
let mut status = match state.phase.as_str() {
let status = match state.phase.as_str() {
"completed" => GameCreationAppTaskStatus::Completed,
"failed" | "cancelled" | "budget-exhausted" => GameCreationAppTaskStatus::Failed,
_ => return Ok(false),
@@ -1550,27 +1523,6 @@ pub(in crate::agent) fn project_autonomous_manifest_ready_task_terminal_at_locke
manifest_task,
&task_text,
)?;
if status == GameCreationAppTaskStatus::Completed
&& !autonomous_relaxed_run_profile(&state.run_profile)
&& autonomous_manifest_ready_task_requires_visual_asset(&manifest_task.id)
&& !manifest_has_required_visual_asset(root, &manifest, &manifest_task.id)
{
status = GameCreationAppTaskStatus::Failed;
append_agent_db_record(
root,
serde_json::json!({
"recordType": "agent.runtime.autonomous_ready_task.missing_visual_failed",
"agentId": state.agent_id,
"taskId": state.agent_id,
"sessionId": state.session_id,
"runId": state.run_id,
"source": state.source,
"parentAgentId": parent_agent_id,
"parentRunId": parent_run_id,
"terminalPhase": state.phase,
}),
)?;
}
if status == GameCreationAppTaskStatus::Completed
&& !autonomous_relaxed_run_profile(&state.run_profile)
{
@@ -1633,10 +1585,6 @@ pub(in crate::agent) fn project_autonomous_manifest_ready_task_terminal_at_locke
Ok(true)
}
pub(super) fn autonomous_manifest_ready_task_requires_visual_asset(task_id: &str) -> bool {
false
}
fn render_autonomous_manifest_ready_task_owner_prompt(task: &GameCreationAppTaskState) -> String {
let base = render_manifest_ready_task_background_prompt(task);
let paths = autonomous_manifest_owner_artifact_paths(&task.id).join(", ");
@@ -1688,12 +1636,6 @@ pub(in crate::agent) fn render_autonomous_manifest_ready_task_background_prompt(
);
}
if task.id == "art-director" {
if autonomous_manifest_ready_task_requires_visual_asset(&task.id) {
return format!(
prompt_text!("execution.background.artDirection"),
base = base,
);
}
return format!(
prompt_text!("execution.background.artDirectionWithoutCredentials"),
base = base,
@@ -1823,9 +1765,6 @@ mod tests {
assert!(prompt.contains("无生图凭据只读协调任务"));
assert!(prompt.contains("assets/art-spec.png 图片产物与生成验收条款在本轮不适用"));
assert!(prompt.contains("不要修改项目文件"));
assert!(!autonomous_manifest_ready_task_requires_visual_asset(
"art-director"
));
assert!(agent_runtime_task_requires_read_only_delivery(
"art-director",
&prompt
@@ -7232,7 +7232,7 @@ fn reset_cancelled_reconciliation_manifest_tasks_for_continuation_at(
"runtime.autonomous.manifest.reconciliation_cancel_retry",
)?;
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
let failed_task_ids = manifest
.tasks
.iter()
@@ -14626,7 +14626,7 @@ fn reset_autonomous_manifest_seed_tasks_at(
"runtime.autonomous.manifest.reset",
)?;
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
let seed_task_ids = new_game_creation_app_seed_tasks()
.into_iter()
.map(|task| task.id)
@@ -320,28 +320,13 @@ pub(in crate::agent) fn observe_agent_runtime_task_update(
detail: None,
};
}
let relaxed_autonomous = match task_ops_relaxed_autonomous_profile_at(root, agent_id, run_id) {
Ok(value) => value,
Err(error) => {
return AgentRuntimeToolObservation {
tool: "task.update".to_string(),
status: "failed".to_string(),
summary: redact_agent_runtime_project_paths(root, &error, 240),
detail: None,
};
}
};
if status == GameCreationAppTaskStatus::Completed && !relaxed_autonomous {
if let Some(blocker) =
visual_asset_completion_blocker_at_locked(root, task_id.as_str(), None)
{
return AgentRuntimeToolObservation {
tool: "task.update".to_string(),
status: "failed".to_string(),
summary: blocker.summary,
detail: blocker.detail,
};
}
if let Err(error) = task_ops_relaxed_autonomous_profile_at(root, agent_id, run_id) {
return AgentRuntimeToolObservation {
tool: "task.update".to_string(),
status: "failed".to_string(),
summary: redact_agent_runtime_project_paths(root, &error, 240),
detail: None,
};
}
let result = update_manifest_task_status_at(root, task_id.as_str(), status).and_then(|task| {
append_agent_db_record(
@@ -1263,25 +1263,8 @@ fn static_delegate_original_is_awaiting_clarification(
})
}
/// 唯一权威判据:某条 delivery 是否由用户审批的「修改」动作标记为待修订
///
/// 该状态只由后续审批工作包写入;本包只让 lineage 重放认识它,不能自行生成或
/// 把其它状态静默映射成它。
/// 该原 delivery 是否正等着用户提出的修订(而不是质量返工)。
///
/// 用户修订和质量返工都带 `repairOfDelegationId`,但额度完全不同:`repair_depth`
/// 防的是 runaway agent,而用户修订每一轮都由人触发,人本身就是循环边界。委派 task
/// 末尾那句「你在这条链路上的位置」必须按这个判据分开渲染,否则用户第一次点修改就会
/// 被告知「这是唯一返工轮」。
pub(crate) fn static_delegate_original_awaits_user_revision_at(
root: &Path,
delegation_id: &str,
) -> Result<bool, String> {
Ok(read_static_delegate_delivery_at(root, delegation_id)?
.as_ref()
.is_some_and(static_delegate_original_is_user_revision_requested))
}
/// 识别持久交付记录中的用户修订状态,供 lineage 重放和修订请求校验共用
/// 用户修订不消耗质量返工深度;此判据不写入状态,也不把其它状态映射成用户修订。
fn static_delegate_original_is_user_revision_requested(
delivery: &StaticDelegateDeliveryRecord,
) -> bool {
@@ -863,7 +863,7 @@ pub(crate) fn record_preview_state(
port: Option<u16>,
) -> Result<(), String> {
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
let is_running = status == GameCreationAppPreviewStatus::Running;
manifest.preview = Some(GameCreationAppPreviewState { status, url, port });
if is_running && !autonomous_game_build_root_run_active_at(root) {
@@ -881,7 +881,7 @@ pub(crate) fn record_command_run(
run: GameCreationAppCommandRunState,
) -> Result<(), String> {
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
if !autonomous_game_build_root_run_active_at(root)
&& run.command_id == "game.static_smoke"
&& run.status == GameCreationAppCommandRunStatus::Completed
@@ -917,12 +917,12 @@ pub(crate) fn read_manifest_for_project(root: &Path) -> Result<GameCreationAppMa
}
};
let original = manifest.clone();
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
if canonical_manifest_installed && manifest == original {
return Ok(manifest);
}
mutate_manifest_at(root, |current| {
ensure_manifest_seed_tasks(root, current);
ensure_manifest_seed_tasks(current);
Ok(current.clone())
})
}
@@ -932,7 +932,7 @@ pub(crate) fn read_manifest_for_project_with_godot_root_calibration(
) -> Result<GameCreationAppManifest, String> {
let godot_project_root = discover_local_godot_project_root(root)?;
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
manifest.godot_project_root = godot_project_root;
write_manifest(&manifest_path, &manifest)?;
Ok(manifest)
@@ -1071,7 +1071,7 @@ pub(crate) fn ensure_manifest_has_seed_tasks(
goal: Option<&str>,
) -> Result<GameCreationAppManifest, String> {
mutate_manifest_at(root, |manifest| {
ensure_manifest_seed_tasks(root, manifest);
ensure_manifest_seed_tasks(manifest);
if let Some(goal) = goal.map(str::trim).filter(|goal| !goal.is_empty()) {
manifest.goal = Some(goal.to_string());
}
@@ -1086,7 +1086,7 @@ pub(crate) fn record_draft_task_progress(
agent_log_path: &Path,
) -> Result<GameCreationAppManifest, String> {
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
manifest.goal = Some(goal.to_string());
for completed_task_id in [
"design-director",
@@ -1122,7 +1122,7 @@ pub(crate) fn record_draft_task_progress(
Ok(manifest)
}
pub(crate) fn ensure_manifest_seed_tasks(root: &Path, manifest: &mut GameCreationAppManifest) {
pub(crate) fn ensure_manifest_seed_tasks(manifest: &mut GameCreationAppManifest) {
let seed_tasks = new_game_creation_app_seed_tasks();
if manifest.tasks.is_empty() {
manifest.tasks = seed_tasks;
@@ -1148,14 +1148,6 @@ pub(crate) fn ensure_manifest_seed_tasks(root: &Path, manifest: &mut GameCreatio
}
}
pub(crate) fn manifest_has_required_visual_asset(
root: &Path,
manifest: &GameCreationAppManifest,
task_id: &str,
) -> bool {
validate_manifest_required_visual_asset(root, manifest, task_id).is_ok()
}
pub(crate) fn validate_manifest_required_visual_asset(
root: &Path,
manifest: &GameCreationAppManifest,
@@ -1330,7 +1322,7 @@ pub(crate) fn update_manifest_task_status_at(
return Err("任务 ID 不能为空".to_string());
}
mutate_manifest_at(root, |manifest| {
ensure_manifest_seed_tasks(root, manifest);
ensure_manifest_seed_tasks(manifest);
let Some(task) = manifest.tasks.iter_mut().find(|task| task.id == task_id) else {
return Err(format!("项目任务不存在:{task_id}"));
};
@@ -1691,7 +1683,7 @@ pub(crate) fn create_manifest_task_at(
acceptance_criteria: Vec<String>,
) -> Result<GameCreationAppTaskState, String> {
let (manifest_path, mut manifest) = read_or_create_manifest(root)?;
ensure_manifest_seed_tasks(root, &mut manifest);
ensure_manifest_seed_tasks(&mut manifest);
let fallback_id = format!(
"agent-task-{}-{}",
unix_timestamp(),
@@ -7,7 +7,7 @@
## 1. 基线与范围
首次诊断的基线提交为 `016356e509f11a1a638ce45ed51b9e40ef3e36a2`,诊断时工作树干净。环境为 Windows x64、Rust `1.98.1`、Node `v24.15.0`、npm `12.0.2`。第 2~6 节和附录保留首次诊断快照;后续处理状态及契约核查见第 7~18 节,不能将附录的全部条目视为仍未解决。
首次诊断的基线提交为 `016356e509f11a1a638ce45ed51b9e40ef3e36a2`,诊断时工作树干净。环境为 Windows x64、Rust `1.98.1`、Node `v24.15.0`、npm `12.0.2`。第 2~6 节和附录保留首次诊断快照;后续处理状态及契约核查见第 7~19 节,不能将附录的全部条目视为仍未解决。
AGC Rust 使用默认 features、dev profile237 是本轮编译器诊断数,不代表 237 个独立根因,也不是所有平台、features 和 test targets 的总数。另有 5 条不带常规源码 span 的 ts-rs 宏提示,不计入 237。
@@ -615,6 +615,26 @@ W076 只将 Pending(String) 收窄为 Pending;三处生产返回前继续记
最近一次实测仍为第 14 节的 50 条;第 15~16 节预期减少 20 条,本批再处理 6 条,预期剩余 **24 条**,尚未重新编译确认。
## 19. 剩余旧包装、失效门禁及冗余参数清理(2026-09-23)
本批处理 W051、W071、W116、W210W212、W216、W221、W234 共 9 条诊断。此前明确暂留的 W004~W006、W113 以及平台 / feature / 构建脚本项不在本批范围内。
| 编号 | 实施结论 |
| --- | --- |
| W051 | 删除没有调用方的 `generate_platform_art_asset_with_required_slices_at` 及 facade 导出;现役生成入口、内部切片提交和素材校验保留。 |
| W071 | 删除孤立的 Goal 读取 helper,以及只校验身份却以 Goal 持久化命名的转发包装。主循环直接复用父任务身份校验,修正局部变量和错误说明,不恢复已停用的 Goal 前置门。 |
| W116 | 删除无调用的用户修订查询包装;保留持久状态判据、lineage 重放及修订校验。注释改为实际职责,不再声称存在包装的提示词消费者。 |
| W210W212 | 删除恒返回 `None` 的固定视觉素材门禁、不可达旧实现及其专属 UI 检查 helper,移除三个空调用和主循环中只消费旧门禁结果的等待分支。`task.update` 仍执行原有 Run Profile 读取及错误返回,现役图像检查、素材与完成合同校验保留。 |
| W216 | 删除恒为 `false` 的素材需求判断、不可达失败投影、永不选择的提示词分支及其专属文本;顺带删除失去唯一调用方的 `manifest_has_required_visual_asset` 布尔包装。保留实际使用的提示词和原有只读断言,仅移除对恒假 helper 的断言,不迁移或新增测试。 |
| W221 | `ensure_manifest_seed_tasks` 删除未用 `root`,更新全部 11 处调用;任务状态和元数据同步行为不变。 |
| W234 | Direct 无 observer 路径以循环返回值代替必被覆盖的 `response = None`。反馈、重试计数、错误传播和终态报告读取次数 / 顺序保持不变。 |
边界:旧 `art-director` 提示词函数原先无论凭据是否配置都选择只读分支,本批保留该实际行为;现役 relaxed 调度提示词不变。调整提示词的凭据策略不属于 warning 清理,不能借删除恒假条件悄然恢复旧门禁。
验证:修改文件 rustfmt 检查、编码检查、文档索引及 `git diff --check`;静态核对删除符号、全部删参调用、身份校验与异常路径,并解析修改后的提示词 JSON。遵照用户不跑全量编译的要求,未执行 Cargo check/build/test、Rust 单元测试或跨平台构建;静态检查不替代类型检查与运行验证。
最近一次实测仍为第 14 节的 50 条;第 15~18 节已处理 26 条,本批再处理 9 条,预期剩余 **15 条**11 条平台 / feature / 构建脚本项、4 条暂留契约项),尚未重新编译确认。另有 5 条 ts-rs 提示,不包含在本计数中。
## 附录:237 条编译器诊断位置
以下是诊断的人工可读整理,不保存原始构建日志、本机路径或 target 缓存路径。位置相对 `apps/ai-game-creator-shell/src-tauri/`;行号只对应本节基线,修改后以符号搜索及重新编译为准。每条保留一个主要 span,编号用于本清单内跟踪,不表示独立业务缺陷。生成产物项须回到 `build_support/runtime_prompt_bundle.rs` 处理。
@@ -4,6 +4,12 @@
策划 V1、策划会话 Runtime V2 均已删除,当前“做方案”只使用独立 Design Agent,现行合同见[策划 Agent 生产迁移与工作区浏览](./【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md)。旧 V1/V2 Runtime、命令、会话、审批卡、身份白名单和专属测试不作为兼容或恢复目标;历史方案中的 lifecycle v3、planning binding 等要求不能作为孤立代码的保留依据。共享能力按现役调用判断,不因名称相似删除当前 Design Agent 或通用 Runtime。
## 固定视觉门禁与任务身份的现行边界
图片产物按项目需求选择,不恢复按固定 Agent 身份要求视觉资源的旧完成门禁。已停用门禁的空调用、不可达检查和无消费者包装直接清理;现役 `validate_manifest_required_visual_asset`、图片检查、内部切片提交及各完成合同继续按各自调用场景执行,不因清理旧门禁而一并删除。
自主任务父身份校验只核对当前父任务及 Run Profile 绑定,不代表 Goal Contract 已持久化,也不新增等待 Goal 文件的前置条件。manifest seed 同步保留执行状态,不以素材检查结果重新推导任务状态。用户修订的持久状态判据继续供 lineage 重放与修订请求校验使用,不依赖已无消费者的查询包装。
## 2026-09-23 Direct 宿主继续请求输入修复
- 首次模型请求使用原始结构化用户输入,保留 Skill 提及及其它引用;未提供结构化输入时沿用请求正文与图片转换。