Accumulate investigation paths and preserve failed attempts across rounds. Keep graph annotations separate from execution state, synchronize the API contract, and consolidate documentation.
17 KiB
调查进展与实时展示
调查执行中可按需整理正文和流程参考图,Server 累计保留路径并生成 Mermaid,尚未形成结论时也能发布。 Server 将阅读进展、业务报告和浏览器展示请求分别保存。运行结束仍要求同轮最终报告, 图节点不绑定实际执行任务,标记只解释最近整理的路线、结果和限制;不参与调度、审批、等待或结束判断。 路线有实质调整、形成重要结果、需要保留失败尝试或整理报告时更新即可,不要求逐步发布、频繁刷新或及时同步。
进展快照
POST /api/v1/operational-tasks/{task_id}/agent-artifacts 新增可选 progress:
{
"request_id": "<uuid>",
"run_id": "<current-run-uuid>",
"source_session_id": "<claimed-session-id>",
"progress": {
"summary": "整理投诉时段的监测核查路线,尚未形成结论。",
"graph_update": {
"title": "调查流程参考",
"nodes": [{
"node_id": "read",
"label": "核查监测记录",
"status": "reference",
"evidence_refs": [],
"action_refs": [],
"map_targets": [{"source_id": "pipes", "feature_id": "<known-pipe-id>"}]
}],
"edges": []
}
}
}
示例中的编号由实际任务和资产替换。正文最长 20,000 字符,graph_update 可省略。
图示沿用 调查报告契约 的 Mermaid 安全限制。
节点标记可省略或为 null,均显示为参考步骤;新增量更新只接受以下五种:
| status | 显示 | 含义 |
|---|---|---|
| reference | 参考步骤 | 路线或分支说明,不断言是否执行 |
| recorded | 已有结果 | 已整理出结果或依据,不表示任务、计算或现场动作完成 |
| needs_input | 待补充条件 | 记录缺少的资料、权限或人工事实,不控制任务等待 |
| failed | 尝试失败 | 保留一次失败尝试及原因,后续路线另建节点 |
| not_taken | 未采用路线 | 未采用、不适用或改走其他分支 |
旧图读取兼容:pending/running 转为 reference,completed 转为 recorded,waiting/waiting_human 转为 needs_input,
skipped/cancelled 转为 not_taken;failed 保留。仅规范化读取结果,不改写历史文档,不再显示“正在执行”或“记录时执行中”。
REST 与 MCP 使用相同的旧标记映射。MCP 的 progress/report 图示在分页及 data_path 投影之前完成转换,
读取整份说明、节点列表或单个 status 时含义一致;实际 task/run/action 状态和旧执行计划状态保持各自语义。
map_targets 只接受 junctions/pipes/valves/pumps/tanks/reservoirs/scada 七类来源和要素编号。
图中节点引用唯一,证据和动作引用必须属于该任务。新 Agent 使用下述增量更新,节点编号在任务各轮保持稳定。
Server 不验证依赖执行顺序或推断节点完工。
progress.graph_update 包含可选 title、nodes 和 edges。节点沿用 node_id/label/status/evidence_refs/action_refs/map_targets,
可用 detail 记录实际结果或失败原因;连线为 {source,target,label?}。仅提交新增或变化的内容,
update_investigation_graph 合并节点、追加明确连线并生成 Mermaid,保留已有路径和引用。
尝试失败时标记 failed,重试或替代路线使用新节点及连线;原失败节点不能改写为成功。
仅更新正文或传入 diagram: null 均保留累计图,原始 Mermaid 不再由新 Agent 生成。
首次增量更新沿用最近保存的旧图,将原源码保存在 source_mermaid,保留原分支和形状后追加内容;
旧图内节点不得改名或重用为其他步骤。已被旧实现覆盖且未存入报告的内容无法还原。
尚未迁移的旧图仍接受旧客户端显式提交的完整图;仅更新正文或传入 diagram: null 时自动接管旧图,
保留原源码并转为累计图。任务启用累计图后拒绝旧客户端重画覆盖,不提供通过空值清图的入口。
省略 progress 保留原快照,同一个请求编号重试只发布一次。
workbench.operational_task_progress 每个任务和 run 保存最新一份快照,独立于七天事件清理。
任务详情和 Agent 上下文返回 latest_progress,包含 revision/run_id/execution_generation/
published_at/source_session_id/progress。优先返回当前执行代次;新轮次尚未发布时保留最近的累计图及其原始轮次。
get_task_context(section="progress") 同样允许读取上轮累计图以接续,摘要和图示不证明新轮次已执行。
报告发布时由 Server 存入累计图及其已有依据,历史报告保持独立快照;最多保留 100 个节点、200 条连线,超限显式报错,不静默裁剪。
快照更新发出 operational.progress.changed,前端据此读取最新内容。
旧任务图迁移
在 Server 仓库运行 python -m scripts.migrate_investigation_graphs --plan /受保护目录/plan.json --project-id <项目UUID>;
多个项目重复指定 --project-id。预览只读数据库,计划文件以私有权限保存原始进度文档和迁移后的完整文档。
核对项目、业务库、任务和图数量后,运行 python -m scripts.migrate_investigation_graphs --apply /受保护目录/plan.json。
连接使用 MetaDB 路由,计划中不保存连接凭据。迁移逐项目事务执行,与正常发布使用相同的事件锁和任务锁,
预览后仍为旧图但已发生变化的行会使该项目回滚;重复执行跳过已经接管的图。
迁移仅更新已有进度图及其 revision,保留原 summary、发布时间、run、会话、节点说明和引用;
原 Mermaid 字节保存在 source_mermaid,旧节点标记转换为参考标记,不解析或猜测原始连线。
历史报告保持原样,通过读取兼容显示新标记。迁移逐项目校验任务、run 和报告整行摘要未变,
并发出进度变更事件及写入独立执行回执;不产生报告更新通知。备份和回执不得提交到仓库。
浏览器实时联动
POST /api/v1/operational-tasks/{task_id}/presentation-events 接收
request_id/run_id/source_session_id/command,要求任务执行权限。
Server 校验当前 run、绑定会话、有效租约和幂等身份,记录 operational.presentation.requested。
响应为 recorded/event_seq/run_id/execution_generation,表示展示请求已保存,
不表示浏览器已显示或现场动作已执行。
| command.action | 参数 |
|---|---|
| locate_features | layer、feature_ids |
| zoom_to_map | center:WGS84 经度纬度、zoom:0–24 |
| highlight_features | layer、feature_ids、必填 effect:steady 或 pulse |
| clear_highlights | 无 |
| open_chart | chart_id、chart、非空 evidence_refs |
| close_chart | chart_id |
| set_overlay | overlay_id、title、mode:geometry 或 heatmap、evidence_id,可选 data |
| clear_overlay | overlay_id |
| render_scada_analysis | items:device_id 与 high/medium/low/unrated 等级,设备编号不重复 |
| clear_scada_analysis | 无 |
以上十种动作与 Chat 的 present_view、Dev JSONL 共用扁平 command: {action, ...字段}。Chat 使用 frontend-action@2 和执行回执;任务仍只记录展示请求,Dev 只做本地预览。三者使用独立的地图源、SCADA 图层和图表状态。Dev 的动作数据行必须为 {"record_type":"presentation","command":{...}};界面块行使用 record_type: ui_block,新示例明确带 phase: final。普通调查数据保持来源字段,不执行其中的 action。仓库示例见前端统一展示夹具,其中编号来自测试夹具。
图表使用普通折线 line、柱状 bar,或当前曲线加历史散点的 time_comparison,包含 title/chart_type/x_data/series。最多 100 个横轴值和 8 组有限数值序列,
序列长度与横轴对齐,引用证据必须属于当前任务。地图高亮来源沿用上述七类。
覆盖层的权威数据来自不可变证据。省略 data 时,Server 从证据快照提取现有 GeoJSON,
或使用已记录的 longitude/latitude 点位,将 FeatureCollection 加入事件中的 command.data。
若传入 data,必须与同一证据快照解析出的内容一致;Server 始终发布快照解析结果,不能用调用参数覆盖证据。
热力图只接受记录中的点,权重为有限非负数,未记录权重时取 1。
没有坐标的地址、空数据、非法几何、模型自绘区域均不能生成覆盖层。该接口不做地址解析、
范围推算或污染传播计算。展示事件总大小上限为 512 KiB,超限返回 422。
generate_node_coverage 是独立的节点空间覆盖工具,适用于普通项目聊天和后台调查,
不绑定爆管、阀门隔离或固定执行顺序。调用者提供需要比较的节点分组,Server 从当前项目
gis.node_geometries 读取真实位置。监测设备、投诉、地址等须先关联模型节点,
不接受模型自由生成的坐标。具体适用范围和参数见节点覆盖工具。
计算先投影到局部米制坐标,取凹包(默认 ratio=0.25)、加展示缓冲(默认 25 m),
再以 2 m 容差简化并转回 WGS84;凹包比例与缓冲距离可在有界参数内选择。
默认展示各组的地理包络,不判断连接关系;需要时可按模型连接拆分,额外指定视为断开的连接。
少量点、重合点和共线点同样通过缓冲形成面。多组结果一起保存在 result.map_payload,
避免连续 set_overlay 覆盖前一组;result.coverage 保存来源节点、映射完整性及算法参数。
该面不推断故障、污染、实际停水、水力影响或用户服务边界,缓冲距离也不是供水服务半径。
缺失几何时标记 partial,没有可用位置时不生成面。输入最多 8 组、合计 10000 个不同节点;
几何输出遵守覆盖层顶点和大小限制,超限要求缩小范围,不静默抽样或改变原分析结果。
MCP 保存完整查询响应作为不可变证据,展示解析器同时支持响应信封中的
data.result.map_payload。Agent 使用 set_overlay 引用本次 evidence_id 并省略 data。
超过内联返回预算时,响应的 data.presentation.command 仍保留可发布的展示命令,
data.presentation.groups 保留覆盖完整性计数,
完整几何留在证据中,不能把缩略返回误认为没有空间成果。调查按实际步骤同步发布展示:
地址得到明确坐标后缩放定位,取得候选资产后定位候选,检查影响节点后生成并展示覆盖示意,
形成或调整关阀方案后定位阀门,读取监测对照后展示点位及序列。
图表同样随结果返回发布:监测趋势与事件对照用折线图,可比候选评价或方案用柱状图,
水力及污染传播等模拟按实际返回的时刻、对象和指标画图。压力、流量、浓度等不同单位分图,
注明来源、范围与实测或模型属性;没有同口径基准时不计算或绘制改善量,缺测不补零。
过程图表通过 open_chart 提供 chart_id/chart/evidence_refs,每图最多100个横轴值、8组序列,
超限时分图或明确说明抽样、聚合范围;单值或无可比数据用文字或表格。
同指标、单位和窗口的同期复合图按对象分别发布稳定 chart_id,标题为“对象ID 共同标题”,每条序列名以“对象ID ”开头。共同标题、chart_type、轴名、x_data、当前序列去掉对象前缀后的名称与 sample_times 完全一致时,浏览器将对象数据集聚合为一个子图表:右侧按钮切换对象,下方图例控制序列;窄屏对象列表移到下方。普通趋势总览、柱状图和结构化 Chart 保持独立,不新增 objects 字段。原 chart_id 的 close_chart 只移除对应对象,关闭聚合卡片移除组内对象。
浏览器的总图表窗口统一管理过程图组与报告 Chart,子图表仍可手动独立弹窗放大。只有正在跟随的运行中任务新收到 open_chart 时可自动弹出总窗口;后续命令更新内容,不自动打开子窗口,用户关闭后不重弹。任务打开、切换、刷新、已完成任务载入、SSE 重连历史补载及历史导航只恢复数据,不弹窗。窗口意图是浏览器临时状态,不写入事件或历史快照,不新增协议字段;open_chart 的内容加载与窗口是否弹出是两个不同状态,Server 的 recorded 也不表示浏览器已经打开窗口。
time_comparison 的 x_data 使用精度一致、按窗口排列的 UTC+8 HH:mm 或 HH:mm:ss 共享槽,允许跨午夜但短于一天,不追加历史日期。series 同时包含当前 line 与历史 scatter,不混入 bar;sample_times 与 data 等长,有效值和真实带时区时间成对保留,缺测值与时间均为 null。时间转换后须与横轴槽一致,当前线使用同一窗口,每条历史序列来自同一历史日的对应窗口,不接受当天或未来日期。新任务展示与报告发布不满足这些规则时返回 TIME_COMPARISON_INVALID,旧保存内容保持结构读取。普通 line/bar 跳过同期语义,但不能将 line/scatter 复合图标为 line。
前端维护的脚本 scripts/export-view-command-contract.mjs 同步 Agent/Server 的结构协议及 tests/fixtures 下的统一 JSONL 和 chart-publication-cases.json;JSON Schema 不代替跨字段语义校验。Server 的独立测试用相同正反例校验 Pydantic 边界和 validate_time_comparison_chart;Agent 主机、原生工具及 Dev 的新图表输入也执行对应规则。
关键趋势与比较结论保留到报告中,最终报告的图表不替代过程发布。
业务 Skill 说明本步骤应展示什么,调查指令统一说明发布方法、非空几何检查、去重和失败处理。
同一阶段批量展示,数据或方案没有变化时不重复请求;不为地图动作增加无关业务分析。
报告的 map_targets 仅为手动定位入口。关键步骤的数据缺失或展示失败需记录具体限制,
没有浏览器连接也不阻止分析或报告收尾。
GET /api/v1/operational-tasks/{task_id}/presentation-cursor 在同一事务中读取
task_id/execution_generation/active_run/event_cursor,其中活跃 run 仅返回 run_id/generation/status。
浏览器打开 Dev 联动、切换任务或断线重连时,以此建立新基线,只消费之后的展示事件。
跟随开关只影响当前浏览器的临时展示,正文和图示更新始终可读,调查仍由后台继续执行。
关闭 Dev 面板不改变跟随开关。关闭跟随开关、切换任务或断线时清理临时效果,
执行结束停止执行态动效,已显示的图表与覆盖层保留供阅读。不回放历史请求,不重新执行调查。
人工反馈续调
外围同步器根据动作回执找到关联子工单。样板创建固定为 revision=1,首次创建回执不作为
新的现场反馈入队。后续版本可唤醒已结束调查,旧报告和证据保留,生成新的执行代次。
现场备注从工单 activity.kind=feedback 的记录进入反馈证据,仍标明样板合成来源。
重复请求或同一源版本重放不增加执行代次,取消调查拒绝新反馈。
同步器先送达各父调查反馈,再推进预约工单投影的源版本。定向源事件和动作回执补查保留, 处理源更新早于回执保存的情况。全量对账只为源版本变化补查已结束调查,本次不回填历史反馈。 原投诉收到新版本后同步推进其已有来源修订号。数据不足仍正常结束本轮, 只有新的可信业务输入进入后续轮次,不依赖图示节点制造人工等待。
部署与验证
新增 023 迁移 仅适用于 tjwater_v2,
增加进展表和两个事件 topic 的 CHECK 取值。2026-10-10 已在目标库完成全库备份、
迁移事务回滚演练及正式应用,其他项目和旧任务未改动。
实际 worker 曾成功投递指定调查,模型发布进展和报告,但因 service 账号的任务权限过滤
导致 approved_data_scopes 为空,误作数据不足结束。这不是业务数据确实不足。
用户确认开放规则后,任务 API 已移除该额外过滤,沿用账号已有的项目读取权限。
在线上下文返回七类来源,同一身份实际读取 SCADA 设备和外围系统工单成功;没有新增
角色权限或放宽跨项目、审批和设备控制边界。旧委托路径保留兼容,已有权限无需委托凭据。
用户级 tjwater-operational-worker.service 已重新启用。旧报告保留,未自动重新调查,
不能把旧报告视为修复后的业务验收。任务创建时间下界和并发配置见
执行 worker,未回填旧任务。
进展读接口在表尚未部署时返回空,写入口须在迁移与 Server 更新后启用。
按现有数据库发布流程应用迁移,再更新 Server、Agent 和前端,运行中的 worker 需要加载更新。
聚焦检查:
conda run -n server python -m pytest tests/unit/test_operational_tasks.py tests/unit/test_operational_presentation.py tests/unit/test_peripheral_task_sync.py tests/unit/test_peripheral_push_sync.py tests/api/test_operational_task_dynamic_flow.py tests/api/test_openapi_contract.py -q
git diff --check
这些检查覆盖隔离 HTTP 与状态机,不代替共享数据库迁移、真实模型运行或现场复测验收。