fix: resolve runtime, review, channel and chat state failures
Keep remote startup cancellable without blocking other sessions and surface local OpenCode submission failures promptly. Preserve supervisor project isolation, pause behavior and valid story destinations. Restore generated-image channel delivery, Telegram reconnection on unchanged Save and DingTalk business-error retries. Preserve virtualized message disclosures using sparse state and release stale supervisor UI requests. Add production-path regressions, Electron checks, isolated SQLite validation and audit evidence. Fix the SDK cleanup test fixture lifetime under garbage collection without weakening its assertions. Validation: 6136 tests passed, 87 skipped; typecheck, lint and diff checks passed. Seven real text-model calls, current-source Linux x64 Host scenarios and large-history Electron comparisons completed. Release note: Fix stuck runtime requests, inconsistent review results and channel delivery failures, and retain expanded details while browsing long conversations. Remote runtime fixes require an Agent build containing these changes.
This commit is contained in:
@@ -4,6 +4,24 @@
|
||||
|
||||
当前记录以已验证生产行为为准。监督者尚未覆盖全部 user stories。
|
||||
|
||||
## 2026-10-05 后端阶段审查 A03/A04/A05
|
||||
|
||||
对应 SL-5、SL-8、FR-S6、FR-S10。生产候选读取现在将批次项目和跨项目设置传到只读 Worker;最终候选读取返回后检查暂停/取消;故事归属和拆分在原写事务内拒绝已移除或合并的目标。存储、停止与重试规则见[技术设计](./technical-design.md#单次执行与取消)。没有 schema 变更,原始消息、历史结果及人工确认字段保留。
|
||||
|
||||
先加回归、后改实现的结果:8 个新用例中旧代码失败 7 个,取消用例原本通过。失败覆盖跨项目开/关两种生产候选、最终候选读取期间暂停、归属期间移除/合并目标、拆分前移除功能/子线索。旧暂停用例实际返回 `completed` 并发布结果;旧归属用例写入隐藏目标且把事件标为已处理。修复后暂停不发布结果或 checkpoint,继续仍复用原批次;失效故事批次回滚且事件可重试。生产身份测试补充真实项目事件关联,保留 UUID 别名、确认字段及失败后继续的断言。
|
||||
|
||||
验证命令与结果:
|
||||
|
||||
- `npm test -- src/main/assistant/supervision-production.test.ts src/main/assistant/supervision-worker.test.ts src/main/assistant/supervision-stories.test.ts src/main/assistant/supervision-review.test.ts src/main/assistant/supervision-timeline.test.ts src/main/assistant/supervision-experiences.test.ts src/main/assistant/supervisor-service.test.ts src/main/readonly-query-reader.test.ts`:8 个文件、96 项通过。Worker 回归每轮使用两个项目、422 条来源,并检查候选隔离、实体数量、外键及暂停后的完整发布。
|
||||
- 本次修改的 Main 源码、测试和验证脚本定向 ESLint、`git diff --check` 通过。`npm run typecheck` 首轮发现本轮 fixture 缺默认设置字段,修正后曾被并行 `tests/message-expansion.electron.test.ts:39` 类型错误阻塞;该文件由其负责方修正后,Main/Agent/Web 三组最终全部通过。本轮未修改该文件。
|
||||
- 定向验收时 `npm run lint` 曾被并行 OpenCode 修改中的三项错误阻塞;负责方修正后,最终全仓 lint 与 typecheck 均通过。两份后端文档扫描阻断项为 0;人工复核保留取消与事务顺序的边界说明。完整集成结果见[阶段修复验收](../../review/stage-audit-fixes-2026-10-05.md#最终检查)。
|
||||
- `node --import jiti/register scripts/supervision-audit-validation.ts scale <临时父目录>`:真实文件 SQLite,10 个项目、1,000 个实体、10,000 个事件、10,000 条事件实体关联、10 条来源,库文件 10,964,992 字节。三轮交替查询中,每轮十次旧相关子查询合计 3,517/5,302/4,190 ms;新 Worker 查询合计 39.18/34.01/36.04 ms,包含传输。逐项目返回的 100 个候选 ID 及顺序与旧 SQL 完全一致;跨项目读取每轮 0.95~1.79 ms。120 个事件的单批归属事务为 6.63 ms。计数不变,`foreign_key_check` 为空,`integrity_check` 为 `ok`。
|
||||
- 查询测量是同一合成库内的 SQL 对照,非完整 App 基线;同时有其他本地验证任务运行。原相关查询在修复传参后首次实测暴露每十次 3.60~4.65 秒耗时,随后改为实体集合查询。没有新增索引或迁移,也不据此宣称整窗性能改善。
|
||||
|
||||
真实模型检查沿用 `scripts/supervision-production-live.ts` 的环境文件读取与 `ModelAgentRuntime` 无工具模式,由新增合成验证脚本执行。`node --import jiti/register scripts/supervision-audit-validation.ts live <临时父目录> .env.deepseek.local` 只发送一条 147 字符合成消息,真实生产工厂和文件 Worker 完成提取、保存及故事归属。外部请求准确为 **2 次**:提取 1 次、故事归属 1 次;无变化重跑新增请求 0 次。原文片段精确重建,外键与完整性检查通过,总耗时 3.84 秒。脚本上限为 3 次 HTTP 请求、每次模型阶段 45 秒、1,800 输出 token;凭据仅在进程内读取,终端与指标文件只输出计数和验证信息。本机继承的 TLS 环境设置未由本次修改。
|
||||
|
||||
报告位于系统临时 `opencode/supervision-audit-Ggn5uW/metrics.json`(规模检查)和 `opencode/supervision-audit-WNu08s/metrics.json`(模型检查)。只写隔离合成库,未读取或修改用户库,未运行完整 App/Electron 回归或整包构建;没有提交。修改位于桌面监督服务及其 SQLite Worker,GoodBuddy Agent 与远程 Runtime 控制路径未改变。
|
||||
|
||||
## 2026-10-04 螺旋工具栏与事件颜色修正
|
||||
|
||||
接续未提交的回顾布局调整。平铺与螺旋共用标题工具栏样式,项目层级菜单放在面包屑旁,画布内的视角入口和左下角圈数说明已移除。默认斜俯视,拖动及键盘操作保留;两种图谱均以共享 InlineHelp 的 i 图标打开图例。共用历史回顾栏、下钻返回、详情选择与中窄窗口详情面板保留。当前规则见 [UI 设计](./ui-design.md#故事线图谱)。
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
|
||||
本文回答如何在现有 GoodBuddy 桌面端中实现监督者。它不改变产品范围,也不把模拟 Demo 当作生产数据模型。
|
||||
|
||||
FR-S11 的读取架构见[时态 Story Graph 内置 MCP 设计](./story-graph-mcp-design.md)。三个只读工具通过 `readStoryGraph` 投影现有 SQLite,Main 在发现、调用和返回前检查监督者启用、会话开关及 Runtime 分配。绑定携带会话 ID,按主键读取当前设置;原生客户端的复用键包含会话 ID 和开关值。本地 MCP、Model、Harness Main 代理和远程受管工具通道共用此入口;会话开关复用 `context_state_json`,无 schema 迁移。该文独立定义对象/版本合同、时间语义、配置映射及后续跨 scope 复用和记忆过渡。当前 memory 背景读取、精确 scope checkpoint 与候选身份保留;结果快照不支持 `as_of` 历史重建。
|
||||
FR-S11 的读取架构见[时态 Story Graph 内置 MCP 设计](./story-graph-mcp-design.md)。三个只读工具通过 `readStoryGraph` 投影现有 SQLite,Main 在发现、调用和返回前检查监督者启用、会话开关及 Runtime 分配。绑定携带会话 ID,按主键读取当前设置;原生客户端的复用键包含会话 ID 和开关值。本地 MCP、Model、Harness Main 代理和远程受管工具通道共用此入口;会话开关复用 `context_state_json`,无 schema 迁移。当前监督阶段使用共享时间线 checkpoint;候选按下文的批次项目与跨项目设置筛选。memory 继续作为背景读取,结果快照不支持 `as_of` 历史重建。
|
||||
|
||||
生产入口由 `supervision-production.ts` 组装服务、SQLite、共享池和无工具 Runtime。`supervision-review-store.ts` 保存冻结来源清单,按有界页和片段供 `SupervisorService` 派发;叶子及连续位置先提交,导航和完整结果之后发布。消息已有知识引用保留本地或外部 locator,已确认记忆通过独立背景输入提供。不会检索外部全库。详细存储、调度及当前限制统一见[分块调度第 0 节](./review-scheduling-design.md#0-生产接线与剩余边界)。
|
||||
|
||||
模型实体 `id` 只在单次输出内有效。Main 从同一 scope 的故事线提供最多 100 个未撤销实体候选,生产提示只暴露 `candidateRef`(如 `known_1`)、名称和说明。模型显式选择候选后,Main 转换为严格 UUID 类型的内部 `persistedId`。服务校验候选集成员和重复映射,保存事务再次按实体主键校验故事线归属及撤销状态。没有有效候选引用时分配新 UUID,不按名称或裸模型 ID 合并。来源仍按每次结果分配 UUID,保留原始 `source_id` 和 locator。
|
||||
模型实体 `id` 只在单次输出内有效。生产服务将批次的 `projectId` 和 `crossProject` 经 `supervisionCandidates` 传到只读 Worker,再由 `listSupervisionCandidates` 查询共享时间线。跨项目关闭时,只提供该项目当前事件关联的未撤销实体;开启时允许其他项目的实体。候选仍最多 100 个,按更新时间和 ID 排序。查询先取得项目事件关联的实体集合,再筛选候选,避免对每个实体重复扫描事件。省略批次参数的旧读取入口保留精确 scope 查询。
|
||||
|
||||
生产提示只暴露 `candidateRef`(如 `known_1`)、名称和说明。模型显式选择候选后,Main 转换为严格 UUID 类型的内部 `persistedId`。服务校验候选集成员和重复映射,保存事务再次按实体主键校验存在性及撤销状态。没有有效候选引用时分配新 UUID,不按名称或裸模型 ID 合并。来源仍按每次结果分配 UUID,保留原始 `source_id` 和 locator。
|
||||
|
||||
新实体省略 `candidateRef`,不要求模型生成数据库 ID。未知非空 `candidateRef`、冲突身份和候选集之外的 UUID 均拒绝。旧输出中的 `persistedId` 仅在 UUID 合法且属于候选集时复用;空值、占位符和格式错误值不能证明已有身份,保留为独立新实体。局部 ID 或同名不会触发合并。
|
||||
|
||||
@@ -71,6 +73,10 @@ schema 47 的四张批次相关表使用外键随监督运行清理,未完成
|
||||
|
||||
`supervision:execution` 返回进程内 `{ active, runId?, stopping? }`,配置读取期间可有 `active: true` 而尚无 runId。`supervision:cancel({ runId })` 先在既有 `supervision_runs` 写入 `cancelled`、清除错误并保存取消时间,再向父 controller 传播 abort;重复取消保留原时间。该接口等待执行 Promise 结束,包含并行批次的 `allSettled` 和 Runtime `releaseConversation`,之后才释放准入。暂停只请求 abort,执行停止后保存 `paused`;取消优先于暂停。迟到模型输出不得保存叶子、导航或完整结果,成功批次保留,自动 checkpoint 不推进。发布是同步 SQLite 事务,已完成或无变化的运行拒绝取消,不撤销已发布结果;本次无 schema 迁移。
|
||||
|
||||
发布前重读已保存批次所需候选后,再检查父 signal。此时收到暂停或取消,走原有停止分支;完整叶子和导航保留,结果及 checkpoint 尚未提交。该检查与同步保存之间没有新的异步等待。
|
||||
|
||||
故事归属和子线索拆分在既有写事务内,按主键检查模型选中的目标、父故事和跨项目功能仍为 `current`。模型等待期间若用户移除或合并目标,整批写入回滚,包含新建故事和已处理标记;重新整理使用当前候选。拆分同样检查原功能及目标子线索。已发布回顾、用户调整和此前成功批次保留,不增加版本表或恢复日志。
|
||||
|
||||
Preload 暴露类型化 `execution`、`cancel`,取消输入使用 UUID schema 并校验可信 sender。活动 UI 用实时执行状态覆盖持久记录的停止显示;工作回顾只在发起前查询执行状态,Main 仍作最终准入判断。`resume` IPC 直到运行结束才返回,Renderer 发出请求后释放提交锁并独立处理结果,确保继续中的回顾仍可暂停或取消。
|
||||
|
||||
`App` 将既有通知回调经 `HeartbeatCenter` 传给 `SupervisorWorkspace`。回顾操作用 `supervisor-review` 去重键发送本地化 Toast,结果读取失败仍写入 `loadError` 并就地重试;实体、关系操作和来源读取失败也使用通知。工作回顾不再为状态条轮询执行状态,历史读取不发送操作通知。请求锁覆盖发起前检查和整次运行;页面刷新只使旧结果选择失效,不丢弃运行结束反馈。卸载后忽略迟到响应,检查阶段尚未提交的回顾不再发起,已提交的后台运行不取消。活动查询、原始错误持久化和 Main 生命周期保持原路径。
|
||||
@@ -98,7 +104,7 @@ IPC `supervision:suggestions`、`supervision:suggestion-action`、`supervision:r
|
||||
|
||||
只有实际送入模型、通过结果校验且成功落库的完整片段推进位置。心跳报告及其进度、监督结果及其进度分别在各自 SQLite 事务提交。监督服务串行执行,后续自动请求在前次保存后重新收集。报告成功而监督失败时,下一次自动检查跳过已成功的报告输入,但重试监督输入;无变化不创建报告、来源或图谱事件。
|
||||
|
||||
已有同 scope 故事线的 scope 表示和实体 ID 保留;比较项目集合时忽略排序。模型接收最近摘要和同 scope 最多 100 个未撤销实体的候选引用、名称、说明,显式选择候选才复用,身份转换按上文执行。不同范围不合并,已有重复实体不自动修复。知识引用继续以独立来源保存 locator;当前记忆和旧摘要不作为新事件。
|
||||
已有故事线的 scope 表示和实体 ID 保留;比较项目集合时忽略排序。生产候选按上文的项目归属与跨项目设置读取,显式选择候选才复用;已有重复实体不自动修复。监督 checkpoint 的共享时间线规则见[故事线模型](./storyline-model-design.md)。知识引用继续以独立来源保存 locator;当前记忆和旧摘要不作为新事件。
|
||||
|
||||
迁移在事务中扩展心跳计划及运行表的状态 CHECK,保留列、索引、ID、计划、报告与引用;消息版本列使用默认值,无需遍历或重写旧正文。进度初始为空,首次自动运行从配置窗口开始。报告保留期限覆盖 `no_change` 运行,但不删除来源进度;删除报告不触发重新消费。
|
||||
|
||||
@@ -326,7 +332,7 @@ IPC 返回图谱查询结果时使用分页和有界字段;详情中的来源
|
||||
## 当前剩余差距
|
||||
|
||||
- 实体与关系 revoke 保存状态;界面没有 undo 或恢复入口。
|
||||
- 跨 run identity 依赖同 scope 候选 UUID 的显式引用,不自动合并历史重复实体;模型漏选候选时会创建新身份。
|
||||
- 跨 run identity 依赖候选 UUID 的显式引用,候选范围受批次项目及跨项目设置控制;不自动合并历史重复实体,模型漏选候选时会创建新身份。
|
||||
- 结果图谱使用真实事件实体连线,侧栏已按固定目标过滤并支持结果直达图谱;逐事件状态回放和 Experiment 尚未实现。
|
||||
- 用户暂停已接到排队/在途 signal,并保留已保存批次;源版本变更后的局部重算、完整模型配置冻结及其他限制见分块调度第 0 节。
|
||||
- 监督知识实体与知识库正文条目仍是不同对象,知识正文只能通过现有条目定位和预览接口处理。
|
||||
|
||||
@@ -96,6 +96,8 @@ Modal 按[共享表单 Modal 规则](../../../UI-DESIGN.md#615-表单-modal)复
|
||||
|
||||
选择历史结果后,图谱读取该结果的成员和内容,历史菜单显示其回顾区间和生成时间。切换时清空旧图谱和详情并显示加载状态,迟到请求不得替换新选择。确认、修订和移除反馈更新当前所选结果,后续自动回顾不改写旧结果。
|
||||
|
||||
切换语言或手动回顾完成引起刷新时,同时解除被替代的来源读取、实体和关系操作的等待状态。新图谱读取完成后,历史选择、刷新和详情操作恢复可用;旧请求迟到时既不显示旧内容,也不能解除后来发起的请求的等待状态。
|
||||
|
||||
手动“回顾当前进展”新建回顾,活动页“继续”恢复原 run;运行中再次发起按上文显示提示,停止清理结束后才能开始新回顾。失败保留上次结果、本次范围和成功批次;已取消回顾不能继续。手动操作不推进自动位置,删除报告也不重置自动位置。
|
||||
|
||||
## 会话侧栏
|
||||
|
||||
Reference in New Issue
Block a user