feat(storage): move desktop SQLite ownership into a storage utility process

Main no longer opens desktop business SQLite. A single utility-process
storage owner holds the Assistant, Knowledge, attachment, document-result,
remote-binding and native model-ledger databases and runs whole domain
transactions; Main and Runtime callers use explicit async domain operations.

- Remove the Main readWithFallback path and the supervision worker's
  separate business write connection; manifests are scanned read-only and
  committed by the sole writer.
- Remote events are ACKed only after commit; process loss reports
  unconfirmed writes instead of replaying them.
- Use native utilityProcess messaging with one in-flight bound (32) and
  ordered waiting instead of capacity rejection and retries.
- Start the storage process before the window so startup overlaps.
- Keep short tool output in memory and store full output once in owned
  storage; paging, branching, restart and deletion reuse that copy.
- Put required runtime launch files under goodbuddy-prefixed owned temp
  directories and reclaim confirmed stale ones; stop writing duplicate
  parsed.md.
- Add lint guards for SQLite ownership and architecture, concurrency
  acceptance fixtures, and maintenance/architecture documentation.

Validation: typecheck and lint pass. Alternating baseline (edf019aa) vs
candidate runs show no regression on single-session, C01, C02, C04 and a
5-minute C06; Main p99 drops from ~21 ms to ~16.7 ms under concurrency.
Fresh portable copy (1.75M events) upgrade content unchanged; real-model
output paging passes with 4 external requests. Full npm test runs had
1-9 different timing-sensitive failures per run that pass when rerun.
Not covered: C03 review publication, C07 source body, app-level C05.
This commit is contained in:
mesalogo
2026-10-06 15:40:18 +08:00
parent bc677a3718
commit d80d42b032
229 changed files with 13632 additions and 3800 deletions
+1
View File
@@ -5,6 +5,7 @@
| 文档 | 职责 |
| --- | --- |
| [Electron UI 自动化测试规范](./electron-ui-automation.md) | 测试分层、当前源码启动、视觉与原生交互取证、真实调用计数、脱敏报告和清理 |
| [桌面并发架构验收](./concurrent-desktop-acceptance.md) | 一次完整架构交付的多项目/会话/子任务负载、计时口径、正确性断言、平台与验收记录要求;当前候选仍有未完成项 |
| [复发缺陷与防复发规则](./recurring-defects.md) | 已重复出现的缺陷类型、对应的共享机制和自动发现测试 |
| [开发与构建](../../BUILD.md#质量验证) | 依赖、测试、类型检查、Lint 和构建命令 |
| [UI 设计系统](../../UI-DESIGN.md#155-验收) | 全局视觉、交互和响应式验收要求 |
@@ -0,0 +1,175 @@
# 桌面并发架构验收
## 状态与职责
2026-10-05,设计基线为 `2be57492`。本文定义一次完整架构交付的验证要求,测试脚本与结果尚未完成。
目标架构见[桌面存储与并发执行](../architecture/desktop-storage-direction.md),规范和数值预算以
[性能原则](../architecture/performance-principles.md)为唯一依据。既有 KISS 测量只作为基线证据,不能替代本矩阵。
验收对象是同一候选中的完整产品路径,不单独验收“接口改成 Promise”“Worker 可调用”或“单会话很快”。
所有必测场景完成前,不标记 PERF-15/PERF-16 为完成;未测平台及指标明确列出,不以跳过视为通过。
## 发布门槛与目标差距
2026-10-06 起按两类判定,沿用既有“历史回归上限”与“性能预算”的分层,不新增判定体系:
| 类型 | 内容 | 发布判定 |
| --- | --- | --- |
| 正确性与稳定性 | A01–A10;请求排空、无静默丢弃、提交后 ACK、取消结算、故障不传染、资源回落、进程退出后可恢复 | **必须全部通过**,不能用“比旧版好”替代 |
| 性能对照 | 同机、同数据、同负载,与改造前提交交替三轮;含单会话简单操作和后台吞吐 | **不得退化**:候选不差于基线的重复测量波动范围 |
| 性能预算 | 性能原则第 1 节的绝对数值 | 未达到时记录为目标差距,不阻断本次发布 |
“不得退化”同时覆盖单会话路径。存储迁到独立进程后多一次 IPC,单个简单操作最可能变慢,只测并发场景会漏掉这种退化。
后台吞吐、回顾发布和事件提交也要对照,界面流畅但后台明显变慢不算改善。
## 固定负载
以下为验收档位,不是已验证的容量承诺,也不改变产品并发限制。当前产品若不能达到某档位,记录原因并保留未满足项。
使用本地确定性模型与隔离目录,每个输入、事件和工具结果有稳定标识,能够逐项验证顺序及重放结果。
不得用真实提供商的网络速度作为应用性能基准。
本地临时库、日志和源码测试产物遵守仓库 [AGENTS 临时文件规则](../../AGENTS.md#local-temporary-files),
使用仓库根目录 `temp/` 的任务子目录并在关闭资源后清理;可复用夹具提交到 `tests/` 或 `scripts/`,
正式验收摘要记录在文档中,不依赖唯一一份临时结果。远程临时目录沿用 Host 专用规则。
| 场景 | 项目/并行会话/同时活动子任务 | 必须同时执行的用户动作 |
| --- | --- | --- |
| C01 日常并行 | 3/4/8,子任务为全场景总数 | 持续打字、跨项目切换、查看来源和工具详情、首次进入监督者 |
| C02 并发压力 | 4/8/16,子任务为全场景总数 | 滚动长历史、搜索、切换缓存会话、取消其中一个父任务,其他会话继续 |
| C03 混合存储 | C01 加 100 批次回顾发布、知识导入和检索 | 前台输入与保存,打开图谱,观察远程事件提交/ACK;各操作必须真实重叠 |
| C04 运行时故障隔离 | C01 中挂起一个启动、模型路由准备或清理 | 查询其他任务、取消故障请求、继续健康 peer;覆盖本地及受影响的远程路径 |
| C05 存储故障与饱和 | C01 中注入读 Worker 失败、队列达到上限、存储进程退出 | 页面报错与重试,已提交结果可重读,未确认写入不盲目重放,UI 仍可响应 |
| C06 持续生命周期 | C02 连续 30 分钟,每轮完成、关闭并重开任务/会话 | 保持草稿、展开、焦点及滚动状态,观察队列、缓存、订阅和所属进程回落 |
| C07 冷热进入 | 新进程首次打开及同进程暖返回,分别在空闲和 C01 下测量 | 输入框、监督概览、图谱、历史选择、来源正文分开记录可用时刻 |
默认数据为 300 个已保存会话、每个 20 条消息,另加 2,000 条消息的长会话;压力数据改为 10,000 条长会话消息。
监督数据沿用可复现样本:20 个结果、40,000 条消息、8,000 事件/来源、400 故事、800 经验;消息及来源正文各 2,048 ASCII 字节。
回顾发布为 100 批、每批 20 来源,知识检索保留既有 5,000/20,000/50,000 文本块样本。各场景只装入相关数据,不把互不相关的大样本无条件叠加。
活动流初始使用每会话每 16 ms 一个文本片段、每父会话每秒一个有界工具/子任务更新;工具输出固定为 4 KiB,实际数量、字节数和时间表写入 fixture。
每个会话的首次响应、持续流、完成和清理都要经过生产路径。调度抖动时记录实际发送率及迟到分布,不能丢弃片段以保持设定速率。
若现有 Runtime 会自然合并事件,分别记录生产与消费数量,按可还原内容验证等价。
## 计时和判定
| 指标 | 起止与用途 |
| --- | --- |
| 输入/点击反馈 | 原生输入事件至目标反馈后的帧机会;记录方法局限,不把两帧等待称为纯渲染时间 |
| 内容可用 | 请求发起至所需正文/图谱/来源提交到界面;加载占位出现不能替代该指标 |
| Main 阻塞及 p99 延迟 | 连续事件循环采样,排除夹具生成和数据库初始化;与 Renderer 长任务分别记录 |
| 存储排队 | 入队至执行开始,记录操作类型、项目/会话归属及队列深度,不记录用户正文 |
| 执行/提交 | 存储执行开始至结果或事务提交;完成响应不能早于承诺的提交点 |
| 取消/清理 | 分别记录请求取消、执行结算、资源释放;UI 清除等待不等于清理完成 |
| 吞吐和积压 | 固定 offered load 下完成数、字节数、队列高水位及输入停止后的排空时间 |
| 内存与进程 | 全应用及各实际 PID 的工作集/堆;记录缓存条目、监听器、连接及 worker 数 |
标准机和 Renderer 4× 降速分别报告,UI 与 Main 的绝对预算引用性能原则第 1 节。
Renderer 降速不等于模拟慢磁盘、慢 Main 或真实低配整机,不能从该结果推断它们合格。
原有 `perf:check` 回归上限比规范宽松;即使上限检查通过,违反规范仍须报告失败或明确的未满足项。
存储排队、吞吐、内容就绪和取消清理不得被 UI 流畅掩盖。每份 fixture 在测试实现时固定最大等待/排空期限,
使用既有产品期限或改造前重复测量支持的验收值,先记录依据再运行候选;禁止测完候选后放宽期限。
没有期限、样本不足或未采集的必需指标不能记为通过。固定输入下吞吐不得低于基线的重复测量波动范围,
队列不得持续增长,有限后台任务在持续前台负载下必须完成。容量溢出按设计等待或明确失败,不能静默丢事件。
每版本至少三轮交替运行,基线从独立 worktree 获得。交互延迟每轮每个指标至少 100 个有效样本;
首次进入通过独立启动样本报告各次值,不用三次启动估计 p95。持续负载场景先预热 30 秒,测量至少 120 秒;
C06 单独执行完整 30 分钟。记录 OS、CPU、内存、磁盘、Electron/Node、提交、数据校验值、并发、缓存状态和后台负载。
无新增数据的重复生命周期测试中,逻辑缓存/订阅/连接应回到约定存续范围,队列排空后为零,结束的所属子进程退出。
RSS 未立即回落不能单独判为泄漏;需结合存活对象、资源计数和重复轮次趋势。不能通过杀掉健康共享 Runtime 达到清零。
## 正确性断言
| ID | 断言 | 对应架构要求 |
| --- | --- | --- |
| A01 | Main 不直接或间接打开业务 SQLite;正常、失败、饱和、维护及退出路径均无同步回退 | SA-01、SA-06 |
| A02 | 同会话事件不丢、不重、不乱序;不同项目/会话/子任务的结果、取消和凭据不串用 | SA-03、SA-05 |
| A03 | 远程事件、checkpoint 提交后才 ACK;崩溃后重放去重;发件箱与模型账本不重复执行 | SA-02、SA-05 |
| A04 | 事务失败整体回滚,提交后立即读取可见;回顾结果与 checkpoint 同步发布 | SA-02、SA-05 |
| A05 | 取消排队请求不执行,取消在途请求等待实际结算;迟到结果不污染新请求,健康 peer 不受影响 | SA-03、SA-06 |
| A06 | 关闭前先停止新写入、排空必要写入、关闭连接;替换存储进程前观察旧进程退出 | SA-06 |
| A07 | 多项目切换不丢草稿、展开、选区、焦点和滚动;后台任务继续,切回不全量重建历史 | SA-04、SA-05 |
| A08 | UI DOM 随视口有界;缓存和队列有清理;未访问正文不随摘要列表整包返回 | SA-04 |
| A09 | 已发布数据库升级保留用户内容、ID、顺序、引用、去重与落盘语义,不静默换空库 | SA-02、SA-05、SA-06 |
| A10 | GoodBuddy 中转无非必要落盘;完整输出复用唯一正文,分页和释放正确,必要临时文件及历史残留按归属清理 | SA-04、SA-05、SA-08 |
故障注入覆盖提交前、提交后但响应前、初始化期间和退出期间。使用现有业务 ID 查询实际结果;
不得为了让测试容易恢复而引入新的持久化 receipt 或盲目重放。强杀共享存储进程仅用于隔离测试中的服务故障场景。
## 输出与临时资源验收
按[源码调查](../architecture/runtime-storage.md#output-and-temporary-file-investigation)选取生产入口,
在 C01/C02/C06 中记录 GoodBuddy 创建的文件数、写入字节、峰值保留字节、清理后残留及内存高水位。
区分正式保存、必要启动文件和中转写入;结果只计 GoodBuddy 所有的文件,不把第三方内部缓存归为产品临时副本。
沿用三轮前后对照,不以目录改名或文件移到数据库目录证明减少写入。
| 覆盖 | 必须验证的结果 |
| --- | --- |
| 普通 MCP、短命令输出、空 stderr、短搜索/子任务输出 | 中转不创建输出临时文件;需要保存的正常消息/事件仍持久化,MCP SDK 实际 transport 路径纳入检查 |
| 超出预览的输出 | 从现有工具到下一次模型 `output_read` 的生产链逐字节还原,覆盖 UTF-8、JSON 转义、游标、EOF、stdout/stderr、失败与取消;只保留一份所属正文,无 Temp 全文再复制 |
| 并发与生命周期 | 保留现有会话归属检查,不能读取其他会话输出;多路输出内存有界,释放调用资源不删除仍被历史/分支引用的内容 |
| 数据等价 | 分别核对模型收到的内容、工具事件预览和历史内容;不能用最终回答等价替代工具全文,也不新增整份事件正文副本 |
| 文档解析 | 不再新写/复制重复 `parsed.md`,manifest 内容、原文件、图片及附件采用/复制/重开仍正常;旧数据可读 |
| 必要启动文件 | 配置/插件加载正常,创建中失败能清理所属半成品,子进程及句柄关闭后再删除;失败不误删预先存在的同名文件 |
| 升级与再次启动 | 隔离夹具覆盖旧版失效目录、同版崩溃目录、仍活跃的子进程、归属不明目录和删除失败;只回收确认失效者,失败下次可重试,启动预算不退化 |
复用 `paged-output-store.test.ts`、`direct-model-process-service.test.ts`、
`direct-model-ripgrep.test.ts`、`direct-model-subagent-service.test.ts` 和
`model-runtime.test.ts` 中已有分页与模型下一轮请求断言,并扩展文档存储、附件及 Runtime 生命周期测试。
远程路径单独验证事件映射和提交后 ACK,不声称本地分页测试覆盖远程全文。
无需真实模型即可确定的字节、文件和清理断言使用固定输出;受影响的 Runtime 再按既有 Host 规则验证。
交付记录列出删除的旧 spool 创建入口、复用的正式内容入口、仍必要的文件及理由、实际残留与未能确认归属的旧目录。
本次文档调查未执行上述验收,没有磁盘节省或性能改善的实测结论。
## 平台与生产路径
性能主对照使用固定参考机。Windows、macOS、Linux x64/arm64 的原生验证检查进程启动、SQLite 可用性、
文件路径及关闭、升级和重启;没有硬件性能基线的平台只报告功能结果,不与参考机数字混算。
受影响的远程事件持久化、ACK、binding 和 Runtime 生命周期在共享 Linux x64 Host 开发时验收,
采用专用目录和既有固定身份;真实模型调用数单独报告,不混入无外部请求的性能基准。
正常 UI → Preload → Main → 存储进程 → SQLite 的完整路径必须至少覆盖 C01、C03、C07;
仅组件 mock bridge、独立 SQL 或进程握手均不能替代。原生客户端 ledger 的创建、失败、不确定结果及关闭删除也必须覆盖。
生产构建、各平台包内入口及进程启动通过既有 CI 和[发布手册](../development/release-runbook.md)验证。
本规范不授权发布准备期间本地打包或启动 portable 原始用户目录;源码测试使用隔离数据。
## 自动检查与交付记录
### 复用既有验收入口
扩展下表中的脚本和测试,不新增一套并行性能框架。现有能力与缺口均来自源码核对,不能把“已有测试文件”等同于已覆盖新语义。
| 场景/断言 | 既有入口 | 本次需要补齐的内容 |
| --- | --- | --- |
| C01/C02/C06/C07 | `build/run-app-perf.cjs`、`tests/support/app-perf-driver.mjs`、`build/run-startup-perf.cjs` | 多项目生产路由、并行流和子任务、冷热功能进入、资源回落;为 30 分钟场景显式设置匹配的运行期限,保留原场景期限 |
| C03/A04 | `build/run-main-perf.cjs`、`build/run-knowledge-perf.cjs`、`build/run-write-perf.cjs` | 保留既有数据,新增存储客户端和真实重叠负载;与完整 App 结果对应,不把分开测量冒充同时执行 |
| C04/A02/A03 | `remote-event-batcher.test.ts`、`ipc.test.ts`、`runtime-acp-backend.test.ts`、`runtime-controller.test.ts` | 异步提交延迟/拒绝时禁止提前通知及 ACK;覆盖交互、后台和恢复三个入口,open/prepare/close 清理时健康 peer 仍可操作 |
| C05/C06/A05/A06 | `readonly-query-reader.test.ts`、`supervision-model-pool.test.ts`、`subagent-scheduler.test.ts`、`shutdown.test.ts` | 取消后真实容量、队列饱和、进程丢失和等待退出;升级预检 SQL 迁出,checkpoint 终止得到确认 |
| A04/A07/A09 | `supervision-worker.test.ts`、`supervision-ui-reads.test.ts`、`supervisor-layout.electron.test.ts`、`message-expansion.electron.test.ts` | 保留事务、来源及交互断言;完整 App 扩展 UI 到真实存储链,不能只用组件模拟 bridge |
| SA-07 | `eslint.config.js`、`build/check-perf-thresholds.cjs`、`tests/perf-thresholds.test.ts`、已有 Desktop/Agent workflow | 间接打开点、白名单基线、负载元数据、缺失指标及并发场景;预算与历史回归上限分别报告 |
既有部分脚本默认使用系统临时目录,复用时按 AGENTS 统一到仓库 `temp/`;新增的可重用夹具进入 `tests/` 或 `scripts/`。
当前 App 基准默认期限不足 30 分钟,C06 需要独立场景时长参数,不能通过放宽所有测试超时处理。
现有阈值检查未验证全部负载规模,需校验项目、会话、子任务、数据量及降速条件,缺少或不匹配时不能产生合格结果。
### 替代路径核验
A01/A03/A05/A06 还必须逐项确认:Main 升级预检与间接 ledger 打开已迁出,生产 `readWithFallback` 同步回退已删除,
监督清单不再持有独立业务写入权限,远程 `flush` 等待提交且失败可传播,原生客户端先完成 ledger claim 再发模型请求,
关闭 ledger 后才删所属目录。检查外部 live repository 工厂、重复客户端、重复队列和旧 shutdown 回调无生产调用。
保留合法的仓储同步单测、原子事务内部读取和远端数据库实现;不以删除测试或已发布兼容代码实现“清零”。
### 最终记录
- 静态检查覆盖 `DatabaseSync`、同步文件 API、`openPrivateSqliteDatabase` 及桌面间接构造点;
允许的存储宿主/测试/远端代码按执行环境列出,不能整片豁免 `src/main`。
- 白名单和 App 上限与已提交基线比较;迁出后删除例外,不因换文件名增加例外。
- 普通 CI 运行契约、顺序、取消、资源释放和生产路径测试;可复现性能执行环境运行上述关键并发基准,
在合并/发布候选检查中提供必需结果。没有合适 runner 时,记录为验收缺口,不能默认通过。
- 最终同一候选运行 `npm test`、`npm run typecheck`、`npm run lint`,并核对 native CI/Host 与性能报告对应的源码。
- 验收记录列出每个 C/A 编号的结果、命令、日志位置、样本数、原始数据和未测项;单独报告低配、故障注入及真实模型结果。
截至本文编写,只有历史局部测量可引用,尚无本矩阵的全项通过记录。待实现完成后新增具体日期的验收报告,
保留失败结果和复测理由,不把目标架构文档改写成未经验证的进度证明。
@@ -0,0 +1,306 @@
# 存储架构升级实施与验收记录
## 交付范围
本记录跟踪 [架构设计](../architecture/desktop-storage-direction.md) 的 SA-01 至 SA-08,并汇总
[Assistant 消费者](../architecture/assistant-storage-consumers.md)、[Knowledge 迁移](../architecture/desktop-storage-knowledge.md)、
[文件存储](../architecture/desktop-storage-files.md) 和 [Runtime 存储](../architecture/desktop-storage-runtime-integration.md) 的当前实现。
同一候选已完成多项桌面数据库所有权迁移、异步生产调用、输出唯一存储和临时资源清理。
内部工作按依赖并行执行,最终整体交付。接口、进程握手或分组测试通过均不代表产品完成。
保留现有未提交文档及仓库规则修改,不自动提交或发布。
## 实施分工
| 工作包 | 实施内容及替代入口 | 验证要求 | 当前状态 |
| --- | --- | --- | --- |
| S01 存储宿主 | 复用 reader 请求关联与 utilityProcess;宿主打开 Assistant/Knowledge,负责升级、查询分派、提交和退出 | 真实 Electron 进程、升级失败重试、取消结算、提交后读取、退出排空 | 已实现并接入生产组合;全量验收未完成 |
| S02 Assistant 调用 | IPC、心跳、监督、任务、笔记、通道、审计和工具接口改用异步领域操作;回调事务留在宿主 | 先写后读、回顾原子发布、项目隔离、暂停/恢复、错误传播 | 已接入生产组合;完整并发验收未完成 |
| S03 Knowledge 调用 | 数据库与 external repository 归宿主;解析、模型与凭据保留原所属;发布 DTO 替代事务回调 | 导入、检索、重建、embedding、删除和取消 | 已接入生产组合;完整 App 和并发验收未完成 |
| S04 文件与关联 | 文档结果、附件引用、正文分页由同一存储宿主管理;删除重复 Markdown;保留分支引用 | 采用/复制/释放/重启,取消失败全文,删除项目引用回收 | 已接入生产组合;完整 App 和并发验收未完成 |
| S05 绑定与账本 | 桌面远程绑定和原生客户端账本迁入宿主;远端数据库保持原所有权 | claim 后派发、提交后 ACK、响应不确定、关闭后删除目录 | 已接入生产组合;完整 App 和并发验收未完成 |
| S06 输出与启动材料 | 短输出有界内存,全文唯一 backing;必要配置文件归属、部分创建清理、启动回收 | 字节等价、内存上限、无多余文件、活跃所有者保护 | 生产 backing 已接入;跨场景文件与生命周期验收未完成 |
| S07 应用组合 | Main 初始化、事件通知、远程批处理、shutdown 接入统一存储;删除旧打开和同步回退 | 正常 UI 进入真实宿主,后台/恢复入口,退出失败可见 | 当前 Main 组合已接入;全路径验收未完成 |
| S08 守护与验收 | 扩展现有 lint、性能脚本和 Electron 测试;复核旧调用及重复实现 | 全仓检查、C01–C07/A01–A10、真实模型及数据副本 | 待最终候选 |
S01 的契约供 S02–S06 复用,S07 统一组合。跨包共享文件由指定整合者修改;业务代理提供所需操作和测试。
全量测试只对组合后的候选作最终判定。每次失败记录源码版本、原因、修复及复测,不放宽预算。
## 已发现问题对应关系
监督者重读/发布 Main 阻塞对应 S01/S02/S07;过大响应、窗口化和摘要缓存保留此前修复并在 C03/C07 回归。
跨会话全局等待、取消/迟到路由、超限用量与 Telegram 交付保留已有修复,纳入故障和混合负载验收。
输出短内容写后即删、全文引用缺失、重复解析 Markdown、Continue 部分创建和 helper 退出、Python 归档残留对应 S04/S06。
Agent 旧包/远程 staging 的失败清理、项目删除附件回收、诊断解析结果归属及笔记原子临时残留需逐项核对现有实现后记录处理结果。
有意保留的原生历史、安装缓存、用户导出、模型文件与 WAL 不作为垃圾删除。
## 真实数据与模型
已定位 portable:`dist/GoodBuddy-windows-x64/data`。该位置是原始数据,只读取统计并制作一致性备份,禁止直接启动候选写入。
数据库存在活动 WAL 时使用 SQLite 一致性备份;备份与工作副本分开,测试材料位于仓库 `temp/goodbuddy-storage-upgrade/`。
仅复制测试必需的数据库及所引用文件,记录校验值、schema、行数与完整性;不把凭据或正文写入报告。
源库无 WAL 且确认关闭时才允许直接文件复制。升级后逐项比较稳定 ID、顺序、引用、事件还原与重放去重。
性能采用本地确定性模型,真实模型用于生产功能链:普通会话及工具、子任务、监督发布、本地/远程 Runtime。
外部调用有界,记录实际请求数;真实数据内容不会为了性能测试默认发送到外部模型。
远程验证沿用共享 Linux x64 Host、现有凭据和专用测试目录,结束确认所属进程退出。
## 完成条件
最终运行 `npm test`、`npm run typecheck`、`npm run lint` 和差异检查;构建入口变化验证开发构建。
按 [并发验收规范](./concurrent-desktop-acceptance.md) 固定负载和三轮前后对照,包含 30 分钟生命周期。
分别报告界面延迟、Main 阻塞、存储等待/提交、吞吐、取消、内存和文件增长,禁止将单测通过替代性能结论。
实测超预算、未覆盖平台或外部环境阻断均保留为未满足项,不能宣称全部已解决。
当前记录确认 S01-S07 已有生产组合和定向证据;完整架构验收、平台包验证和 C01-C07/A01-A10 仍未完成。
## 2026-10-05 Portable 真实副本验证
本轮已执行当前源码的 `DesktopStorageClient → utilityProcess → DesktopStorageOwner`,
使用生产升级、读取、发布和关闭入口。脚本为
`tests/support/portable-storage-upgrade.mjs` 与 `portable-storage-upgrade-fixture.ts`。
成功运行始于 `2026-10-05T12:03:32.624Z`,总耗时 265.074 秒;
基于提交 `4bb7573b10ecc46f746fbe04cf6b1e2c05647d1a` 的未提交工作树。
环境为 Windows `10.0.26200`、Intel Core Ultra X7 358H、33,873,752,064 字节内存、
Node `24.21.0`、Electron `44.5.1`。这次未启动完整桌面 UI。
### 原件、备份与清理
原件位于 `dist/GoodBuddy-windows-x64/data`。成功运行没有在该目录打开 SQLite 连接,
也没有启动以该目录为用户数据目录的候选程序。先复制主文件与 WAL 到隔离 capture 目录,
确认源文件的大小、修改时间和 SHA-256 未变,再从 capture 执行 SQLite online backup,
由备份生成独立工作副本。本轮四个源 WAL 均为 0 字节;不能据此声称已覆盖持续写入的活动 WAL。
各数据库分别备份,文件集合不构成跨数据库事务快照。
四个源主文件及各自 WAL/SHM 共 12 个文件的前后大小、修改时间和 SHA-256 全部一致。
升级后的四个备份主文件 SHA-256 也与升级前一致。73 个附件引用均有可复制内容,
包括目录附件,合计 12,720,927 字节;50 个笔记文件合计 431,056 字节。
附件及笔记在复制时校验内容摘要,生产写入与重开后再次确认原件及工作副本内容未变。
日志只保存表名、计数、摘要和断言结果;没有复制设置或凭据,没有把正文写入报告,外部模型调用为 0。
被取消的旧探针曾继续占用 `run/work` 的 Assistant 文件。环境中的 `node` 实际由
`GoodBuddy.exe` 承载,按可执行文件名查询 Node/Electron 会漏掉该进程。
确认其命令行为本任务旧探针后,终止所属进程树并删除残留文件。
成功运行自动删除 `fresh-run` 的 capture、backup、work、WAL/SHM 与 Electron 临时目录;
旧 `run` 也已删除。保留的 `temp/goodbuddy-storage-upgrade/summary.json` 为无正文统计证据。
原取消轮没有保存完整源文件前后报告,因此上述原件不变结论限定于本次有记录的验证区间。
### 数据与正确性
| 数据库 | 源主文件/备份字节数 | schema 前 → 后 | 实际数据规模 | 完成写入练习后的主文件字节数 |
| --- | ---: | --- | --- | ---: |
| Assistant | 2,429,247,488 | 61 → 62 | 11 项目、312 会话、4,836 消息、2,353 任务、1,755,171 事件、233 成果、23,690 活动记录 | 2,432,491,520 |
| Knowledge | 1,568,768 | 13 → 13 | 2 知识库、2 文档、27 分块、27 embedding | 1,568,768 |
| Attachments | 98,304 | 1 → 1 | 73 附件、73 引用 | 98,304 |
| Runtime Bindings | 143,360 | 0 → 0 | 53 绑定 | 143,360 |
本轮实际覆盖的 Assistant 61 → 62 迁移新增监督来源/结果索引;数据已有历史差量存储,
没有重跑 schema 33/34 的正文压缩迁移。
在追加合成记录之前,对四库全部已有用户表逐行计算规范化摘要,比较行数与表摘要。
比较包含稳定 ID、顺序字段、时间、引用和远程来源字段;子任务事件按任务及事件 ID 顺序,
调用生产 `restoreSubagentPayload` 还原后比较。未变的不可变过程块复用内容摘要,
过程块数量与顺序仍参与每条事件的摘要。所有已有表的 `changed` 与 `added` 列表均为空,
没有需要豁免的启动恢复差异。Assistant 完整扫描前/后分别耗时 80.393/107.989 秒。
备份、升级副本及完成写入练习后的四库 `integrity_check` 均为 `ok`,
`foreign_key_check` 均为 0 条。真实监督数据包含 3 个结果、434 个事件、758 个来源;
读取其中一个图谱并关闭/重开,内容摘要一致。
新增远程事件的首次写入、同内容重放去重、冲突拒绝、已提交序号读取,以及重开后的重放去重均通过。
100 批合成监督发布每批包含 20 个来源及 20 个事件;最后一批的事件、来源和 20 条关联均存在,
关联端点有效,关闭/重开后图谱摘要一致。
Assistant 空闲页从 1,643 变为 1,619,Knowledge 维持 90 页;本轮没有证明空间回收收益。
表中 Assistant 最终大小包含后续合成发布与去重记录,不能当成仅升级造成的增长。
最终工作 WAL 的独立字节数没有写入该轮报告,退出后相关副本已清理。
### 耗时与边界
| 项目 | 单轮观测 |
| --- | --- |
| 首次生产存储就绪/关闭后再次就绪 | 557.778/308.364 ms |
| 后续练习初始化/再次就绪 | 333.349/286.487 ms |
| 100 次发布与 100 组图谱+结果列表读取重叠执行 | 32,363.016 ms |
| 发布 p50/p95/max | 10.830/15.269/27.026 ms |
| 读取组 p50/p95/max | 334.647/355.728/368.961 ms |
| 夹具 Main 事件循环延迟 p99/max | 16.482/17.121 ms,共 2,117 个采样 |
| 结束时 pending/Main RSS | 0/93,634,560 字节 |
这些数值来自单轮、两个有界生产者的闭环负载,不能替代固定 offered load、三轮前后对照、
多项目混合负载或 C01–C07/A01–A10。pending 高水位只在请求完成后采样,观测值 1 不是全程峰值。
未测 UI 响应、Renderer、存储进程内的等待与提交分解、30 分钟生命周期、真实模型及远程 Host。
Main 延迟采样也不能替代单次阻塞测量,当前证据不足以宣称所有性能预算达标。
探针设有 15 分钟总期限、每个 Electron 练习 180 秒期限、完整扫描 600 秒检查,
扫描每 100,000 行报告进度,练习每 10 秒报告阶段;通过后台运行与有界轮询执行。
前一版重复序列化累计过程的扫描超过期限,修正为复用块摘要后才完成全量比较,未减少事件数。
另外修复了 `publishedGraph` 的 `unknown` 使用:用共享 `supervisionGraphViewSchema` 校验响应,
没有用类型断言跳过检查。依赖目录缺失曾阻断续跑,经用户授权按 lockfile 恢复后完成执行。
### 检查结果
`npm run typecheck` 全仓通过,用时 14.312 秒。两个探针文件的 ESLint 通过。
定向运行 `desktop-storage.test.ts`、`desktop-storage-files.test.ts`、
`desktop-storage-runtime-operations.test.ts` 与 `assistant-storage-upgrade.test.ts`,
4 文件、31 测试全部通过,Vitest 报告 8.56 秒;包含真实 Electron 存储及历史迁移合成回归。
结束前执行 `--verify-source`,再次确认 12 个源 DB/WAL/SHM 指纹和笔记摘要与本轮基线一致。
`git diff --check` 无空白错误。中文审校扫描无阻断项,复核项中的测试边界与实际统计表述保留。
全仓 `npm run lint` 最后仍有一个范围外错误:
`tests/support/story-graph-focus-driver.mjs:122` 的 `console` 未定义;没有修改该探针。
全仓 `npm test` 使用 300 秒总期限启动,结束时没有留下最终汇总或退出结果,不能标记为通过。
已输出的失败涉及 `MarkdownRenderer.cache.test.tsx` 的 1 个微基准、
`image-tool-mcp.test.ts` 的 3 个测试及 `obsidian-electron.test.ts` 的 1 个测试。
这些失败保留给对应实现负责者,不以本轮存储验证通过覆盖全仓失败。
检查产生的本任务临时目录也在所属进程退出后清理;没有提交代码。
## 2026-10-05 C01-C07 并发桌面验收(未完成)
本轮使用现有 `build/run-app-perf.cjs` 与
`tests/support/app-perf-driver.mjs`,新增最小并发模式夹具
`tests/support/app-perf-concurrent.mjs`。夹具通过真实 UI、Preload、Main、存储宿主和本地回环确定性模型运行;没有启动 portable 原始目录,也没有外部模型请求。基线使用独立 worktree 的提交
`4bb7573b10ecc46f746fbe04cf6b1e2c05647d1a`,候选为同一提交的当前未提交工作树。日志和原始 JSON 位于 `temp/goodbuddy-concurrent-upgrade/`。
本轮没有达到验收规范要求的三轮交替、每项三轮各 100 个有效样本,也没有完成全部 C01-C07。因此不能标记 PERF-15/PERF-16 或本架构验收通过。
| 场景 | 实际结果 | 证据与主要指标 |
| --- | --- | --- |
| C01 3/4/8 | 未通过 | 当前候选首轮测量 1,898 个按键样本,p95 输入 16.8 ms、p95 帧 17.0 ms,但 Main 最大事件循环延迟 64.4 ms;请求未排空,驱动超时。基线首轮在第一批真实发送前等待发送按钮超时。 |
| C02 4/8/16 | 未通过 | 两个 30 秒测量周期完成;周期 1 有 494 个按键样本,p95 输入 17.4 ms、p95 帧 17.2 ms、4.2% 抖动、Main p99 18.4 ms、最大 25.3 ms。第三周期在请求排空前超时;标准机输入和帧 p95 均超预算。 |
| C03 回顾发布+知识重叠 | 未执行 | 现有 App 夹具没有真实重叠的 100 批回顾发布、知识导入/检索和图谱读取生产动作。 |
| C04 故障隔离 | 未执行 | 没有挂起启动/模型路由/清理并验证取消及健康 peer 的夹具。 |
| C05 存储故障与饱和 | 未通过 | C06 运行期间生产存储路径实际多次返回 `STORAGE_CAPACITY`;错误来自 `ReadonlyQueryReader.call` 的会话队列读取,已保留在 `soak-current/execution.log`。专门读 Worker 失败、存储进程退出和提交前后故障注入尚未完成。 |
| C06 30 分钟生命周期 | 未完成 | 已启动完整期限为 1,800,000 ms 的后台运行,实际约 34.5 分钟后因驱动超时退出;首个 30 秒测量有 494 个按键样本,p95 输入 16.6 ms、p95 帧 16.9 ms、Main p99 17.5 ms。由于请求持续在途且存储容量错误,未完成规范要求的完整生命周期、关闭重开和排空,不能算通过。 |
| C07 冷/暖进入 | 未通过 | 两个周期完成;周期 1 有 442 个按键样本,p95 输入 17.8 ms、p95 帧 50.0 ms、8.2% 抖动、Main p99 17.7 ms。夹具尚未分别测量监督概览、图谱、历史选择和来源正文的冷/暖内容可用时刻。 |
资源证据包括每个场景的 Browser、Tab、GPU、Utility PID、CPU 和工作集快照。当前候选的 C02 周期 1 Tab 工作集约 210 MB、Browser 约 200 MB;C07 周期 1 Tab 约 210 MB、Browser 约 212 MB。夹具已记录 3/4 和 4/8 项目/会话档位及 8/16 子任务 offered load,但生产事件中没有形成稳定的 8/16 个同时运行子任务,不能把 offered load 当成实际吞吐。周期性 4 KiB 工具更新、存储排队/执行拆分、缓存/订阅计数、临时文件字节数、C03-C05 故障动作和完整 supervisor 冷/暖内容指标均为未采集项。
本轮没有修改核心存储或调度实现。`node --check build/run-app-perf.cjs` 和
`node --check tests/support/app-perf-concurrent.mjs` 通过;未运行全仓 `npm test`,
因此本节只记录局部复测,不改变 C01-C07 的未完成状态。
### 2026-10-05 C01/C02/C07 实际证据复核与局部修复
复核了上述原始 JSON、`soak-current/execution.log` 及生产源码。容量错误的实际调用链为
`pumpConversationQueue` → `DesktopStorageClient.listConversationQueueItems` →
`ReadonlyQueryReader.call`;同一压力段还可见 `tasks:execution-stats`、工作区变化和概览读取竞争同一
有界读容量。C01 候选首轮为 1,898 个输入样本,输入 p95 16.8 ms、帧 p95 17.0 ms、Main 最大
64.4 ms;C02 周期 1 为 494 个样本,输入 p95 17.4 ms、帧 p95 17.2 ms、Main p99 18.4 ms、
最大 25.3 ms;C07 周期 1 为 442 个样本,输入 p95 17.8 ms、帧 p95 50.0 ms、Main p99
17.7 ms。C02/C07 的长帧主要出现在持续事件输入和显示刷新期间,采样中没有长任务脚本时间,
但有长动画帧的渲染/样式布局时间;因此未减少 offered load、输入样本或阈值。
本轮应用了三个最小局部调整:隐藏窗口时丢弃已过时的会话显示刷新并在重新可见时重读;侧栏隐藏时
不挂载项目切换器、活动菜单及其项目行;队列泵遇到 `STORAGE_CAPACITY` 时按会话只保留一个
50 ms 后重试,避免同一队列因容量瞬时不足进入错误风暴。正常事件、持久化和队列项目均保留。
定向 `ipc`、刷新和项目切换回归为 248 passed、1 skipped;类型检查和相关 lint 通过。
重新构建后以相同 C02 档位(4 项目/8 会话/16 子任务、每轮 30 秒输入)执行了四个周期,
原始报告位于 `temp/goodbuddy-concurrent-upgrade/profile-1MGfH7/artifacts/result.json`。修复后四轮
输入 p95 为 16.9/16.9/17.0/17.3 ms,帧 p95 为 16.9/16.9/17.0/17.1 ms,Main
最大事件循环延迟为 46.5/31.1/45.8/292.8 ms;最后一轮仍有 1 个 51 ms 长任务,驱动因
请求未排空而超时。日志仍观察到少量其他后台读取的 `STORAGE_CAPACITY`,所以本轮只能证明显示
刷新和队列重试的局部改善,不能标记 C02 或容量验收通过。相对原 C02 周期 1,前三轮输入/帧
p95 已回到约 17 ms,但 Main 尾延迟和完整排空仍未达预算;C01/C07 尚未取得修复后的同口径复测。
## 2026-10-05 C03/C04/C07 补充运行(仍未满足)
本轮只扩展现有 `build/run-app-perf.cjs`、`tests/support/app-perf-driver.mjs` 的
并发夹具,并通过已有 Preload/IPC/存储宿主/SQLite 生产入口执行。模型仍为本地
回环确定性模型,数据目录和运行目录均由 `run-app-perf` 隔离在
`temp/goodbuddy-concurrent-upgrade/`。构建命令为 `npm run build:bundle`;本轮没有
修改核心存储或调度实现,也没有提交。
| 场景 | 实际结果 | 证据 |
| --- | --- | --- |
| C03 混合存储 | 未满足 | `C03-current-r4/result.json` 记录知识导入耗时 4,307.193 ms,100 个重叠批次,100 次历史读取、100 次知识检索、100 次图谱读取,重叠窗口 3,784.373 ms。当前隔离数据没有已持久化监督结果,回顾发布批次为 0,因此没有把图谱读取冒充回顾发布;运行期间日志出现 `STORAGE_CAPACITY`。结果状态保留为 `not-fulfilled`。 |
| C04 故障隔离 | 未满足 | 复核发现原夹具在请求观察器登记前允许点击取消,且 HTTP `request.close` 被误记为模型中止;现已改为等待请求登记、使用响应 `close` 判断异常中止,并等待健康 peer 真正进入和完成。`C04-final-local-r2/result.json`(本地确定性、Windows x64、Electron 44.5.1)记录取消后请求结算、查询和 Runtime status 响应、清理完成,健康 peer 用时 37,142 ms,但 `healthyPeerUnaffected: false`,且循环账本 4 次请求中没有 `fault-hung` 条目,因此不能声称挂起模型路径已完成。外部模型请求数为 0;未授权执行真实模型。 |
| C07 冷/暖进入 | 未满足 | `C07-current-r1/result.json` 记录冷进入:输入 0.591 ms、历史 41.889 ms、监督概览 2.532 ms、图谱 2.244 ms、知识快照 2.555 ms;暖返回:输入 18.844 ms、历史 219.868 ms、图谱 10.757 ms、知识快照 2.062 ms。暖监督概览因 `STORAGE_CAPACITY` 无可用时刻;来源正文没有持久化来源,仍未测得。夹具状态为 `measured-with-gaps`,整体未满足。 |
所有补充运行均保存原始 `result.json` 和执行日志;模型边界仍为本地回环,外部请求数为 0。运行中观察到的存储容量错误及一次存储 Worker 退出均保留为当前候选的未满足项,不能以夹具已采集样本或构建成功覆盖。三轮交替、每项三轮 100 个有效交互样本、C03 回顾发布、C04 健康 peer 完成和 C07 来源正文时刻仍未完成。
## 2026-10-06 Portable 证据轻量复核
本次只读复核针对原始 `dist/GoodBuddy-windows-x64/data`、保留的
`temp/goodbuddy-storage-upgrade/summary.json` 和当前仓库状态执行;没有启动 portable 原始目录,
没有复制或写入原始数据库,也没有提交。保留证据的成功运行时间仍为
`2026-10-05T12:03:32.624Z`,记录提交为 `4bb7573b10ecc46f746fbe04cf6b1e2c05647d1a`,
且记录的工作树为未提交状态。当前 HEAD 为
`edf019aaa728f094a433a2601d149d0ec9b28a21`,工作树仍有大量未提交修改,因此 portable 运行早于当前
源码状态,不能把它当作当前 HEAD 的运行结果。
保留验证器 `node tests/support/portable-storage-upgrade.mjs --verify-source` 本次未通过:
当前 `assistant.sqlite` 与保留基线的 SHA-256 和修改时间不同,当前 `knowledge.sqlite` 的修改时间不同,
且保留基线中的四个 0 字节 WAL 与四个 SHM 当前已不存在。当前四个主库的字节数仍分别与记录一致;
`conversation-attachments.sqlite` 和 `remote-runtime-bindings.sqlite` 的 SHA-256/修改时间仍一致,
`knowledge.sqlite` 的 SHA-256 仍一致。当前 `notes` 仍为 50 个文件、431,056 字节,内容指纹与保留证据一致。
因此原件相对本轮 portable 执行后的“当时未变”结论有后续漂移,不能宣称当前原始数据仍与 portable 运行基线完全相同。
对当前四个原始主库执行只读 SQLite `PRAGMA integrity_check` 均为 `ok`,`foreign_key_check` 均为 0 条,
版本分别为 Assistant 62、Knowledge 13、Attachments 1、Runtime Bindings 0。这只证明当前文件的轻量结构完整性,
不恢复 portable 运行与当前源码的一致性,也不替代一次新的隔离副本迁移验证。
清理复核确认 portable 验证使用的 `temp/goodbuddy-storage-upgrade/fresh-run`、`run` 目录均不存在,
保留目录中只有日志、JSON 结果和源基线等证据文件;进程命令行未发现 portable 数据目录、验证脚本或
`goodbuddy-storage-upgrade` 相关进程。机器上发现的已安装 GoodBuddy 进程使用独立用户数据目录,未计入本次
portable 验证进程。上述结果只更新本实施记录,未修改原始目录或其他实现文件。
## 2026-10-06 简化与前后对照验收
### 简化
按“出现实测问题才加机制”复核并发修复期间新增的机制,删除以下实现(共约 400 行):
| 删除项 | 原因 | 替代 |
| --- | --- | --- |
| 自定义分帧传输 `desktop-storage-wire.ts` | 同机实测原生 `utilityProcess.postMessage` 传 32 MB 文本 126–139 ms、5 万行 71–85 ms,Main 最大延迟在 16 ms 计时精度内;自定义分帧分别为 249–271 ms、448–496 ms | 原生结构化克隆 |
| 读/写/后台三类准入预算、交互保留槽 | 容量错误是“满了就拒绝”造成的,分类只是缓解 | 单一在途上限 32,超出按顺序等待,不再拒绝 |
| 同键读取合并、存储进程侧重复准入、整值读取串行 | 客户端已限流,宿主再做一遍没有新约束 | 删除 |
| 队列泵 `STORAGE_CAPACITY` 50 ms 重试 | 等待替代拒绝后不再出现容量错误 | 删除 |
另把存储进程启动移到建窗口之前,与窗口创建重叠。取消、提交后才确认、进程丢失时不重放、关闭前排空的语义不变;真实 Electron 存储夹具(含 16 MiB 视频、2,560 万字符历史)通过。
### 前后对照
基线为独立 worktree 的 `edf019aa`,候选为同一提交加当前工作树;同机交替运行,本地确定性模型,无外部请求。判定口径见[并发验收的发布门槛](./concurrent-desktop-acceptance.md#发布门槛与目标差距)。
| 场景 | 正确性门槛 | 对照结果(基线 → 候选,3 轮) |
| --- | --- | --- |
| 单会话 11 个场景 | — | 输入、切换、长会话打开、流式均在轮间波动内;Main 延迟 p99 在流式场景约 20.6 → 16.8 ms;启动至输入框可用中位数约慢 33 ms(1,300 → 1,333 ms),与轮间波动同量级 |
| C01(3/4/8) | 两版均 3/3 通过:全部排空、0 错误 | 排空耗时一致(约 37 s/17.5 s);Main p99 约 21 → 16.7 ms |
| C02(4/8/16) | 两版完成的轮次均通过 | 排空耗时一致(约 23 s/53 s);Main p99 约 22 → 16.7 ms |
| C03 混合读取 | 两版均无回顾结果可发布,标未满足 | 100 批重叠读取窗口约 1,010 → 912 ms;基线知识导入在该夹具中报错,候选无错误 |
| C04 故障隔离 | 两版均 3/3 通过:挂起请求取消结算,健康会话完成 | 取消观测约 135 → 101 ms,健康会话耗时一致 |
| C06 5 分钟生命周期 | 两版均通过 | 每轮排空耗时一致;4 轮后堆 18.2 → 17.8 MB;另有候选 30 分钟运行 21 轮全部排空、0 错误,堆每轮约增 0.3 MB,与每轮新增 8 条持久化会话一致,结束时驱动退出出错,未记为通过 |
| C07 冷/暖进入 | 无持久化来源,来源正文未测 | 冷进入各阶段 1–7 ms,两版一致;暖返回监督概览 38–45 → 25–38 ms |
产品子任务调度上限为 3,16 个子任务按设计排队,因此“同时运行子任务”门槛按 `min(负载, 3)` 判定。夹具修正:排空等待改为 180 s(两版相同)、子任务按 `childTaskId` 统计、输入框焦点未就绪时重试输入。
结论:**正确性门槛在 C01/C02/C04/C06 两版都通过,候选在单会话和并发场景均未退化,Main 尾延迟有改善。** 剩余未满足项:C03 回顾发布与 C07 来源正文需要先有持久化回顾数据的夹具;C05 存储故障注入只有真实 Electron 存储夹具中的进程丢失、发送失败、取消覆盖,未做 App 级故障矩阵。输入 p95 约 8–9 ms,帧 p95 多数 8.5 ms,部分轮出现 16.5/58 ms,两版相同,记为目标差距。
### 真实数据与真实模型
portable 新副本(`--fresh`)当前源码复验通过:Assistant 库 175 万条事件、4,848 条消息,schema 62,所有已有表规范化摘要无变化,`integrity_check` 为 ok,外键违规 0;73 个附件、50 个笔记前后一致,原件 DB/WAL/SHM 指纹未变,副本已删除。100 批发布与读取重叠时,发布 p95 19 ms,夹具 Main 延迟 p99 16.4 ms。
真实模型输出分页首次走通:使用当前默认 `openai-responses` 配置,模型调用 1 次 `process_execute`、2 次 `output_read`,逐页游标连续至 EOF,恢复两个随机标记,**4 次外部请求**。之前两次失败的原因是该手动用例未注入输出正文存储(生产在 `index.ts` 注入),工具在模型分页前就报错;已改为注入与其他单测相同的文件存储。
### 全仓检查
`npm run typecheck`、`npm run lint` 通过。`npm test` 三次全量结果:1 失败(`workspace-import` 图片加载超时)、9 失败、1 失败(`local-runtime-reuse` 压缩返回 false),每次失败的用例不同,单独复跑均通过(`local-runtime-reuse` 3/3、`workspace-import` 4/4、其余 3 个文件 481/481)。判定为满载时的时序敏感用例,未放宽断言或超时,但不能记为全仓一次通过。
## 2026-10-06 有界真实模型复验
本节记录当前未提交源码的最终有界复验。没有启动 portable 原始数据目录,也没有把其中的会话、附件、笔记、日志或凭据发送给外部模型。所有发送给模型的监督输入均为脚本内合成内容;取消和输出分页场景也只使用脚本生成的短提示、临时工作区和随机标记。请求计数来自生产 Runtime 的 fetch 层或本地计数 relay,不记录请求正文、响应正文、请求头、端点或密钥。
| 路径 | 实际外部 HTTP 请求 | 结果 | 范围与边界 |
| --- | ---: | --- | --- |
| 生产存储宿主监督链 | 4 | 通过,4 次 HTTP 200 | `supervision-storage-live.cjs` 使用当前运行时设置读取凭据,在隔离 Electron、Assistant/Knowledge 存储宿主、生产监督工厂和 Heartbeat 入口中运行合成项目;故事、经验、建议发布成功,`no_change` 重跑新增 0 次,设置未改变,pending 为 0 |
| 生产监督审核工厂 | 2 | 通过,完成 | `supervision-audit-validation.ts live` 使用当前 `ModelAgentRuntime`、生产监督服务和隔离 SQLite;1 条合成消息完成提取与故事归属,重跑新增 0 次,SQLite 完整性与外键检查通过 |
| 直连 Runtime 取消 | 3 | 通过 | 现有 `cancelled-turn-live.test.ts` 的两个 direct-model 取消后续答复用本地计数 relay 执行;取消轮和后续请求均完成,取消内容没有并入下一轮,3 次请求均由 relay 计数 |
| 直连 Runtime 输出分页/工具请求 | 2 | 未通过覆盖断言 | 现有 `runtime-e2e.manual.test.ts` 的生产源测试到达模型两次,但模型没有发出 `process_execute` 或 `output_read`,因此没有证明真实模型工具请求和分页闭环;该次仅计入实际请求,不把失败运行写成通过 |
| 本地 OpenCode | 0 | 未执行 | 当前源码 checkout 没有 `.runtime-resources/win32-x64/opencode.exe`;没有改用已发布 portable 或其他缓存二进制 |
| 本地 Continue | 0 | 未执行 | 当前源码 checkout 没有 `node_modules/@continuedev/cli/dist/cn.js`;没有改用已发布包 |
| 共享 Linux Host | 0 | 未执行 | `192.168.0.23` 的 SSH 连接可达,但 BatchMode 连接在认证前由 Host 关闭;没有凭据交换或模型请求 |
本节合计观察到 **11 次** 外部模型 HTTP 请求:监督存储 4 次、监督审核 2 次、取消 3 次、输出分页失败尝试 2 次。没有重试被计入,也没有远程或 OpenCode/Continue 本地请求。监督链使用的运行时设置仅在隔离进程内解密,原设置字节保持不变。
验证结束后,隔离数据库、Electron profile、临时工作区、凭据副本、计数 relay 和生成的 probe 目录均已删除;进程检查没有发现属于这些运行的残留进程。该结果证明了当前源码的生产存储监督与直连取消路径,以及一次明确失败的真实模型工具分页尝试;不证明本地 OpenCode、Continue、远程 Linux Host、真实模型工具分页成功、完整桌面 UI、portable 数据副本或 C01–C07/A01–A10 验收已经完成。