diff --git a/.project-docs/20-architecture/data-flow.md b/.project-docs/20-architecture/data-flow.md index 1bf84c2..0325d06 100644 --- a/.project-docs/20-architecture/data-flow.md +++ b/.project-docs/20-architecture/data-flow.md @@ -19,6 +19,7 @@ | 客户端更新检查 | 设置页 | Renderer update store → IPC → Main AppUpdater → 目标 feed | Main 记录并重抛原始错误;Renderer 只显示去重、脱敏的单条提示,稳定源缺包不伪装为最新版 | | 设计会话创建/切换 | AI 绘画页面或侧栏 | Renderer API → Main → Workspace Conversation API | 新会话属于现有 Workspace;读取独立消息、Brief、Quote 和 `turnRevision` | | 设计消息与确认 | 当前 Conversation | Main ↔ 持久 Agent Gateway Session WebSocket → Conversation 快照 | `command.submit`、Run 与设计事件共用连接;传输失败才以同一幂等 ID 回退 REST;结构化业务错误不重试且未知文本由 Main 脱敏;请求和流式结果同时绑定 Workspace + Conversation | +| 设计有限请求生命周期 | Renderer Workspace JSON 调用 / shared Works token refresh | Main deadline → Electron transport → safe-read-only Node fallback → Host API timeout envelope | 包括取凭据、请求头和响应 body 的完整生命周期最多 30 秒;超时 abort transport 并稳定返回 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT`;透明 fallback 只允许 `GET`/`HEAD`/`OPTIONS`,mutation 不隐式重放 | | 设计单图来源选择 | 当前 Workspace 已完成图片 / 本地图片 | 现有 Asset 上传或选择 → `attachmentAssetIds` → 当前 Conversation Turn | 图片 Brief 用作图生图参考图;视频 Brief 用作首帧;只提交一个真实 Workspace Asset ID | | 设计任务同步 | 任一 Conversation 的事件流 / Quote REST 对账 | Renderer Workspace 任务列表 | Task 和 Asset 按 Workspace 归并;任务已落库但 Run 失败时恢复可见性,内部对账失败不覆盖新会话错误,切换 Conversation 后仍同步任务但不回写旧会话 | | 设计 Quote 编辑与重报价 | 当前 Conversation 的 active Quote | Renderer 修改最终 Prompt/参数 → Main Host API → Works Square Quote update → 当前 Conversation | 服务端返回最新参数与设计点;报价完成前不能确认,确认提交最新原值,客户端不自行计价 | @@ -38,6 +39,7 @@ - 本地构建临时目录、HTTP origin 和预检 WebContents/partition 只属于一次调用;预检读取与 `built_archive` 相同的内存字节,但结果不写为可信上传 receipt,也不覆盖生产 opaque-origin。 - 旧 schema v1 `submitted` 记录迁移并保留;旧 `armed`、`waiting_for_package`、`waiting_for_login`、`uploading`、`failed` 归一为 `legacy_retired`,不再启动 watcher 或上传任务。 - AI 绘画 Conversation 持有消息、Brief、Quote、`turnRevision` 和服务端 Session 绑定;Workspace 持有 Conversation 列表、生成任务和资产。 +- AI 绘画 Main 持有 Workspace 请求 deadline、底层 transport fallback 和共享 Works token refresh flight。共同等待者必须在同一有限期限内 settle,refresh flight 结束后必须释放,后续刷新可重新发起;底层 mutation transport failure 不得自动产生第二次上游请求。 - Prompt Museum pending Prompt 是 Renderer 进程内一次性导航状态;Canvas 消费后立即清除,不进入 Workspace/Conversation 直到用户主动发送。 - Learning Main 本地课程库按当前认证身份派生的不透明 account partition 持有 archive 路径、安装记录和 player registration;Renderer 只接收课程 DTO、classroom 投影和当前账号的 loopback player URL。账号 epoch 变化会使旧异步结果、runtime 事件、player URL/cookie 与注册资源失效。云端进度以课程 aggregate hash 为身份,模块进度附带受控 module id/hash。 - 图生图参考图与视频首帧都先归一为当前 Workspace 的 Asset;从作品选择时复用生成结果 Asset,本地选择时先走既有上传接口,再把唯一 Asset ID 随 Turn 提交。选择或上传成功后关闭选择器。 @@ -68,4 +70,4 @@ ## Last Updated -2026-08-17 +2026-08-19 diff --git a/.project-docs/20-architecture/system-overview.md b/.project-docs/20-architecture/system-overview.md index 4249fe2..99da1f7 100644 --- a/.project-docs/20-architecture/system-overview.md +++ b/.project-docs/20-architecture/system-overview.md @@ -65,6 +65,7 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展 - AI 绘画中,一个 Workspace 可包含多条 Conversation;消息、Brief、Quote 和 `turnRevision` 属于 Conversation,生成任务和资产属于 Workspace。新建 Conversation 不得隐式创建新 Workspace。 - 每条 Conversation 复用服务端持久 Agent Gateway Session。客户端不得在注销或退出时 DELETE 该 Session;只关闭本地事件流并清除本机 Session-id 缓存,重新访问时从 Conversation API 刷新。 - 已连接的 Conversation Session 通过同一 WebSocket 提交 `command.submit` 并接收 `command.accepted`、Run 与设计事件。只有发送失败、连接关闭或 ACK 超时属于可回退的传输故障,REST 必须复用同一 `client_command_id`;结构化 Gateway 业务错误不得再次提交,未知上游错误文本不得穿透 Main 安全投影。 +- Main-owned Canvas Workspace JSON 请求和 shared Works token refresh 的完整生命周期最多 30 秒,超时 abort transport 并以固定 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT` 结束 Renderer 等待。Electron `net.fetch` 失败后的 Node fetch 透明回退只允许 `GET`、`HEAD`、`OPTIONS`;PATCH/POST 等 mutation 只允许由持有显式幂等身份的上层协议决定重试,不能由底层 transport 隐式重放。该边界不改变上面的 WebSocket→REST 幂等 fallback。 - Renderer 的异步与流式状态必须同时校验 Workspace + Conversation 身份;项目任务事件只按 Workspace 归并,避免切换会话时丢失任务或接收迟到消息。 - 确认生成按 Quote 对账 Workspace 任务。任务事务已提交但 Run 随后失败时可通过 REST 恢复任务可见性;内部任务对账失败不写当前 Conversation 的用户错误,任务恢复也不授权旧请求回写已切换的 Conversation 或清理新 pending turn。 - Updater feed 选择、原始错误日志、下载和安装生命周期只属于 Electron Main。Renderer 不得把缺失稳定 manifest 投影为“已是最新版”,也不得显示原始堆栈、URL、路径或错误码;并发检查共享同一错误事件时只发送一次错误状态,后续独立重试仍可重新报告。 @@ -79,4 +80,4 @@ Makelore 是 Electron 桌面客户端。Renderer 负责项目操作与状态展 ## Last Updated -2026-08-17 +2026-08-19 diff --git a/.project-docs/30-worklog/current-state.md b/.project-docs/30-worklog/current-state.md index 52b085e..d95ae2c 100644 --- a/.project-docs/30-worklog/current-state.md +++ b/.project-docs/30-worklog/current-state.md @@ -4,6 +4,17 @@ This file is the integrated default-branch snapshot. Feature tasks record progre ## Integrated Through +- AI Design request-freeze source commit `87e4140` from feature task + `20260819-design-freeze-live-6e2c` is integrated by task + `20260819-integrate-design-freeze-3f8b7c`. Main-owned Workspace JSON + requests and shared Works token refreshes now have a complete 30-second + lifecycle deadline, including response-body consumption. Timeout settles as + stable `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT`; low-level Electron-to-Node + fetch fallback is limited to `GET`/`HEAD`/`OPTIONS`, so mutation failures are + not implicitly replayed. The native password/SMS login and temporary + `disable-http2` diagnostic bootstrap remain included. Automated client + verification does not yet prove the installed-client freeze is resolved or + establish HTTP/2 as the root cause. - AI Design history source commit `bf0b805` from feature task `20260819-history-load-stall-a92d` is integrated on local `main`. Conversation reads start with the newest ten messages and fetch older pages @@ -46,7 +57,7 @@ This file is the integrated default-branch snapshot. Feature tasks record progre 客户端面向非专业用户提供“创建小游戏或小程序 → 项目配置中一键提交 → Main 本地 npm/Vite 构建 → Electron 双视口预检最终产物 → 上传 source+built 双归档与 contract → 运营审核”的唯一创建者链路。Main 对安全源码快照运行安装包内固定 npm 11.6.2 的 `npm ci --ignore-scripts`,再显式调用项目 `package-lock.json` 锁定的 Vite;Vite config/plugins 以当前桌面用户权限执行,因此只适用于用户信任的本地项目,不是 sandbox。预检由 Main 以临时 loopback origin 和 Electron WebContents/CDP 检查与最终 `built_archive` 相同的内存文件字节,覆盖桌面/移动视口、运行错误、白屏和外域访问;不使用 Playwright。该检查仍可由非官方客户端绕过,不产生可信 receipt,也不复刻生产 opaque-origin。服务端不再替客户端运行项目 Vite,而是把源码、构建归档和 contract 视为不可信输入,逐字节重算与校验并固化不可变 Release;人工审核仍不可绕过。自定义和缺少类型字段的旧项目不提供该入口。已发布作品优先使用安全投影后的 `play_url`,`runtime_url` 仅保留一个客户端版本的兼容回退。 -AI 绘画的一个 Workspace 可包含多条 Conversation。消息、Brief、Quote 和 `turnRevision` 随 Conversation 隔离;生成任务和资产保持 Workspace 级共享。图片 Brief 支持文生图,以及从当前项目已完成作品或本地上传中选择一张参考图继续生成;视频复用同一选择器绑定首帧。两条路径都通过现有 Workspace Asset 契约提交一个真实 Asset ID。每条 Conversation 使用服务端持久 Agent Gateway Session;连接正常时命令、Run 与设计事件共用双向 WebSocket,只有发送、断连或 ACK 超时等传输故障才以同一 `client_command_id` 回退 REST,结构化业务错误不重复提交且未知上游文本由 Main 脱敏。确认栏允许编辑服务端最终 Prompt 与 generation options,每次修改都由服务端 Quote 重算设计点,确认时提交最新原值;客户端不推算供应商或积分价格。任务详情可预览/下载结果。侧栏删除项目要求完整输入项目名,删除当前项目后切换到最近更新的剩余项目;服务端删除/结算语义仍由 Works Square 契约负责。确认生成会按 Quote 对账 Workspace 任务;任务已经落库但 Run 随后失败时仍恢复任务列表,内部对账失败不覆盖当前 UI 错误,同时 Conversation 写入继续受 Workspace-load 与 Conversation-selection generation 保护。 +AI 绘画的一个 Workspace 可包含多条 Conversation。消息、Brief、Quote 和 `turnRevision` 随 Conversation 隔离;生成任务和资产保持 Workspace 级共享。图片 Brief 支持文生图,以及从当前项目已完成作品或本地上传中选择一张参考图继续生成;视频复用同一选择器绑定首帧。两条路径都通过现有 Workspace Asset 契约提交一个真实 Asset ID。每条 Conversation 使用服务端持久 Agent Gateway Session;连接正常时命令、Run 与设计事件共用双向 WebSocket,只有发送、断连或 ACK 超时等传输故障才以同一 `client_command_id` 回退 REST,结构化业务错误不重复提交且未知上游文本由 Main 脱敏。Main-owned Workspace JSON 请求与共享 Works token refresh 的完整生命周期均限制为 30 秒,超时稳定投影为 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT`;底层 Electron-to-Node fetch 回退只允许 `GET`、`HEAD`、`OPTIONS`,PATCH/POST 等变更请求失败时不得隐式二次发送。确认栏允许编辑服务端最终 Prompt 与 generation options,每次修改都由服务端 Quote 重算设计点,确认时提交最新原值;客户端不推算供应商或积分价格。任务详情可预览/下载结果。侧栏删除项目要求完整输入项目名,删除当前项目后切换到最近更新的剩余项目;服务端删除/结算语义仍由 Works Square 契约负责。确认生成会按 Quote 对账 Workspace 任务;任务已经落库但 Run 随后失败时仍恢复任务列表,内部对账失败不覆盖当前 UI 错误,同时 Conversation 写入继续受 Workspace-load 与 Conversation-selection generation 保护。 Canvas 侧栏提供“获取灵感”进入 Prompt Museum。列表、筛选、分页、详情、作者/来源/许可证和图片地址全部由服务端经 Main-owned Host API 提供,客户端不打包静态数据集;服务端相对媒体只允许固定 `/api/image-prompt-museum/{entry}/media/{thumbnail|number}` 形状,并由 Main 注入 Works Bearer、执行一次 401 刷新、可信 raster MIME 与 10 MiB 上限后转为 Renderer data URL;credential-free HTTPS CDN 图片保持直连。图片失败只显示卡片内占位,不阻断卡片或详情;缺少来源 URL 时显示纯文本。“使用此 Prompt”只把原文带回当前 Canvas 输入框,不自动发送。该模块不是投稿、点赞、评论或排行榜社区。客户端契约已就绪,但不据此宣称 Works Square 内容后台和生产数据已经部署。`pnpm run dev` 现在默认使用云端 Canvas 适配器,本地适配器只能通过显式开发命令启用;产品 UI 只保留中文。 @@ -62,6 +73,7 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选 ## Recently Completed +- 2026-08-19: Integrated native password/SMS login, the temporary HTTP/2-disabled diagnostic bootstrap, and the AI Design freeze fix. Workspace JSON calls and shared token refresh now settle within 30 seconds, transport abort is paired with deterministic rejection, and implicit Electron-to-Node fallback no longer replays mutation requests. Installed-client Quote retry/confirm smoke and the final HTTP/2 policy decision remain pending. - 2026-08-17: Integrated application-side multi-Session isolation for AI Programming. Session A may remain busy while Session B is independently accepted or terminally rejected; errors, startup deadlines and uncertain-failure cleanup stay Session-scoped. Main now fail-closes stale Agent/provider runtime state before execution, applies bounded manager/project FIFO acceptance with revocable timeouts, and never refreshes the shared runtime automatically from ordinary execution paths. Full unit, typecheck, lint, build, focused Electron E2E and independent Sol review passed; a real paid-provider/bundled-runtime concurrency smoke remains pending. - 2026-08-17: Replaced the temporary coverless-first-create fallback with a required PNG/JPEG/WebP picker, preview, file name, reselect action, Renderer/Main signature and size validation, and one Main-owned multipart metadata-plus-cover create request. Create conflicts fail before version upload; existing project metadata and covers remain unchanged. - 2026-08-17: Corrected macOS Robot hotspot discovery after a system-visible `Xiaozhi-*` report. CoreWLAN now gets one bounded retry when its first result is empty or all SSIDs are unavailable; a persistent non-empty redacted result becomes the existing safe permission state. Open-only filtering, firmware, Host/Renderer contracts, exact-current-SSID verification, and the system-Wi-Fi fallback are unchanged; signed-package physical smoke remains pending. @@ -94,10 +106,11 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选 ## Next Recommended Steps -1. 部署 Works `module_access` migration 与 `/api/auth/me` 权限 API,打包新 Makelore 客户端,再用真实账号分别关闭 Code、Canvas、Learning、Robot 执行卡片、根/深层/别名路由 smoke;同时独立验证模块 API 服务端授权。 -2. 使用真实 Works 账号和固定 SHA-256 的 production Stage artifact 验收 Learning 课程目录/生成/材料上传/取消恢复、下载、离线播放、进度、Agent、ASR、PBL/评分 runtime,并完成 Windows 与签名 macOS 安装包 smoke。 -3. 对 default-on Guided Hotspot Binding 核对指定固件镜像与六位码发行/消费契约,补齐 Windows 真机热点连接、签名 macOS x64/arm64 CoreWLAN/CoreLocation/worker 打包验证、真实 Host API/native seam Electron E2E 和完整真机 smoke;发布支持保留精确 `=0` 回滚,不把缺失证据表述为已验收。 -4. 成组核对客户端 source+built+contract 上传 → 服务端逐字节校验 → OSS immutable Release → CDN/Edge 的发布契约与客户端 `play_url` 消费契约。 +1. 用包含本次修复的安装包和真实 Works 账号重复执行 Quote PATCH、重试报价与继续调整,确认任一超时在 30 秒内释放 UI、其他请求可继续、服务端不收到隐式重复 mutation;确认后单独恢复 HTTP/2 再对照 smoke,决定是否移除临时 `disable-http2`。 +2. 部署 Works `module_access` migration 与 `/api/auth/me` 权限 API,打包新 Makelore 客户端,再用真实账号分别关闭 Code、Canvas、Learning、Robot 执行卡片、根/深层/别名路由 smoke;同时独立验证模块 API 服务端授权。 +3. 使用真实 Works 账号和固定 SHA-256 的 production Stage artifact 验收 Learning 课程目录/生成/材料上传/取消恢复、下载、离线播放、进度、Agent、ASR、PBL/评分 runtime,并完成 Windows 与签名 macOS 安装包 smoke。 +4. 对 default-on Guided Hotspot Binding 核对指定固件镜像与六位码发行/消费契约,补齐 Windows 真机热点连接、签名 macOS x64/arm64 CoreWLAN/CoreLocation/worker 打包验证、真实 Host API/native seam Electron E2E 和完整真机 smoke;发布支持保留精确 `=0` 回滚,不把缺失证据表述为已验收。 +5. 成组核对客户端 source+built+contract 上传 → 服务端逐字节校验 → OSS immutable Release → CDN/Edge 的发布契约与客户端 `play_url` 消费契约。 ## Open Questions / Blockers @@ -120,6 +133,7 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选 - 项目 Vite config/plugins 以桌面用户权限执行,不能称为 sandbox;此风险边界必须在发布说明中保留。 - AI 绘画消息、Brief、Quote 和 `turnRevision` 必须按 Workspace + Conversation 隔离;任务事件仍按 Workspace 归并,迟到的异步结果不得污染已切换的会话。 - AI 绘画 WebSocket 命令只能在传输发送、连接关闭或 ACK 超时时回退到 REST,并必须复用原 `client_command_id`;Gateway 结构化业务错误不得触发重复提交,未知错误文本不得进入 Renderer。确认后的任务恢复必须按不可变 Quote 身份归并到 Workspace,不能用任务恢复放宽 Conversation generation 门禁或覆盖新会话错误。 +- AI 绘画 Main-owned Workspace JSON 请求和共享 Works token refresh 必须在 30 秒内结束并释放共同等待者;只允许 `GET`/`HEAD`/`OPTIONS` 在 Electron transport 失败后透明改走 Node fetch,PATCH/POST 等 mutation 必须由具有显式幂等身份的上层协议决定是否重试。临时 `disable-http2` 只用于安装包诊断,不能替代该有限生命周期与非重放边界。 - 服务端持久 Conversation Session 不由客户端在注销或退出时删除;Main 只关闭本地流、清除本机缓存并撤销本地凭据。 - 客户端对最终构建字节的 loopback 检查没有可信 receipt,且不复刻生产 opaque-origin;服务端必须独立重算 source/built/contract、校验不可变 Release,人工审核仍不可绕过。如未来需要不可绕过的 runtime gate,必须引入可信 verifier 并绑定精确构建产物。 - AI proxy 的明确饱和 `429 → 400` 是与当前 OpenCode 重试契约匹配的内部投影;升级 OpenCode 或上游饱和错误文案变化时必须复核。不得把通用 `429` 或仅含 `rate_limit_exceeded` 的响应误分类为终止饱和。 @@ -131,4 +145,4 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选 ## Last Updated -2026-08-18 +2026-08-19 diff --git a/.project-docs/30-worklog/task-history.md b/.project-docs/30-worklog/task-history.md index c52b142..1128fb6 100644 --- a/.project-docs/30-worklog/task-history.md +++ b/.project-docs/30-worklog/task-history.md @@ -12,6 +12,7 @@ | 2026-08-12 | Makelore 内置浏览器发布前预检 | Electron WebContents/CDP loopback UX fail-fast;服务端受控构建与审核仍为唯一可信门禁 | current-state、architecture、domain、evidence、commitments | | 2026-08-12 | Makelore 本地构建静态 Release | 固定 npm + 项目 lockfile Vite、本地同字节双视口预检、source+built+contract 双归档协议 | current-state、architecture、domain、evidence、commitments、skills | | 2026-08-13 | 图生图与 Updater 主线集成 | 单参考图 Asset 链路、旧 Brief medium 兼容,以及稳定更新源缺包诊断/错误脱敏 | README、current-state、architecture、domain、evidence、commitments | +| 2026-08-19 | AI Design 请求冻结修复集成 | 原生密码/SMS 登录与临时 HTTP/2 诊断包合并;Workspace/token refresh 有限 deadline;mutation transport failure 不隐式重放 | README、current-state、architecture、domain、evidence、commitments | ## Notes diff --git a/.project-docs/30-worklog/tasks/20260819-design-freeze-live-6e2c.md b/.project-docs/30-worklog/tasks/20260819-design-freeze-live-6e2c.md deleted file mode 100644 index 6127a9f..0000000 --- a/.project-docs/30-worklog/tasks/20260819-design-freeze-live-6e2c.md +++ /dev/null @@ -1,94 +0,0 @@ -# Task: Diagnose live AI design freeze after HTTP1 package - -## Identity - -- Task ID: 20260819-design-freeze-live-6e2c -- Mode: Feature -- Branch: codex/20260819-design-freeze-live-6e2c-design-freeze-live -- Worktree: D:\mk-design-freeze-live-6e2c -- Base commit: 1ba68a9e41ea5eb4cf03bd11ef18ad61023cd069 -- Owner: codex-root -- Status: Completed - -## Scope - -- Inspect the live installed Makelore process after the combined native-login and HTTP/2-disabled diagnostic package froze in AI Design. -- Verify package provenance, Chromium transport flags, process health, TCP state, local Host API responsiveness, session-refresh eligibility, Works service health, and the matching request implementation. -- Implement the directly authorized fix in the same task: bound finite AI Design and Works session-refresh requests, prevent implicit replay of non-idempotent requests, and add focused regressions. -- Build a Windows diagnostic package that retains native password/SMS login and `disable-http2` so this behavior change can be isolated in the user's next smoke test. - -## Intent And Constraints - -- The user explicitly requested direct execution without sub-agents. -- Treat the observed 409, global Loading state, and previous `ERR_HTTP2_PROTOCOL_ERROR` as separate signals until live evidence connects them. -- Read the encrypted session only to project expiration/activity metadata and to issue bounded read-only requests; never print or persist access/refresh tokens. -- Do not replay the Quote PATCH because its idempotency and server-side commit state are not proven. -- Remove every temporary harness and isolated Chromium profile before completion. - -## Outcome - -### Confirmed facts - -- The installed `app.asar` SHA-256 exactly matched the combined diagnostic package: `80948DDBBD5F9BDE9B4C75CB40E515E63200AA79582BF16CF88347DECCD864C6`. -- The live Network Service process had `--disable-http2`; HTTP/2 was genuinely disabled. -- Main, Renderer, GPU, and Network Service remained Windows-responsive. A three-second sample showed zero Main/Renderer CPU growth and only `0.0156` seconds in Network Service, so the process was passively waiting rather than spinning or blocking the UI thread. -- While the UI remained stuck, three rounds of 20 concurrent requests to the live Host API all completed with the expected unauthenticated `401` in `47/16/14 ms`. Main's HTTP event loop and listener were not globally blocked. -- The stored access token was more than 157 minutes from expiry and outside the 30-second refresh skew. The shared `refreshFlight` was not active for this incident. -- With the same authenticated session, read-only Node probes to `/api/auth/me`, Design capabilities, Workspace list, the affected Workspace, and its two Conversations returned `200` in `31-159 ms`. Works, the account, and that Workspace were not globally locked. -- A fresh Electron `43.4.0` Network Service with `disable-http2` returned `200` for the same three read-only endpoints in `1764-1853 ms`. HTTP/1.1 itself remained functional. -- Product code gives `net.fetch`, its global-fetch fallback, session refresh, design `authorizedFetch`, IPC Host API requests, Workspace/Conversation loads, and Quote repricing no common deadline or abort contract. Their UI cleanup runs only after the Promise settles. -- `proxyAwareFetch` catches every Electron `net.fetch` exception and unconditionally replays the same request with global `fetch`. That is unsafe for mutation methods such as Quote `PATCH` when the first request may have committed before its response transport failed. - -### Conclusion - -- Disabling HTTP/2 did not fix the freeze and is not the root cause. -- The live symptom is an unbounded in-process network/IPC Promise in the current Makelore network context. The process remains healthy but a request can wait forever, leaving Renderer loading/busy state waiting for `finally`. -- The observed `409` is a completed conflict response and cannot itself block the JavaScript thread. It may be a secondary symptom of the unconditional transport fallback replay after an earlier protocol failure, but that specific mutation was not replayed during this diagnostic task. -- The user's “one request hangs, then everything stays Loading” report is consistent with missing deadlines/cancellation plus page-level state ownership, not with a dead request thread. - -### Implemented fix - -- Added a reusable deadline primitive that aborts the active transport and still rejects deterministically when a transport ignores `AbortSignal`. -- Bounded the complete AI Design JSON request lifecycle to 30 seconds, including token lookup/refresh, response headers, and response-body parsing. The adapter returns a stable `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT` with `AI 设计服务响应超时,请重试`. -- Bounded the shared Works access-token refresh to 30 seconds. All coalesced callers settle together, `refreshFlight` is released by its existing `finally`, and a later refresh can retry without clearing a still-valid refresh token. -- Restricted Electron-to-Node fetch fallback to safe reads (`GET`, `HEAD`, `OPTIONS`). `POST`, `PATCH`, `PUT`, and `DELETE` transport failures now propagate without implicitly replaying the mutation. -- Preserved native password/SMS login and the temporary global `disable-http2` switch in the diagnostic installer so the user can isolate this request-lifetime/replay fix before HTTP/2 policy is revisited. - -## Verification - -- Live installed-package hash comparison — PASS, exact match. -- Live process command-line projection — PASS, Network Service had `disable-http2`. -- Live process responsiveness/CPU sampling — PASS, responsive passive wait. -- Host API concurrency probe — PASS, 60/60 requests completed within 47 ms per round maximum. -- Encrypted-session metadata projection — PASS, no refresh window and no token output. -- Authenticated read-only Works differential probes — PASS, account/Design/Workspace/Conversation endpoints responsive. -- Fresh Electron HTTP/1.1 differential probe — PASS. -- Static request-path inspection — confirmed missing deadlines/AbortSignals and unconditional fallback replay. -- Temporary scripts, metadata output, and isolated Electron profile — removed. -- Red-phase regression run — PASS as evidence: the new mutation-replay, stuck request, and stuck shared-refresh tests all failed against the previous implementation. -- Focused unit tests — PASS, 59/59. -- TypeScript check — PASS, `pnpm run typecheck`. -- Lint check — PASS with zero errors and seven pre-existing unrelated warnings. -- Full unit suite — PASS on clean rerun, 184 files and 2190 tests. The first run had one unrelated Windows port-release timing failure; its focused rerun passed before the clean full rerun. -- Production compile — PASS, `pnpm run build:vite`. -- Windows package build — PASS after the verified prior uv binary and verified Learning Player artifact were reused when GitHub download timed out. -- Packaged Learning Player verification — PASS, SHA-256 `748d6d7c74d9d0ba444e0c051a50010f7070e7d6e46442b1e60f1e2be80fd020`. -- Packaged `app.asar` marker inspection — PASS for `disable-http2`, `DESIGN_WORKSPACE_REQUEST_TIMEOUT`, and the request-deadline implementation. -- Packaged Electron runtime verification — PASS, including Electron `43.4.0`, Node `24.18.1`, OpenCode, Python, uv, npm, and native addons. -- Installer SHA-256 — `FB3BDA4F464770E58EA0AA6E989366685976D5FA7B76E6944B92879B423D83D4`. -- Packaged `app.asar` SHA-256 — `A752255B43694814CC3D3FB86C75E024D39E67BBF87BE273960A1FA9FA0366A6`. - -## Follow-ups - -- Smoke the original Quote edit/retry/confirm sequence in the diagnostic package. A stalled request should now leave Loading within 30 seconds and show the explicit timeout message; a transport exception must not produce a second Quote PATCH. -- After the user confirms the bounded-request fix, restore HTTP/2 in a separate package and repeat the same regression smoke. `disable-http2` remains a diagnostic variable, not the root-cause fix. -- Add privacy-safe request lifecycle instrumentation (`route kind`, transport, phase, elapsed time, deadline outcome, correlation id) so a future live freeze identifies the exact pending boundary without DevTools or credentials. - -## Promotion Candidates - -- Target: `.project-docs/20-architecture/data-flow.md` and the AI Design transport boundary. -- Proposal: document the implemented bounded AbortSignal/deadline contract for Main-owned finite Works requests and the prohibition on implicit mutation replay without an explicit idempotency contract. -- Evidence: this live differential diagnosis, the focused/full regression results, `electron/utils/proxy-fetch.ts`, `electron/services/works-square-session.ts`, `electron/image-workspace/works-square-workspace.ts`, `src/lib/host-api.ts`, and `src/stores/image-workspace.ts`. -- Future impact: network failures become terminal and recoverable instead of leaving permanent Loading state or ambiguously duplicating Quote mutations. -- Semantic conflicts: none with ADR-001; Workspace/Conversation ownership remains unchanged. -- Human confirmation required: no for a bounded bug fix, but permanent HTTP protocol policy should be decided separately after the fixed package is validated. diff --git a/.project-docs/30-worklog/tasks/20260819-integrate-design-freeze-3f8b7c.md b/.project-docs/30-worklog/tasks/20260819-integrate-design-freeze-3f8b7c.md new file mode 100644 index 0000000..88f140e --- /dev/null +++ b/.project-docs/30-worklog/tasks/20260819-integrate-design-freeze-3f8b7c.md @@ -0,0 +1,54 @@ +# Task: Integrate AI design request freeze fix + +## Identity + +- Task ID: 20260819-integrate-design-freeze-3f8b7c +- Mode: Integration +- Branch: codex/20260819-integrate-design-freeze-3f8b7c-integrate-design-freeze +- Worktree: D:\mk-integrate-design-freeze-3f8b7c +- Base commit: 9ff79e96813ebadade0aecb8f407edf5aee0144a +- Owner: codex-root +- Status: Completed + +## Scope + +- Integrate `codex/20260819-design-freeze-live-6e2c-design-freeze-live` at `87e4140f8a7ae3da8dcbf592c8f7604f7fb2ea37` onto the current `main` baseline `9ff79e96813ebadade0aecb8f407edf5aee0144a`. +- Preserve the already-combined native password/SMS login and temporary `disable-http2` diagnostic bootstrap. +- Promote the durable AI Design request-lifecycle facts into canonical project documentation. +- Verify the integrated result before advancing `main`. + +## Intent And Constraints + +- Fix the observed renderer-wide loading state by ensuring Main-owned AI Design requests and shared token refreshes settle within a finite deadline. +- Prevent Electron network failures from implicitly replaying mutation requests through Node `fetch`; transparent fallback remains limited to safe reads. +- Preserve the existing explicit WebSocket-to-REST fallback contract and its idempotency identity. +- Treat `disable-http2` as a temporary diagnostic packaging policy, not as the confirmed root-cause fix. +- Do not modify or discard unrelated user work. The checked-out `main` worktree is clean but is still registered to a superseded packaging task, so final promotion must follow the ownership protocol. + +## Outcome + +- Source tip `87e4140f8a7ae3da8dcbf592c8f7604f7fb2ea37` merged without conflict as `471e738e77b8df46ae2ad54b9f5a241a36b0ee0f` on the isolated integration branch. +- The integrated tree contains native password/SMS login, temporary `disable-http2`, bounded AI Design requests/token refresh, and safe-read-only low-level transport fallback. +- Durable architecture, domain, evidence, current-state, commitment, and task-history records were promoted in integration mode. +- The integration branch is complete and verified. Final `main` advancement is handled as a separate promotion task after safely releasing the clean superseded-task ownership on the checked-out main worktree. + +## Verification + +- Pre-merge ancestry check: source tip contains the current `main` baseline. +- Merge conflict check — PASS; source merged through Git `ort` with no conflicts. +- Frozen dependency install — PASS with pnpm `10.33.4`, 931 packages reused from the local store. +- Focused integrated regression — PASS, 7 files / 134 tests covering login, HTTP/2 bootstrap, proxy fallback, Workspace deadlines, and shared token refresh. +- TypeScript — PASS, `pnpm run typecheck`. +- Lint — PASS with 0 errors and 7 pre-existing warnings, `pnpm run lint:check`. +- Full unit suite — PASS, 184 files / 2190 tests, `pnpm test`. +- Renderer/Main/Preload/utility production compile — PASS, `pnpm run build:vite`; existing chunk-size/dynamic-import warnings remain non-fatal. +- Whitespace validation — PASS, `git diff --check`. + +## Follow-ups + +- Run installed-client real-account Quote PATCH / retry quote / continue-adjusting smoke and verify a stalled request releases the UI within 30 seconds without blocking unrelated calls. +- Restore HTTP/2 for a controlled comparison after the finite-lifecycle fix is confirmed; keep `disable-http2` temporary until that evidence exists. + +## Promotion Candidates + +- Accepted into `20-architecture/data-flow.md`, `20-architecture/system-overview.md`, `40-domain/business-rules.md`, `30-worklog/current-state.md`, `50-evidence/evidence-index.md`, and `80-commitments/commitments.md`. diff --git a/.project-docs/30-worklog/tasks/20260819-native-http1-package-c7e4.md b/.project-docs/30-worklog/tasks/20260819-native-http1-package-c7e4.md deleted file mode 100644 index 89f1dc1..0000000 --- a/.project-docs/30-worklog/tasks/20260819-native-http1-package-c7e4.md +++ /dev/null @@ -1,60 +0,0 @@ -# Task: Integrate native login and HTTP2-disabled diagnostic package - -## Identity - -- Task ID: 20260819-native-http1-package-c7e4 -- Mode: Integration -- Branch: codex/20260819-native-http1-package-c7e4-native-http1-package -- Worktree: D:\mk-native-http1-package-c7e4 -- Base commit: 9ff79e96813ebadade0aecb8f407edf5aee0144a -- Owner: codex-root -- Status: Completed - -## Scope - -- Integrate the completed native password/mobile-code login change from commit `5a048da8a615792dee9e0c76b6fda814aaa1b854`. -- Integrate the temporary Electron HTTP/2 diagnostic bootstrap from commit `411cd9cedfeb14df0c839e6e1cbf1110826ad0e6`. -- Produce and verify a Windows x64 diagnostic installer without promoting either change to the default branch. - -## Intent And Constraints - -- Preserve the Main-owned authentication boundary: Renderer login requests continue through Host API routes. -- Replace the failing browser desktop-auth flow with the already completed password and mobile verification-code surfaces. -- Keep `app.commandLine.appendSwitch('disable-http2')` before the single-instance lock and `app.whenReady()` so every Electron network context inherits the diagnostic switch. -- Treat this as an isolated diagnostic package. The default branch and canonical current-state snapshot are not advanced by this task. -- Use the project-pinned Python runtime and verified `uv 0.10.0`; do not reuse the earlier native-login package's temporary `uv 0.10.9` substitution. -- The user explicitly requested direct execution without sub-agents, so verification was performed in the primary task. - -## Outcome - -- Merged native login as integration commit `3ba90af` and HTTP/2 disablement as integration commit `c1548e6` with no conflicts. -- Generated `D:\mk-native-http1-package-c7e4\release\Makelore-2.0.0-win-x64.exe`. -- Installer size: `302025649` bytes. -- Installer SHA-256: `2A81ECC39A55E3F01ED90A8D1D564E020E82671779E72B50EB76282197D31EC2`. -- Authenticode status: `NotSigned`, consistent with the local diagnostic-package environment. -- Final `app.asar` contains the password login, mobile login, SMS-code and image-code routes and native login UI, while `/api/auth/browser/start` is absent. -- Final `app.asar` contains `disable-http2` before both `requestSingleInstanceLock` and `whenReady` in the packaged Main bootstrap. - -## Verification - -- `pnpm exec vitest run tests/unit/http2-diagnostic-bootstrap.test.ts tests/unit/auth-routes.test.ts tests/unit/auth-store.test.ts tests/unit/login-page.test.tsx tests/unit/works-square-session.test.ts tests/unit/works-square-session-persistence.test.ts tests/unit/works-square-session-persistence-policy.test.ts --reporter=dot` — PASS, 7 files / 98 tests. -- `pnpm run typecheck` — PASS. -- Scoped ESLint over the changed Main, Renderer, E2E and unit-test files — PASS. -- `pnpm test` — PASS, 184 files / 2185 tests. -- `pnpm run build:vite` — PASS. -- Electron smoke test `can skip setup and open the native login surface` — PASS, 1 test. -- `pnpm run package:stage:win-x64` with the verified Learning Player artifact — PASS. -- `node scripts/run-electron-builder.mjs --win --publish never` — PASS. -- `pnpm run verify:publish-runtime` — PASS, npm `11.6.2`. -- `pnpm run verify:artifact:win -- --allow-dirty --installer .\release\Makelore-2.0.0-win-x64.exe` — PASS; Electron `43.4.0`, Node `24.18.1`, OpenCode `1.18.9`, Python runtime present, `uv 0.10.0`, native addons present. -- `node scripts/verify-learning-player-artifact.mjs release\win-unpacked\resources\resources\learning-player` — PASS, SHA-256 `748d6d7c74d9d0ba444e0c051a50010f7070e7d6e46442b1e60f1e2be80fd020`. -- Direct packaged `app.asar` assertions for the HTTP/2 switch ordering, native auth routes/UI and removal of the legacy browser-start route — PASS. - -## Follow-ups - -- Install this diagnostic package and confirm that password/mobile-code authorization succeeds against the live Works service. -- Reproduce the generation-quote request sequence. If the global loading freeze still occurs, the result rules out HTTP/2 as the sole cause and request ownership/cancellation in the quote flow should be instrumented next. - -## Promotion Candidates - -- None from this packaging task. Promotion of native login or temporary HTTP/2 disablement remains an explicit default-branch integration decision after live validation. diff --git a/.project-docs/40-domain/business-rules.md b/.project-docs/40-domain/business-rules.md index 4cff759..367ffbc 100644 --- a/.project-docs/40-domain/business-rules.md +++ b/.project-docs/40-domain/business-rules.md @@ -29,6 +29,7 @@ - 每条 Conversation 使用服务端持久 Agent Gateway Session。客户端注销或退出时只关闭本地流并清除本机 Session-id 缓存,不删除服务端 Session。 - Conversation 异步与流式更新必须同时核对 Workspace 和 Conversation 身份;任务事件按 Workspace 归并。 - 已连接的 Conversation Agent 命令、Run 和设计事件共用 WebSocket。只有命令发送失败、连接关闭或 ACK 超时可用同一 `client_command_id` 回退 REST;Gateway 结构化业务错误不得重复提交。Main 只向 Renderer 投影已知错误码的固定中文提示,未知上游错误文本必须脱敏为通用提示。 +- AI 绘画 Workspace JSON 请求与 shared Works token refresh 必须覆盖取凭据、发请求和读取响应 body 的完整 30 秒 deadline;即使底层 transport 忽略 abort,调用方也必须确定性结束为 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT` 并释放共同等待者。Electron-to-Node 透明 fallback 仅允许 `GET`/`HEAD`/`OPTIONS`;mutation 不得因 transport failure 被隐式重放,任何重试必须由上层显式幂等合同授权。 - 确认生成后按 Quote 对账 Workspace 任务。任务已经落库但 Run 随后失败时应恢复右侧任务列表;切换 Conversation 后仍同步 Workspace 任务,但旧确认不得覆盖当前 Conversation、清除其 pending turn,或用任务对账失败覆盖新会话错误。 - 图片生成支持无参考图的文生图和单参考图图生图;参考图必须来自当前 Workspace 的已完成图片 Asset,或先通过现有 Workspace 上传接口把本地图片转成 Asset,再随当前 Conversation Turn 提交唯一 Asset ID。 - 视频首帧与图生图参考图复用单图选择器,但用途由当前 Brief medium 决定:只有明确 `image` 使用图生图语义,`video`、null 或缺失值保持视频首帧兼容语义。选择作品或上传成功后应关闭弹窗。 @@ -65,6 +66,7 @@ - 图生图随客户端发布前,需确认相匹配的服务端 `image_to_image` Brief/Quote/Task 冻结、私有源图复核与 Bailian edit 执行链已部署,并使用真实 Workspace Asset 完成生产 smoke。 - Updater 生产恢复仍需对齐权威版本、发布正式签名/公证的平台产物,并从旧安装版本执行发现、下载、重启和安装 smoke;源码提示修复本身不构成发布链恢复。 - AI Canvas 双向 Gateway 与 Quote 任务恢复仍需真实账号执行一次生产确认 smoke,核对 WebSocket 不产生 `/runs/{run_id}` 轮询、任务按 Quote 出现在 Workspace 列表,并区分真正的 `agent_runtime_unavailable` worker 故障。 +- AI Canvas 请求冻结修复仍需在安装包内用真实账号重复 Quote PATCH、重试报价和继续调整:确认超时在 30 秒内释放 UI、并行请求可继续、服务端没有隐式重复 mutation。临时 `disable-http2` 不构成根因结论;修复确认后应恢复 HTTP/2 做对照 smoke,再决定正式协议策略。 - Robot Guided Hotspot Binding default-on 发布仍需确认指定硬件/固件确实提供被审计的开放 Hotspot/Portal、部署端签发严格六位 ASCII 数字码且与 Works validator 的时效/消费语义一致,并完成 Windows 真机、签名 macOS x64/arm64 native worker/association 与真实设备端到端 smoke。 - Prompt Museum 客户端契约和页面完成不等于 Works Square 内容后台、审核数据或 CDN 已部署;上线前需以真实登录账号验证列表、详情、署名链接、分页、图片和 Prompt 回填。 - Learning 客户端集成不等于 Works 课程服务、权益、生成流水线、production Stage artifact 或签名安装包已验收;上线前需以真实账号和固定 artifact 完成 Windows/macOS 整链 smoke。 @@ -72,4 +74,4 @@ ## Last Reviewed -2026-08-17 +2026-08-19 diff --git a/.project-docs/50-evidence/evidence-index.md b/.project-docs/50-evidence/evidence-index.md index d123523..aa8032b 100644 --- a/.project-docs/50-evidence/evidence-index.md +++ b/.project-docs/50-evidence/evidence-index.md @@ -4,6 +4,7 @@ Use this index for searchable, traceable evidence records. | Date | Topic | Status | Source | Detail | |---|---|---|---|---| +| 2026-08-19 | AI Design 请求冻结与 mutation 隐式重放修复 | 客户端实现与自动化验证通过;安装包真实账号 smoke 待验收 | 源任务 `20260819-design-freeze-live-6e2c`、源提交 `87e4140`、集成任务 `20260819-integrate-design-freeze-3f8b7c` | 源分支通过 59 focused、2190 full unit、typecheck、lint(0 errors / 7 existing warnings)、Renderer/Main/Preload production build 与 package verifier;集成树另行通过 7 files / 134 focused、184 files / 2190 full、typecheck、同样的 lint 结果和 Renderer/Main/Preload/utility production build。覆盖 30 秒完整 Workspace JSON deadline、忽略 abort 时确定性 reject、shared refresh coalescing/释放/后续重试,以及只对 `GET`/`HEAD`/`OPTIONS` 保留 Electron→Node fallback;PATCH/POST transport failure 不再隐式二次发送。原生密码/SMS 登录与临时 `disable-http2` 诊断 bootstrap 同包保留;不据此宣称现场冻结已消失或 HTTP/2 是根因。 | | 2026-08-17 | AI 编程多 Session 应用侧隔离与 runtime/Agent acceptance | 客户端实现及独立复审通过;真实 bundled OpenCode/provider 并发 smoke 待验收 | 源任务 `20260817-multichat-runtime-fix-f3a91c`、源提交 `6504073` | 最终 176 files / 2100 unit tests、Main focused 164/164、typecheck、full lint(0 errors / 7 existing warnings)、Renderer/Main/Preload build、Electron E2E 1/1 与第七轮独立 Sol Standards/Spec review PASS。覆盖 per-Session run/error/queue、hard 10s startup ACK、无自动重放、Agent fingerprint + fresh generation、typed pre-send pending、manager/project FIFO、timeout lease revocation、A-held/B-abort/C ordering 和无普通路径自动 runtime restart/dispose;不据此宣称真实 provider 同时执行两个模型 turn。 | | 2026-08-17 | 首次项目封面原子提交 | 客户端与匹配服务端本地集成;发布/部署待验收 | 客户端源 `145a6ce`、服务端源 `407c883` / merge `0cedfc4`、任务 `20260817-project-cover-upload-a6a98e56` | 首次弹窗必选 PNG/JPEG/WebP ≤10 MiB,提供预览/文件名/重选;Main 用 `metadata` + `cover` multipart 创建,409 不上传版本,已有项目 version-only。源验证通过 76 单测、typecheck、scoped ESLint、Vite build、Electron E2E 1/1 和跨仓库 Sol review;未执行真实账号、生产对象存储或安装包 smoke。 | | 2026-08-17 | Makelore 用户级四模块入口策略 | 客户端实现与独立复审通过;服务端部署、新包与真实账号 smoke 待验收 | 源任务 `20260817-makelore-module-access-6f2a91c4`、源 tip `3b799af` | 4 files / 69 focused tests、175 files / 2047 full tests、TypeScript、scoped ESLint、Renderer/Main/Preload production build 与最终独立 Sol review PASS。覆盖 Main 四布尔安全投影、缺失默认开启、`design` → `painting`、卡片置灰不可点、根/深层/别名路由初始化前阻断、Code policy hydration、terminal `401` 双层清会话和全局 `/settings`;不据此宣称 API 授权或生产发布已验收 | diff --git a/.project-docs/80-commitments/commitments.md b/.project-docs/80-commitments/commitments.md index 1e8faa0..44d8da1 100644 --- a/.project-docs/80-commitments/commitments.md +++ b/.project-docs/80-commitments/commitments.md @@ -4,6 +4,7 @@ Track future-facing memory: promised follow-ups, unfinished loops, timed checks, | Date | Commitment | Trigger / Due | Owner | Status | Next Action | |---|---|---|---|---|---| +| 2026-08-19 | 验收 AI Design 有限请求生命周期并决定正式 HTTP/2 策略 | 发布包含源 `87e4140` 的正式安装包前 | 客户端/Works 服务端/发布集成 | Pending | 使用真实账号连续执行 Quote PATCH、重试报价与继续调整,制造或等待慢响应,确认 30 秒内稳定返回、其他请求不被共同挂住、服务端无隐式重复 mutation;随后恢复 HTTP/2 重新打包做同场景对照。只有证据确认后才能移除临时 `disable-http2` 或把协议策略固化为正式决定。 | | 2026-08-17 | 验收 AI 编程真实双 Session runtime/provider 行为与 Agent 刷新边界 | 升级 bundled OpenCode、改变 provider 并发策略,或对外宣称双会话真实并发/即时 Agent 热更新前 | 客户端/OpenCode/provider 集成 | Pending | 使用明确配置的测试 provider 运行 opt-in bundled OpenCode 双 Session smoke,区分应用隔离与上游并发/串行/限流;若要求运行期即时应用 Agent 编辑,先提供 directory-scoped authoritative invalidation 或 whole-instance quiescence oracle。在此之前只允许回复完成后的手动 runtime restart,不从 `/session/status` 推断 dispose/reload 安全。 | | 2026-08-17 | 验收用户级四模块入口策略的真实发布链 | 发布包含源 tip `3b799af` 的 Makelore 安装包前 | Works 服务端/客户端/发布集成 | Pending | 部署 `module_access` migration 和 `/api/auth/me` API,重新打包并安装 Makelore;使用真实账号依次关闭 Code、Canvas、Learning、Robot,重启后验证卡片置灰/不可点、根/深层/别名路由阻断、`/settings` 仍可访问和 terminal `401` 退出;另行以直接 API 请求确认服务端授权,不以 UI 置灰代替 | | 2026-08-16 | 验收 AI Learning 的真实 Works、课程包与 production Stage 发布链 | 发布包含 `01bee31` Learning 行为的安装包前 | 客户端/服务端/发布集成 | Pending | 使用真实账号核对课程广场、单课生成(无材料/5 文件边界)、取消/恢复/finalize、同源最多 5 跳下载、512 MiB archive 上限、大小/SHA-256/原子安装、账号切换隔离、离线多模块播放、进度、Agent、ASR、PBL/评分权益;以固定 URL/SHA-256 的 player artifact 构建并完成 Windows 与签名 macOS 安装包 smoke,验证 packaged Chromium 的 loopback cookie/nonce,不以客户端单测替代生产验收 |