合入独立game-chat release构建、内置Runner与退出收束。 合入自动预览刷新、结构化进度展示及强化试玩验收。 保留master资源画布、共享预览和原生壳严格门禁。 修复Windows Runner单实例锁与GUI owner锁固定路径兼容。
72 KiB
开发工作流
用途:给本地 Agent 和开发人员提供统一的开发、测试、提交流程。具体命令以
package.json、server-rs/Cargo.toml、AGENTS.md和相关docs/最新文档为准。
标准任务流程
同步代码 → 读取 AGENTS.md → 复杂任务读取 Agent 执行准则 → 读取 docs/project-memory/shared-memory → 查找/完善 docs → 制定计划 → 小步实现 → 本地验证 → 更新文档/记忆 → 提交
建议启动方式
在项目根目录启动本地 Agent:
cd /path/to/Genarrative
hermes
在本机当前常见路径为:
/home/dsk/workspace/Genarrative
其他开发者以自己本地实际路径为准,不要把个人绝对路径写入共享文档作为通用规则。
开发前检查清单
- 当前分支是否正确
- 是否已拉取最新代码
- 是否阅读
AGENTS.md - 复杂任务是否阅读
docs/【协作规范】Agent工作入口与执行准则-2026-06-22.md - 是否阅读
docs/project-memory/shared-memory/相关文件 - 是否阅读
README.md中的运行和检查命令 - 是否阅读
docs/README.md及任务相关分类 README - 是否存在足够具体的 PRD / 设计 / 技术文档
- 是否明确测试、验收和文档更新方式
本地运行命令
安装依赖:
npm install
仓库当前不使用 npm workspaces,根目录 npm install 是统一安装入口。子包新增运行时依赖时,必须同步写入根 package.json 和根 package-lock.json;不能只修改子包 package.json。
完整联调开发环境:
npm run dev
AI 游戏创作独立客户端常用短命令:
npm run agc
需要构建只能打开“游戏运行 + 聊天”页面的独立 release 包时使用:
npm run agc:build:game-chat-release
该命令启用 Rust game-chat-release feature,并配合编译期前端入口锁定生成独立 NSIS 包。当前专用 release 版本为 0.1.1;产物的 productName 为 Genarrative Game Chat,identifier 为 world.genarrative.ai-game-creator.game-chat,安装身份和 AppData 不与普通 AI 游戏创作客户端混用。独立包直接渲染本地 GameChatReleaseApp,绕过平台 AuthenticatedClient,进入本地项目工作台不依赖 api-server;普通 npm run agc、npm run agc:dev、debug game-chat 和 npm run agc:build 继续走既有认证入口与配置。
game-chat 的用户可见 preview 必须由 Tauri 客户端 PreviewRegistry 持有。External Runner 和 Tauri 的 registry、server 句柄与 running 状态是进程内资源,不得互相推断或把 Runner 验证用 server 直接交给 iframe。当前 accepted Supervisor 父 run 下真实 preview-playtest scheduler child 首次给出结构化成功证据、且其 revision 精确等于项目当前 revision 后,客户端才消费一次性授权并启动一个 Tauri preview server,随后自动显示 iframe;preview.start 必须携带 expectedRevision,Tauri 在取得项目写锁后再次原子比对。same-run steer 授权必须记录授权前 revision / validation cursor 和唯一 generation ID,旧证据、旧 policy await 或旧 start 返回均不能清除新授权。同一 run 的更高 validated revision 只刷新原 iframe,不能重复 preview.start 或新增 server,相同 / 更低 revision 不刷新;同 revision 的最新失败证据必须关闭该 revision 的可玩判定。preview HTTP 的 HTML、脚本、样式、资源和错误响应都必须返回 Cache-Control: no-store。没有 Tauri 用户预览时,顶部状态必须显示“预览未启动”,不能只写“未启动”。
generic-v1 的真实试玩必须从 ready 且正整数 level 开始;start 推进到 playing 后,必须先持续观察 2 秒并取得至少 8 个实际样本,期间保持 playing,以确认玩家获得正常操作机会;随后点击唯一可见、启用且真实可交互的 data-playtest-id="primary-action",由该控件触发真实主要玩法操作,并以 sequence 相对点击前严格推进证明操作已被接受。操作被接受前进入 won | lost 代表玩家没有获得正常操作机会,必须失败;操作被接受后的单次 lost 是合法结局,但不能成为所有受控尝试的唯一结果。若主要操作后仍为 playing,则继续观察 3 秒并取得至少 12 个实际样本;won 可提前证明非失败推进。之后 restart 必须推进 sequence、恢复到 ready | playing,并持续观察 3 秒、取得至少 12 个实际样本;若首轮结果为 lost,重开稳定后必须再执行一次必要的 start、2 秒 / 8 样本操作机会和真实 primary-action,第二次必须进入或保持 playing(再观察 3 秒 / 12 样本且不得转为 lost)或进入 won。两次受控尝试都固定 lost 代表无法正常推进的恶性 bug,必须失败。各观察窗口内 sequence 不得回退,restart 窗口只能保持 ready | playing。样本数和观察时长必须同时满足,窗口末端必须强制再读取一次有效状态,不能靠前段样本数提前通过。selector、时长、样本门槛、终态边界、非失败推进、窗口末端覆盖、required assertions 和 sequence 规则都属于 scenario fingerprint。旧 fingerprint 回执在读取和 plan liveness 检查时按 stale missing 处理,让同一 run 可重新 preview.validate;身份、digest、路径或内容完整性篡改仍失败关闭,最终完成门仍须现场重算当前 fingerprint 并严格拒绝旧证据。
进度展示只把结构化 preview.validate 的 passed=true && playtestPassed=true 认作试玩通过,不从 summary 的 :ok 推断结论。image.inspect status=ok 只表示工具成功;passed=null 或缺少结构化布尔结论时显示中性“截图分析完成”,不得显示绿色通过。
真实 Chrome 回归必须用同一前缀同时覆盖尚未接受 primary-action 就瞬时进入 lost 的 FAIL、两次受控尝试都固定 lost 的 FAIL,以及首轮合法 lost 后重开并在第二轮证明非失败推进的 PASS:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml real_chrome_generic_playtest_ --features game-chat-release -- --ignored --nocapture --test-threads=1
修改 game-chat release flavor 后,至少执行壳配置门禁、AppSurface game-chat 定向测试、前端类型检查、AppData / 诊断日志 / release flavor 相关 Rust 定向测试、npm run check:encoding 和 git diff --check。打包 smoke 必须确认:安装信息和产物版本为 0.1.1;无参数启动直接进入且只能停留在 game-chat 页面;停止或断开 api-server 后本地工作台仍能打开;普通 dev / release 与 debug game-chat 仍走原认证入口;独立 AppData 生效。预览 smoke 应先让当前 run 成功验证 revision N,确认 Tauri registry 启动一个 server 且 iframe 自动出现;在 validate 后、start 取得锁前推进项目 revision,必须确认原子 expectedRevision 门禁拒绝启动且授权保留等待新证据;再验证 revision N+1,确认 server 进程和 loopback origin 不变、iframe 显示新版本且响应为 no-store。same-run steer 还要覆盖旧验证不消费新授权、旧异步 attempt 不清新 generation;Runner registry 单独 running、失败 / 相同 / 更低 revision 均不能触发用户预览或重复刷新,停止后顶部显示“预览未启动”。独立包退出时必须通过 runner.shutdown_for_client_exit 先进入 draining 再结束本 boot,保留 durable sidecar 供下次 reconciliation,不把中断任务写成 completed;Windows Runner 必须 CREATE_SUSPENDED -> AssignProcessToJobObject -> ResumeThread,分配或恢复失败时 kill + wait,客户端持有 kill-on-close Job 兜底,关闭主窗口后 Runner、MCP、command、ConPTY 及其后代都应消失。普通 dev / release 和 CLI 继续使用 runner.shutdown_if_idle。
Windows release 的非交互后台命令统一使用 CREATE_NO_WINDOW,包括 command.exec / project.verify、STDIO MCP、Repository Context Git、git.inspect / project.git_commit 和 taskkill 清理命令;需要进程组终止时再叠加 CREATE_NEW_PROCESS_GROUP,不要使用 DETACHED_PROCESS。smoke 时应在实际任务运行期间观察无额外控制台窗口,并在关闭客户端后核对整棵后台进程树为零,再重启确认 reconciliation 可继续。
Provider 失败回归必须同时检查等待态和耗尽态:用本地 mock 503 证明 Runtime 从 durable retry record 显示精确 HTTP 状态、真实 nextAttempt/maxRetries 和退避秒数;最后一次重试仍失败时,状态卡与持久 conversation 只显示安全中文摘要。测试正文应包含诱饵 Provider URL/query、API Key 和 Windows / Unix 绝对路径,并断言这些正文、内部 fingerprint / chars 与 [redacted ...] 占位符均未进入用户可见消息;不能只验证状态卡而漏掉 SupervisorChatOnlyView 直接渲染的 conversation。
Windows 安装包还必须覆盖 AppData 与诊断失败路径:新建目录的 owner 必须等于进程 TokenUser SID 且 DACL 仅允许当前用户;历史 foreign-owner 目录应先拒绝任何 reparse / junction / symlink,再原子重命名为同级唯一 .owner-mismatch-backup-* 并重建安全目录,旧配置不得覆盖。Windows 新建 Runner lock、endpoint temp、project-owner diagnostic temp 与 real-E2E 私有文件的 owner 可能仍是 token 默认 owner Administrators;只允许本进程 create_new 后仍持有不共享独占句柄、且句柄确认普通 / 非 reparse / 单链接的对象在写入或原子安装前初始化为 TokenUser,失败时清理该新文件。既有 durable 文件读取、活锁、access denied、硬链接或非固定 lock 路径不得删除、接管或截断。startup.log 与 agent-runner.log 达到 256 KiB 时只保留一份 .previous.log,并扫描 API Key、Authorization、AppData 和其它绝对路径零泄漏;AppData 不可写时 startup.log 应回退系统 TEMP 的 Genarrative-Game-Chat-Diagnostics,故意注入 .setup() / .build() 初始化失败时必须出现带诊断日志位置的 Windows 对话框;.setup() 发生在 app.run 阶段,错误对话框必须由 setup 失败路径直接触发,不能只处理 .build() 返回值。Runner 子进程已退出时父进程应立即报告,不得继续等待完整启动期限。
开发侧需要无 UI 验收某个单 Agent 的完整 Runtime 时使用:
npm run ai-game-creator-shell:agent-task -- --config-dir /absolute/app-data --init /absolute/project code-prototype "修复失败测试并完成验证"
省略 --init 时项目必须已经由客户端初始化。所有 Runtime 写命令都必须显式传入项目外 --config-dir 并投递给独立 Runner;--runner-status 和 Agent 状态查询只读取已有配置与 endpoint,不得创建 AppData、修改权限或为了查询启动 Runner。遇到权限确认会返回非零并保留待确认动作,继续操作应回到开发窗口,不能用 CLI 静默绕过。
通用 Agent Runtime 内核抽取复验
修改 server-rs/crates/agent-runtime-core、AGC capability registry、Agent catalog、Run Profile 或 Completion Policy 后,先运行纯内核与适配器定向门禁:
npm run agent-runtime-core:check
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml interaction_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml native_runtime_capability_registry_is_the_bidirectional_catalog -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml game_creator_runtime_ -- --nocapture --test-threads=1
修改 Provider 中立契约、注册表、platform-llm adapter 或 AGC interaction Provider 路由时,追加:
cargo test --manifest-path server-rs/crates/agent-runtime-core/Cargo.toml --test provider_registry
cargo test --manifest-path server-rs/Cargo.toml -p platform-llm
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml agent::interaction::tests:: -- --nocapture
cargo check --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --tests
验收必须同时证明同 protocol 多实例可并存、能力不匹配时 adapter 零调用、三种现役 protocol 仍复用原 HTTP/SSE/parser,以及 AGC stream/non-stream/fallback 均经 registry。Provider Key、base URL、HTTP client 和 raw-log 目录必须保留在 LlmClient/LlmConfig 实例,不得下沉 core descriptor/error 或进程全局状态。
修改通用 run 状态机、Store/ToolHost、Agent lane、action 恢复或 delegation/join 时,追加执行内核 conformance 和 AGC 恢复优先级回归:
cargo test --manifest-path server-rs/crates/agent-runtime-core/Cargo.toml --test runtime_execution_conformance
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml background_agent_runtime_legacy_waiting_task_blocks_pending_recovery -- --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml background_agent_runtime_recovers_stale_running_before_pending_task -- --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml background_agent_runtime_recovers_pending_task_after_cancelled_canonical_run -- --test-threads=1
action conformance 必须在 ToolHost 调用前看到 durable executing,并在 observation commit 失败后用全新 engine 重载快照;只在同一进程里重试不能作为 crash recovery 证据。all-join 结果顺序按 child 注册顺序,不按完成先后。
内核必须保持纯 Rust,只允许 serde / serde_json 和标准库依赖;用 cargo tree --manifest-path server-rs/crates/agent-runtime-core/Cargo.toml --depth 1 核对不得出现 Tauri、platform-llm、MCP、HTTP、图片、浏览器、SpacetimeDB 或游戏领域 crate。AGC 的 function name、schema、Agent id、profile、权限和持久协议必须保持兼容;新增内建 capability 只能经统一 registry 建立双向唯一 binding,不能重新增加平行字符串清单。独立 core 测试会生成 crate 内 Cargo.lock/target 时,开发者只保留源码和 manifest,交付前清理生成物;正式 AGC lock 仍需提交 path dependency 变更。
AI 游戏创作 Runtime V1.2 定向复验
command.exec 动作必须保留固定程序和逐项 argv,不得把参数拼成 shell 字符串。例如,定向执行当前仓库的受控命令测试时,action 形状为:
{
"program": "cargo",
"args": ["test", "project_command_"],
"cwd": "apps/ai-game-creator-shell/src-tauri",
"timeoutSeconds": 120
}
该 action 仍需开发窗口精确确认;不能用 CLI 或项目策略把 command.exec 默认改为 auto。实现或调整 Runtime V1.2 后,从仓库根目录优先运行以下定向命令:
只有 cargo check/test/clippy/fmt/build、npm test、规范命名的 npm 验证脚本和精确 node --test 可以形成验证凭证;git、rg、cargo metadata 与普通 npm run 即使成功也只是诊断结果,最后仍需执行验证型命令。
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_command_
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml config_file_overrides_defaults_without_env
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml llm_reasoning_effort_supports_provider_default_and_explicit_levels
npm run test -- packages/shared/src/contracts/gameCreationApp.test.ts
npm run ai-game-creator-shell:typecheck
第一条覆盖固定程序 / argv 拒绝规则、输出清洗、超时和源码改写检测;第二条覆盖全局 / per-Agent 配置继承,第三条覆盖 default / low / medium / high 到 Provider 请求的映射;后两条覆盖共享 confirm 契约、配置结构和发布默认 high。模块级定向验证通过后,再按改动范围运行 npm run ai-game-creator-shell:check、npm run check:encoding 和 git diff --check。
AI 游戏创作 Swarm 显式重试真实复验
正常 supervisor-swarm 全部 completed 不能替代真实 retry 证据。修改 Runtime 显式重试、Provider lifecycle、隔离 AppData 或 Swarm 验收器后,先跑代理夹具和静态门禁,再运行独立真实 suite:
npm run test -- apps/ai-game-creator-shell/tests/llmTransientFaultProxy.test.ts
npm run ai-game-creator-shell:typecheck
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_retry_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_transient_retry_ -- --nocapture --test-threads=1
npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-transient-retry-real-e2e -- --config-dir <AppData>
V1.39 真实门禁把一次故障注入到 Project Supervisor 的首次 tool-plan,使退避期强杀发生在子 Agent Provider 请求产生之前;恢复后仍须在同一父 Session/run 完成双专业 Agent 真重叠与唯一 repair。suite 使用 30s 退避,必须先观察 sidecar 已落盘且 task/state 均为 running / waiting-for-provider-retry,再强杀 Runner;新 boot 接管后 sidecar identity、字节、attempt、slot 与 retryAt 不变,重启后和到期前代理请求数都只能为 1。代理的 metadata-only 请求日志只允许保存序号与毫秒时间,第二个请求的 acceptedAtMs 必须不早于 retryAtMs,且不得包含 URL、method、headers 或正文。forwarding gate 放行前 action、receipt、子委派、claim、assistant、pending、project revision 与 upstream forwarding 全为 0;受控 request identity 必须恰好包含 1 个 failed lifecycle、1 条 retry audit 和 1 个 -transient-1 后继 identity。其它真实瞬态失败按 incidental failure/retry 分开计数,每条仍须通过既有 lifecycle、retry audit、唯一后继和终局门禁且两类计数相等;不能把它们混入受控注入链,也不能跳过唯一 Supervisor assistant 和零重复/残留/泄漏要求。首批双专业 Agent 使用正式 collaboration policy 固定为同批两个指定 static delegate,不能只靠提示碰运气;该 suite 已在 Provider 退避边界完成唯一一次 Runner 强杀,后续 repair 只验证持久 pending/确认链,不重复制造第二个 kill 边界。
V1.40 final-reply 持久恢复先运行确定性门禁:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_retry_waiting_final_reply_restart_commits_once -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_retry_waiting_final_reply_compaction_resumes_without_new_tool_plan -- --nocapture --test-threads=1
第一条测试必须停在 final-reply retry sidecar 已提交而 task/state 尚未投影的窗口,恢复扫描补齐 waiting 后在到期前保持零请求;第二条必须让 final-reply 前置自动压缩先失败并进入 requestKind=final-reply-context-compaction 等待态,到期后恢复同一压缩请求,再继续原 final-reply。两条链路都不得重新调用 tool-plan;失败和恢复请求只比较 HTTP body 字节、SHA-256 和长度,测试失败不得打印正文。真实 Provider 验收必须另起独立 suite,在 Supervisor 已认领全部专业回执、repair 和宿主验证后注入 final-reply 故障并于退避期强杀 Runner;该 suite 尚未 PASS 前,不能复用 V1.39 首次 tool-plan 的真实证据。Provider 成功返回到 finalization journal prepared 之间的崩溃窗口仍须独立补齐和验收,当前门禁不能据此宣称 Provider 调用 exactly-once。
AI 游戏创作 Runtime V1.41 成功交接与回复流恢复复验
修改 Provider 成功响应、持久重试、finalization、response stream 或 Runner idle 判定后,至少运行:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_handoff_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml response_stream_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml durable_provider_handoff_prevents_shutdown_even_when_corrupt -- --nocapture --test-threads=1
复验和排障按 durable ownership 的顺序取证:
- 先按 handoff 中保存的真实
providerRequestId / requestSlot / attempt核对 Provider lifecycle。成功响应必须先原子写入 handoff 并回读完全一致,再为同一真实 requestId 补completed;恢复不得生成替代 requestId。 - 在 handoff 已提交、lifecycle 仍只有
started的 checkpoint 停止执行,关闭 mock Provider 后再恢复。final-reply 必须零网络回放并只产生唯一 assistant/completed/committed stream;前置压缩只允许在回放压缩结果后发出后续必要的 final-reply,不能重复 tool-plan 或 compaction。 - 同一 run 同时存在 handoff 与 retry 时,完全匹配才允许回放并清理 retry;identity、attempt 或 slot 冲突必须零网络进入
needs-reconciliation,保留两份 sidecar 和真实 requestId 证据,不要为了让 Runner 退出而手工择一删除。 - finalization 已到
runtime-completed后,故意删除 stream、保留streaming半句、注入 committed 写失败、在 committed 后 journal 清理前停止,并在期间推进全局 project revision。恢复必须始终使用 journal 固定的 run/request slot/steer cursor/response revision 与正文重建或幂等提交,写入后回读成功才可删除 journal。 - 固定身份或正文冲突、stream 写入或回读失败时,断言 journal 保留且恢复扫描继续处理同一 finalization;Runner 对 primary、
.previous或损坏 handoff 都应保持 busy,runner.shutdown_if_idle不得返回 idle。终局再核对 retry/handoff/finalization sidecar 全部为零,并扫描公共 task/event/Agent DB/CLI,确保没有响应正文、thinking、凭据、Provider URL 或绝对路径。
V1.41 只覆盖无 tool call 的 context-compaction / final-reply-context-compaction / final-reply。Runner 在 Provider 成功后、handoff 原子提交并回读前被硬杀时,仍只能把未闭合 started 视为结果未知并失败关闭;该窗口不是 exactly-once。tool-plan 及其 function arguments 不进入 handoff,真实外部 Provider 的 final-reply 退避期 Runner 强杀仍需独立 E2E,不能用上述确定性测试或 V1.39 PASS 代替。
AI 游戏创作 Runtime V1.42 Supervisor final-reply 强杀真实复验
V1.42 不改变生产 Runtime 协议,只补一次性 fault proxy selector 和独立真实 suite。先完成确定性门禁,再显式传入发布 AppData 的绝对路径运行长链路:
npm run test -- apps/ai-game-creator-shell/tests/llmTransientFaultProxy.test.ts
node apps/ai-game-creator-shell/scripts/agent-runtime-real-e2e.mjs --self-test
npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-final-reply-transient-retry-real-e2e -- --config-dir <发布AppData绝对路径>
- proxy selector 只允许读取冻结的
sequence / acceptedAtMs,不得接触 URL、header、body 或 Key。harness 从持久层识别同一父 Session/run 的唯一 base final-reply,先核对2初始加1repair delivery 均已 claim、两次 observed claim 完整覆盖3receipts 且 assistant 为0;selector 再在 proxy reset/forward 该请求前,以可信宿主 Node 在 disposable project cwd 同步运行固定的node verify-e2e.mjs。仅real-e2e-command=passedmarker 成功且无失败 marker 才允许注入;失败、超时或 marker 无效时不注入,stdout/stderr 不得写入 state、checkpoint、report 或公共日志。父 run 的project.verifyaudit/receipt/observation 计数仅用于诊断,不是注入门禁。 - base final-reply failed lifecycle、retry audit、sidecar 和 task/Runtime
running / waiting-for-provider-retry全部成立后,才在30sbackoff 内用 pidfdSIGKILL强杀 suite 自有 Runner。新 boot 必须保持 Session/run/request fingerprint/attempt/next slot/sidecar 字节/retryAt;重启后和到期前零新请求,到期后只允许唯一-transient-1,并证明acceptedAtMs >= retryAtMs。 - forwarding gate 放行前再次比较 delivery/claim/receipt、assistant、pending、project revision、可信宿主 marker 结果和父 tool-plan 数;后者在恢复前后必须相等,父
project.verify仍只保留诊断计数。终局要求唯一成功 parent final-reply、唯一 Supervisor assistant、唯一 committed response stream,retry/handoff/finalization artifacts、重复和公共正文/Key/绝对路径泄漏均为0。 - task/Runtime 到达终态后仍要显式等待 pending、retry、handoff、finalization、confirmation sidecar 全部清零,并设置
10s硬超时。终态采样与 durable 清理之间允许存在短窗口,但超时仍有残留必须判该轮 FAIL,不得复用后续轮次的清理结果。 - 并行 Agent 执行
file.write / file.patch / file.delete时统一走 Runtime 短等待项目写锁。锁竞争失败只返回脱敏错误,尤其不得让file.writeobservation 携带绝对锁路径后再进入 pending 持久化;定向 Rust 回归至少覆盖短等待写锁和file.write错误脱敏两条边界。
旧 supervisor-swarm-transient-retry 继续只复验首次 tool-plan,不能替代新 suite。确定性门禁已完成 fault proxy 14/14、E2E self-test PASS、前端 308/308,以及 shell typecheck、platform-llm 41/41、platform-agent 17/17、shared-contracts 7/7。真实外部 Provider suite 共执行六轮,前五轮均为 FAIL 且不得拼接:第一、二轮沿用既有失败记录;第三轮因终态后过早观察到 1 个 finalization journal 失败;第四轮因 quality-review 普通 tool-plan 连续 transport/connectivity 失败并耗尽重试、未进入目标故障而失败;第五轮因并行 file.write 与项目写锁竞争,绝对锁路径进入失败 observation 后触发 pending 持久化拒绝和 needs-reconciliation 而失败。完成终态 sidecar 等待和写锁/脱敏修正后,第六轮在同一轮内完整 PASS。
第六轮使用 gpt-5.5 / openai_chat,形成 2 条初始加 1 条 repair delivery 和 3 条专业 Agent assistant,精确命中 Project Supervisor base final-reply,可信宿主 verify marker 门禁通过;受控 Provider failed=1 / retry=1、incidental failure=0 / retry=0,30s backoff,pidfd claim=2 / signal=2,Runner resumed=true / identityStable=true。父 tool-plan 在故障前后均为 13,parent final-reply 与最终 assistant 唯一,response stream sequence=2 / committed;pending、retry、handoff、finalization、confirmation sidecar、全部重复计数及 API Key、私有正文、项目路径、正式配置路径和公共报告泄漏扫描命中均为 0。V1.41 handoff 落盘前 unknown-result 边界和 tool-plan handoff 未覆盖状态保持不变。
suite 只能读正式 AppData,在其同级目录写入 sentinel 管理的 0600 私有副本和 overlay;启动 CLI/Runner 时须把 loopback 合并进大小写两套 no-proxy 环境,防止系统 HTTP 代理绕过本地故障门禁;source-dir guard 必须证明本 suite 前缀未进入源目录,源配置和 endpoint 身份保持不变,报告不得保存 Provider URL、headers、正文、凭据或绝对配置路径。sidecar 先于 task/state 投影是合法提交窗口,验收器应等待完整等待态后再强杀;若后续协作或终局失败,partial report 仍应保留已取得的 retry checkpoint,但失败轮不得与后续成功轮拼接。
AI 游戏创作自主 Swarm 终端复验
日常人工验收优先使用短入口,不再手工拼 AppData、临时项目和预览命令:
npm run agc:test
npm run agc:test:chat
agc:test 委托确定性 lane-defense E2E,使用本地 loopback Provider 完成 Runtime、项目写入和真实浏览器 37/37 门禁,不消耗外部 Provider。agc:test:chat 按当前平台自动查找发布客户端 AppData 中的 game-creator.config.json,把主配置和可选 local overlay 私有复制到 sentinel 管理的单次隔离 AppData,绝不复制正式 agent-runner.endpoint.json、Runner lock、备份或其它文件;随后创建一次性项目,进入 project-supervisor + autonomous-game-build。用户只输入一条需求并以 EOF 交付,收束后复用正式 localhost preview server 并打开试玩。正常收束后按 Ctrl+C,脚本先通过内部 CLI 仅关闭已经空闲的隔离 Runner,再清理隔离 AppData 和一次性项目;Runner 仍有任务或无法确认退出时必须同时保留项目与隔离配置并报告路径,不得触碰或强退正式客户端 Runner。需要主动保留项目时显式追加 -- --keep-project,需要覆盖配置来源或项目时使用 --config-dir / --project-dir 绝对路径。脚本不得读取或打印 API Key,显式项目永不自动删除,非空且未初始化目录必须拒绝。
修改 Supervisor 自主编排、agent.message、static delivery/claim/repair、Swarm CLI turn.report、Runner 恢复或 autonomous harness 后,先跑确定性收敛门禁,再运行真实终端 suite:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml background_agent_runtime_bounds_duplicate_agent_message_livelock -- --nocapture
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml agent_runtime_context_window_ -- --nocapture
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_supervisor_ -- --nocapture
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml swarm_cli::tests:: -- --nocapture
npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-autonomous-chat-real-e2e -- --config-dir <AppData>
业务任务和一次性仓库规则不得出现 Agent ID、数量、并行/同轮、工具、repair 次数、run/action/delegation 或 Runner 配方。PASS 必须由真实发布二进制的 --swarm-chat 自主形成至少两个不同专业 Agent 的同批委派和真实 Provider 重叠,在 acceptance criteria 不满足时只形成一个继承原合同的 repair;repair 确认边界执行 Runner 强杀后仍保持父 Session/run、delivery、claim、pending action 和 Provider started 身份。父 run 的 project.verify 是允许的宿主验证,其它意外父 pending action继续失败关闭。
终局必须同时得到 turn.report=settled、新增 Supervisor assistant 恰好 1、专业 assistant 只在内部 Session、队列/确认/用户输入/reconciliation/sidecar 全 0,以及重复 action/delivery/message/receipt/Provider lifecycle 和正文/凭据/绝对路径泄漏全 0。agent.message 完整回归还要证明同语义消息只写一次、后续 no-op 不刷新进展、6 轮后保持未完成计划并诚实 budget-exhausted。隔离 AppData 必须位于正式 AppData 同级并自动清理;失败尝试与后续 PASS 不能拼接,maxRetries=0 下的真实外部 Provider 失败应单独保留为失败证据。
AI 游戏创作静态与隔离混合 Swarm 复验
修改 static delivery/claim、isolated group/result/all-join、父 waiting phase、agent.run_status 混合认领、Supervisor 混合协作策略、Runner 恢复或 finalization blocker 后,先运行三条确定性回归,再运行独立真实终端 suite:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_supervisor_mixed_ -- --nocapture --test-threads=1
npm run agc:mixed-swarm-e2e -- --config-dir <AppData>
业务任务只写正式交付、临时检查和验证等结果范围,不写 Agent ID、数量、并行方式、具体工具或 Runner 操作。真实 suite 必须以单个独立 run 证明两类 Provider 真重叠、两类 durable 记录绑定同一父 Session/run、认领 observation 早于唯一父 finalization、Runner 恢复身份稳定、isolated 实际零 mutation、唯一用户回复、零重复/残留/泄漏并完成 sentinel 清理;不能把 isolated 的 suite 零写入要求解释成生产权限层面的只读沙箱。命令未运行、退出非零或报告字段不完整时不得标记 PASS,也不得把失败轮和后续成功轮拼接。
AI 游戏创作 Supervisor 协作策略复验
修改 .agent/collaboration-policy.json、Supervisor 首波预检、Provider action batch v2、委派后总控 mutation/MCP 门禁、协作 finalization blocker 或对应恢复顺序后,先跑确定性回归,再运行独立真实 suite:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml supervisor_collaboration_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml provider_action_batch_ -- --nocapture --test-threads=1
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml project_supervisor_mixed_ -- --nocapture --test-threads=1
npm run agc:collaboration-policy-e2e -- --config-dir <AppData>
真实 suite 必须在隔离 AppData 和单个父 Session/run 中写入 mixed 策略,要求两个指定 static Agent 与同一 group 的三个 isolated child。首批 batch 必须先停在 waiting-confirmation / nextActionIndex=0 且副作用为 0;此时强杀 Runner,恢复后 batchId、policy/contract fingerprint 和全部 actionId 必须逐项稳定,再继续完成 V1.31 mixed chain。为避免长链路被偶发外部 transport 抖动误判,suite 只在隔离配置副本中启用有限瞬态重试,必须同时证明正式 AppData、源配置和 Runner endpoint 未被改动,并在报告中保留 retry 计数。最终仍要求两类真实 Provider 重叠、唯一 Supervisor assistant、零重复/残留/泄漏和 sentinel 清理;命令未运行或报告门禁不完整时不能把确定性测试或 V1.31 PASS 当成 V1.32 PASS。
AI 游戏创作 Runtime V1.10 持久进程定向复验
V1.10 的 PTY 只通过四个 Runner-owned 工具开放;不要把 V1.2 command.exec 改成长驻入口。最小工具输入保持结构化:
{"tool":"command.start","input":{"program":"npm","args":["run","dev"],"cwd":".","timeoutSeconds":300}}
{"tool":"command.poll","input":{"processId":"proc-...","cursor":"v1:proc-...:0","maxChars":8000,"waitMs":1000}}
{"tool":"command.stdin","input":{"processId":"proc-...","data":"q","appendNewline":true,"eof":false}}
{"tool":"command.terminate","input":{"processId":"proc-...","cursor":"v1:proc-...:254"}}
定向复验按以下顺序取证:
- 用 Runner-owned PTY fixture 覆盖 start、增量 poll、stdin、自然退出和 terminate;确认
processId绑定完整 owning project / Agent / task / session / run / start action / Runner boot,而不是 OS PID。 - 让发起 App / CLI 在 start 后退出,确认 Runner 仍持有会话;随后分别在 launch、running、stdin 和 graceful / force 终止窗口强杀 Runner,确认恢复只进入 reconciliation,不增加 fixture launch / stdin 次数,也不按 PID 重连。
- terminate 必须携带最后一次 poll 的
nextCursor,返回同一 cursor 且不消费输出;活会话和 unresolved reconciliation 期间尝试 finalization 与runner.shutdown_if_idle,必须分别被完成门禁和 busy 状态阻断;终止成功必须同时满足 child terminal、同组残留清理、wait / reap 和 PTY drain。 - 使用不同静态 Agent、动态 sibling、run 和项目重放同一
processId,全部必须失败关闭。扫描 task、event、Agent DB、receipt、action history、activity/output、UI snapshot 和报告,PTY 输出正文命中数必须为 0,stdin 只能出现bytesWritten / contentSha256 / stdinOpen / eof。 - Linux 用忽略 SIGHUP 的 npm / Node fixture 验证 Runner 强杀后 owner watchdog 回收同一前台进程组;Windows 验证 kill-on-close Job Object。仍要明确 PTY、固定 argv、隔离环境和两阶段终止不是容器或 OS sandbox,主动
setsid/ 外部 service 仍不在完整隔离承诺内。
实现用例统一使用可检索的 process_session_ 前缀。先运行定向 Rust 用例,再跑 Tauri 全量和真实 Provider:
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml process_session_ -- --nocapture
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml
npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite process-session
npm run ai-game-creator-shell:agent-runtime:real-e2e -- --config-dir <AppData> --suite process-session-runner-kill
定向命令必须实际匹配到 V1.10 用例,0 tests 不算通过。真实 Provider fixture 不得把工具顺序、processId、readiness 文本所在 chunk 或 OS PID 写进任务提示;验收器只按持久 action identity、fixture 计数、私有输出和公共泄漏扫描判定。三项门禁实际通过后才能把日期、Provider、数量和 PASS 结果写入技术方案或 decision log;未运行或被外部配置阻断时只记录 BLOCKED / 未验收事实。
npm run agc 会启动 Tauri 开发客户端;其 beforeDevCommand 通过 npm run agc:serve 先完成壳 typecheck,再启动或复用配套 SpacetimeDB、api-server 和固定 127.0.0.1:3080 Vite。开发态只打开游戏创作聊天入口使用 npm run agc:game-chat -- [--project-path <absolute-path>]。只需要浏览器预览同一客户端时可用 npm run agc:serve;只启动配套后端和数据库时可用 npm run agc:backend -- --database <name>。
Linux 多用户共享同一台机器开发时,本地 dev 脚本会为当前 Linux 用户分配一个固定端口段并写入系统级注册表 /var/tmp/genarrative-dev-port-ranges/registry.json,自动分配从 10000-10099 开始,每段 100 个端口,五个 dev 服务依次使用 start 到 start + 4,其中 BgFilter worker 固定为 start + 4。可用 GENARRATIVE_DEV_PORT_RANGE 或 npm run dev -- --port-range 手动指定端口段用于特殊场景;注册表会阻止不同用户使用相同或重叠段,并让同一用户后续启动继续复用自己已占用的固定段。该机制只在 Linux 生效,Windows 把第五个服务纳入原有统一端口探测与漂移逻辑。
本地 npm run dev、npm run dev:spacetime、npm run dev:api-server 和 npm run dev:bgfilter-worker 会在 Rust 子进程环境中绕过项目默认 sccache wrapper,避免损坏的本机 cache daemon 阻断 spacetime publish 或 Rust 服务启动;显式设置的非 sccache 自定义 wrapper 会被保留。生产 / Jenkins 构建仍按流水线自身的 sccache 策略执行。
该命令会启动:
- SpacetimeDB standalone
- 独立
bgfilter-worker - Rust
api-server - 主站 Vite
- 后台 Vite
npm run dev 和单模块 dev:* 命令会更新根目录 .app/dev-stack.json,记录五个本地服务的 pid、端口、URL、启动状态和当前命令。该目录只作本机运行态观测,不提交 Git。
开启自动刷新:
npm run dev -- --watch
watch 模式只由外层调度器自动处理后端侧刷新:spacetime-module 改动后重新发布模块但不重启 standalone 宿主;完整栈和 dev:api-server 只创建一套 Rust watcher,改动后先停止 API 与 BgFilter worker,再先启动并验活 worker、最后启动并验活 API。主站 Vite 与后台 Vite 的源码变化交给 Vite 自身 HMR,避免外层 watcher 监听到依赖缓存或临时文件后循环重启。
非 watch 模式下,npm run dev 终端支持输入 rs spacetime、rs api-server、rs bgfilter-worker、rs web、rs admin-web 或 rs all。其中 rs spacetime 只会重新发布 spacetime-module,不会重启 standalone 宿主;重启任一 Rust 角色都会走 API / BgFilter worker 组合重启。
单独启动 SpacetimeDB:
npm run dev:spacetime
单独启动 Rust API server:
npm run dev:api-server
该命令会由同一 runner 自动带起独立 BgFilter worker,确保共享实际内部 base URL 和 Token。只单独启动内部 worker 时使用:
npm run dev:bgfilter-worker
单独启动前端:
npm run dev:web
单独启动后台管理前端:
npm run dev:admin-web
本地 SSH 服务器管理面板:
npm run server-manager:panel
该命令启动 server-rs/crates/server-manager-panel 的 egui 桌面工具,从本机 ~/.ssh/config 读取可用 Host alias,支持多服务器健康巡检、可折叠侧边栏和受控 systemd 服务启停。服务操作通过远端 sudo -n systemctl start|stop|restart <unit> 执行,目标服务器需要提前配置对应 unit 的免交互 sudo 权限。
面板启动时会自动注入本机中文字体;如开发机中文仍显示为方块,可设置 GENARRATIVE_SERVER_PANEL_CJK_FONT=/path/to/font.ttc|index 指向本机 CJK 字体。
npm run dev:api-server 会保留终端实时输出,并把 API 输出持久化到 logs/api-server/api-server-<timestamp>.log、BgFilter worker 输出持久化到 logs/bgfilter-worker/bgfilter-worker-<timestamp>.log。完整联调入口 npm run dev 使用同一套日志规则。API 日志可通过 GENARRATIVE_API_SERVER_LOG_FILE / GENARRATIVE_API_SERVER_LOG_DIR 改写,worker 日志可通过 GENARRATIVE_BGFILTER_WORKER_LOG_FILE / GENARRATIVE_BGFILTER_WORKER_LOG_DIR 改写。
开发态 npm run dev / npm run dev:api-server 默认打开 GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED=true,密码入口可以直接注册未知手机号账号;生产默认仍关闭该开关。
生产 Genarrative-Stdb-Module-Publish 的备份默认使用 DATABASE_BACKUP_MODE=async:流水线在 publish 前先生成本地冷备份,随后继续 publish,并把同一份发布前备份交给后台 Node 进程上传 OSS,避免低带宽 OSS 上传长时间占住部署窗口。需要强制在 publish 前等待打包和上传并让失败阻断发布时,手动选择 DATABASE_BACKUP_MODE=sync;已有其他备份窗口且明确接受风险时才选择 skip。
生产 API / Web / Stdb 发布流水线不在目标机器 checkout Git。对应 Build 流水线必须把发布产物、校验文件、release-manifest.json 和部署 / 发布脚本一起归档;Deploy / Publish 流水线只通过 copyArtifacts 复制上游构建归档并执行随产物归档的脚本,避免目标机器 Git 访问和产物 commit 与部署脚本 commit 漂移。
查看本地 Rust/SpacetimeDB 日志:
npm run dev:spacetime:logs
本机隔离验证外部生成 worker 队列、API-only 更新和 worker 动态扩缩容时,优先使用:
npm run container:worker-smoke -- smoke
该命令生成 deploy/container/worker-smoke/ 下的 gitignored env 与端口 state,启动独立 compose project 和独立 SpacetimeDB,用 unsupported job 验证 worker claim / fail 回写;排查时用 api-update 确认 API 重建不触碰 worker,用 scale <n> 调整 worker 数量。
external_generation_job 是 private table,worker-smoke 通过 worker 日志里的 job_id 和 unsupported 记录确认消费,不通过 CLI SQL 查询队列表。
worker-smoke 默认把本机 spacetime CLI 打成轻量 SpacetimeDB 镜像,避免首次 smoke 依赖官方大镜像下载。若容器内 Cargo 下载依赖不稳定,追加 --local-binary,让容器内 Cargo 复用本机 Cargo 缓存构建当前 api-server 二进制,并把产物放进 Debian bookworm smoke runtime;可用 GENARRATIVE_WORKER_SMOKE_LOCAL_BASE_IMAGE 覆盖运行时基础镜像;隔离端口或库数据需要重建时追加 --force。
后台管理前端:
npm run admin-web:build
npm run admin-web:typecheck
SpacetimeDB bindings 生成:
npm run spacetime:generate
CodeGraph 本地语义索引:
npm run codegraph:init
npm run codegraph:status
npm run codegraph:sync
npm run codegraph:index
.codegraph/config.json 可随仓库共享;.codegraph/codegraph.db、缓存和日志为本机生成物,不提交。
Codex 项目级 hook 保存在 .codex/config.toml 与 .codex/hooks/:
PreToolUsehook:node .codex/hooks/pre-submit-compile-check.mjs,Codex 准备执行git commit前检查npm run typecheck、npm run admin-web:typecheck、cargo check -p api-server --manifest-path server-rs/Cargo.toml。PostToolUsehook:node .codex/hooks/post-edit-codegraph-sync.mjs,工具修改文件后执行npm run codegraph:sync。
个人 token、模型路由、MCP server 仍属于个人环境;需要时由成员本机执行 codegraph install 或查看 codegraph install --print-config codex,不要提交个人全局配置。
Agent 本地 RAG 文档索引:
npm run rag:index
npm run rag:search -- --query "搜索内容"
RAG 主要供 Agent 检索项目上下文,开发者仍按 AGENTS.md、docs/README.md 和 docs/project-memory/ 阅读正式文档。RAG 仅索引项目文档和项目共享记忆,默认不把 LanceDB、Transformers.js 或本地 embedding 模型装入根 package.json。需要启用 RAG 时,Agent 必须先询问用户是否安装本地运行时依赖;用户确认后只安装到 gitignored 的 .rag/runtime/,模型缓存和向量库也留在 .rag/。具体命令见 scripts/rag/README.md。
常用检查命令
Rust 格式检查:
npm run check:rustfmt
仓库通过根目录 rust-toolchain.toml 固定 Rust 1.96.0 和 rustfmt 组件,
并通过 rustfmt.toml 固定 Edition 2024 格式口径。需要修复格式时运行:
cargo fmt --all --manifest-path server-rs/Cargo.toml
- 后端通用用户行为埋点统一通过
record_tracking_event_and_returnprocedure、SpacetimeRuntimeClient::record_tracking_event(...)与 api-servertracking中间件写入tracking_event/tracking_daily_stat;现役账号、钱包、编辑器、项目、精选素材和公共设置路由按tracking.rs的显式静态路由表记录,后台路由默认排除。旧玩法、公开作品和专属运行态路由已经退役,不再维护作品级游玩埋点覆盖。
编码检查:
npm run check:encoding
ESLint:
npm run lint:eslint
类型检查:
npm run typecheck
综合 lint:
npm run lint
测试:
npm run test
生产构建:
npm run build
原生壳验收:
npm run check:native-shells
该命令会覆盖 H5 HostBridge 关键测试、微信 / Expo / Tauri 三端桥接层文件结构门禁、完整相对路径文档反查、微信 capability 到真实 WebView / 支付 / 分享页面流程和测试清单的映射门禁、H5 HostBridge 事件订阅双能力门控反查、H5 navigation.canGoBack 消费 hook 与直达二级页返回锚点测试、移动端和桌面端单端源码清单门禁、Expo 壳 typecheck / test / EAS build config smoke / config smoke / Metro export smoke、Tauri 壳 typecheck / cargo test、桌面壳 release --no-bundle 构建烟测,以及可分发壳与 H5 HostBridge 真实调用链的临时替身词扫描,确认 Expo managed config、移动端 EAS 原生包构建 profile、移动端 iOS / Android production bundle、打包 H5 资产、Tauri release 入口、H5 页面内导航保留完整原生宿主上下文和 H5 HostBridge 真实调用链没有漂移;扫描范围包含微信小程序壳生产 .js、Tauri Info.plist、共享 HostBridge 契约、H5 native transport,并自动覆盖已接入真实宿主能力 facade 的 H5 生产调用链文件,但不扫描 Expo export、Tauri target/、Cargo / Metro 缓存或 release 构建产物。移动壳配置检查必须反查 EAS 生产 profile、文本 / 文档 / 图片 / 音频导入边界都来自共享 HostBridge 契约。登录与支付外链跳转必须保持在该调用链扫描内,src/services/authService.ts 和 src/services/payment/paymentRedirect.ts 是必扫文件;AuthGate 的登录成功、退出登录、身份边界刷新和登录状态异常重试都必须通过 app.reloadWebView 优先路径,并由 src/components/auth/AuthGate.test.tsx 进入该门禁。壳源码和配置继续严格禁止 mock / fake / placeholder / stub / TODO / FIXME / 占位 / 模拟 / 伪造 / 未实现 / 临时;H5 业务调用链允许正常表单 placeholder 属性、业务占位图文案和真实兼容 / 故障语义中的“未实现”“临时”表述,但仍禁止 mock / fake / stub / TODO / FIXME / 模拟 / 伪造等替身痕迹。
根仓 Vitest 加载独立 AI 游戏客户端源码时,不得为了模块解析把 @tauri-apps/api 或 @tauri-apps/plugin-* 加入根 H5 依赖;根测试只通过 vitest.config.ts 的精确别名使用无副作用测试替身,独立客户端的正式 Tauri guest 依赖继续只由 apps/ai-game-creator-shell/package.json 与其 lock 管理。隔离 worktree 验收前需分别执行根 npm ci 和 npm ci --prefix apps/ai-game-creator-shell。
反馈页上传凭证在原生壳声明 file.importImage 时必须优先走宿主图片导入;移动壳声明 file.captureImage 时才显示拍摄凭证入口,并把拍摄图片同样转为 File 后复用反馈页原有数量、大小、MIME、data URL 预览和提交 payload 校验。
Expo / Tauri 声明 navigation.openNativePage 时,只用于现役同源 H5 路由的受控导航和宿主上下文续接;微信小程序不再声明该能力。旧儿童动作 Demo、模板工作台、生成页、结果页和运行态不得作为 HostBridge 导航验收入口。
H5 支付链接跳转在原生壳声明 app.openExternalUrl 时必须优先走宿主系统浏览器;原生壳未接真实支付 SDK 前不得声明 payment.request,也不得把外部 H5 支付跳转伪装成原生支付成功。
微信 OAuth 登录授权 URL 在原生壳声明 app.openExternalUrl 时必须优先走宿主系统浏览器;原生壳未接真实登录 SDK 前不得声明 auth.requestLogin,也不得把网页登录跳转伪装成原生登录成功。
现役编辑器与个人中心新增文件导入能力时,继续复用共享 file.importDocument、file.importImage、file.captureImage 和 MIME / 大小门禁,不得把已退役模板的上传 service、玩法 DTO 或页面测试重新纳入原生壳门禁。
视觉小说结果页封面 / 角色 / 场景图片和音乐 / 环境音上传在原生壳声明 file.importImage / file.importAudio 时必须优先走宿主受控导入,并把 H5 base64 转 File 后继续交给 uploadVisualNovelAsset 与当前素材字段写回链路;用户取消原生选择不应再连带弹出浏览器文件输入,历史素材选择和 AI 图片生成保持原链路。
该命令会反查微信小程序 WECHAT_HOST_CAPABILITIES 与共享 HOST_BRIDGE_WECHAT_MINI_PROGRAM_CAPABILITIES 一致;小程序生产代码继续保留 CommonJS 运行时镜像,不直接 import TypeScript shared 包。
该命令同时会运行微信小程序 miniprogram/host-bridge/、miniprogram/shell/、pages/web-view 样式和 scripts/miniprogram-web-view-auth.test.ts 的壳层测试,保证微信桥接层拆分后的支付、订阅消息、九宫切图、分享目标和 WebView 登录 / 分享入口行为与 Expo、Tauri 壳一起验收。
该命令还会反查微信小程序 app.json.pages 与 host-bridge/protocol.js 现役页面 URL、H5 小程序页面常量、WebView 分享入口、分享目标消息类型、WEB_VIEW_SOURCE_QUERY、微信请求头运行时标记、H5 runtime parser、H5 路由保留字段和 H5 / API base URL 格式,避免页面路由、来源标记、宿主上下文 query 或域名配置在微信壳、H5 HostBridge 与运行时配置之间分叉。旧生成结果订阅授权页和对应 H5 service 不再进入清单。生产 / 开发 H5 与 API 域名都必须显式配置为纯 HTTPS domain,运行时开发域名回退生产域名只作为异常兜底。
内容检查:
npm run check:data
npm run check:overrides
npm run check:smoke
npm run check:content
全量检查:
npm run check
DDD 边界检查:
npm run check:server-rs-ddd
Gitea CI 与 PR 检查
- 仓库 CI 入口是
.gitea/workflows/project-ci.yml,向master、codex/ai-game-creator-app推送和所有 PR 创建、更新时必须运行,也允许手工触发。 - CI 固定拆分为
Repository checks、Frontend tests、Backend tests、Native shell tests四个 required job;对应 PR context 完整名称是Project CI / Repository checks (pull_request)、Project CI / Frontend tests (pull_request)、Project CI / Backend tests (pull_request)、Project CI / Native shell tests (pull_request),首次运行后仍须从 Gitea 最近一周 context 表复核。测试使用独立 job,不能只藏在综合检查 step 中;原生壳验收单独运行以便定位重型构建失败。 - 四个 job 共同覆盖
npm run check,并追加npm run check:server-rs-ddd、cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml、cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml和cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml。后端 runner 安装ffmpeg,避免视频抽帧测试因工具缺失提前返回。codex/ai-game-creator-app分支必须用独立 lockfile 安装 AI 游戏创作壳依赖,其原生壳入口还必须覆盖npm run ai-game-creator-shell:check、release build smoke,并检查 AI TauriCargo.lock不漂移。原生壳 job 还要通过 Google 官方签名 APT 源安装google-chrome-stable,用于 headless preview 的真实 DOM / canvas smoke;同时安装ripgrep,把actions/setup-node的完整 Node.js 22 发行目录与 root-owned rustup proxy 映射到/usr/local,供只接受受信任系统命令目录的command.exec沙箱测试使用,不能放宽生产命令目录白名单。Tauri 的 1132 项级别 suite 固定--test-threads=1,避免共享 Agent Runtime 后台锁与异步终态在 libtest 并行调度下互相干扰。 - checkout 必须使用完整历史。PR 将 base SHA 写入
SPACETIME_SCHEMA_BASE_REF,直接推送master使用 before SHA;事件基线不可解析时直接失败。Gitea 检查的是 PR head 而非预合并 commit,workflow 必须拒绝不包含最新 base commit 的过期 PR,分支保护同时保持“PR 过期禁止合并”。 - 普通 PR job 不读取业务 secret,不运行真实 API/SpacetimeDB/OSS/支付/生成/live smoke,也不执行会修改外部状态的维护、迁移、发布或备份命令。
- Gitea 至少升级到
1.26.4后才能注册执行 PR job 的 runner;ubuntu-latest标签只映射到固定 digest 的 Ubuntu 24.04 级 Docker/临时隔离镜像,不使用浮动镜像 tag,不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。runner 能访问 Gitea、GitHub Actions 与actions/node-versions、nodejs.org、npm、Rust 分发、crates.io 和 Google Chrome 的dl.google.com官方签名 APT 源;workflow 的官方 action 固定完整 commit,若内网禁用 GitHub,先在当前 Gitea 镜像对应 commit 并改用绝对 URL。受控镜像优先预装 rustup。Gitea 1.26 的任务超时由 runner 全局配置控制;首次运行成功后,master分支保护必须要求上述四个 job 全部成功。 genarrative-station当前使用 Gitea1.26.4+ 基于 Runner2.0.0-dind-rootless的固定 digest 修补镜像:只修复systempaths=unconfined的空 slice 被mergo丢失,真实 job 必须保持MaskedPaths=[]、ReadonlyPaths=[];外层仍非 privileged、无CAP_SYS_ADMIN,内部 Docker 只监听 Unix socket,docker_host: "-"阻止 socket 进入 job。job 只在gitea-actionsinternal network,通过/gitreverse gateway 访问 Gitea,通过拒绝私网、保留地址和 metadata 的 80/443 proxy 访问公共依赖;直连公网和 Gitea 数据网必须失败。内层 bwrap 所需 namespace/proc 选项只能用于该 rootless DinD,不能放宽宿主 rootful runner。系统依赖步骤在 root job 中不调用 sudo,非 root 时用sudo -E保留受控 proxy;Cargo 关闭 HTTP multiplexing 并设置 10 次网络重试,rustup bootstrap/toolchain 安装也按有界次数重试。AI 原生壳 job 把 Node 发行目录与 rustup proxy 安装到/usr/local的受信任只读路径,并在测试前执行完整 bwrap canary。宿主 compose helper 必须把/opt/gitea-stack挂到同名绝对路径,避免相对 volume 错误落到/stack空目录。- 四个 job 共同覆盖
npm run check,并追加npm run bgfilter-worker:smoke-test、npm run check:production-health-patrol、npm run check:production-api-release、npm run check:production-api-deploy、npm run check:server-rs-ddd、cargo test --locked --workspace --no-fail-fast --manifest-path server-rs/Cargo.toml、cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml和cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml。BgFilter 的.test.mjs使用 Node test runner,必须由 workflow 显式调用;生产巡检 / 发布 / 部署行为检查只运行无密钥临时 fixture,不连接现场环境。ffmpeg由预构建 job 镜像提供,避免视频抽帧测试因工具缺失提前返回。codex/ai-game-creator-app分支的原生壳入口还必须覆盖npm run ai-game-creator-shell:check和 release build smoke。 - checkout 必须使用完整历史。PR 将 base SHA 写入
SPACETIME_SCHEMA_BASE_REF,直接推送master使用 before SHA;事件基线不可解析时直接失败。Gitea 检查的是 PR head 而非预合并 commit,workflow 必须拒绝不包含最新 base commit 的过期 PR,分支保护同时保持“PR 过期禁止合并”。 - 普通 PR job 不读取业务 secret,不运行真实 API/SpacetimeDB/OSS/支付/生成/live smoke,也不执行会修改外部状态的维护、迁移、发布或备份命令。
- Gitea 至少升级到
1.26.4后才能注册执行 PR job 的 runner。runner 保留ubuntu-latest固定 digest 映射,并把 workflow 使用的genarrative-ci映射到 runner 内层 Docker 已装入的完整 Image ID;不映射 host,不向 job 暴露 Docker socket、业务 secret 或不必要内网。当前 CI 镜像约1.788 GB,Image ID 为sha256:c04b114b1f145072c9df7842c4c974e1bb2eaaf391d95d84c9212a460546b7d5,标签映射为genarrative-ci:docker://sha256:c04b114b1f145072c9df7842c4c974e1bb2eaaf391d95d84c9212a460546b7d5。内层 Docker 数据持久化且force_pull: false,该 ID 缺失时失败关闭,不现场拉取或回退浮动 tag。Runner 2.0.0 支持 job 级timeout-minutes,但 runner 全局3h仍是硬上限;首次运行成功后,master分支保护必须要求上述四个 job 全部成功。 deploy/container/gitea-ci-job.Dockerfile固定 Ubuntu base digestsha256:58ea92624c7c09582e05594d95488331045053d3a3f34cf09649f2a32313a614、Rust stage digestsha256:19817ead3289c8c631c73df281e18b59b172f6a31f4f563290f69cddd06c30e9、带 SHA-256 校验的 Node22.23.1、Google Linux 主签名指纹和 Chrome150.0.7871.181-1,预装 Rust 1.96、rustfmt、Chrome、bwrap、rg、ffmpeg、clang/lld与 Tauri / 后端系统依赖,并预热根 npm、server-rs 与桌面壳 Cargo 下载缓存。构建脚本使用约1.638 MB的白名单 tar context,不发送源码、素材或本地私密文件;cargo fetch --locked同时受 Cargo 网络重试和最多 5 次整命令级重试保护,最后必须通过断网 fetch。更新按scripts/gitea-ci-job-image.sh build/verify -> export 仓库外镜像归档 -> load-runner -> 确认无活跃 job -> 仓库外备份 config -> 替换 label -> docker restart --timeout 660执行;真实 CI 全部通过后才清旧镜像。回滚先把 workflow 改回ubuntu-latest,再恢复 config 备份并重启。备份不进 Git,不在共享文档记录宿主私密路径或注册信息。- 四个 workflow job 都使用
runs-on: genarrative-ci,先用镜像内脚本直接从 Gitea checkout,再以GENARRATIVE_GITEA_CI_CHECK_RUNTIME=1运行scripts/check-gitea-ci-job-image.sh,同时校验缓存锁、工具链、完整 bwrap sandbox 和 Chrome headless。workflow 不再包含 GitHub checkout action、apt、setup-node 或 rustup 安装,并设置RUSTUP_AUTO_INSTALL=0;工具链变更时先重建镜像。每个 job 仍各自执行npm ci以校验 lockfile 和隔离 PR 依赖,但优先复用镜像只读 cache,不烘入node_modules,不挂载跨 PR 可写 Actions cache。genarrative-station继续使用固定 digest 的 Runner2.0.0-dind-rootless修补镜像,真实 job 保持MaskedPaths=[]、ReadonlyPaths=[]、Privileged=false、Binds=[],docker_host: "-"阻止 socket 进入 job。job 只在gitea-actionsinternal network,锁文件差量依赖只经拒绝私网、保留地址和 metadata 的 80/443 proxy,直连公网和 Gitea 数据网必须失败;npm 与 Cargo 都设置 10 次网络重试,Cargo 继续关闭 HTTP multiplexing。
后端相关默认验证
后端修改后,按 DDD 文档中的验收命令执行。涉及 API smoke 时:
- 使用
npm run dev:api-server重新拉起后端。 - 禁止使用
npm run api-server:maincloud、npm.cmd run api-server:maincloud或任何GENARRATIVE_SPACETIME_MAINCLOUD_*口径;这些只属于历史残留。 - 本地 smoke 检查
/healthz;发布后或确认实例可接生产流量时检查/readyz。 - 执行对应自动测试。
- 涉及 SpacetimeDB 表、reducer、procedure、row shape 或绑定变化时,同步更新
migration.rs、表目录和生成绑定。 - SpacetimeDB 已有表新增字段必须放在 Rust 表结构体最后,并设置明确默认值;需要修改字段名时,先询问用户并确认迁移计划,再同步更新
server-rs/crates/spacetime-module/src/migration.rs、表目录和生成绑定。 - 修改 SpacetimeDB schema 后运行
npm run check:spacetime-schema,用自动检查拦截缺 default、插入中间、字段删除/改名/重排/改类型,以及漏改迁移、表目录或绑定。
关键文档:
docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.mddocs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.mddocs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.mddocs/technical/SERVER_RS_DDD_G1_CONTRACT_AND_ROUTE_MATRIX_2026-04-29.mddocs/technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.mddocs/technical/SPACETIMEDB_TABLE_CATALOG.mddocs/technical/MAINCLOUD_REFERENCE_REMOVAL_POLICY_2026-05-06.md
生产压测与观测默认口径
- 作品列表 50 HTTP req/s 压测使用
scripts/loadtest/README.md中的 K6 命令;当前脚本一次 iteration 请求两个公开列表接口,因此目标 50 HTTP req/s 对应PEAK_RPS=25。 - 生产
api-server默认 backlog、worker threads、HTTP 并发背压、/readyz接流检查、systemd 优雅停机窗口、Nginx upstream timing log 和 OTLP 开关以docs/【开发运维】本地开发验证与生产运维-2026-05-15.md为准。 - OpenTelemetry 现阶段可选发送 traces / metrics / logs,但不会取代本地
journalctl -u genarrative-api.service、logs/api-server/与/var/log/nginx/genarrative.*.log。 - 指标 label 不写 raw URI、userId、profileId 或 request_id;request_id 只用于 trace/log 串联。
前端相关默认验证
前端修改后,应根据修改范围选择:
npm run check:encodingnpm run lint:eslintnpm run typechecknpm run test- 页面交互 smoke
- 移动端视口检查
前端原则:
- 移动端优先,再兼容网页端。
- 页面只展示后端返回的状态,不自行计算结论型业务状态。
- 现役一级入口为
/creation、/project、/profile,桌面侧边栏和移动端底部 dock 都固定显示“创作 / 项目 / 我的”。/creation只读取图片编辑器项目与GET /api/editor/showcase/resources,不得重新接入旧模板入口配置、旧作品架或专属运行态。 - 旧创作模板目录和顶层旧业务模块必须持续退出 Vite、TypeScript、ESLint 与 Vitest;旧
/api/creation-entry/config、模板 API、公开作品详情和运行态 API 必须保持未挂载。SpacetimeDB 历史表、迁移白名单与必要兼容类型只作为数据壳保留,不得据此恢复业务逻辑。 - 优先复用现有面板、抽屉、弹窗,不新建独立大系统。
- 不在 UI 中默认写功能说明类文本。
- 弹出独立面板的交互不要实现成在当前面板下方追加内容。
文档更新规则
- 工程修改要同步更新对应文档。
- 如果没有现成文档,新文档统一放入
docs/下合适分类。 docs/project-memory/shared-memory/只记录高频、长期、团队共享的摘要和索引,不替代完整 PRD/技术文档。- 如果
docs/project-memory/shared-memory/与代码或docs/冲突,以代码和最新docs/为准,并同步修正共享记忆。
提交前建议让 Agent 执行
涉及现役编辑器、项目、精选素材、账号、钱包、公共设置或本地 dev 栈时,按对应定向测试、类型检查、Rust / SpacetimeDB 门禁、真实浏览器 smoke 与本文件当前命令验收。旧跨玩法回归和单玩法质量门禁只作历史记录,不再作为提交前现役检查入口。
请检查当前 git diff,指出:
1. 是否违反 AGENTS.md、Agent 执行准则或 docs/project-memory/shared-memory 约定;
2. 是否需要补充 docs;
3. 是否有长期知识需要写入 docs/project-memory/shared-memory;
4. 建议的测试命令和提交信息。
AI 游戏创作 App 命令沙箱验证
- Linux
command.exec / command.start / project.verify必须经过受信任系统 bubblewrap;缺失或 namespace / mount preflight 失败时工具失败关闭,不能回退宿主执行。 - 修改命令执行、PTY、项目验证或发布配置后,至少运行
GENARRATIVE_COMMAND_SANDBOX_REAL_TEST=1 cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml command_sandbox -- --nocapture --test-threads=1、cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml command_exec和cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml process_session -- --test-threads=1。 - 真实门禁必须同时证明项目内 Cargo / npm / Git 成功,项目外普通文件读写失败,
.git / .agent / .agents / .codex / .hermes写入失败,网络默认不可达,shell / PTY 后代在setsid + chdir后仍继承相同边界;process record、poll / stdin / terminate 和 project.verify 审计必须断言bubblewrap / workspace-write / disabled / workspace-v1。另测RUSTUP_HOME=$HOME与.rustup -> $HOME必须在目标执行前失败。Linux deb / rpm 包必须声明bubblewrap依赖;AppImage 发布说明必须要求宿主预装受支持的 bwrap,缺失时只能返回 sandbox unavailable。
AI 游戏创作 App Provider 成功交接验证
- 文本回复继续使用
game-creator-provider-handoff.v1;tool-plan/function arguments 使用独立game-creator-tool-plan-handoff.v1,禁止为省事放宽文本 handoff。两类 handoff 都必须在 Provider lifecyclecompleted前原子落盘并回读。 - tool-plan
repair-0..N必须共用持久 retry 与 handoff-first 恢复;测试停止点按 request kind/精确 slot 命中,不能让较早的 tool-plan 抢占 final-reply 断点。恢复测试必须关闭 mock Provider,证明零网络、原 requestId 唯一闭合、audit 幂等和终局零 sidecar。 - function arguments 只能进入私有
0600handoff 和后续 pending/action batch。参数命中密钥、配置痕迹或结构化可执行路径中的绝对路径时失败关闭,不得先脱敏再执行;源码正文与计划叙述不能用日志路径 token 扫描,以免把 HTML</tag>当路径。未闭合/错配 thinking wrapper 要保留无正文的无效事实并走 repair,不能清洗成可执行计划。公共事件、Agent DB、CLI 和报告只保留哈希、计数与安全身份字段;tool-plan protocol 不保存原始 callId/callIds/responseId/providerRequestId,只保存 call ID SHA-256 数组、catalog-bound function names、response ID SHA-256/字符数和 Provider request ID SHA-256,repair 只保存 call ID/function name SHA-256 及协议错误/preview 哈希。protocol/repair 审计必须在 Agent DB append 锁内按完整身份全历史 compare-and-append。 - steer/cancel/终态/身份漂移删除 tool-plan handoff 前,必须先按账本顺序幂等闭合全部实际 requestId lifecycle;不能只闭合当前 base entry 后删除后继 repair。Runner 恢复必须扫描 hash 路径归属、primary/
.previous和安全临时文件,回收合法终态残留;Unix 读写、扫描和删除固定在逐层打开的目录句柄,handoff 根目录和 Agent 目录用跨进程flock序列化,临时文件再用非阻塞flock判断写入方是否仍持有。已有 primary 的安装通过RENAME_EXCHANGE双端复核并在冲突时回滚;删除先以RENAME_NOREPLACE隔离到可恢复 temp 名、复核 inode,再按原 fd 清空并同步私有内容。Windows 逐层使用相对父句柄打开,并用GetFileInformationByHandleEx直接枚举已验证目录句柄,拒绝 reparse point/junction 与硬链接,临时文件以禁止共享的独占句柄表示活跃写入。不得再用文件名中的 PID 或进程存活推断临时文件所有权。未知、链接、身份替换或内容冲突项保持 busy 并失败关闭;主动忽略 advisory lock 的同 UID 进程仍属于宿主 OS 信任边界,不能宣称为完整沙箱隔离。 - 修改 Provider handoff/retry/Runner idle 判断后,至少运行
tool_plan_、tool_plan_handoff_、provider_handoff_、provider_retry_、相关强杀恢复用例、Tauri 串行全量cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --test-threads=1、编码检查和git diff --check;涉及跨平台扫描、PID 或临时文件回收时追加cargo check --tests --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --target x86_64-pc-windows-gnu。当前默认并发全量会受 Tauri 共享执行器饱和影响,曾在不同异步投影断言上偶发失败;它只作竞态诊断,失败时必须精确复跑,不能替代串行门禁,也不能把精确复跑结果伪装成默认并发 PASS。真实 Provider suite 单轮 PASS 前,确定性 mock 结果不得写成外部验收完成。 supervisor-swarm-tool-plan-handoff-runner-kill已实现并在 Shell/Root 两级注册。真实外部 Provider 复验从仓库根目录运行:
npm run ai-game-creator-shell:agent-runtime:supervisor-swarm-tool-plan-handoff-runner-kill-real-e2e -- --config-dir <发布AppData绝对路径>
- suite 必须使用 sentinel-owned sibling AppData;metadata-only zero-fault proxy 不注入 Provider 故障,为转发请求只做协议校验,请求日志仅记录验收所需的序号/时间等元数据,不得持久化或暴露 URL、method、headers、正文或凭据。每轮随机 capability 必须严格绑定 disposable project、目标 Agent、run 和实际 request slot,任一身份漂移、复用或越权命中都失败关闭。
- checkpoint 只允许在目标 tool-plan handoff 原子落盘并逐字段回读一致后、同一实际 requestId lifecycle
completed前 ACK;收到 ACK 后才可用 pidfdSIGKILL强杀 suite 自有 Runner。新 boot 恢复前不得出现由该计划产生的 action、pending、delivery、claim 或其它副作用。 - 单轮验收必须证明同一 requestId 唯一闭合且没有替代 identity,proxy
networkReplayCount=0,protocol/repair audit 幂等,handoff plan fingerprint 与恢复后的 durable pending/action batch 对应;终局 retry/tool-plan handoff/provider handoff/finalization/confirmation sidecar、重复 lifecycle/audit/action/message、capability/Runner/AppData 临时资源和正文/API Key/Provider URL/项目及正式配置绝对路径泄漏全部为0。失败轮不得与后续轮拼接。 - 当前该 suite 的实现、E2E self-test、Tauri/Rust 串行全量
1054 passed / 4 ignored / 0 failed、Linuxcargo check --tests与x86_64-pc-windows-gnu cargo check --tests已通过。2026-07-20 的真实外部 Provider 单轮已到达 checkpoint,并证明旧/新 Runner boot 切换、同一请求恢复、networkReplayCount=0、恢复前零 action/pending/delivery 与生命周期唯一闭合;但该轮随后因专业 Agent 连续连接失败而以 FAIL 结束,另一独立轮首批工具数不满足 fixture 也以 FAIL 结束,因此仍没有该 suite 的外部 PASS,且不得拼接两轮证据。Provider 成功到 handoff 原子落盘回读前的 unknown-result 仍未关闭,手动 context-compaction 也不在覆盖内;确定性 mock、命令注册成功或其它 suite PASS 都不能替代单轮完整真实验收。