feat(tasks): define investigation report contract and history
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
# 调查报告数据契约
|
||||
|
||||
本契约适用于供水事件调查,由 Server 的 `InvestigationReportInput`(写入)和
|
||||
`InvestigationReport`(读取)定义。Agent 和前端采用同样的字段和约束。
|
||||
不增加格式版本标签;原字段的类型保持稳定。`revision` 是报告修订号,
|
||||
`execution_generation` 是调查轮次,两者均不用于选择格式解析器。
|
||||
|
||||
## 数据模型
|
||||
|
||||
| 字段 | 类型 | 新写入规则 |
|
||||
| --- | --- | --- |
|
||||
| title | 非空字符串 | 报告标题 |
|
||||
| current_conclusion | 非空字符串 | 当前判断文字;无结论时明确写无法判断,不编造原因 |
|
||||
| conclusion_boundary | 非空字符串 | 判断范围及限制 |
|
||||
| evidence_refs | 字符串数组 | 引用该任务中已持久化、不可变的证据编号 |
|
||||
| recommendations | 字符串数组 | 保持原类型,处置建议不等于已执行动作 |
|
||||
| pending_items | 字符串数组 | 保持原类型,不从文字推断状态 |
|
||||
| stage | interim / final | 必填;阶段性报告不能用于结束运行 |
|
||||
| outcome | concluded / insufficient_data | 必填;业务调查结果,与运行成功/失败独立 |
|
||||
| stop_reason | 非空字符串或 null | 证据不足时必填;已形成结论时必须为 null |
|
||||
| data_gaps | 缺口对象数组 | 必填;空数组表示已记录且没有缺口 |
|
||||
| diagram | 调查脉络对象或 null | 可选;给人阅读的 Mermaid 说明,不控制执行或任务状态 |
|
||||
|
||||
缺口对象除 node_id 外的字段必填:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --- | --- | --- |
|
||||
| gap_id | 非空字符串 | 报告内唯一的缺口编号 |
|
||||
| node_id | 非空字符串或 null | 可选的展示关联,不要求有执行计划 |
|
||||
| missing_data | 非空字符串 | 缺失数据内容 |
|
||||
| scope | 非空字符串 | 查询对象、地点及时间范围 |
|
||||
| impact | 非空字符串 | 因此无法回答的调查问题 |
|
||||
| required_data | 非空字符串 | 新一轮调查需要补齐的具体数据 |
|
||||
| evidence_refs | 至少一个证据编号 | 实际查询或可信输入记录;必须也出现在报告 evidence_refs 中 |
|
||||
| blocking | boolean | 是否阻止形成结论 |
|
||||
|
||||
禁止未知字段、未知枚举和重复 gap_id。各引用在 Server 中校验。
|
||||
查询失败、权限配置异常不能作为“没有数据”的证明。
|
||||
|
||||
调查脉络对象包含 `title`、`mermaid` 和可选的 `node_refs`(默认空数组)。
|
||||
`mermaid` 最长 20,000 字符,必须以 `flowchart` 或 `graph` 及方向开头,
|
||||
不包含 Markdown 围栏、初始化指令和 click 命令。前端使用 strict 安全级别渲染 SVG。
|
||||
完整图语法的解析失败只影响图示,正文、依据和审核仍可阅读。
|
||||
|
||||
每条 node_ref 包含 `node_id`、`label`、`evidence_refs`、`action_refs`;后两项默认空数组。
|
||||
node_id 为最多 80 字符的 ASCII 标识符,必须以字母或下划线开头,在本图引用内唯一;
|
||||
最多 100 条引用。证据必须来自报告 evidence_refs,动作必须属于当前任务。
|
||||
节点可以说明候选方向与条件关系;图中的分支、状态文字不能证明实际并发、动作执行或现场完成。
|
||||
图的颜色、字体和交互由前端统一配置。正文不包含 SVG 或 HTML。
|
||||
|
||||
## 业务约束
|
||||
|
||||
1. `concluded` 允许 interim/final,stop_reason 为 null,不允许 blocking 缺口。
|
||||
2. `insufficient_data` 只能是 final,至少一个 blocking 缺口,必须提供 stop_reason;
|
||||
recommendations 和 pending_items 必须为空,不发起补数据的工单动作。
|
||||
3. 报告必须来自当前执行轮次、会话和有效租约;执行计划与图示均可缺省。
|
||||
历史计划或未结束的解释节点不阻止发布与正常收尾。运行状态来自 Server run,
|
||||
审核和业务结果来自真实动作与回执,图示不参与计算。
|
||||
4. 尚有待审核、已批准未提交、已提交或结果未知的动作时,不能发布数据不足退出报告。
|
||||
不自动撤销已有动作,不影响独立现场处置。
|
||||
5. 数据不足报告保存后,本执行代不再接受新的报告。补齐数据应使用已有 retry 接口
|
||||
创建新 execution_generation,原报告、证据和回执保持可追溯。
|
||||
6. 事件调查提议动作前必须已保存本轮 outcome=concluded 的报告。
|
||||
顺序为阶段性结论、动作提议、最终报告、运行收尾。图示可在报告中关联动作编号。
|
||||
7. 数据不足时顺序为查询证据、最终报告、运行收尾。
|
||||
运行正常结束为 succeeded,调查生命周期为 completed;页面显示“已结束·证据不足”,
|
||||
不显示正常水质、不自动关闭原投诉工单,不等待人工授权或补数据。
|
||||
8. 数据读取范围由系统配置;本场景的人工审核只针对具体业务动作。
|
||||
既有数据访问审核接口仅保留兼容其他调用,不作为事件调查的产品入口。
|
||||
|
||||
## 历史读取与兼容
|
||||
|
||||
旧报告缺少 stage/outcome/stop_reason/data_gaps 时,Server 统一返回 null。
|
||||
null 表示未记录,不能转换成 concluded、空缺口清单或正常水质。
|
||||
前端兼容滚动发布期间的缺省/null,未知字段仍严格拒绝;一旦提供 outcome,
|
||||
其余结构化字段和业务约束必须完整满足。新写入不接受全空的历史格式。
|
||||
|
||||
历史导入脚本的 dry-run 继续校验原始记录;缺少结构化结果的历史报告不能直接发布为新调查报告,实写在创建任务前拒绝,避免按旧正文编造结果。
|
||||
|
||||
无需改写历史报告或新增数据库表,新增字段保存在原报告 document 中。
|
||||
上线顺序:先部署能读取可选新字段的前端,再协调更新 Server 新写入契约与 Agent。
|
||||
在切换写入端前应结束旧 Agent 在途运行,旧写入格式会被明确拒绝,不能静默推断结果。
|
||||
回退前须保留支持新字段的读取端;不能直接回退到会拒绝新字段的旧前端。
|
||||
|
||||
## 接口与错误
|
||||
|
||||
所有路径均以 `/api/v1` 开头,保留现有 Bearer 身份与项目范围校验。
|
||||
|
||||
| 方法与路径 | 用途 |
|
||||
| --- | --- |
|
||||
| GET /operational-tasks/{task_id} | 读取统一的报告模型,旧结构化字段返回 null |
|
||||
| GET /operational-tasks/{task_id}/reports?limit=20&offset=0 | 按修订号倒序读取历史,返回 items 与 next_offset |
|
||||
| GET /operational-tasks/{task_id}/reports/{revision} | 读取指定报告快照,任务及项目范围校验 |
|
||||
| GET /operational-tasks/{task_id}/agent-context?report_revision=1 | selected_report 是所选报告,task 保留当前真实状态;未传则 selected_report 为 null |
|
||||
| POST /operational-tasks/{task_id}/agent-artifacts | 写入报告和计划;保留 request_id 幂等、run_id 与会话归属校验 |
|
||||
| POST /operational-tasks/{task_id}/runs/{run_id}/complete | 事件调查校验本轮最终报告后结束运行;检查 expected_revision |
|
||||
| POST /operational-tasks/{task_id}/actions | 仅本轮已保存 concluded 报告的事件调查允许提议动作 |
|
||||
| POST /operational-tasks/{task_id}/retry | 创建新调查轮次,不覆盖上一轮报告 |
|
||||
|
||||
| 错误码 | HTTP | 含义 |
|
||||
| --- | --- | --- |
|
||||
| 请求体校验错误 | 422 | 新报告缺字段、未知枚举、无关键缺口或相互矛盾的字段 |
|
||||
| REPORT_GAP_EVIDENCE_INVALID | 422 | 缺口依据不在报告的证据集合内 |
|
||||
| REPORT_NOT_FOUND | 404 | 指定任务中的报告修订不存在 |
|
||||
| REPORT_ACTION_PENDING | 409 | 缺数退出仍有关联的未决动作 |
|
||||
| INVESTIGATION_ENDED | 409 | 本轮已经发布缺数退出报告,再写成果需要新轮次 |
|
||||
| ACTION_CONCLUSION_REQUIRED | 409 | 没有本轮已形成结论的报告,不得生成动作 |
|
||||
|
||||
complete 接口保留已有返回方式:不完整成果会把 run 标为 failed,
|
||||
failure_code 为 ARTIFACT_INCOMPLETE;调用方须读取返回的业务状态,不能只看 HTTP 200。
|
||||
|
||||
## 缺数报告示例
|
||||
|
||||
以下为 agent-artifacts 请求中 report 字段的完整示例。
|
||||
`sample-query-empty` 必须是同一任务内已持久化的空查询证据;示例本身不构成真实查询事实。
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "水质投诉调查报告",
|
||||
"current_conclusion": "缺少投诉时段的末梢采样,无法确定异常来源。",
|
||||
"conclusion_boundary": "已核对可用记录,本轮未确认水质异常原因。",
|
||||
"evidence_refs": ["sample-query-empty"],
|
||||
"recommendations": [],
|
||||
"pending_items": [],
|
||||
"stage": "final",
|
||||
"outcome": "insufficient_data",
|
||||
"stop_reason": "关键采样数据缺失,本轮调查结束。",
|
||||
"data_gaps": [{
|
||||
"gap_id": "terminal-sample-gap",
|
||||
"node_id": null,
|
||||
"missing_data": "投诉时段末梢水样检测结果",
|
||||
"scope": "投诉小区,2026-09-24 08:00 至 09:00(北京时间)",
|
||||
"impact": "无法判断异常来自供水管网还是用户端。",
|
||||
"required_data": "该地点和时段的采样检测记录",
|
||||
"evidence_refs": ["sample-query-empty"],
|
||||
"blocking": true
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## 验收
|
||||
|
||||
- 新写入缺字段、不一致结果、无证据的关键缺口、未知业务证据或动作引用均被拒绝。
|
||||
- 关键数据不足保存报告并正常结束;无运行失败、无待人工通知、无后续动作。
|
||||
- 阶段性报告不能冒充最终报告;旧代结论不能授权新代动作。
|
||||
- 已有未决动作阻止矛盾的缺数退出;重试幂等,不重复生成报告。
|
||||
- 新轮次保留旧报告历史标识,不能显示成当前轮次已结束。
|
||||
- 桌面及 320/375px 展示结果、缺口、证据,审批区不出现数据授权入口。
|
||||
|
||||
## 发布、阅读与协作
|
||||
|
||||
每次发布保留 `operational.report.published` 同步事件。首次 final、阶段报告转 final、
|
||||
新轮次 final 或判断/边界/依据/建议/缺口实质变化时,生成 `report_updated` 通知,
|
||||
其中 `report_reference = {execution_generation, revision}`。纯图示修订不生成额外成果提醒。
|
||||
新提醒取代同任务之前的成果提醒;读取相应报告后按用户确认已读。
|
||||
前端在调查列表显示“新报告”,这类提醒不进入“待办与告警”。
|
||||
|
||||
正在阅读的报告和图示固定在所选修订,收到更新后显示“查看新报告”,不自动替换正文。
|
||||
当前待审核动作单独读取最新真实状态,即使用户正在阅读旧报告也不会审批旧版本。
|
||||
协作请求 `task_context` 可携带 report_revision、evidence_id、gap_id;轮次和报告修订号由
|
||||
Agent 服务根据 Server 返回的快照生成 `data-task_context`,随回答流和历史消息持久化。
|
||||
该引用说明回答依据,不授予访问权限,也不成为执行约束。
|
||||
Reference in New Issue
Block a user