Compare commits

..

2 Commits

Author SHA1 Message Date
lhk229 dfb7617cbb 补充AGC工作目录创建测试
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Successful in 5m14s
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Successful in 5m33s
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Successful in 5m49s
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Successful in 5m52s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 1m39s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m23s
Project CI / Frontend tests (pull_request) Failing after 2m46s
Project CI / Repository checks (pull_request) Failing after 3m29s
Project CI / AI game creator shell web tests (pull_request) Failing after 3m24s
Project CI / Native shell tests (pull_request) Successful in 8m35s
Project CI / Backend tests (pull_request) Successful in 10m52s
覆盖子目录创建、重名和路径分隔符校验
2026-09-15 14:42:10 +08:00
lhk229 fa2a7caa95 新增AGC首页自定义工作目录
新增用户目录创建命令与首页接线

保持普通用户权限并避免ACL和UAC耦合

补充里程碑与实施计划
2026-09-15 14:38:04 +08:00
431 changed files with 6249 additions and 34926 deletions
@@ -32,7 +32,6 @@ Prefer `scripts/genarrative_external_api.py` for runnable REST calls. It uses on
- Use stable references such as `objectKey`, project resource ID, or asset ID where each operation permits them. Image edit/redraw is stricter: `sourceReferenceId` accepts only a registered project resource ID or asset ID; upload confirmation alone is not enough. Use `/assets/read-url` only for temporary preview/download access.
- Preserve both warning channels after completion. A general `warning` can coexist with `sliceWarning`; do not discard either.
- Do not invent missing derivatives. A source-preserved warning means the main source remains usable but requested post-processing failed. A slice warning means the complete transparent sheet is usable but individual slices are absent.
- Icon spritesheet generation accepts `sliceMode="connected-components"` (default alpha-connectivity detection) or `sliceMode="grid"`. Grid mode requires `gridX` and `gridY` (1-32); use `sliceCount` only to constrain connected-component output.
- For successful `style="pixelArt"`, treat completed-result and nested resource/asset dimensions as the final logical-grid PNG dimensions. They may differ from `size`, `imageSize`, the provider image, and `canvasCompletion.placeholder`; do not rescale or reject the artifact to match those inputs.
- Keep generated artifacts in the canvas and asset library together. Character animation accepts `assetFolderId` and `assetLabel`; its completed result directly returns the final `assetKind="character-animation"` resource and asset with formal sequence fields. Do not create a duplicate first-frame record.
@@ -52,7 +52,7 @@ Every generation row requires a stable `Idempotency-Key` header and returns HTTP
| Image generation | `/api/external/v1/editor/images/generations` | `prompt` | `kind`, `style`, `model`, `aspectRatio`, `imageSize`, `size`, `referenceImageSrcs`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion`, `generationInputs` |
| Image edit/redraw | `/api/external/v1/editor/images/edits` | `prompt`, `sourceReferenceId` | `referenceImageSrcs`, `model`, `size`, `projectId`, `assetFolderId`, `assetLabel`, `targetLayerId`, `canvasCompletion` |
| Background removal | `/api/external/v1/editor/images/background-removals` | `sourceImageSrc` | `projectId`, `sourceResourceId`, `targetLayerId`, static-image `assetKind`, `assetFolderId`, `assetLabel`, `canvasCompletion`, `generationInputs` |
| Icon spritesheet | `/api/external/v1/editor/icon-spritesheets/generations` | `referenceId`, `iconDescriptions` | `sliceMode`, `gridX`, `gridY`, `sliceCount`, `style`, `referenceImageSrcs`, `screenColor`, `model`, `aspectRatio`, `imageSize`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion` |
| Icon spritesheet | `/api/external/v1/editor/icon-spritesheets/generations` | `referenceId`, `iconDescriptions` | `sliceLayout`, `style`, `referenceImageSrcs`, `screenColor`, `model`, `aspectRatio`, `imageSize`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion` |
| UI asset extraction | `/api/external/v1/editor/ui-designs/assets/extractions` | `sourceImageSrc`, `aspectRatio`, `imageSize` | `screenColor`, `model`, `referenceImageSrcs`, `projectId`, `assetFolderId`, `spritesheetLabel`, `canvasCompletion` |
| Character animation | `/api/external/v1/editor/character-animations/generations` | `sourceLayerId`, `sourceImageSrc`, `sourceWidth`, `sourceHeight`, `promptText`, `resolution`, `ratio`, `frameCount`, `durationSeconds`, `model` | `projectId`, `sourceResourceId`, `assetFolderId`, `assetLabel`, `canvasCompletion` |
| Video generation | `/api/external/v1/editor/videos/generations` | `prompt`, `model`, `aspectRatio`, `durationSeconds`, `resolution`, `mode`, `sound` | `referenceImageSrcs`, `referenceVideoSrcs`, `referenceAudioSrcs`, `webSearchEnabled`, `projectId`, `assetFolderId`, `assetLabel`, `canvasCompletion` |
@@ -94,7 +94,7 @@ For image edit/redraw, confirming an upload is not sufficient: create a project
The icon-spritesheet primary `referenceId` is intentionally stricter than ordinary image references: it accepts only a current-owner project resource ID or asset ID whose authoritative `assetKind` is `icon-spec`. It does not accept an `objectKey`, URL, Data URL, or Blob URL.
`sliceMode` controls atlas splitting. Use `"connected-components"` (default) to detect independent opaque regions by alpha connectivity, or `"grid"` with positive `gridX` and `gridY` values (maximum 32 each). `sliceCount` optionally constrains the connected-component result.
`sliceLayout: "grid-2x2"` is an opt-in contract for four fixed game-runtime assets. The provider prompt and server persistence both preserve the ordered slots left-top, right-top, left-bottom, right-bottom. Omit it to retain the default connected-component slicing behaviour for ordinary free-form icon sheets.
## Common Values
@@ -79,9 +79,9 @@ Keep the existing autonomous-build task graph. Do not add a parallel task system
1. `art-director` generates `assets/art-spec.png` with image generation, `kind: "spec"`, then registers it as `assetKind: "icon-spec"`. This image is the authoritative visual spec; `generationInputs.artSpec` is supporting structured context.
2. `design-foundation` generates `assets/ui-prototype.png` with `kind: "ui-design"`, using the registered art-spec resource ID in `referenceImageSrcs`.
3. `art-asset-plan` generates transparent `assets/art-spritesheet.png` through icon spritesheet generation, using the same registered art-spec resource ID as `referenceId` plus concrete `iconDescriptions`. For a fixed four-category game contract it may send `sliceMode: "grid"`; for free-form assets use `sliceMode: "connected-components"` (the default).
3. `art-asset-plan` generates transparent `assets/art-spritesheet.png` through icon spritesheet generation, using the same registered art-spec resource ID as `referenceId` plus concrete `iconDescriptions`. For the four-category game contract it must also send `sliceLayout: "grid-2x2"`; this is an explicit fixed-slot contract, not a client-side guessed crop.
For a playable Canvas game, do not stop at generation. Make `code-prototype` depend on `art-asset-plan` and consume the persisted `iconImageSrcs` slices for core players, blocks or targets, scene obstacles, and feedback. When using the fixed four-category contract, require response `sliceMode: "grid"` and exactly four slices before registering the local runtime sheet; both fewer and extra components fail closed. Treat `art-spec.png` as reference-only. A full-sheet `<img>`, CSS background, path-only mention, guessed equal-grid crop, or code-drawn replacement for core entities is not runtime asset use. If slicing produces `sliceWarning`, keep the complete transparent sheet as a valid editor artifact, but fail the playable game asset gate until real slice files or verified atlas coordinates exist; never invent coordinates or replace the icon-spritesheet route with ordinary image generation.
For a playable Canvas game, do not stop at generation. Make `code-prototype` depend on `art-asset-plan` and consume the persisted `iconImageSrcs` slices for core players, blocks or targets, scene obstacles, and feedback. For the four-category game-chat contract, require response `sliceLayout: "grid-2x2"` and exactly four slices before registering the local runtime sheet; both fewer and extra components fail closed. Treat `art-spec.png` as reference-only. A full-sheet `<img>`, CSS background, path-only mention, guessed equal-grid crop, or code-drawn replacement for core entities is not runtime asset use. If slicing produces `sliceWarning`, keep the complete transparent sheet as a valid editor artifact, but fail the playable game asset gate until real slice files or verified atlas coordinates exist; never invent coordinates or replace the icon-spritesheet route with ordinary image generation.
Never use `assets/ui-prototype.png` as the spritesheet visual-spec reference. UI extraction is outside this canonical DAG.
@@ -881,14 +881,12 @@ def _self_test() -> None:
["蛇头向上", "蛇身直线", "转角", "尾部", "四类食物"],
canvasSession=session,
assetLabel="贪吃蛇透明图集",
sliceMode="connected-components",
referenceId="must-not-override-explicit-reference",
iconDescriptions=["不得覆盖显式图标描述"],
)
assert calls[0]["path"] == "/api/external/v1/editor/icon-spritesheets/generations"
assert calls[0]["body"]["referenceId"] == "editor-resource-spec"
assert calls[0]["body"]["screenColor"] == "auto"
assert calls[0]["body"]["sliceMode"] == "connected-components"
assert calls[0]["body"]["iconDescriptions"][0] == "蛇头向上"
assert calls[1]["path"] == "/api/external/v1/generations/task-operation-demo"
print("self-test ok")
+5 -10
View File
@@ -1,8 +1,8 @@
# Server-side OpenAI-compatible LLM endpoint base URL.
LLM_BASE_URL="https://api.tiantoken.com/v1"
LLM_BASE_URL="https://api.vectorengine.cn/v1"
# Server-side API key used by the local Vite proxy.
# Recommended: set `LLM_API_KEY` locally, or use `TIANTOKEN_API_KEY`
# Recommended: set `LLM_API_KEY` locally, or use `VECTOR_ENGINE_API_KEY`
# through the Rust api-server proxy.
# Legacy compatibility: `VITE_LLM_API_KEY` is still supported by the proxy,
# but it should not be relied on by browser code.
@@ -122,7 +122,7 @@ WECHAT_MINIPROGRAM_MESSAGE_ENCODING_AES_KEY=""
# Model name for chat completions.
VITE_LLM_MODEL="gpt-5.4-mini"
GENARRATIVE_LLM_PROVIDER="openai-compatible"
GENARRATIVE_LLM_BASE_URL="https://api.tiantoken.com/v1"
GENARRATIVE_LLM_BASE_URL="https://api.vectorengine.cn/v1"
GENARRATIVE_LLM_API_KEY=""
GENARRATIVE_LLM_MODEL="gpt-5.4-mini"
@@ -130,15 +130,10 @@ GENARRATIVE_LLM_MODEL="gpt-5.4-mini"
DASHSCOPE_BASE_URL="https://dashscope.aliyuncs.com/api/v1"
DASHSCOPE_API_KEY="YOUR_DASHSCOPE_API_KEY"
# Tiantoken LLM and GPT-image-2 / Gemini image generation config.
TIANTOKEN_BASE_URL="https://api.tiantoken.com"
TIANTOKEN_API_KEY=""
TIANTOKEN_IMAGE_REQUEST_TIMEOUT_MS="1000000"
# VectorEngine is retained for Suno audio generation only.
# VectorEngine LLM and GPT-image-2 / Gemini image generation config.
VECTOR_ENGINE_BASE_URL="https://api.vectorengine.cn"
VECTOR_ENGINE_API_KEY=""
VECTOR_ENGINE_AUDIO_REQUEST_TIMEOUT_MS="180000"
VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS="1000000"
# ElevenLabs editor sound-effect generation is server-side only.
ELEVENLABS_BASE_URL="https://api.elevenlabs.io"
-1
View File
@@ -164,7 +164,6 @@ module.exports = {
'server-rs/target-*',
'apps/desktop-shell/src-tauri/target',
'apps/ai-game-creator-shell/src/features/ui-editor/types/**',
'apps/ai-game-creator-shell/src/features/project-workspace/generated/**',
'target',
'src/main.tsx',
'src/App.tsx',
-4
View File
@@ -7,10 +7,6 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: project-ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
-3
View File
@@ -1,4 +1 @@
# Git 在链接工作树里执行 Hook 时会注入 GIT_DIR 等仓库定位变量,优先级高于 cwd;
# 子进程(npm、lint-staged、测试夹具)会继承它们并写到真实仓库,故在入口统一清除。
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_COMMON_DIR GIT_PREFIX GIT_CONFIG_PARAMETERS GIT_CEILING_DIRECTORIES
npm run format:staged
-3
View File
@@ -1,4 +1 @@
# Git 在链接工作树里执行 Hook 时会注入 GIT_DIR 等仓库定位变量,优先级高于 cwd;
# 钩子链(npm → check:repository-ci → 测试夹具)会继承它们并写到真实仓库,故在入口统一清除。
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE GIT_COMMON_DIR GIT_PREFIX GIT_CONFIG_PARAMETERS GIT_CEILING_DIRECTORIES
npm run check:pre-push-master -- "$@"
-29
View File
@@ -44,35 +44,6 @@ _Avoid_: 把同一资源的全局元数据和某一次摆放坐标混在同一
由图片生成或图片修改流程产生的画布资源,必须记录来源资源、提示词、实际提示词、模型、provider、任务 ID 和生成时间;本期 `/editor` 的生成修改先允许 mock 生成资源,但仍按生成资源元数据形状保存。
_Avoid_: 无来源的静态素材、只显示在 UI 但不落工程资源记录的生成结果
**图片模型历史值与使用端解析**:
图片资源中已持久化的 `gpt-image-2` 是历史业务事实,读回时保持原值;新任务使用业务模型值 `gpt-image-2.5`。当用户基于历史资源再次发起生成或编辑任务时,服务端只在新任务的使用端把历史值解析为当前业务模型,不改写历史资源。provider route 属于服务端执行与审计边界,前端不接收、不持久化、不展示,也不据此分支。
_Avoid_: 读取数据库时改写历史模型值、把 provider route 暴露为前端模型选项或公开 DTO
**图片 provider 显式路由**:
api-server 在任务入口按业务语义显式选择具体 provider model name(生成或编辑),并把同一具体名传给图片平台适配器和后台定价解析;图片平台适配器不从参考图数量或前端字段猜测任务。具体 provider model name 只存在于服务端调用、定价配置和审计边界。
后台管理 Web/API 是明确例外,可以查看和编辑两个具体定价 key;主站普通前端与公开定价 API 不接收这些 key。
_Avoid_: 让图片适配器隐式猜路由、让主站前端携带 provider model name
**业务模型**:
面向任务与产品契约的稳定模型值;当前 GPT 图片新任务的业务模型是 `gpt-image-2.5`。业务模型不等同于 provider 的具体计费/请求 model,也不暴露 provider 凭证或 endpoint。
_Avoid_: 把 provider concrete model 当作前端业务选项、用业务模型值直接推断 provider 凭证
**具体模型**:
服务端发送请求和定价使用的 concrete model name。GPT Image 2.5 生成与编辑分别是 `gpt-image-2.5-flare-c``gpt-image-2.5-sunburst-c`nanobanana 仍使用 `gemini-3.1-flash-image-preview`。具体模型只在服务端执行、定价和审计边界出现。
_Avoid_: 把具体模型写入普通前端 DTO、让未知字符串自动选择 provider
**provider client**:
按具体模型选出的外部图片 provider 连接配置,包含 provider identity、base URL 和 API keyVectorEngine 与 Tiantoken client 共享图片协议执行器,不复制请求/响应业务逻辑。两套 required client 在 api-server 启动时构造。
_Avoid_: 在首次请求时才创建 client、在 provider client 中复制尺寸/重试/审计逻辑、跨 provider credential fallback
**历史模型值**:
已持久化的 `gpt-image-2``gpt-image-2-c` 字符串,只作为历史事实原样读取和审计;基于历史资源提交新任务时,在使用端解析为当前 GPT Image 2.5 业务任务,不回写历史记录,也不把旧值作为现役 provider route。
_Avoid_: 数据库批量改写历史值、把历史值重新路由到 VectorEngine、把兼容解析扩散到普通前端
**GPT Image 2.5 新生成展示名**:
`GPT Image 2.5` 是新生成任务的产品展示名;历史资源与既有编辑上下文不因新模型上线而改写展示语义。
_Avoid_: 把新生成展示名扩散到历史记录、历史生成器或旧编辑上下文
**系列素材图集生成**:
一组同类素材的统一批量生成方式,采用批量规划、sheet 生图、后端切图、透明化、OSS 持久化和局部重生成的通用流水线。
_Avoid_: 为每个玩法单独发明素材流水线、把系列素材建模成任一玩法专属 DTO
@@ -38,7 +38,6 @@ vi.mock('../api/adminApiClient', () => ({
interface MockIntersectionObserverController {
enter: (target: Element) => void;
enterAll: (targets: Element[]) => void;
isObserved: (target: Element) => boolean;
}
@@ -107,25 +106,6 @@ function installIntersectionObserverMock(): MockIntersectionObserverController {
);
});
},
enterAll(targets) {
act(() => {
for (const target of targets) {
const record = observed.get(target);
if (!record) {
throw new Error('目标缩略图尚未进入 IntersectionObserver');
}
record.callback(
[
{
isIntersecting: true,
target,
} as IntersectionObserverEntry,
],
record.observer,
);
}
});
},
isObserved(target) {
return observed.has(target);
},
@@ -773,10 +753,10 @@ test('后台素材查询为大量同时可见的缩略图持续错峰换签', as
const thumbnails = entries.map((entry) =>
thumbnailElementForLabel(entry.label),
);
for (const thumbnail of thumbnails) {
thumbnails.forEach((thumbnail) => {
expect(observer.isObserved(thumbnail)).toBe(true);
}
observer.enterAll(thumbnails);
observer.enter(thumbnail);
});
await act(async () => {
await Promise.resolve();
});
@@ -796,7 +776,7 @@ test('后台素材查询为大量同时可见的缩略图持续错峰换签', as
await vi.advanceTimersByTimeAsync(200);
});
expect(getAdminAssetReadUrl).toHaveBeenCalledTimes(105);
}, 10_000);
});
test('后台素材查询读取更多后为新进入可视区域的素材换签', async () => {
const observer = installIntersectionObserverMock();
@@ -2,8 +2,6 @@
"schemaVersion": "game-creator-config.v2",
"agentMode": "codex_app_server",
"llm": {
"customEnabled": false,
"visibleModels": [],
"apiKey": "",
"baseUrl": "https://dev.genarrative.world/gpt/v1",
"model": "gpt-6-astra",
@@ -15,7 +13,7 @@
"autoCompactTokenLimit": 64000,
"toolOutputTokenLimit": 12000,
"requestTimeoutMs": 180000,
"maxRetries": 10,
"maxRetries": 2,
"retryBackoffMs": 500
},
"agentLlm": {}
+1 -4
View File
@@ -1,7 +1,7 @@
{
"name": "@genarrative/ai-game-creator-shell",
"private": true,
"version": "0.1.47",
"version": "0.1.29",
"type": "module",
"scripts": {
"dev": "node scripts/start-tauri-dev.mjs",
@@ -57,8 +57,6 @@
"react-colorful": "^5.8.0",
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"react-window": "^1.8.11",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
"vite": "^6.2.0",
"zustand": "^5.0.14"
@@ -71,7 +69,6 @@
"@testing-library/user-event": "^14.6.1",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/react-window": "^1.8.8",
"tailwindcss": "^4.1.14",
"typescript": "~5.8.2",
"vitest": "^0.34.6"
@@ -1295,7 +1295,7 @@ for (const requiredSource of [
}
}
if (tauriConfig.productName !== '陶泥儿') {
if (tauriConfig.productName !== 'Genarrative AI Game Creator') {
throw new Error('AI game creator shell productName drifted');
}
@@ -1307,19 +1307,19 @@ const expectedBundledDesignAgentResources = {
'design-agent': 'design-agent',
};
const expectedBundledWindowsResources = {
'resources/codex/win-x64/bin/codex.exe': 'coding-agent/win-x64/bin/codex.exe',
'resources/codex/win-x64/bin/codex.exe': 'codex/win-x64/bin/codex.exe',
'resources/codex/win-x64/bin/codex-code-mode-host.exe':
'coding-agent/win-x64/bin/codex-code-mode-host.exe',
'codex/win-x64/bin/codex-code-mode-host.exe',
'resources/codex/win-x64/codex-path/rg.exe':
'coding-agent/win-x64/codex-path/rg.exe',
'codex/win-x64/codex-path/rg.exe',
'resources/codex/win-x64/codex-resources/codex-command-runner.exe':
'coding-agent/win-x64/codex-resources/codex-command-runner.exe',
'codex/win-x64/codex-resources/codex-command-runner.exe',
'resources/codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe':
'coding-agent/win-x64/codex-resources/codex-windows-sandbox-setup.exe',
'codex/win-x64/codex-resources/codex-windows-sandbox-setup.exe',
'resources/codex/win-x64/codex-package.json':
'coding-agent/win-x64/codex-package.json',
'resources/codex/win-x64/NOTICE.md': 'coding-agent/win-x64/NOTICE.md',
'resources/codex/win-x64/manifest.json': 'coding-agent/win-x64/manifest.json',
'codex/win-x64/codex-package.json',
'resources/codex/win-x64/NOTICE.md': 'codex/win-x64/NOTICE.md',
'resources/codex/win-x64/manifest.json': 'codex/win-x64/manifest.json',
'resources/plugins': 'plugins',
};
assert.deepEqual(
+1 -1
View File
@@ -1725,7 +1725,7 @@ dependencies = [
[[package]]
name = "genarrative-ai-game-creator-shell"
version = "0.1.47"
version = "0.1.29"
dependencies = [
"agent-runtime-core",
"axum",
@@ -1,14 +1,11 @@
[package]
name = "genarrative-ai-game-creator-shell"
version = "0.1.47"
version = "0.1.29"
edition = "2021"
publish = false
[features]
default = []
# 模板库假数据注入(仅本地页面压测/演示用):只有显式开启该 feature 才会编译并在读取清单后
# 把条目循环补齐成假数据;计数由 AGC_TEMPLATE_LIBRARY_SYNTHETIC_COUNT 控制(默认 1000)。
template-library-fixtures = []
cocos-editor = ["cocos-editor-bridge/process-discovery"]
cocos-editor-execute = ["cocos-editor", "cocos-editor-bridge/windows-bootstrap"]
cocos-editor-injection = ["cocos-editor-execute", "cocos-editor-bridge/windows-injection"]
@@ -1,4 +1,4 @@
概念阶段定稿时,创建或更新 `project/速览卡.md`下面是速览卡的参考结构;根据游戏类型、项目规模和用户要求选择字段,同类内容可以合并,项目不需要的字段可以省略,复杂项目可以增加必要字段。表格和列表中的示例行可按实际对象逐行扩展,不代表数量上限
概念阶段定稿时,还必须创建或更新 `project/速览卡.md`Runtime 只检查该文件是否存在,不检查内容。请使用下面的固定结构,不要加入审批操作说明或独立的决定状态段落
# 速览卡:《游戏名》
@@ -20,7 +20,7 @@
## 6. 核心循环
## 7. 目标用户与情境
## 7. 目标用户
- 核心用户:
- 游戏偏好:
- 单次游玩时长:
File diff suppressed because one or more lines are too long
@@ -33,7 +33,7 @@ description: 写"美术圣经"(美术侧)分册时使用。与总纲(技
对象(资产总清单的范围)、物品表(item_id 绑定依据,数据侧已定)、
画风 skill(全局画风库可引用)。
2. 本件在数据侧表结构定稿后开写(素材清单引用 item_id)。
3.金样 exemplars/stardew-tdd-art-bible.md 了解契约表与资产状态表包含的信息类型(同层只读一次)。
3. 读金样 exemplars/stardew-tdd-art-bible.md——契约表与资产状态表的登记密度以它为准(同层只读一次)。
## 三、怎么写(模板即流程,按节)
@@ -34,7 +34,7 @@ description: 写"数据与配表"(数据侧)分册时使用。与总纲(
(架构层的定性基准,在本件落成前 N 日验算)。
2. 先读两份提取件:字段字典全套规则与验收模板已在那里成文,本件是
项目实例化,不是重新发明。
3.金样 exemplars/stardew-tdd-data.md 了解数据清单、验算表与验收结论包含的信息类型(同层只读一次)。
3. 读金样 exemplars/stardew-tdd-data.md——总清单规模、验算表与验收结论的写法以它为准(同层只读一次)。
## 三、怎么写(模板即流程,按节)
@@ -28,7 +28,7 @@ description: 写"技术实现"(程序侧)分册时使用。与总纲(技
1. 输入齐了吗:架构层系统范围表+P0 清单(拆模块依据)、数据侧表结构契约
(加载与校验要引用)、skill 选型卡(实现类需求先查卡,不自造轮子)。
2. 读总纲判断立场;本件在数据侧表结构定稿后开写。
3.金样 exemplars/stardew-tdd-tech.md 了解技术实现文档包含的信息类型(同层只读一次)。
3. 读金样 exemplars/stardew-tdd-tech.md——各节的填充密度与"实证参照"写法以它为准(同层只读一次)。
## 三、怎么写(模板即流程,按节)
@@ -13,13 +13,10 @@ description: 写游戏策划案(GDD)系统架构时使用。在顶层设计
> 本文件是系统架构层唯一承载写作流程的教学件。
> 模板与例子文件保持纯净:不含任何步骤、检验提示与标记。
## 〇、结构适配原则
本分册的章节、字段和数量是参考结构,不是固定清单。先根据游戏类型、项目规模、用户要求和顶层设计判断适用项:适用项写入,同类项可合并,若某项对本项目没意义则省略;复杂项目可以拆分补充,简单项目可以压缩为最小可用架构。
## 一、这一层的判断立场
你是架构师,切系统的刀在你手里。在这个层里你相信:
- 切分是为了**职责清晰、可独立讨论**,不是为了凑数量。只有确实需要独立职责、状态或数据边界的部分才拆成系统;每个实际拆出的系统应能说明删除后的影响。
- 切分是为了**职责清晰、可独立讨论**,不是为了凑数量——每个系统必须能
一句话答出"删了它,什么塌"(P0 原因)。
- **数据所有权唯一**:同一事实只由一个系统维护,其他系统只引用稳定 ID,
不复制主数据。两个系统管同一件事 = 架构事故。
- **依赖无环**是硬要求;信息呈现层只读状态、只经行动入口写入。
@@ -31,11 +28,11 @@ description: 写游戏策划案(GDD)系统架构时使用。在顶层设计
## 二、动笔前
1. 顶层设计已定稿可用——把它的**系统范围表**(粗清单)和**顶层定稿约束**
摊开当输入;切分是对粗清单的正式化(拆、并、裁都在这层做)。
2. exemplars/stardew-architecture.md 了解内容组织方式
2. 读 exemplars/stardew-architecture.md 做质量锚(模仿密度,不抄内容)
然后往 templates/architecture.md 里填。
3. 记住顶层的核心循环图——切完必须跑覆盖检查。
## 三、架构设计的组织维度:写什么、为什么、怎么咬合
## 三、十二节总览:写什么、为什么、怎么咬合
架构文档回答四个问题:
**这个架构为什么这样切(1~3)→ 系统是什么、怎么连接(4~6)→
@@ -77,7 +74,7 @@ description: 写游戏策划案(GDD)系统架构时使用。在顶层设计
三个接口:**对上**承顶层系统范围表并跑循环覆盖检查;**对内**地图↔职责↔依赖
三方一致、主数据归属唯一;**对下**目录映射 + MVP 闭环喂系统文档站。
## 四、怎么写(模板参考结构,建议按此组织
## 四、怎么写(模板即流程,十二节按序
(本节是带写法要领的教学版;实际填写的纯净模板在 templates/architecture.md
### 1. 架构定位与目标
@@ -88,10 +85,10 @@ description: 写游戏策划案(GDD)系统架构时使用。在顶层设计
→ 没有变更记录的架构文档,第二轮迭代就会变成黑箱。
### 2. 系统地图
Sxx 编号清单(核心系统通常 1-5 个,有明确要求可超出 5 个)+ 支撑层(存档/UI,不拥有核心规则)。
Sxx 编号清单(核心系统 2~12 个)+ 支撑层(存档/UI,不拥有核心规则)。
P0 段五列表:
| 系统 | 目的 | 输入 | 输出 | P0 原因 |
对实际拆出的系统说明删除后的影响;无法形成独立职责的部分合并,不为满足数量新增系统
每行 P0 原因必须答"删了它,__ 塌";答不出的降级或合并
### 3. 系统职责
| 系统 | 主要职责 | 不负责 → 移交谁 |
@@ -13,10 +13,6 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
> 本文件是概念层唯一承载写作流程的教学件。
> 模板与例子文件保持纯净:不含任何步骤、检验提示与标记。
## 〇、结构适配原则
本分册的章节、字段和数量是参考结构,不是固定清单。先根据游戏类型、项目规模、用户要求和上层已定范围判断适用项:适用项写入,同类项可合并,若某项对本项目没意义则省略;复杂项目可以拆分补充,简单项目可以压缩为最小可用规格。
## 一、这一层的判断立场
你是资深游戏策划,看过上千份概念案,清楚绝大多数死在"什么都说、什么都不尖"。
在这个层里你相信:
@@ -31,11 +27,11 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
## 二、动笔前
1. 拿到用户真实回答过的定调信息(参照对象、题材偏好、压力档位)。
没有 → 先问一个定调问题,禁止自问自答充当用户。
2. exemplars/stardew-concept.md 了解内容组织方式
2. 读 exemplars/stardew-concept.md 做质量锚(模仿密度,不抄内容)
然后往 templates/concept-design.md 里填。
3. 零参照时在文档头注明"零参照"。
## 三、概念设计的组织维度:写什么、为什么、怎么咬合
## 三、九节总览:写什么、为什么、怎么咬合
概念文档回答四个问题:
**这是什么(1~5)→ 它不是什么(6)→ 它靠什么让人一直玩(7)→
@@ -54,7 +50,7 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
| 6 | 不是什么 | 负面定位表:不是 X,因为 Y | 正面定义写多必然发散;负面定位用"误会方向+封死原因"收边界,比光秃的非目标锋利一档 | 2 的非目标与跑偏风险的表化展开;与 5 的防串味声明呼应 |
| 7 | 核心张力 | 玩家持续面对的两难,两端各有代价 | 长期游玩的根本动力;没有张力,再丰富的内容玩几次就腻 | **向下接口**:每条张力必须在顶层变成取舍表里的具体决策 |
| 8 | 边界与约束 | 本层只定什么、什么留给后面 + 规模回流 | 防止概念层越层写数值和系统(越层是下游返工之源);给写作画线 | 保护 2 的纯度;告诉顶层"你们的地盘从哪开始" |
| 9 | 概念定稿 | "核心不是 __ 而是 __"重述 + 按需记录给顶层的约束 | 收口并检查概念是否写散;把承诺成对下的契约 | 回环呼应 1;把边界和交接约束传给下一层 |
| 9 | 概念定稿 | "核心不是 __ 而是 __"重述 + 给顶层的约束 | 收口重锤:写完九节重述一遍,检验整份文档有没有写散;把承诺成对下的契约 | 回环呼应 1;把 8 的交接具体化成 2~4 条硬约束 |
咬合一图:
@@ -73,7 +69,7 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
记住三个接口:**对内**锚点仲裁一切;**对下**张力变取舍表、定稿变硬约束;
**对上**边界画线防止越层。九节不是清单,是一台咬合的机器。
## 四、怎么写(模板参考结构,建议按此组织
## 四、怎么写(模板即流程,九节按序
(本节是带写法要领的教学版;实际填写的纯净模板在 templates/concept-design.md
### 1. 一句话概念
@@ -84,7 +80,7 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
**定调记录**(全项目调性真源,此节定死):
- 参照选择:以 __ 为主、__ 学 __(参照即定调,选完调性随之而来)。
- 调性滑杆:压力感/战斗比重/管理深度/叙事比重/节奏,各一档。
- 调性锚 T 原则:按项目需要提炼并逐条具名(如"T2 不劝退——凡惩罚类问题默认取最轻档")。
- 调性锚 T 原则:3~7 条逐条具名(如"T2 不劝退——凡惩罚类问题默认取最轻档")。
检验:每条 T 都能当一句 IF-THEN 用——"凡__类问题默认__";写不出口径的 T 是空话。
→ 下游每个开放问题先来这里级联批量起草,级联不了的才升级提问。
**设计锚点(六项,争议时的仲裁原则,全部具名)**
@@ -116,7 +112,8 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
### 7. 核心张力
- __ 有限,但 __
- __ vs __(两端的代价各是什么)。
如果项目存在核心张力,保留的每条张力都应说明双方代价;没有形成有效张力时,不为了满足结构新增张力。这些是顶层取舍表的种子,后面按需对应。
每条两端都必须有代价,只有一端的"假张力"删掉。这些是顶层取舍表的
种子,后面要逐条对应。
### 8. 边界与约束
- 概念边界放首位:本层只定幻想、用户、基调与排除方向;具体数值、
@@ -127,9 +124,9 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
### 9. 概念定稿(收口重锤)
这个游戏的核心不是 __,而是:
> (一句话重述核心承诺)
交给下一层的约束:按项目需要记录,顶层据此展开。
交给下一层的约束:__ 必须 __2~4 条,顶层必须围绕它们展开
某节对本项目没意义,直接省略
某节对本项目没意义 → 写一行"略,因为 __",不硬凑
## 五、分析文档(全局一份,按层分节)
@@ -161,4 +158,4 @@ description: 写游戏策划案(GDD)概念层时使用。把一句话游戏
## 七、红线(只有三条)
1. 不冒充用户决定:用户没说的方向标"待确认",正文不写死。
2. 不越层:出现具体数值、按键、界面即删。
3. 不凑数:章节对项目有意义但信息不足时,记录已确定内容与待补问题;章节对项目无意义时,直接省略
3. 不凑数:写不满就说明缺什么,禁止万金油句填充
@@ -2,7 +2,7 @@
---
name: game-gdd-system-doc
description: 写单个系统的设计文档(Sxx)时的总纲——通用纪律、十二类常见内容
description: 写单个系统的设计文档(Sxx)时的总纲——通用纪律、十二节同构骨架
红线与分析文档格式。每类系统的专属写法与模板在 modules/system-types/ 下对应目录的 SKILL.md
与对应模块的模板.md 里,按需取用。
---
@@ -12,10 +12,6 @@ description: 写单个系统的设计文档(Sxx)时的总纲——通用纪
> 本文件是系统文档层的总纲;各系统的专属写法在 `modules/system-types/` 下对应目录的 `SKILL.md`
专属模板在 `modules/system-types/` 对应目录的 `模板.md`。通用纪律不在各系统 skill 里重复。
## 〇、结构适配原则
本分册的章节、字段和数量是参考结构,不是固定清单。先根据系统类型、实际复杂度、用户要求和架构职责判断适用项:适用项写入,同类项可合并,若某项对本系统没意义则省略;复杂系统可以拆分补充,简单系统可以压缩为最小可执行规格。
## 一、这一层的判断立场
你是写单个系统的策划。在这个层里你相信:
- 系统文档是**执行层**:刀已经在架构层切好——服从系统地图编号、职责表
@@ -24,15 +20,15 @@ description: 写单个系统的设计文档(Sxx)时的总纲——通用纪
防返工价值最高的几行。
- 接口纪律:引用具名系统与具名数据,禁泛称;别家主数据只引 ID 不复制。
- 字段定义、数值配置、表结构不归你——写交接声明,交技术文档层(数值策划)。
- 系统文档保持基本可读的一致性,但不要求所有系统使用相同章节;结构应服从系统类型和实际行为
- 所有系统同构:读者读熟一份就能读所有份
## 二、动笔前
1. 架构已定稿:找到本系统的 Sxx 编号、职责表行、依赖方向——这是合同。
2. 在 01~12 文件夹里选最接近的系统类型(可组合,如"钓鱼"=05 采集+06 战斗
的判定部分),读取对应的 `SKILL.md``模板.md`
3. 该文件夹标注"参考例子"的,先读例子了解写法
3. 该文件夹标注"必读例子"的,先读例子全文做密度锚
## 三、常见内容总览:写什么、为什么、怎么咬合
## 三、十二节总览:写什么、为什么、怎么咬合
系统文档回答四个问题:
**这个系统为什么存在(1~2)→ 玩家怎么用它(3~5)→ 它怎么运转(6~8)→
@@ -47,7 +43,7 @@ description: 写单个系统的设计文档(Sxx)时的总纲——通用纪
| 5 | 取舍表 | 玩家在本系统内的决策 | 张力在系统内的落地 | 概念张力→顶层取舍表→本表 |
| 6 | 状态与规则 | 对象/状态/转换/异常,枚举表达 | 定性规则真源 | 架构职责表对齐 |
| 7 | 数值与数据交接 | 本系统交 TDD 的数据类别+定性约束 | 分层边界 | 技术文档层承接 |
| 8 | 反馈 | 关键结果何时、以何种方式反馈 | 让实际结果可理解 | 与本系统实际结果对应 |
| 8 | 反馈 | 何时/何强度/何通道 | 无反馈=没发生 | 顶层反馈四层 |
| 9 | 内部循环 | 本系统内的小循环 | 系统自己的心跳 | 顶层小循环的组成 |
| 10 | 输入、输出与依赖 | 消费/交付/依赖谁 | 接口真源 | 架构依赖图逐边对齐 |
| 11 | 边界与非目标 | 不负责什么→移交谁 | **防返工价值最高** | 架构职责表"不负责"列 |
@@ -56,20 +52,20 @@ description: 写单个系统的设计文档(Sxx)时的总纲——通用纪
咬合:**对上**服从架构三条合同(编号/职责/依赖);**对内**状态与接口不越
职责边界;**对下**第 7 节交接喂 TDD。
## 四、常见内容的参考写法
## 四、十二节通用写法
(各系统类型的特殊写法见对应文件夹 SKILL.md;纯净模板在其 模板.md
1 系统目的:若删除它,__ 会塌——一句话说不出 = 该系统不该存在。
2 支撑体验:对应顶层目标第__条、调性原则第__条。
3 进入与退出:按本系统实际存在的入口、退出和恢复路径记录
4 玩家行动:记录本系统实际存在的具名动词组;编排类写"安排"动词,活动类写"操作"动词。
3 进入与退出:常规进入/读档恢复/特殊事件后返回,三入口必写
4 玩家行动:≥4 个具名动词组;编排类写"安排"动词,活动类写"操作"动词。
5 取舍表:决策/立即收益/延迟收益/主要代价;挂顶层张力编号。
6 状态与规则:对象-状态-转换-异常,全部枚举表达,不许整段散文。
7 数值与数据交接:列数据类别名 + 设计侧定性约束;字段定义归 TDD。
8 反馈:记录本系统关键结果的可理解反馈;存在失败时说明原因和恢复路径。
8 反馈:每种关键结果给独立反馈形态;失败必须说明原因和恢复路径。
9 内部循环:动词链;可拆单次/区域/长期三层。
10 输入输出与依赖:引用具名系统与具名数据,禁泛称"资源"。
11 边界与非目标:参考该类型 skill 的三不”说明边界;建议说明字段数值的交接边界
11 边界与非目标:该类型 skill 的"三不"写全;必含"字段数值归 TDD"一条
12 开放问题:结构级才留;手感数值类标"待原型验证"。
## 五、分析文档(全局一份,按层分节)
@@ -104,4 +100,4 @@ description: 写单个系统的设计文档(Sxx)时的总纲——通用纪
1. 不冒充用户决定:用户没说的方向标"待确认",正文不写死。
2. 不越层:不翻架构的案(要改走分析文档+登记表),不写字段数值(归 TDD),
不替别的系统定规则。
3. 不凑数:写不出"删了塌什么"的系统直接删除;章节对项目有意义但信息不足时,记录已确定内容与待补问题
3. 不凑数:写不出"删了塌什么"、填不满的节,说明缺料——停笔说明,不硬凑
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More