Files
Cyrene_v2/internal/db/migrations/0022_flow_graphs.up.sql
T
AskaEth a6cb44b8a8
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(flow): 链路图本地落盘 + 多轮历史回放(design/19 §P3,契约 v0.73)
主人要求「链路流程应该有本地数据,不然每次重载之后页面就没数据了」:
- 落盘:迁移 0022_flow_graphs(session_id/turn_id/graph_json/时间戳 + 唯一键 upsert)+ internal/runtime/flowgraph(RecordRound/Graph/Latest/Turns/Turn + 保留期 GC)
- 写入:loop.EndRound **每轮一条**(锁外深拷贝后写;失败 WARN 且不打印图内容);只落发布会话白名单(复用 flowSessionAllowed)
- 读回:端点加 turnId + source(live/persisted/none) + turns[](最新在前,空为 []);**内存优先、miss 才落盘**(最新一轮永远最新)
- 前端:flowGraphs 纳入 persistOptions.partialize(**刷新即刻有图**,version 3→4 + migrate)+ 历史轮选择器 + 诚实文案;顺带收 L1 转交的 flow/NodeDetail.tsx 节点日志倒序
- 新 env 键:FLOW_GRAPH_RETENTION=168h / FLOW_GRAPH_GC_INTERVAL=1h
- 变异实测:每 span 一行 / 保留期守卫失效 / partialize 去掉 flowGraphs / 去掉内存优先 / 白名单失效 ⇒ 全部打红
- 3 个禁动面文件的纯追加改动(Flow.tsx 挂选择器、FlowSnapshotHint 纠已成假话的文案、其渲染断言随之更新)由主会话裁定认可
- 登记存疑:图桶持久化无体积上限;useFlowTurns 的 effect 无自动化证据(项目无 jsdom)
2026-10-05 16:19:32 +08:00

42 lines
3.0 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 0022_flow_graphs: 链路图的**本地落盘**(design/19 §4 P3「多轮历史回放」;切片 F2)。
--
-- 动因(主人 2026-10-05 追加要求):「链路流程应该有本地数据,不然每次重载之后页面
-- 就没数据了」。F1 的只读快照(契约 v0.71)只修了「后端进程活着时刷新能看到最近一轮」;
-- 真正的本地数据要**落盘**:后端重启后仍在、能翻前几轮。
--
-- 与既有实现在语义上的分工(一句话):
-- - `loop.FlowPublisher` 的每会话内存图 = **正在跑 / 刚跑完的那一轮**(实时帧的唯一来源);
-- - 本表 = **每轮一行**的收尾存档(`EndRound` 时落),供「多轮历史回放」按 `turn_id` 取回。
-- 每轮一行、**不是每 span 一行**:span 级写放大纯属浪费,图本身在收尾时已完整。
--
-- 命名口径:表名复数、主键 id、时间戳 created_at/updated_at、索引 idx_{table}_{col}
-- (援引 AGENTS §10 已登记例外,与既有迁移一致)。时间戳沿用 0001 起的
-- `strftime('%Y-%m-%dT%H:%M:%fZ','now')`(UTC ISO-8601 毫秒),定宽 ⇒ 字典序比较
-- 等价于时间序,时间窗 GC 因此能直接吃上 idx_flow_graphs_created_at。
--
-- 写入范围只有**发布白名单内的会话**(`cmd/cyrene` 的 `flowSessionAllowed`):发布器
-- 的 `EndRound` 对白名单外的会话直接返回 ⇒ 从不调用落盘出口,本表因此与「哪些会话能
-- 产出链路图」同一判据,不存在第二份白名单。隔离渠道会话(群聊/陌生人)绝不入库。
--
-- 脱敏:`graph_json` 是 `trace.FlowGraph` 的 JSON,节点 `props`/`log` 出图前已按
-- design/19 §1.1 清洗(args 白名单 + trace.RedactText 的凭据形状清洗),label 也经
-- RedactText —— 因此本列**不会**承载原始凭据。图里可能含用户输入文本 ⇒ 日志侧一律
-- 不打印图内容(只在写入失败时记 session/turn 标识)。
CREATE TABLE IF NOT EXISTS flow_graphs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT NOT NULL, -- 归属会话(web / web:<uuid> / sess-backthink)
turn_id TEXT NOT NULL, -- 轮次标识 = trace.FlowGraph.ID("<session>-<round>")
graph_json TEXT NOT NULL, -- 该轮的整张图(trace.FlowGraph 的 JSON)
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
-- 唯一键承载 upsert(`ON CONFLICT(session_id, turn_id) DO UPDATE`):同一会话同一轮
-- 二次收尾(重放/重试)是同轮覆盖,而不是插出两行「同一轮」。
CREATE UNIQUE INDEX IF NOT EXISTS idx_flow_graphs_session_id_turn_id
ON flow_graphs (session_id, turn_id);
-- 保留期清扫(Sweep)的**唯一依赖**:按 created_at 删过期行。
CREATE INDEX IF NOT EXISTS idx_flow_graphs_created_at ON flow_graphs (created_at);