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
@@ -802,7 +802,7 @@ npx eslint scripts/review-algorithm.mjs scripts/review-algorithm.test.mjs script
### 2026-09-24 模型阶段超时、并发与设计边界
- 本次静态核对当前新代码:报告 `heartbeatReportTimeoutSeconds`、监督 `supervisorOrganizeTimeoutSeconds` 已接入共享校验、设置存储、App/设置表单及 Main 摘要器;整数 30..600 秒、默认 240。报告在等待池前冻结值,监督在摘要器入池前读取值,均在获槽及 Runtime 解析后才计时。完整控制及未覆盖环节见[控制清单](./review-scheduling-design.md#当前超时与调度控制清单已实现)。
- 本次静态核对当前新代码:报告 `heartbeatReportTimeoutSeconds`、监督 `supervisorOrganizeTimeoutSeconds` 已接入共享校验、设置存储、App/设置表单及 Main 摘要器;整数 30..600 秒、默认 240。报告在等待池前冻结值,监督在摘要器入池前读取值,均在获槽及 Runtime 解析后才计时。该次记录对应的完整控制及未覆盖环节见[初稿控制清单](./review-scheduling-design.md#初稿时超时与调度控制清单历史截面),不代表当前实现。
- `supervisorModelConcurrency` 已接入同一设置链路,整数 1..4、默认 1;报告与监督共用 FIFO 池,普通聊天排除,降限不终止在途项。报告获槽后才领取,每次到期领取最多一条;租约为 `max(300, 报告超时 + 60)` 秒,实际请求开始前按运行 ID、owner、attempt、claimed 和未过期条件校验并刷新。报告提交或无变化后先释放槽位,再进入下游监督。尚无提供商全局并发、RPM、TPM 或监督层 Retry-After 控制。
- 本轮协作提供的新增验证记录:24 项并发相关测试、33 项租约相关测试及 typecheck、lint 通过。本次文档修订仅核对实现,没有重新执行这些测试;记录未附精确过滤命令,不补造命令或与此前批次相加。
- 实现代理报告:87 项测试、App/IPC 聚焦用例、另 19 项取消测试,以及 typecheck、lint 通过。本次文档修订未复跑这些命令,不将数量相加当作独立用例总数,也不推断全量测试已通过。
@@ -98,9 +98,11 @@ schema 47 增加运行配置、来源清单、成功批次、导航节点四张
目标是不再静默裁剪,把单次上限改成分页、分块和暂缓派发的依据,直至冻结范围内全部项目、会话、消息及其他入选来源处理完毕。模型提取仍可能遗漏原文含义,但已产出的叶子事实、事件、冲突及来源必须完整保留、可分页读取。摘要只用于导航,不能替代叶子结果;“原文已处理”也不等于模型识别了全部事实。
### 当前超时与调度控制清单(已实现)
### 初稿时超时与调度控制清单(历史截面)
以下是当前代码事实,不是后文拟议的多层调度预算。设置暴露两个阶段超时和一个监督并发数。
以下表格及其后说明保留初稿时的实现截面,不定义当前生产行为或本次存储迁移需要新增的机制。
其中“无用户取消入口”“收齐后检查 100KB”和原心跳报告交接已被后续实现替代。
现状以本页第 0 节及[监督者技术设计](./technical-design.md)为准,复用既有回顾准入、模型池和暂停/继续机制,不据此再建一套调度器。
| 控制 | 实际值、读取时点与范围 | 代码依据与边界 |
| --- | --- | --- |
@@ -21,7 +21,7 @@ FR-S1:将现有智能心跳入口整合、升级为监督者,不增加另一
FR-S2:应用包含“工作回顾 / 故事线图谱 / 自动监督 / 活动记录 / 设置”五个主视图。工作回顾提供统一监督结果阅读、历史选择和手动新回顾,结果显示自身范围与日期;自动监督集中展示计划状态、范围、周期及下次执行时间,以及运行概览、指标、趋势、自动监督报告、待处理记忆与行动建议和心跳审计,创建和编辑使用同一份 Modal 表单;活动记录展示统一实际执行、进度、详情及结果入口,支持按计划 ID 筛选;设置管理模型选择、超时、并发、分页、分批及单次响应容量,分类页签见 UI 设计。计划保存失败保留草稿,关闭未保存修改须确认;编辑已暂停计划保持暂停,创建须显式保存并启用。原有运行记录及应用、存储标识保留。
当前设置还支持分别调整报告与监督整理的模型超时,以及两者共用的监督并发数。并发设置不限制普通聊天,也不保证避免上游限流;排队不消耗模型阶段时限,降低并发不打断在途请求。取值及生效规则由[当前控制清单](./review-scheduling-design.md#当前超时与调度控制清单已实现)定义。
当前设置支持监督整理模型超时及监督模型并发数。并发设置不限制普通聊天,也不保证避免上游限流;排队不消耗模型阶段时限,降低并发不打断在途请求。取值、生效规则及历史报告设置的保留边界由[模型阶段调度](./technical-design.md#模型阶段超时与调度)定义。
FR-S13:监督者的“设置 → 模型”可选择跟随应用默认文本模型或已有文本模型连接,复用连接及其凭据。回顾执行中修改设置不切换模型;生效时点、继续和重试规则见[监督者模型选择](./logic-design.md#监督者模型选择)。
@@ -129,7 +129,9 @@ Modal 按[共享表单 Modal 规则](../../../UI-DESIGN.md#615-表单-modal)复
时间螺旋使用所选回顾的时间区间与完整事件集合,半径和区间着色规则见 [3D 密度规则](../story-graph/3d-concept.md)。当前故事成员按精确事件 ID 与结果求交;其余事件按来源确定的项目进入“当前无故事归属”分组,项目未知时显示“项目范围不可用”。图例说明“本次回顾事件按当前故事归属分组;未保存当时的故事归属”。故事与经验列表仍提供该范围的当前完整记录,供查看和调整。
根视图直接显示事件点,同一主故事的邻近事件按画布密度聚合并显示数量,未归属点使用中性色。事件和经验从左侧列表选择,画布不重复提供这两种选择器。保留一个层级菜单:左侧列表选择记录并打开详情,标题区层级菜单改变画布中的项目、功能或子线索层级。菜单与面包屑均可用键盘操作。默认斜俯视,不显示视角按钮、菜单或页签;自由拖动、平移、滚轮、方向键、数字键和 Escape 返回上层操作保留。
根视图直接显示事件点,同一主故事的邻近事件按画布密度聚合并显示数量,未归属点使用中性色。事件和经验可从左侧列表或画布标记选择,画布不重复提供这两种选择器。保留一个层级菜单:左侧列表选择记录并打开详情,标题区层级菜单改变画布中的项目、功能或子线索层级。菜单与面包屑均可用键盘操作。无选择时默认斜俯视,不显示视角按钮、菜单或页签;自由拖动、平移、滚轮、方向键、数字键和 Escape 返回上层操作保留。
时间螺旋选中故事、事件或经验后,相机沿较短方向旋转并平移到对应位置,保留当前缩放;缩放超出 0.8~1.4 时收回到该区间。列表选择的目标不在当前层级时,切换到能显示该目标的层级;经验须在本次回顾内有跨木片的形成与应用连接才能定位,没有对应几何对象的记录仍可查看详情。选中的经验不受默认六条连接的显示上限限制。鼠标拖动、滚轮和方向键立即接管相机,后续相同选择和同内容刷新不重新定位。启用减少动态效果时直接定位,离开视图时取消未完成动画。
关联来源详情属于会话时,显示“打开会话”按钮,使用来源保存的会话 ID 跳转并切换到所属项目;不发送消息或启动回顾。另提供“继续讨论”,使用上述可编辑正文预览,点击发送后提交到来源会话并打开它。详情继续展示整理时保存的原文快照。会话已删除或读取失败时,沿用应用会话导航的提示;其他来源类型不显示此按钮。
@@ -116,13 +116,11 @@ confidence 改为可选,保持本地返回原值;多块内容组成逐页 se
original.<ext>
documents/<attachmentId>/
original.<ext>
parsed.md
manifest.json
images/<imageId>.<ext>
knowledge/<kbId>/<sourceId>/
<managed-original-files>
knowledge-assets/<kbId>/<documentId>/
parsed.md
manifest.json
images/<imageId>.<ext>
temp/document-parsing/<operationId>/
@@ -155,7 +153,7 @@ confidence 改为可选,保持本地返回原值;多块内容组成逐页 se
也需验证同一规则。采用暂存、现有事务和按数据库引用核对清理,不新增恢复引擎。
测试解析使用任务临时目录,结束预览且无有效引用后清理。知识库正文及 chunks 继续存数据库,
`knowledge-assets` 的 `parsed.md` 为解析正文文件,随同一次结果提交保持一致,不独立修改
`knowledge-assets` 的 `manifest.json` 保存解析正文,随同一次结果提交保持一致,不独立修改
或替代数据库中的检索内容。图片归知识库文档所有,不依赖聊天存活;managed 与 reference
派生文件均存该目录,reference 外部原件保持原路径,现有 managed 原件目录不迁移。
重解析或同步先在本次暂存目录完成新结果与必要资源校验,成功提交替换后清理无引用旧资源;
@@ -44,17 +44,21 @@ PPTX 回退提示按实际 OCR 来源显示,并在图片处理失败时包含
conversation-assets/<conversationId>/
images/<resourceId>/original.<ext>
documents/<resourceId>/original.<ext>
documents/<resourceId>/parsed.md
documents/<resourceId>/manifest.json
documents/<resourceId>/images/<imageId>
knowledge/<libraryId>/<sourceId>/<managed-original>
knowledge-assets/<libraryId>/<documentId>/<resultId>/
parsed.md
manifest.json
images/<imageId>
temp/document-parsing/<resourceId>/
```
S04 (2026-10-05): new results store parsed content in `manifest.json` only;
`parsed.md` is no longer written or copied. Released manifests remain readable,
including directories containing the old duplicate. Async storage-host integration
and its remaining composition work are specified in
[Desktop File Storage Integration](../../architecture/desktop-storage-files.md).
会话资产的 `request.json` 保存已转换的请求内容,用于恢复内存 context;原件字节单独保存,
缩放和 JPEG 请求副本不覆盖原图。提取图片文件使用 UUID 无扩展名,MIME 在清单记录。
图片显式 OCR 后生成解析文件。切回原图保留已有结果,并重新进入图片能力校验。
+1 -1
View File
@@ -10,7 +10,7 @@ Smart Heartbeat 已提供按计划或手动执行的有界回顾,生成报告
## 文档导航
当前监督者设置已接入报告与监督整理两项模型阶段超时(30 至 600 秒,默认 240)及共享监督并发数(1 至 4,默认 1),模型超时不包含排队、采集、保存或整次执行期限。报告先获槽再领取,实际请求开始前校验并刷新租约,报告提交或无变化后释放槽位再进入监督。普通聊天不入监督池,尚无跨聊天与监督的提供商全局并发或 RPM/TPM 限制。租约、固定传输时限及重试与用户超时分开,见[控制清单](../conversation-supervision/review-scheduling-design.md#当前超时与调度控制清单已实现)。完整分页与持久化续跑仍为设计,不能把现有增量检查称为完整调度器。
当前心跳将到期计划交给监督回顾,不再额外生成独立报告。监督整理使用模型阶段超时和共享监督并发池,普通聊天不入池;模型超时不包含排队、采集和保存,也不是整次回顾期限。分页、批次持久化和暂停/继续已接入生产路径,范围及剩余限制见[生产接线](../conversation-supervision/review-scheduling-design.md#0-生产接线与剩余边界)。超时、并发、重试及保留的历史报告设置由[模型阶段调度](../conversation-supervision/technical-design.md#模型阶段超时与调度)定义,不据初稿控制表另建调度器。
监督者“活动记录”页签同时显示手动回顾和心跳执行,将新心跳报告与下游监督按运行 ID 合并,保留各阶段真实状态。心跳审计、运行概览、指标、趋势、自动监督报告阅读和建议处理与计划列表同在自动监督页;工作回顾只读取统一监督结果,设置只保留配置。当前布局见[监督者 UI 设计](../conversation-supervision/ui-design.md#应用入口)。心跳审计继续读取报告自身状态,完整执行状态以[活动规则](../conversation-supervision/logic-design.md#活动记录)为准。
+1 -1
View File
@@ -196,7 +196,7 @@ type HeartbeatScope =
- Main 在创建、编辑、列出和执行时验证 Project 归属。
- Global 读取所有 Project 的有界会话和任务,但长期记忆仍只读取 Global。
- 指定 Project 读取选中项目的有界会话和任务,以及 Global 与选中项目记忆。
- 现有输入条数、字符预算、输出大小、超时、重试、租约和工具禁用边界继续生效。报告与监督整理共用监督专用并发池,普通聊天不入池;具体设置、租约和未实现的限流边界见[当前控制清单](../conversation-supervision/review-scheduling-design.md#当前超时与调度控制清单已实现)。
- 心跳交接、监督分页与输出容量、模型阶段超时、重试和工具禁用边界以[生产接线](../conversation-supervision/review-scheduling-design.md#0-生产接线与剩余边界)及[模型阶段调度](../conversation-supervision/technical-design.md#模型阶段超时与调度)为准。监督模型池不限制普通聊天,不将历史独立报告阶段作为当前必须执行的路径。
- 多项目汇总后统一应用上限,不能按项目倍增预算。
- 心跳结果默认不在系统通知中暴露私人正文。
- 数据迁移必须使用 SQLite 事务,保留外键、级联删除和现有历史。