文档先行:AGC 命令错误结构化与错误报告口径

- 新增 ADR:命令错误按具体变体结构化(ts-rs 导出)、报告池只收没人处理的错误、前端按 type 分流不匹配文案
- 更新【技术方案】AGC错误报告与诊断上传:采集口径改为"只收没有调用方处理的错误",补命令变体分流与 clientApi 边界
- 更新共享记忆 decision-log:记录本次口径与影响范围
- 更新共享记忆 pitfalls:记录"输错密码被当成客户端缺陷上报"的现象、根因与判据
- 修正 DirectTurnError 模块注释中"命令边界只给字符串"的过期描述,改为结构化拒单载荷
- docs/README.md 登记新 ADR
This commit is contained in:
2026-10-01 14:52:28 +08:00
parent 66e12cc3fd
commit fe200598c0
6 changed files with 112 additions and 4 deletions
@@ -1,5 +1,13 @@
# 决策记录
## 2026-10-01 AGC 命令错误结构化与错误报告口径
- 决策:AGC 命令失败按**具体变体**建模(Rust `#[derive(Serialize, TS)]` 枚举 + `#[serde(tag = "type", rename_all = "camelCase")]` + ts-rs 导出,生成物不手改),`#[tauri::command]` 的 `Err` 直接携带结构化枚举;前端只按 `type` 分流,**任何地方都不对错误文案做判断**。做法沿用 DirectProject 既有约定(`enqueue_direct_codex_turn -> Result<(), DirectTurnEnqueueFailure>`),不是新机制。
- 决策:错误报告池只收**没有任何调用方处理**的错误。预期业务拒绝(用户输入 / 前置条件 / 预期 4xx)由调用方消化并给反馈,永不进池;真故障由调用方带上下文重抛(`ClientActionError` 承载 `source/action/page`),经 `window.onerror` / `unhandledrejection` 入池;`clientApi` 作为 `fetch` 的调用方在抛出前判定 408/5xx/网络为缺陷(4xx 一律不报);Rust agent 终态失败仍由失败投影入池。删除 WebView 侧 `shouldCaptureClientError`。
- 边界:变体按**可判定的事实**命名——服务端 400 只给 `status + message`(`AppError.code` 仍是通用 `BAD_REQUEST`),所以 400 变体按"哪条请求的输入被拒"命名(如 `passwordEntryInputRejected`),不假装能区分密码长度/手机号格式。报告面板默认全选、只由通知打开的既有承诺不变。`captureAgentRuntimeError`、`ResourceReferenceInput` 偏好写盘、`invokeDiagnostic` 三处显式采集点保持原行为,按同一口径重抛/删除留在后续变更。
- 影响范围:`apps/ai-game-creator-shell/src-tauri/src/{auth_error.rs,auth_session.rs}`、`apps/ai-game-creator-shell/src/services/{clientAuthError.ts,clientActionError.ts,errorReporting.ts,clientApi.ts,clientAuth.ts}`、`apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx`、`apps/ai-game-creator-shell/src/services/generated/ClientAuthError.ts`(ts-rs 生成)。
- 验证:见 [`【ADR】AGC命令错误结构化与错误报告口径-2026-10-01`](../../adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md) 的验收清单;关键判据是"登录 400/401 业务变体不产生 `report_client_error`、不弹「发现问题」"。
## 2026-09-30 release 渠道移除产品名与包名后缀
- 决策:`release` 渠道的正式产品名统一为 `陶泥儿`,Windows NSIS、macOS DMG / updater 归档等由 Tauri `productName` 派生的包名不再包含 `Release` 文本;`identifier=world.genarrative.ai-game-creator.release` 与 `release-win` 更新分区保持不变。
@@ -2,6 +2,14 @@
这里只记录对当前开发仍有用的症状、根因、排查方法和风险边界。同一事实保留一个当前口径;退役对象的专属过程与单轮测试结果由 Git 历史追溯。遇到旧路径或版本时,以现行代码和专题文档为准。
## 2026-10-01 用户输错一次密码被当成"客户端出问题了"引导上报
- **现象**:登录页密码输错(或密码长度不合规)后弹出「发现问题」,报告面板「错误事件(2)」列出 `密码长度需要在 6 到 128 位之间 — auth · 1 次` 与 `手机号或密码错误 — auth · 1 次`,默认全选,与 react-render / 5xx / agent-runtime 终态失败视觉等价。
- **原因**:① 登录已下沉 Rust,`login_client_with_password` 等命令失败返回 `Err(String)`,Tauri 以**裸字符串**拒绝 `invoke`,前端拿不到任何类型信息;② `shouldCaptureClientError` 对非 object 值走默认 `return true`,`handleLoginSubmit` 的 catch 把预期业务拒绝报进了错误池。技术方案里"预期 4xx 登录/鉴权失败不进池"的口径早就成立,是错误通道的实现方式违背了它。
- **处理(现行口径)**:命令错误一律按具体变体结构化(`Result<_, ClientAuthError>` + ts-rs 导出),UI 调用方按 `type` 分流:认得的业务变体只给用户反馈,系统变体/未识别变体/非结构化拒绝原样抛出走上报链路;删除 `shouldCaptureClientError`。详见 [`【ADR】AGC命令错误结构化与错误报告口径-2026-10-01`](../../adr/【ADR】AGC命令错误结构化与错误报告口径-2026-10-01.md)。
- **判据/取证**:`npx vitest run apps/ai-game-creator-shell/tests/errorReporting.test.ts`——登录返回结构化业务变体时 `report_client_error` 不被调用;系统变体经 `unhandledrejection` 只上报一次且 `source=auth`。Rust 侧 `cargo test --locked --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml auth_error` 钉住变体 `type` 与 400/401/429/5xx/网络映射。
- **关联**:`apps/ai-game-creator-shell/src-tauri/src/auth_session.rs`、`apps/ai-game-creator-shell/src/services/errorReporting.ts`、`apps/ai-game-creator-shell/src/app/AuthenticatedClient.tsx`。
## 2026-09-30 构建期 staging 撞上不装 npm 依赖的 Linux 门禁:AGC 壳 Rust lane 全红
- **现象**:`Project CI` 的 AGC 壳 Rust 三条 lane(`npm run check:native-shells:agc-rust-shard-*`)在 `fb130d184` 之后全部失败,日志只有 `error: failed to run custom build command for genarrative-ai-game-creator-shell` 与 `thread 'main' panicked at build.rs:65:28: Claude Agent SDK 缺失;请先执行 npm ci`(run 3083 / job 17521 实测,1 分钟即失败)。