强类型化协作Prompt选择器

将role overlay source改为构建期强类型语义selector
消除Supervisor身份合同的第二个配置入口
强制Supervisor规划与最终回复复用同一身份section
移除user context中的Supervisor重复身份注入
收窄background context builder接口并补齐失败关闭回归
同步协作graph配置化边界文档
This commit is contained in:
2026-08-04 18:30:49 +08:00
parent b8e3eb4c7f
commit 07a18d516b
10 changed files with 178 additions and 89 deletions
@@ -39,7 +39,14 @@ struct PromptBundleManifest {
struct PromptCompositions {
runtime: Vec<String>,
supervisor: Vec<String>,
supervisor_chat: Vec<String>,
supervisor_chat: SupervisorChatComposition,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct SupervisorChatComposition {
identity: String,
final_reply: String,
}
#[derive(Debug, Deserialize)]
@@ -63,11 +70,25 @@ struct VisualContractVariants {
editor_unavailable: String,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd)]
#[serde(rename_all = "camelCase")]
enum RoleOverlayRootSourceKind {
SupervisorGameChat,
}
impl RoleOverlayRootSourceKind {
fn rust_variant(self) -> &'static str {
match self {
Self::SupervisorGameChat => "SupervisorGameChat",
}
}
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct RoleOverlay {
agent_id: String,
root_source: Option<String>,
root_source_kind: Option<RoleOverlayRootSourceKind>,
sections: Vec<String>,
}
@@ -82,7 +103,6 @@ struct ProviderFragments {
supervisor_delivery_convergence_repair: String,
manifest_dag_wait_repair: String,
delegated_playtest_repair: String,
supervisor_identity_contract: String,
}
#[derive(Debug, Deserialize)]
@@ -217,12 +237,33 @@ pub fn compile_manifest(manifest_path: &Path) -> Result<CompiledPromptBundle, St
&sections,
&["$base", "$visualContract"],
)?;
validate_composition(
"supervisorChat",
&manifest.compositions.supervisor_chat,
validate_section_reference(
&manifest.compositions.supervisor_chat.identity,
&sections,
&[],
"composition supervisorChat.identity",
)?;
validate_section_reference(
&manifest.compositions.supervisor_chat.final_reply,
&sections,
"composition supervisorChat.finalReply",
)?;
if manifest.compositions.supervisor_chat.identity
== manifest.compositions.supervisor_chat.final_reply
{
return Err(
"Prompt composition supervisorChat identity/finalReply 必须引用不同 section"
.to_string(),
);
}
if !manifest
.compositions
.supervisor
.contains(&manifest.compositions.supervisor_chat.identity)
{
return Err(
"Prompt composition supervisor 必须复用 supervisorChat.identity section".to_string(),
);
}
validate_section_reference(
&manifest.variants.platform.default,
&sections,
@@ -276,23 +317,20 @@ pub fn compile_manifest(manifest_path: &Path) -> Result<CompiledPromptBundle, St
overlay.agent_id
));
}
if let Some(root_source) = &overlay.root_source {
validate_identifier(root_source, "role overlay rootSource", false)?;
}
if overlay.sections.is_empty() {
return Err(format!(
"role overlay {} sections 不能为空",
overlay.agent_id
));
}
let overlay_key = (overlay.agent_id.clone(), overlay.root_source.clone());
let overlay_key = (overlay.agent_id.clone(), overlay.root_source_kind);
if !overlays.insert(overlay_key) {
return Err(format!("role overlay 重复:{}", overlay.agent_id));
}
if manifest.role_overlays.iter().any(|other| {
other.agent_id == overlay.agent_id
&& other.root_source != overlay.root_source
&& (other.root_source.is_none() || overlay.root_source.is_none())
&& other.root_source_kind != overlay.root_source_kind
&& (other.root_source_kind.is_none() || overlay.root_source_kind.is_none())
}) {
return Err(format!("role overlay selector 重叠:{}", overlay.agent_id));
}
@@ -315,10 +353,11 @@ pub fn compile_manifest(manifest_path: &Path) -> Result<CompiledPromptBundle, St
.runtime
.iter()
.chain(manifest.compositions.supervisor.iter())
.chain(manifest.compositions.supervisor_chat.iter())
.filter(|item| !item.starts_with('$'))
.cloned()
.collect::<BTreeSet<_>>();
used_sections.insert(manifest.compositions.supervisor_chat.identity.clone());
used_sections.insert(manifest.compositions.supervisor_chat.final_reply.clone());
used_sections.extend([
manifest.variants.platform.default.clone(),
manifest.variants.platform.linux.clone(),
@@ -365,7 +404,7 @@ pub fn compile_manifest(manifest_path: &Path) -> Result<CompiledPromptBundle, St
fn provider_fragment_entries(
fragments: &ProviderFragments,
) -> [(&'static str, &'static str, &String); 9] {
) -> [(&'static str, &'static str, &String); 8] {
[
(
"providerFragments.isolatedToolContract",
@@ -407,11 +446,6 @@ fn provider_fragment_entries(
"RUNTIME_PROMPT_PROVIDER_DELEGATED_PLAYTEST_REPAIR_SECTION",
&fragments.delegated_playtest_repair,
),
(
"providerFragments.supervisorIdentityContract",
"RUNTIME_PROMPT_PROVIDER_SUPERVISOR_IDENTITY_CONTRACT_SECTION",
&fragments.supervisor_identity_contract,
),
]
}
@@ -791,9 +825,10 @@ fn render_rust(manifest: &PromptBundleManifest, sections: &BTreeMap<String, Stri
"RUNTIME_PROMPT_SUPERVISOR_COMPOSITION",
&manifest.compositions.supervisor,
));
output.push_str(&render_string_slice_const(
"RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION",
&manifest.compositions.supervisor_chat,
output.push_str(&format!(
"pub(crate) const RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION: &[&str] = &[{}, {}];\n",
rust_literal(&manifest.compositions.supervisor_chat.identity),
rust_literal(&manifest.compositions.supervisor_chat.final_reply)
));
output.push_str(&format!(
"pub(crate) const RUNTIME_PROMPT_PLATFORM_DEFAULT_SECTION: &str = {};\n",
@@ -812,18 +847,20 @@ fn render_rust(manifest: &PromptBundleManifest, sections: &BTreeMap<String, Stri
rust_literal(&manifest.variants.visual_contract.editor_unavailable)
));
output.push_str(
"pub(crate) const RUNTIME_PROMPT_ROLE_OVERLAYS: &[(&str, Option<&str>, &[&str])] = &[\n",
"#[derive(Clone, Copy, Debug, Eq, PartialEq)]\npub(crate) enum RuntimePromptRootSourceKind {\n SupervisorGameChat,\n}\n\n",
);
output.push_str(
"pub(crate) const RUNTIME_PROMPT_ROLE_OVERLAYS: &[(&str, Option<RuntimePromptRootSourceKind>, &[&str])] = &[\n",
);
for overlay in &manifest.role_overlays {
let root_source = overlay
.root_source
.as_deref()
.map(|value| format!("Some({})", rust_literal(value)))
let root_source_kind = overlay
.root_source_kind
.map(|kind| format!("Some(RuntimePromptRootSourceKind::{})", kind.rust_variant()))
.unwrap_or_else(|| "None".to_string());
output.push_str(&format!(
" ({}, {}, &{}),\n",
rust_literal(&overlay.agent_id),
root_source,
root_source_kind,
render_string_slice(&overlay.sections)
));
}
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"id": "genarrative.agent-runtime",
"version": "2026-08-04.4",
"version": "2026-08-04.5",
"sections": {
"common": "common.md",
"isolatedTemplateCatalogIntro": "isolated-template-catalog-intro.md",
@@ -17,8 +17,8 @@
"providerSupervisorDeliveryConvergenceRepair": "provider/supervisor-delivery-convergence-repair.md",
"providerManifestDagWaitRepair": "provider/manifest-dag-wait-repair.md",
"providerDelegatedPlaytestRepair": "provider/delegated-playtest-repair.md",
"providerSupervisorIdentityContract": "provider/supervisor-identity-contract.md",
"providerSupervisorFinalReplyContract": "provider/supervisor-final-reply-contract.md",
"supervisorIdentityContract": "supervisor/identity-contract.md",
"supervisorFinalReplyContract": "supervisor/final-reply-contract.md",
"supervisorIntro": "supervisor/intro.md",
"supervisorVisualWithoutEditor": "supervisor/visual-contract-without-editor.md",
"supervisorVisualWithEditor": "supervisor/visual-contract-with-editor.md",
@@ -37,16 +37,17 @@
],
"supervisor": [
"$base",
"supervisorIdentityContract",
"supervisorIntro",
"$visualContract",
"supervisorPlaybook",
"supervisorClaimGate",
"supervisorRepair"
],
"supervisorChat": [
"providerSupervisorIdentityContract",
"providerSupervisorFinalReplyContract"
]
"supervisorChat": {
"identity": "supervisorIdentityContract",
"finalReply": "supervisorFinalReplyContract"
}
},
"variants": {
"platform": {
@@ -61,7 +62,7 @@
"roleOverlays": [
{
"agentId": "code-prototype",
"rootSource": "project-supervisor-game-chat",
"rootSourceKind": "supervisorGameChat",
"sections": ["codePrototypeGameChat"]
}
],
@@ -73,8 +74,7 @@
"autonomousInitialCollaborationRepair": "providerAutonomousInitialCollaborationRepair",
"supervisorDeliveryConvergenceRepair": "providerSupervisorDeliveryConvergenceRepair",
"manifestDagWaitRepair": "providerManifestDagWaitRepair",
"delegatedPlaytestRepair": "providerDelegatedPlaytestRepair",
"supervisorIdentityContract": "providerSupervisorIdentityContract"
"delegatedPlaytestRepair": "providerDelegatedPlaytestRepair"
},
"agentCatalog": {
"supervisor": {
@@ -1 +1 @@
你当前是项目唯一面向用户的 Project Supervisor,并拥有最终回复权。每一轮都必须把用户原始目标视为最高层业务目标,专业 Agent 回执只能补充证据,不能把回执内容改写成新目标。总控不能替代已有专业角色完成其领域交付:只要仓库目标同时包含两个以上互不依赖的专业方向,就必须自行查看静态角色目录,选择最匹配的不同专业 Agent,并在同一个 native planning 批次用带 acceptanceCriteria 和 expectedArtifacts 的 agent.delegate 发起委派,让这些方向并行;用户不需要点名 Agent、指定数量或提醒并行。
总控不能替代已有专业角色完成其领域交付:只要仓库目标同时包含两个以上互不依赖的专业方向,就必须自行查看静态角色目录,选择最匹配的不同专业 Agent,并在同一个 native planning 批次用带 acceptanceCriteria 和 expectedArtifacts 的 agent.delegate 发起委派,让这些方向并行;用户不需要点名 Agent、指定数量或提醒并行。
@@ -484,10 +484,6 @@ pub(crate) fn game_creator_project_supervisor_chat_system_prompt() -> &'static s
.as_str()
}
pub(crate) fn game_creator_project_supervisor_identity_contract_prompt() -> &'static str {
required_runtime_prompt_section(RUNTIME_PROMPT_PROVIDER_SUPERVISOR_IDENTITY_CONTRACT_SECTION)
}
fn game_creator_design_foundation_tool_plan_prompt(
prompt: &str,
editor_api_key_is_configured: bool,
@@ -615,11 +611,18 @@ pub(crate) fn game_creator_agent_runtime_role_overlay_prompt(
agent_id: &str,
root_source: Option<&str>,
) -> String {
let root_source_kind = match root_source.map(str::trim) {
Some(AGENT_RUNTIME_SUPERVISOR_GAME_CHAT_SOURCE) => {
Some(RuntimePromptRootSourceKind::SupervisorGameChat)
}
_ => None,
};
let sections = RUNTIME_PROMPT_ROLE_OVERLAYS
.iter()
.filter(|(overlay_agent_id, overlay_root_source, _)| {
.filter(|(overlay_agent_id, overlay_root_source_kind, _)| {
*overlay_agent_id == agent_id
&& overlay_root_source.is_none_or(|required| Some(required) == root_source)
&& overlay_root_source_kind
.is_none_or(|required| Some(required) == root_source_kind)
})
.flat_map(|(_, _, sections)| sections.iter().copied())
.map(required_runtime_prompt_section)
@@ -682,7 +685,7 @@ mod tests {
#[test]
fn runtime_prompt_bundle_manifest_covers_all_embedded_sections() {
assert_eq!(RUNTIME_PROMPT_BUNDLE_ID, "genarrative.agent-runtime");
assert_eq!(RUNTIME_PROMPT_BUNDLE_VERSION, "2026-08-04.4");
assert_eq!(RUNTIME_PROMPT_BUNDLE_VERSION, "2026-08-04.5");
assert_eq!(
RUNTIME_PROMPT_RUNTIME_COMPOSITION,
&[
@@ -696,10 +699,7 @@ mod tests {
);
assert_eq!(
RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION,
&[
"providerSupervisorIdentityContract",
"providerSupervisorFinalReplyContract"
]
&["supervisorIdentityContract", "supervisorFinalReplyContract"]
);
for section_id in [
"common",
@@ -716,8 +716,8 @@ mod tests {
"providerSupervisorDeliveryConvergenceRepair",
"providerManifestDagWaitRepair",
"providerDelegatedPlaytestRepair",
"providerSupervisorIdentityContract",
"providerSupervisorFinalReplyContract",
"supervisorIdentityContract",
"supervisorFinalReplyContract",
"supervisorIntro",
"supervisorVisualWithoutEditor",
"supervisorVisualWithEditor",
@@ -766,15 +766,15 @@ mod tests {
RUNTIME_PROMPT_PROVIDER_DELEGATED_PLAYTEST_REPAIR_SECTION,
"向 code-prototype 创建一个新的后续修复委派",
),
(
RUNTIME_PROMPT_PROVIDER_SUPERVISOR_IDENTITY_CONTRACT_SECTION,
"唯一默认面向用户的总控 Agent",
),
] {
assert!(required_runtime_prompt_section(section_id).contains(expected));
}
assert!(
required_runtime_prompt_section("providerSupervisorFinalReplyContract")
required_runtime_prompt_section(RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION[0])
.contains("唯一默认面向用户的总控 Agent")
);
assert!(
required_runtime_prompt_section("supervisorFinalReplyContract")
.contains("你拥有最终回复权")
);
}
@@ -1065,6 +1065,7 @@ mod tests {
);
let sections = [
"shared runtime contract",
required_runtime_prompt_section(RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION[0]),
required_runtime_prompt_section("supervisorIntro"),
visual_contract,
required_runtime_prompt_section("supervisorPlaybook"),
@@ -308,7 +308,7 @@ pub(in crate::agent) fn build_game_creator_agent_background_final_reply_request(
Ok((llm, config_path, request))
}
pub(in crate::agent) fn build_game_creator_background_agent_context(
fn build_game_creator_background_agent_context(
root: &Path,
agent_id: &str,
session_id: &str,
@@ -346,11 +346,7 @@ pub(in crate::agent) fn build_game_creator_background_agent_context(
let repository_context = build_repository_startup_context_at(root)?;
let repository_prompt = render_repository_startup_context_for_prompt(&repository_context);
let identity_instruction = if template_agent_id == GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID {
if matches!(mode, AgentBackgroundContextMode::FinalReply) {
""
} else {
game_creator_project_supervisor_identity_contract_prompt()
}
""
} else {
"请只以这个专业 Agent 的身份行动。"
};
@@ -434,15 +430,14 @@ mod tests {
build_game_creator_agent_background_final_reply_request,
build_game_creator_agent_background_tool_plan_request,
game_creator_agent_context_preload_notice, game_creator_agent_runtime_role_overlay_prompt,
game_creator_project_supervisor_chat_system_prompt,
game_creator_project_supervisor_identity_contract_prompt, init_local_game_project_at,
game_creator_project_supervisor_chat_system_prompt, init_local_game_project_at,
provider_command_exec_contract, provider_command_start_contract,
start_game_creator_agent_runtime_task_at, AgentRuntimeTaskLink, AgentRuntimeToolPlan,
GameCreatorMcpCatalog, GameCreatorMcpCatalogTool,
AGENT_RUNTIME_COMPLETION_BLOCKER_TOOL_PLAN_PROTOCOL,
required_runtime_prompt_section, start_game_creator_agent_runtime_task_at,
AgentRuntimeTaskLink, AgentRuntimeToolPlan, GameCreatorMcpCatalog,
GameCreatorMcpCatalogTool, AGENT_RUNTIME_COMPLETION_BLOCKER_TOOL_PLAN_PROTOCOL,
AGENT_RUNTIME_RUN_PROFILE_AUTONOMOUS_GAME_BUILD, AGENT_RUNTIME_SUPERVISOR_CLI_SOURCE,
AGENT_RUNTIME_SUPERVISOR_GAME_CHAT_SOURCE, AGENT_RUNTIME_SUPERVISOR_GUI_SOURCE,
GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID,
GAME_CREATOR_PROJECT_SUPERVISOR_AGENT_ID, RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION,
};
fn native_input_required_fields(
@@ -588,15 +583,19 @@ mod tests {
&catalog,
)
.expect("build supervisor planning request");
let supervisor_system_prompt = &supervisor_request.messages[0].content;
let supervisor_prompt = &supervisor_request.messages[1].content;
let supervisor_identity_contract =
game_creator_project_supervisor_identity_contract_prompt();
required_runtime_prompt_section(RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION[0]);
assert_eq!(
supervisor_prompt
supervisor_system_prompt
.matches(supervisor_identity_contract)
.count(),
1
);
assert!(!supervisor_prompt.contains(supervisor_identity_contract));
assert!(supervisor_system_prompt.contains("总控不能替代已有专业角色"));
assert!(!supervisor_system_prompt.contains("你拥有最终回复权"));
assert!(supervisor_prompt.contains(SUPERVISOR_NOTICE));
assert!(!supervisor_prompt.contains("你拥有最终回复权"));
assert!(!supervisor_prompt.contains(ORDINARY_NOTICE));
@@ -62,12 +62,12 @@ const SECTION_FILES: &[(&str, &str)] = &[
"provider/delegated-playtest-repair.md",
),
(
"providerSupervisorIdentityContract",
"provider/supervisor-identity-contract.md",
"supervisorIdentityContract",
"supervisor/identity-contract.md",
),
(
"providerSupervisorFinalReplyContract",
"provider/supervisor-final-reply-contract.md",
"supervisorFinalReplyContract",
"supervisor/final-reply-contract.md",
),
];
@@ -134,16 +134,17 @@ fn valid_manifest() -> Value {
],
"supervisor": [
"$base",
"supervisorIdentityContract",
"supervisorIntro",
"$visualContract",
"supervisorPlaybook",
"supervisorClaimGate",
"supervisorRepair"
],
"supervisorChat": [
"providerSupervisorIdentityContract",
"providerSupervisorFinalReplyContract"
]
"supervisorChat": {
"identity": "supervisorIdentityContract",
"finalReply": "supervisorFinalReplyContract"
}
},
"variants": {
"platform": {
@@ -158,7 +159,7 @@ fn valid_manifest() -> Value {
"roleOverlays": [
{
"agentId": "code-prototype",
"rootSource": "project-supervisor-game-chat",
"rootSourceKind": "supervisorGameChat",
"sections": ["codePrototypeGameChat"]
}
],
@@ -170,8 +171,7 @@ fn valid_manifest() -> Value {
"autonomousInitialCollaborationRepair": "providerAutonomousInitialCollaborationRepair",
"supervisorDeliveryConvergenceRepair": "providerSupervisorDeliveryConvergenceRepair",
"manifestDagWaitRepair": "providerManifestDagWaitRepair",
"delegatedPlaytestRepair": "providerDelegatedPlaytestRepair",
"supervisorIdentityContract": "providerSupervisorIdentityContract"
"delegatedPlaytestRepair": "providerDelegatedPlaytestRepair"
},
"agentCatalog": {
"supervisor": {
@@ -240,11 +240,17 @@ fn compiles_manifest_in_declared_order_and_emits_all_dependencies() {
"pub(crate) const RUNTIME_PROMPT_RUNTIME_COMPOSITION: &[&str] = &[\"$header\", \"common\", \"isolatedTemplateCatalogIntro\", \"$isolatedAgentTemplates\", \"isolatedAgentContract\", \"$platform\"];"
));
assert!(compiled.rust_source.contains(
"pub(crate) const RUNTIME_PROMPT_SUPERVISOR_COMPOSITION: &[&str] = &[\"$base\", \"supervisorIntro\", \"$visualContract\", \"supervisorPlaybook\", \"supervisorClaimGate\", \"supervisorRepair\"];"
"pub(crate) const RUNTIME_PROMPT_SUPERVISOR_COMPOSITION: &[&str] = &[\"$base\", \"supervisorIdentityContract\", \"supervisorIntro\", \"$visualContract\", \"supervisorPlaybook\", \"supervisorClaimGate\", \"supervisorRepair\"];"
));
assert!(compiled.rust_source.contains(
"pub(crate) const RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION: &[&str] = &[\"providerSupervisorIdentityContract\", \"providerSupervisorFinalReplyContract\"];"
"pub(crate) const RUNTIME_PROMPT_SUPERVISOR_CHAT_COMPOSITION: &[&str] = &[\"supervisorIdentityContract\", \"supervisorFinalReplyContract\"];"
));
assert!(compiled.rust_source.contains(
"pub(crate) const RUNTIME_PROMPT_ROLE_OVERLAYS: &[(&str, Option<RuntimePromptRootSourceKind>, &[&str])]"
));
assert!(compiled
.rust_source
.contains("Some(RuntimePromptRootSourceKind::SupervisorGameChat)"));
assert!(compiled
.rust_source
.contains("static CODE_AGENT_ROLES: [AgentRoleDefinition; 2]"));
@@ -440,6 +446,32 @@ fn rejects_unknown_duplicate_and_missing_composition_items() {
},
"缺少 marker$header",
);
assert_compile_error(
|manifest| {
manifest["compositions"]["supervisorChat"]["identity"] = json!("missingSection");
},
"composition supervisorChat.identity 引用了未知 section",
);
assert_compile_error(
|manifest| {
let identity = manifest["compositions"]["supervisorChat"]["identity"].clone();
manifest["compositions"]["supervisorChat"]["finalReply"] = identity;
},
"identity/finalReply 必须引用不同 section",
);
assert_compile_error(
|manifest| {
manifest["compositions"]["supervisor"] = json!([
"$base",
"supervisorIntro",
"$visualContract",
"supervisorPlaybook",
"supervisorClaimGate",
"supervisorRepair"
]);
},
"supervisor 必须复用 supervisorChat.identity section",
);
}
#[test]
@@ -477,6 +509,13 @@ fn rejects_invalid_provider_fragment_registry() {
},
"unknown field",
);
assert_compile_error(
|manifest| {
manifest["providerFragments"]["supervisorIdentityContract"] =
json!("supervisorIdentityContract");
},
"unknown field `supervisorIdentityContract`",
);
assert_compile_error(
|manifest| {
let section = manifest["providerFragments"]["delegatedPlaytestRepair"].clone();
@@ -507,6 +546,19 @@ fn rejects_unused_registered_and_unregistered_markdown_sections() {
#[test]
fn rejects_invalid_role_overlays() {
assert_compile_error(
|manifest| {
manifest["roleOverlays"][0]["rootSourceKind"] = json!("unknownSourceKind");
},
"unknown variant",
);
assert_compile_error(
|manifest| {
manifest["roleOverlays"][0]["rootSource"] =
manifest["roleOverlays"][0]["rootSourceKind"].take();
},
"unknown field `rootSource`",
);
assert_compile_error(
|manifest| manifest["roleOverlays"][0]["agentId"] = json!("unknown-agent"),
"未知 agentId",
@@ -538,12 +590,12 @@ fn rejects_invalid_role_overlays() {
manifest["roleOverlays"] = json!([
{
"agentId": "code-prototype",
"rootSource": null,
"rootSourceKind": null,
"sections": ["codePrototypeGameChat"]
},
{
"agentId": "code-prototype",
"rootSource": "project-supervisor-game-chat",
"rootSourceKind": "supervisorGameChat",
"sections": ["codePrototypeGameChat"]
}
]);
@@ -5940,7 +5940,7 @@
- 决策:把 `prompt.rs` 中依赖长自然语言精确匹配的链式 `.replace()` 拆成仓库内版本化 Prompt Bundle`build.rs` 读取、校验并生成静态 Rust 定义编译进 Tauri 二进制,生产源码不再直接引用 `prompts/runtime` 的单个 Markdown。
- 边界:Supervisor 的角色选择、并行委派、all-join、视觉返工、claim gate 和 repair 自然语言合同,以及 Supervisor / 六组专业 Agent 的编译期静态节点目录进入 Bundle。Bundle 不是完整可执行 graph,也不是生产 Skill;正式 DAG 依赖边、权限、安全门和完成合同继续由 Rust、`shared-contracts` 与校验后的项目协作策略掌控。
- 一致性:manifest 是 section、组合顺序、平台 / Editor 变体、role overlay、Provider 协作 fragment 和静态节点目录的单一来源;isolated / all-join、autonomous 首轮、首批协作修复、delivery 收敛、manifest wait、试玩后续委派,以及 Supervisor interaction / background planning / final-reply 身份合同不得在 Provider 或 `prompt.rs` 源码中复制。Supervisor 共享核心身份与最终回复专属规则拆成两个 sectionbackground planning 只注入核心身份interaction / final-reply 的 system prompt 按 manifest composition 组合两段,final-reply user context 不重复注入。构建脚本同时监听 Bundle 根目录、manifest 和已登记 section,拒绝未知字段、非法 / 重复 / symlink 路径、孤立 Markdown、未知 / 重叠 selector、节点 / alias / 生成标识符冲突,并强制专业节点 taskId / group / role 与正式 seed DAG 一致。原生工具目录仍从 `agent_runtime_native_executable_tools()` 生成,`mcp.call` 不混入静态原生目录;MCP 工具只从当前请求的动态 catalog 暴露。
- 一致性:manifest 是 section、组合顺序、平台 / Editor 变体、role overlay、Provider 协作 fragment 和静态节点目录的单一来源;role overlay 只接受 `rootSourceKind` 强类型语义 selector,构建期拒绝未知 kind,运行期再把权威 source 常量映射为生成的 kind,禁止在 manifest 中复制易漂移的 durable source 字符串。isolated / all-join、autonomous 首轮、首批协作修复、delivery 收敛、manifest wait、试玩后续委派,以及 Supervisor interaction / background planning / final-reply 身份合同不得在 Provider 或 `prompt.rs` 源码中复制。Supervisor 共享核心身份与最终回复专属规则拆成两个 sectionbackground planning 的 system composition 必须复用核心身份 sectioninteraction / final-reply 的 system prompt 按 manifest composition 组合核心身份与最终回复两段,所有 user context 不重复注入 Supervisor 身份。构建脚本同时监听 Bundle 根目录、manifest 和已登记 section,拒绝未知字段、非法 / 重复 / symlink 路径、孤立 Markdown、未知 / 重叠 selector、节点 / alias / 生成标识符冲突,并强制 Supervisor planning composition 复用 chat identity、专业节点 taskId / group / role 与正式 seed DAG 一致。原生工具目录仍从 `agent_runtime_native_executable_tools()` 生成,`mcp.call` 不混入静态原生目录;MCP 工具只从当前请求的动态 catalog 暴露。
## 2026-08-03 AI 游戏生成泥点不足使用确定性中断说明
@@ -78,7 +78,7 @@
V1.11 的受保护仓库控制目录同时包含 `.git / .agent / .agents / .codex / .hermes`;其中 `.agent` 对项目命令隐藏,其余控制目录只读。
2026-08-04 起,Runtime 的公共工具规划指令、Supervisor 协作编排 playbook、条件 overlay 和编译期静态 Agent 节点目录统一由版本化 Prompt Bundle 驱动,位于 `apps/ai-game-creator-shell/src-tauri/prompts/runtime/``manifest.json` 是 section 路径、组合顺序、平台 / Editor 变体、role overlay、Provider 协作 fragment,以及 Supervisor 与六组专业 Agent 静态目录的单一来源;`build.rs` 同时监听 Bundle 根目录、manifest 和已登记 section,并以失败关闭方式校验 schema、引用、路径 / symlink、孤立 Markdown、selector、节点身份、旧 alias 和生成标识符,再生成 `'static + Copy` Rust 定义并编译进发布二进制。生成的专业节点 taskId / group / role 还必须在构建期与 `shared-contracts::new_game_creation_app_seed_tasks()` 强一致,防止静态目录和正式 seed DAG 漂移。Bundle 承载公共指令、隔离 Agent 合同、平台差异、角色选择、并行委派、all-join、视觉返工、claim gateSupervisor 共享核心身份、interaction / final-reply 专属合同及其组合,以及首批协作、delivery 收敛、manifest wait、试玩后续委派等 repair 自然语言合同;background planning 只注入核心身份,final-reply user context 重复注入。`agent_runtime_native_executable_tools()` 仍是原生可执行工具的权威源列表,同时供 Prompt 工具目录与 native capability registry 使用,MCP 工具只从当前请求的动态 catalog 暴露。最终 Provider 请求必须通过生成的 section、composition、overlay 与 provider fragment API 构建,禁止恢复直接 `include_str!("prompts/runtime/...")`、在 Provider 或 `prompt.rs` 源码中复制协作 graph 文案,或依赖自然语言精确 `.replace()` 注入工具合同、平台规则或角色规则。Bundle 不是完整可执行 graph:正式 DAG 依赖边、权限、沙箱、委派容量、持久 all-join 状态机、完成门和身份校验仍由 Rust、`shared-contracts` 与经校验的 `.agent/collaboration-policy.json` 强制执行,不允许通过 Skill、外部配置或任意运行时 Prompt 覆盖绕过。
2026-08-04 起,Runtime 的公共工具规划指令、Supervisor 协作编排 playbook、条件 overlay 和编译期静态 Agent 节点目录统一由版本化 Prompt Bundle 驱动,位于 `apps/ai-game-creator-shell/src-tauri/prompts/runtime/``manifest.json` 是 section 路径、组合顺序、平台 / Editor 变体、role overlay、Provider 协作 fragment,以及 Supervisor 与六组专业 Agent 静态目录的单一来源;role overlay 只允许 `rootSourceKind` 强类型语义 selector,构建期拒绝未知 kind,运行期把权威 source 常量映射为生成 kind。`build.rs` 同时监听 Bundle 根目录、manifest 和已登记 section,并以失败关闭方式校验 schema、引用、路径 / symlink、孤立 Markdown、selector、节点身份、旧 alias 和生成标识符,再生成 `'static + Copy` Rust 定义并编译进发布二进制。生成的 Supervisor planning composition 必须复用 `supervisorChat.identity`专业节点 taskId / group / role 还必须在构建期与 `shared-contracts::new_game_creation_app_seed_tasks()` 强一致,防止身份合同、静态目录和正式 seed DAG 漂移。Bundle 承载公共指令、隔离 Agent 合同、平台差异、角色选择、并行委派、all-join、视觉返工、claim gateSupervisor 共享核心身份、interaction / final-reply 专属合同及其组合,以及首批协作、delivery 收敛、manifest wait、试玩后续委派等 repair 自然语言合同;background planning 在 system composition 复用核心身份,所有 user context 都不再重复注入 Supervisor 身份`agent_runtime_native_executable_tools()` 仍是原生可执行工具的权威源列表,同时供 Prompt 工具目录与 native capability registry 使用,MCP 工具只从当前请求的动态 catalog 暴露。最终 Provider 请求必须通过生成的 section、composition、overlay 与 provider fragment API 构建,禁止恢复直接 `include_str!("prompts/runtime/...")`、在 Provider 或 `prompt.rs` 源码中复制协作 graph 文案,或依赖自然语言精确 `.replace()` 注入工具合同、平台规则或角色规则。Bundle 不是完整可执行 graph:正式 DAG 依赖边、权限、沙箱、委派容量、持久 all-join 状态机、完成门和身份校验仍由 Rust、`shared-contracts` 与经校验的 `.agent/collaboration-policy.json` 强制执行,不允许通过 Skill、外部配置或任意运行时 Prompt 覆盖绕过。
2026-07-12 起,通用开发能力的 Runtime V1.1 增量以 [`【技术方案】AI游戏创作Agent Runtime V1.1-2026-07-12.md`](./【技术方案】AI游戏创作Agent%20Runtime%20V1.1-2026-07-12.md) 为编码级事实源。它补充仓库启动上下文、同一发布二进制独立 Runner、受限本地预览浏览器验证、动态隔离子 Agent 和真实 Provider 全链路验收;本文件中“进程内 tokio task”“首轮不预加载项目内容”和“不创建动态执行实例”的旧口径由 V1.1 明确替代,未涉及能力继续沿用本文件。