diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index cf2f89177..ae8275e7c 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -164,6 +164,10 @@ module.exports = {
'server-rs/target-*',
'apps/desktop-shell/src-tauri/target',
'apps/ai-game-creator-shell/src/features/ui-editor/types/**',
+ // ts-rs 生成绑定:不接受 eslint --fix 二次改写,必须与原始输出逐字节一致
+ 'packages/shared/src/contracts/generated/**',
+ 'apps/ai-game-creator-shell/src/view/project-development/chat/generated/**',
+ 'apps/ai-game-creator-shell/src/services/generated/**',
'apps/ai-game-creator-shell/src/features/project-workspace/generated/**',
'target',
'src/main.tsx',
diff --git a/.gitattributes b/.gitattributes
index 572a7e25f..a63eef88a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -24,5 +24,10 @@
*.anim text
*.controller text
-# Rust ts-rs 生成的共享契约:保留在仓库中供 TS 消费,但不作为手写源文件统计。
-packages/shared/src/contracts/generated/** linguist-generated=true
+# ts-rs 生成绑定:保留在仓库中供 TS 消费,但不作为手写源文件统计。
+# ts-rs 原始输出在多行对象 / 枚举变体后带行尾空格,生成目录统一豁免行尾空白检查;
+# 一致性由 `npm run check:generated-bindings` 逐字节比对原始输出来保证。
+packages/shared/src/contracts/generated/** linguist-generated=true whitespace=-trailing-space
+apps/ai-game-creator-shell/src/features/ui-editor/types/** linguist-generated=true whitespace=-trailing-space
+apps/ai-game-creator-shell/src/view/project-development/chat/generated/** linguist-generated=true whitespace=-trailing-space
+apps/ai-game-creator-shell/src/services/generated/** linguist-generated=true whitespace=-trailing-space
diff --git a/.prettierignore b/.prettierignore
index 9ec6037f3..a32676e37 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,7 +3,11 @@ node_modules
.git
.codex-logs
public/Icons
+# ts-rs 生成绑定:一律以原始输出提交,禁止 prettier 二次改写
+packages/shared/src/contracts/generated/
apps/ai-game-creator-shell/src/features/ui-editor/types/
+apps/ai-game-creator-shell/src/view/project-development/chat/generated/
+apps/ai-game-creator-shell/src/services/generated/
apps/ai-game-creator-shell/src-tauri/resources/agc-skills/
media
*.log
diff --git a/.prettierrc.json b/.prettierrc.json
index c4f9a8e5d..7d2081a95 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,14 +1,5 @@
{
"singleQuote": true,
"semi": true,
- "trailingComma": "all",
- "overrides": [
- {
- "files": "packages/shared/src/contracts/generated/**/*.ts",
- "options": {
- "printWidth": 1000,
- "singleQuote": false
- }
- }
- ]
+ "trailingComma": "all"
}
diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent.rs b/apps/ai-game-creator-shell/src-tauri/src/agent.rs
index 7a2fd4162..110b0b918 100644
--- a/apps/ai-game-creator-shell/src-tauri/src/agent.rs
+++ b/apps/ai-game-creator-shell/src-tauri/src/agent.rs
@@ -29,8 +29,6 @@ mod direct_project_turn_history;
mod direct_runtime;
mod direct_tool_bridge;
mod direct_tools_mcp;
-mod direct_turn_error;
-mod direct_turn_failure;
mod direct_validation;
mod generation;
pub(crate) mod json_sidecar;
@@ -50,11 +48,12 @@ pub(crate) use claude_code_cli::{
game_creator_claude_code_cli_version_identity,
};
pub(crate) use codex_app_server::direct_game_creator_codex_chat_at;
+pub(crate) use codex_app_server::turn_error::*;
use codex_app_server::*;
#[cfg(not(test))]
pub(crate) use codex_app_server::{
cancel_direct_codex_turn_at, direct_game_creator_home_codex_chat, thread_id_for_project,
- DirectTurnCancelView,
+ TurnCancelView,
};
use codex_cli::*;
pub(crate) use codex_cli::{
@@ -72,8 +71,6 @@ pub(crate) use direct_project_turn_history::*;
pub(crate) use direct_runtime::*;
pub(crate) use direct_tool_bridge::*;
pub(crate) use direct_tools_mcp::*;
-pub(crate) use direct_turn_error::*;
-pub(crate) use direct_turn_failure::*;
pub(crate) use direct_validation::DirectValidationConfig;
pub(crate) use generation::*;
pub(crate) use json_sidecar::*;
diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/claude_code_cli.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/claude_code_cli.rs
index d5c33e971..65b71e4d6 100644
--- a/apps/ai-game-creator-shell/src-tauri/src/agent/claude_code_cli.rs
+++ b/apps/ai-game-creator-shell/src-tauri/src/agent/claude_code_cli.rs
@@ -375,7 +375,7 @@ async fn run_sidecar_turn(
pub(crate) fn cancel_direct_claude_code_turn_at(
root: &Path,
client_turn_id: Option<&str>,
-) -> Result