合并 origin/master 到 chore/rust-compile-warnings:按 M/D/G 分桶解冲突

origin/master = 441be8d62(落后 143 提交);合并前本分支 HEAD = aeebbee28。
冲突 11 处,按「master 侧是否活跃」分三桶处理。

M 桶(master 改过该文件 → 取 master 版本,不把我们的删除加回去):
- agent/codex_app_server/mod.rs(master +348/-108)
- agent/codex_app_server/model_catalog.rs(master +38/-18:CatalogSource::Authenticated / source_for_credential / verify_authenticated_source)
- agent/codex_app_server/model_catalog/auth_handoff.rs(modify/delete → 保留 master 版,OAuth 轮换交接)
- agent/codex_cli.rs(master +190/-44)
- agent/codex_app_server/model_catalog/real_tests.rs:我们把该文件裁到 59 行以适配自建的 capture 签名;master 的 model_catalog.rs 恢复 4 参 capture 后取回 master 的 244 行用例,否则 --all-targets 报 2 处 E0061。

D 桶(master 未动过、我们删除的死码 → 保留删除):
- 合并前已删:patchset.rs、git_inspect.rs、repository_context.rs、generation/pass_artifacts.rs、agent/runtime_models.rs、debug.rs(+debug/debug_drafts.rs) 等。
- process_session/{io,lifecycle,persistence,recovery}.rs 与 process_session/tests/owner_fixture_cleanup.rs → 裁决为「保留删除」:master 在这 4 个文件里只改「死码的错误正文」;实测整棵子树在 AGC 生产构建里 69 条 dead_code、且只被 tests.rs 引用;生产只用到 recovery.rs 的 2 个 shutdown 函数,而那 2 个我们已搬进 process_session/shutdown.rs。

G 桶(双方都改、我们那侧非语义 → 以 master 语义为准,手工合并):
- agent.rs:取 master 的 claude_code_failure_to_turn_error(改名,codex_app_server/mod.rs:5323 依赖该再导出);保留我们的模块集合(provider_request_snapshot,去掉 runtime_models 与 dispatch 的再导出)。
- thread_manager/dispatch.rs:master 的 host_dropped_with_detail(panic 详情)+ 我们的 cfg(not(test))/cfg(test) 收口(测试态不读兜底结果,避免 harness 未用变量告警)。
- generation/llm_request.rs:取 master 的 AgentProgressEmitter(其唯一消费方 maybe_generate_platform_art_asset_step 已在我们那侧删除,随之成为残留,交由后续提交处理)。
- process_session/model.rs:master 的 8 处错误正文(WindowsProcessJob 的 last_os_error)**全部落在我们未裁的区间**,逐 hunk 叠加到我们的 382 行版本(结果 406 行;last_os_error 出现次数与 master 版一致,均为 13)。
- process_session/shutdown.rs:把 master 在 recovery.rs 里给 shutdown 广播加的诊断搬进我们的实现(`process_session.shutdown.send_failed processId=… detail=…`;收敛后的 LiveProcessSession 不再有 process_id 字段,进程身份取注册表 key)。
- docs/project-memory/shared-memory/pitfalls.md:两侧各新增一节,两节都保留。
This commit is contained in:
2026-10-07 13:59:31 +08:00
201 changed files with 10300 additions and 2276 deletions
@@ -616,6 +616,16 @@ Runner-kill E2E 不再以 latest task 或单个 process record 推断整体恢
`command.poll` 私有正文虽然必须进入 owning Agent context 供后续交互,但模型 prompt 不是持久化隔离边界。后台 finalization 在创建 assistant journal 前检查当前 run 的成功 poll observation;只要存在非空输出,就把模型最终回复整体收束为固定安全完成摘要,再计算 response fingerprint 并写 conversation/event/Agent DB。该边界不按长度猜测 token,因此 challenge、ready/echo/stopped 行和短 PIN 的局部回显都不能扩大到公共持久面;没有私有 poll 正文的普通回复保持原样。
### V1.11.2 命令沙箱 Node 版本管理器支持
开发构建(`debug_assertions`)下,AGC 生成和验证 Web 项目所用的 Node 往往由 fnm / nvm 等版本管理器托管:安装前缀位于用户目录下,活动 `PATH` 指向随 shell 会话变化的临时目录(如 fnm 的 multishell)。V1.11.2 让开发构建的命令沙箱原生解析并只读复用这些托管安装,不再要求用户改系统 Node、把宿主 shim 指到 `/usr/bin`,或把托管目录软链进系统路径。发布构建继续只认随包 bundle,不新增托管版本管理器探测,也不改变 bundle 缺失时的失败口径;Windows 行为不变。
- 版本来源是机器上可枚举的托管安装:fnm 的 `node-versions/<version>/installation`(含 `aliases/default` 指向的默认别名)与 nvm 的 `versions/node/<version>`。宿主发现和沙箱只读挂载共用同一套窄叶校验,不允许两处信任口径漂移。
- 解析优先级为:`.nvmrc` / `.node-version` 的权威 pin 命中 > 宿主 `PATH` 能解析出的可用 Node > 版本管理器回退链(`package.json` `engines.node` 偏好中的最高匹配 > 当前活动版本 > 默认别名 > 已安装最高版本)。`.nvmrc` / `.node-version` 能理解但未安装时必须失败关闭(`node-version-pinned-not-installed`),不得静默回退;`engines.node` 只是偏好,任何情况下都不阻塞。只实现文档化的比较子集(精确三元组、major、`>=` / `>` / `<=` / `<`、`^`、`~`、`x` / `*` 通配、`lts/*`);不支持或无法解析的写法按「未 pin」处理并回退。
- 只读挂载只允许通过窄叶校验的完整安装前缀(同时含 `bin/node` 与 npm 的 `npm-cli.js`)。HOME、`FNM_DIR` / `NVM_DIR` 根、`aliases` 目录、宽泛用户目录、不完整前缀,以及 canonicalize 后逃逸出受控前缀的 symlink 全部拒绝并失败关闭;不得为了兼容而挂载整个用户 HOME 或版本管理器数据目录。
- Linux 上 npm 不再直接执行 npm shim,而是以受信任的 `node <npm-cli.js> ...` 启动;`npm install` 的联网判定必须跟随这条真实启动形态,不能因为包装方式变化而丢失联网或反向放开。
- 沙箱内联环境不继承宿主活动版本管理器的临时变量(如 fnm multishell 路径);版本管理器 CLI(`fnm` / `nvm`)本身不需要在沙箱内可用。
## V1.12 受控本地 Git 提交
V1.12 首个切片补齐“修改、验证、审阅、提交”的单 Agent 本地闭环,只新增 `project.git_commit`。它不是通用 Git 写权限:不开放 `push / fetch / pull`、分支创建或切换、merge / rebase、reset、stash、tag、submodule、worktree,也不能通过 `command.exec` 绕过 `.git` 只读沙箱。
@@ -65,7 +65,7 @@ Node/npm 版本探测清空继承环境后,必须设置客户端创建的临
- **网络与凭据只在 Rust**。平台 origin、Bearer/refresh 凭据、OSS 直传票据、Provider 与更新清单请求都由 `src-tauri` 承担;渲染层通过 typed command 提交结构化意图,不再持有 access token,也不再声明 `http:default` 权限(`capabilities/main.json`)。`src/services/clientApi.ts` 与 `fetchClientHttp` 已删除。
- **状态变更由 Rust 事件驱动**。正式状态归 Rust:Direct 活动回合的唯一事实源是 Direct 线程管理器的活动回合快照(`list_direct_active_turns` 只读它),登记、进度内容变化、收口各广播一次 `game-creator-direct-active-turns-changed`;素材生成与插件状态同理。渲染层进入入口时**先订阅、再读一次受控快照**,事件重复或内容未变时保持数组身份,卸载后迟到事件不写回;不恢复任何固定频率轮询(纯 UI 计时器、拖拽重复器与动画 tick 除外)。
- **维护态判定归 Rust,渲染层只订阅**。平台请求的错误分支统一经 `platform_maintenance::watch_platform_response` 分类(只有 `503` 且命中 `MAINTENANCE` 或「维护」才算,对象存储自身的 503 不误伤),命中后广播 `genarrative-client-maintenance-detected`;渲染层由 `clientMaintenance.subscribeClientMaintenanceEvent` 订阅并打开唯一的「系统维护中」弹窗,业务面板各自的错误文案保持不变,同一批并发失败只弹一次。
- **失败文案只展示宿主给的脱敏摘要**。`turn.completed.failure` 是失败说明的唯一来源,渲染层不做 HTTP 判定、不预读诊断正文;失败线索留在 `.agent/runtime/errors`、应用日志与错误上报池(`5398a53e6` 起用户可见文案不再带诊断引用)。
- **失败文案展示宿主给的精确脱敏事实**。`turn.completed.failure` 是失败说明的唯一来源,渲染层按 typed 变体展示 HTTP 状态、错误码、IPC/stdio、操作系统错误和上游正文;只替换凭据值、完整 URL、绝对路径与私钥,不再因命中 `authorization/token/credential` 删除整条错误。失败线索仍写入 `.agent/runtime/errors`、应用日志与错误上报池。
- **活动回合之外的两条配套约束**:命令返回 `Ok` 只代表接单成立,整轮收场只由 `turn.completed` 回答;渲染层的队列、忙态与提示都以事件流的这些终态为准。
证据入口:`cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --offline -- direct_thread_manager --test-threads=1`、`-- platform_maintenance --test-threads=1`、`npx vitest run tests/directActiveTurns.test.tsx tests/maintenanceNotice.test.tsx --root apps/ai-game-creator-shell`。
@@ -855,6 +855,8 @@ Agent 可见的系统指令、工具与参数说明、恢复指引和上下文
2026-07-14 V1.11.1 最终真实验收:发布 AppData 的真实 `gpt-5.5` `process-session` 形成 41 条 task、75 条 event、63 条 Agent DB 和 8 条 receipt,唯一 start、3 poll、唯一 stdin / terminate、3 次 cursor 推进及唯一 terminal / completed / assistant全部通过;Runner kill套件形成 13 条 task、19 条 event、19 条 Agent DB,真实 SIGKILL后项目 cwd进程清零、新 boot保持同 run / session并只形成 1 条 reconciliation。两套的 reconnect、重放、重复 action / message / receipt、公共进程正文、密钥和诱饵泄漏均为 0,disposable项目均自动清理;V1.11.1 持久进程链路据此完成验收。
2026-10-07 V1.11.2 切片:Linux 命令沙箱原生支持 fnm / nvm 托管的 Node。开发构建(`debug_assertions`)先从 `.nvmrc` / `.node-version` 的权威 pin、再按 `package.json` `engines.node` 偏好、活动版本、版本管理器默认别名和已安装最高版本选择托管安装;`.nvmrc` / `.node-version` 能理解但未安装时失败关闭,`engines.node` 和无法解析的写法不阻塞。宿主发现与沙箱只读挂载共用同一窄叶校验,只挂载完整安装前缀(含 `bin/node` 与 npm 的 `npm-cli.js`),拒绝 HOME、管理器根、`aliases`、宽泛目录、不完整前缀和逃逸 symlink。Linux npm 以 `node <npm-cli.js>` 启动,`npm install` 的联网判定跟随该真实形态;sandbox 环境剔除 fnm multishell 变量。发布构建仍只认随包 bundle,Windows 不变。定向 Rust 测试与真实 bwrap 内 fnm v22 的 `node` / npm 运行已通过;真实 nvm 端到端待补。
2026-07-14 起,同一文档的“V1.12 受控本地 Git 提交”补齐单 Agent 的修改、验证、审阅、本地提交闭环。新增且只新增 `project.git_commit`,输入绑定 `message / paths / expectedHead / expectedSnapshotFingerprint`,最多提交 12 个显式安全路径;它是不可降为 `auto` 的强制确认工具,legacy 空策略也继续要求确认,项目策略仍可显式拒绝。动态隔离 child 无条件禁用该工具,最终提交由父 Agent 统一发起。当前 run 必须在当前非零 project revision 上已有 passed verification gate。`git.inspect` 签发的 `commitSnapshotFingerprint` 绑定 HEAD、附着分支、规范化安全状态和全部安全变更文件内容;`.agent` 等控制面正常落盘不制造跨动作漂移,安全源码、HEAD、分支、revision 或 gate 任一变化仍失败关闭。提交只支持标准仓库根和本地附着分支,要求真实 index 没有 staged 内容,并用临时 index、真实 `index.lock`、`commit-tree` 和带 expected old HEAD 的 `update-ref HEAD` 精确前移 ref,同步 HEAD / branch reflog后跨平台原子安装 index;未选改动保持未暂存。它不开放 remote、分支切换、merge / rebase、reset、stash、tag、submodule 或 worktree 写操作,也不能通过 `command.exec` 绕过 `.git` 只读沙箱。成功 observation、Agent DB 审计和 terminal receipt 只保留 parent / commit SHA、分支、安全路径、message SHA-256 和剩余变更计数;ref 前移后的不确定错误或审计失败进入 `needs-reconciliation`,已知 commit 的审计失败仍在 fallback receipt 保存 commit SHA,恢复不得重放提交。
2026-07-14 V1.12 真实 `gpt-5.5` 验收已通过。现有 `llm-runtime` disposable 套件要求模型在完整修改、验证和审阅链路末尾自行创建唯一受控提交,并从原始 commit object、真实 Git parent / HEAD / tree、空 staged index、提交后所选路径状态、封闭字段专用审计、terminal receipt 和 HEAD / branch 双 reflog 验真。最终收紧版形成 151 条 task、258 条 event、266 条 Agent DB、17 次代表性成功工具执行、7 套确认生命周期、9 个实际副作用 action 和 44 条 receipt;唯一提交精确包含 2 个目标路径,预存 sentinel 未被夹带,project revision 保持 3。Runner 强杀恢复后 run / session 身份稳定,副作用重放、重复 action / message / receipt、密钥和诱饵泄漏均为 0,disposable 项目已自动清理。
@@ -62,7 +62,7 @@
### 前端合并与渲染(回合唯一归属,连续工具成块)
- 加载对话时按历史条目进入 `project.jsonl` 的原始顺序投影:用户消息、文本与工具块保持原序,连续工具合为一块、遇到文本另起一块,不按 `turnId` 重新归并、也不再有 `seq` 交替。
- 回合完成后,中间文本及所有工具块统一收进默认关闭的“执行过程”;最终回复及失败提示留在外面。展开后仍按原顺序查看中间输出和工具详情;运行中不使用外层折叠区。用户消息的发送时间从消息自身的历史时间读取,不能拿工具起点补造。
- 回合完成后,中间文本及所有工具块统一收进默认展开的“执行过程”;最终回复及失败提示留在外面。用户仍可收起过程块,重开项目后过程默认再次可见;运行中不使用外层折叠区。用户消息的发送时间从消息自身的历史时间读取,不能拿工具起点补造。
- 实时与回读共用同一投影,正文、工具和耗时不另建实时/未归属渲染出口。先在完整历史按消息身份关联,再分页;禁止按第 N 个工具回合匹配第 N 条用户消息。详情通过当前回合 `callId` 关联;同项目回读与实时增量幂等合并,切项目清空旧状态。完整合同见 [AGC 实施计划](./【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md) 的“DirectProject 回合展示唯一归属”。
- 块 DOM 与交互(对齐 Codex):
@@ -105,7 +105,7 @@
- 当前 Agent 与策划 Agent 共用 `packages/shared` 的 `AgentMessageContent` 表现组件:正文为 14px / `--platform-text-strong`,思考、中间输出和工具调用为 12px / `--platform-text-soft`。实时与历史思考共用同一个折叠入口;工具输入输出继承过程色,失败状态保留错误色。Markdown 标题、表格及代码高亮在过程区同步弱化,最终回复和文档预览仍保留正常排版,不按 Agent 类型复制样式。输入提示与禁用状态保持原有反馈。
- Windows 命令展示:仅 `command` 卡片识别 `pwsh` / `powershell`(含完整路径、`.exe`、常见启动选项)的 `-Command` / `-c` 外层包装,摘要和展开输入只展示脚本正文,并解开单个 shell 参数的引用拼接。摘要优先读取已脱敏的 `detail.command`,再按首行 120 字符截断,避免历史摘要被可执行文件路径占满。无法识别的启动方式、`-File`、`-EncodedCommand`、普通命令和 MCP 输入原样展示;执行参数、持久化原文、脱敏和输出均不改变。
- 调试属性:块与行都带 `data-duration-ms`(原始毫秒,无法计算时为空串)与稳定 `data-testid`(块 `agent-tool-call-group`、行 `agent-tool-call-row`)。
- 必须用 `<button aria-expanded>` + `hidden` 控制展开(键盘可达、可读屏),块头与行都是按钮:`aria-label` = 汇总 / 行文案 + 耗时;默认折叠。
- 必须用 `<button aria-expanded>` + `hidden` 控制行级展开(键盘可达、可读屏),块头与行都是按钮:`aria-label` = 汇总 / 行文案 + 耗时;回合完成后的外层过程块默认展开,用户可手动收起。
- 输入框、消息气泡、消息列表滚动模型**不变**;块只是消息流里的一个块。
## 验收判据(每条都要有可复现证据)