合并主线并修复画布快速编辑冲突
Project CI / Repository checks (pull_request) Failing after 46s
Project CI / Native shell tests (pull_request) Failing after 1m48s
Project CI / Frontend tests (pull_request) Successful in 2m58s
Project CI / Backend tests (pull_request) Successful in 3m49s

合并 Godot 项目导入与 AGC 原生 HTTP 能力。
保留图片快速编辑业务 ID 契约并移除退役 redraw 分支。
同步共享决策、画布文档与回归测试。
This commit is contained in:
2026-08-11 14:22:40 +08:00
47 changed files with 1307 additions and 778 deletions
+76 -7
View File
@@ -64,6 +64,24 @@ const aiGameCreatorShellTauriSource = readSourceTree(
'apps/ai-game-creator-shell/src-tauri/src',
'.rs',
);
const aiGameCreatorClientHttpSource = fs.readFileSync(
'apps/ai-game-creator-shell/src/services/clientHttp.ts',
'utf8',
);
const aiGameCreatorMainCapability = JSON.parse(
fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/capabilities/main.json',
'utf8',
),
);
const aiGameCreatorCargoManifestSource = fs.readFileSync(
'apps/ai-game-creator-shell/src-tauri/Cargo.toml',
'utf8',
);
const aiGameCreatorViteConfigSource = fs.readFileSync(
'apps/ai-game-creator-shell/vite.config.ts',
'utf8',
);
const productionShellScanRoots = [
'apps/mobile-shell',
@@ -2355,6 +2373,46 @@ function assertAiGameCreatorShellUserDevBoundary() {
'AI game creator dev shell must keep local preview iframe access for the developer window',
);
}
if (
!aiGameCreatorClientHttpSource.includes(
"'https://dev.genarrative.world'",
) ||
!aiGameCreatorClientHttpSource.includes("transport: 'tauri-http'") ||
!aiGameCreatorClientHttpSource.includes('target.origin !==')
) {
throw new Error(
'AI game creator release dev API transport boundary drifted',
);
}
if (
!aiGameCreatorCargoManifestSource.includes('tauri-plugin-http = "2.5.9"') ||
!aiGameCreatorShellTauriSource.includes('tauri_plugin_http::init()')
) {
throw new Error(
'AI game creator release must register the native HTTP plugin',
);
}
if (
!aiGameCreatorViteConfigSource.includes("dedupe: ['react', 'react-dom']")
) {
throw new Error(
'AI game creator monorepo build must dedupe React runtime packages',
);
}
const httpPermission = (aiGameCreatorMainCapability.permissions ?? []).find(
(permission) =>
typeof permission === 'object' &&
permission?.identifier === 'http:default',
);
if (
!httpPermission ||
JSON.stringify(httpPermission.allow ?? []) !==
JSON.stringify([{ url: 'https://dev.genarrative.world/api/*' }])
) {
throw new Error(
'AI game creator native HTTP scope must stay limited to the dev API',
);
}
for (const snippet of [
'function isDeveloperMode()',
@@ -2369,11 +2427,13 @@ function assertAiGameCreatorShellUserDevBoundary() {
}
for (const snippet of [
'projectSupervisorOnly ? false : isDeveloperMode()',
"{devMode ? (",
'{devMode ? (',
'className="developer-pane"',
]) {
if (!aiGameCreatorShellAppSource.includes(snippet)) {
throw new Error(`AI game creator user/dev UI boundary drifted: missing ${snippet}`);
throw new Error(
`AI game creator user/dev UI boundary drifted: missing ${snippet}`,
);
}
}
if (
@@ -2391,13 +2451,20 @@ function assertAiGameCreatorShellUserDevBoundary() {
const previewFrameCount = [
...aiGameCreatorShellDeveloperProjectPanelsSource.matchAll(/<iframe\b/g),
].length;
const devModeBranchIndex = aiGameCreatorShellAppSource.indexOf('{devMode ? (');
const developerPaneIndex = aiGameCreatorShellAppSource.indexOf('className="developer-pane"');
const devModeBranchIndex =
aiGameCreatorShellAppSource.indexOf('{devMode ? (');
const developerPaneIndex = aiGameCreatorShellAppSource.indexOf(
'className="developer-pane"',
);
if (previewFrameCount !== 1) {
throw new Error('AI game creator developer pane preview frame count drifted');
throw new Error(
'AI game creator developer pane preview frame count drifted',
);
}
if (developerProjectPanelIndexes.length !== 1) {
throw new Error('AI game creator developer project panels mount count drifted');
throw new Error(
'AI game creator developer project panels mount count drifted',
);
}
if (
devModeBranchIndex < 0 ||
@@ -2406,7 +2473,9 @@ function assertAiGameCreatorShellUserDevBoundary() {
(index) => index < devModeBranchIndex || index < developerPaneIndex,
)
) {
throw new Error('AI game creator preview panels must stay inside the dev-only pane');
throw new Error(
'AI game creator preview panels must stay inside the dev-only pane',
);
}
// 上面几条只约束 DeveloperProjectPanels 自身的 iframe 数量和挂载位置,管不到 App.tsx
// 直接内嵌 iframe 的情况——预览必须一律委托给客户端工作台,外壳自己不持有预览框。