Merge authoritative main into the task branch
Why: include the current integration baseline before verification. Evidence: fetched origin/main=37b272ba0ecfaf97fe71db3947ddf1127594db8e. Impact: integrate upstream changes without rewriting task history. Refs: task-sync
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,112 @@
|
||||
# 文档驾驶舱可视化分阶段实施与验收计划 r1
|
||||
|
||||
状态:待评审;本计划描述后续执行顺序,不构成业务实施授权。真实实现、迁移、部署、模型数据和浏览器验收均为 `NOT_RUN`。
|
||||
|
||||
## 1. 目标
|
||||
|
||||
按四个可独立验证的增量,把既有 RDM 文档树/追溯读取能力提升为项目文档驾驶舱。每个增量都必须保持旧四入口可用,并且不新建写入权威或绕过授权的接口。
|
||||
|
||||
## 2. 依赖与边界
|
||||
|
||||
- 依赖既有 RDM 项目绑定、文档树、关系、事件历史和权限合同;先重新核对当前组件 pin 和接口,再实现。
|
||||
- 复用 Frontend/UI 的三栏工作台、`@ui` tokens、`Collapsible` 和现有异步状态所有者。
|
||||
- 不在本计划内修改模型路由、文档生成/审批、数据库主存储或部署配置。
|
||||
- 任何跨仓 gitlink、领域 schema、权限语义或导出行为变化都要单独建立任务和评审记录。
|
||||
|
||||
## 3. 增量分解
|
||||
|
||||
### I1:聚合读取服务和 DTO
|
||||
|
||||
**产物**:`CockpitOverview`、`TreePage`、`NodeDetail`、来源/历史/影响/冲突分页接口;适配既有 RDM 读取命令;项目/资源/字段级授权;快照 revision、cursor、截断和错误契约。
|
||||
|
||||
**直接验证**:
|
||||
|
||||
- 同一节点在不同项目请求下返回 404/拒绝,不泄露存在性。
|
||||
- 统计、树、详情和面板使用相同 `snapshotRevision`/`asOfSeq`。
|
||||
- 空、部分、受限、过期、上游失败和关系截断都有可判定 DTO。
|
||||
- 历史查询不会落在未提交批次中间序号。
|
||||
|
||||
**停止条件**:若现有领域数据无法提供某字段,返回明确 `unavailable`/`partial`,不得在服务中生成猜测值。
|
||||
|
||||
### I2:共享选择与全景投影
|
||||
|
||||
**产物**:项目统计带、文档结构树、全景中央概览、筛选和分页;共享 `selectedNodeRef`、`filterHash`、`snapshotRevision`;过期/刷新提示。
|
||||
|
||||
**直接验证**:
|
||||
|
||||
- 展开、分页、选择和筛选不会让旧响应覆盖新项目或新筛选。
|
||||
- 树徽标和统计来自同一快照;刷新不重置用户选择。
|
||||
- 无文档、无权限、部分加载和截断状态可读。
|
||||
|
||||
**停止条件**:如果真实数据没有段落级结构,使用实际可用层级并标注 structural gap,不伪造段落。
|
||||
|
||||
### I3:阅读器与右侧依据/影响面板
|
||||
|
||||
**产物**:连续正文阅读、版本摘要/差异折叠、来源/历史/影响/冲突标签页、全景↔阅读器定位、个人视图偏好。
|
||||
|
||||
**直接验证**:
|
||||
|
||||
- 从全景选择段落切换阅读器后,正文、面板和 URL/内存状态指向同一 `nodeRef`。
|
||||
- 私有来源正文按字段级披露脱敏;受限不显示为空。
|
||||
- 乱序事件、断线和后台更新不会抢占滚动位置。
|
||||
- 所有折叠、颜色、字号和动效通过设计令牌守护。
|
||||
|
||||
**停止条件**:不增加第四栏或独立关系图;关系仅在右栏局部展开。
|
||||
|
||||
### I4:组合验证与浏览器验收
|
||||
|
||||
**产物**:跨 RDM/Frontend/UI 的组合测试、权限负例、快照一致性测试、Playwright 场景和设计守护证据。
|
||||
|
||||
**最小场景集**:
|
||||
|
||||
1. 首次进入项目:统计、树、全景可见。
|
||||
2. 选中文档→章节→段落:全景与阅读器双向定位。
|
||||
3. 来源、历史、影响、冲突展开并正确显示计数/截断。
|
||||
4. 未核实来源和冲突状态改变后,所有投影一致。
|
||||
5. 过期/断线/部分失败保留旧快照并给出刷新入口。
|
||||
6. 未授权项目、节点、来源和下载均失败或脱敏。
|
||||
7. 320/390/736/1024/1440 宽度、18px UI 字号、键盘和减少动效。
|
||||
|
||||
## 4. 测试矩阵
|
||||
|
||||
| 类别 | 必测内容 | 结果来源 |
|
||||
|---|---|---|
|
||||
| DTO/服务 | schema、分页、错误、截断、快照一致性 | 单元/集成测试;最终以 CI 为准 |
|
||||
| 授权 | 项目越界、成员/职责、字段级来源披露、下载/导出 | 后端负例与独立重放 |
|
||||
| 状态 | 旧响应、乱序事件、上下文切换、断线、过期快照 | Frontend store 测试 |
|
||||
| 设计门禁 | 裸色、私有 keyframes、行内字号、`details` 禁止 | UI/Frontend design-guard |
|
||||
| 浏览器 | 双视图、定位、面板、窄屏和键盘 | Playwright;真实后端链路另记 |
|
||||
| 组合 | 固定组件 SHA、`make test`、`make build` | Dev 当前 HEAD CI/GATE |
|
||||
|
||||
## 5. 需求到验收映射
|
||||
|
||||
| 需求 | 计划增量 | 验收 |
|
||||
|---|---|---|
|
||||
| DV-R01 | I1/I2 | 项目统计与不可用原因测试 + 首屏浏览器场景 |
|
||||
| DV-R02 | I1/I2 | 树分页/展开/状态测试 |
|
||||
| DV-R03 | I2/I3 | 共享选中节点与视图切换场景 |
|
||||
| DV-R04 | I1/I3 | 四面板分页、计数、截断与定位场景 |
|
||||
| DV-R05 | I1/I2/I3 | 快照 revision、seq、旧响应丢弃测试 |
|
||||
| DV-R06 | I1/I3/I4 | 项目/字段/下载授权负例 |
|
||||
| DV-R07 | I3/I4 | 五宽度、18px、键盘、减少动效浏览器场景 |
|
||||
| DV-R08 | I1/I2/I3 | 空、部分、过期、失败和截断状态场景 |
|
||||
|
||||
## 6. 交付门禁
|
||||
|
||||
每个增量在实现前需有独立任务卡、当前基线和明确文件范围;实现单元按仓库 `AGENT-EXECUTION.md` 路由,主模型负责集成和验证。请求审核、合入和完成声明前分别执行 `make task-sync`,命令输出通过 `make evidence` 写入任务卡。作者本地测试只能标 `SELF`;精确 HEAD 的 CI 标 `GATE`,独立复跑标 `REPLAY`。
|
||||
|
||||
## 7. 契约决策(已冻结 2026-10-16)
|
||||
|
||||
用户于 2026-10-16 评审四份文档并授权进入实施(`/goal 按照方案开始实施`),本节四项取舍由本轮评审冻结。依据为实施前对 RDM 后端(独立仓 `Agent-System-RDM`,main `5df66106`)的只读源审计;后续领域数据演进时按契约 §9 版本规则扩展,不在本版内回改。
|
||||
|
||||
1. **完成度分母只统计已存在的文档/章节节点。** 现状:文档树叶节点即章节 Section(`internal/domain/doctree.go:40-51`),`Section.Require` 标记必选章节,但“模板要求而未实例化的章节”缺少已核实的权威数据源;纳入分母会引入猜测值,触碰“不得生成猜测值”停止条件。树内结构性缺失继续由 `missingChildCount` 与 `structuralGap` 承载;模板级完成度留待后续增量,且须先核对 `Doc.Template` 的实例化语义。
|
||||
2. **置信度由读模型固定为 `high/medium/low/unknown`,适配器不猜测。** 现状:领域仅有来源溯源枚举 `human|rule|model`(`internal/domain/eventlog.go:53-60`),无 confidence 数值;核验语义仅存在于法规双通道 `RegSource.Verified()`(`internal/domain/regcheck.go:13-27`)。v1 适配规则:只有可复核证据(如法规来源已核验)才产出 `high`,其余一律 `unknown`;禁止把溯源枚举直译为置信等级。
|
||||
3. **首期冲突只投影领域现有检测视图,不做字段级断言。** 现状:无持久化冲突实体;冲突是 `fc.Detector` 对切片对的运行时碰撞检测(`internal/domain/fc/collide.go:27-53`),裁决落为 `supersedes` 追溯边并关闭成对 pending 项(`collide.go:125-145`)。v1 映射:pending 碰撞 → `open`;存在 supersedes 裁决 → `resolved`/`superseded`(按实际边语义);`acknowledged` 首期不产生。字段级断言冲突须等领域先有字段级断言登记,属后续领域增量。
|
||||
4. **全景首屏只显示章节概览与统计,不显示段落摘要。** 现状:文档树只有 doc→section 两级,无段落层(`internal/domain/domain.go:23-35`);且首屏共享面上的正文摘要在无逐字段披露检查时会扩大敏感内容暴露。段落/正文摘要在选中节点与阅读器内按权限展示。
|
||||
|
||||
I1 的公开 DTO 实现自本节冻结起解锁;实施落点为 RDM 后端仓(聚合读取服务与命令),Dev 仓只承载文档、组合 pin 与后续前端集成。
|
||||
|
||||
## 8. 当前状态与下一步
|
||||
|
||||
四份文档已于 2026-10-16 评审通过,§7 四项决策冻结,实施授权已由用户给出(`/goal 按照方案开始实施`)。I1–I4、测试、CI、部署和业务验收仍为 `NOT_RUN`。下一步:合入本设计 PR 后,在 RDM 后端仓为 I1(聚合读取服务与 DTO)建立实施任务并按 AGENT-EXECUTION.md 拆分派发;I1 适配目标为 `rdm.inspect.*` 既有事实与 §7 冻结的映射规则。
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
# 项目文档可视化驾驶舱设计规格 r1
|
||||
|
||||
状态:待评审;本文件只冻结设计,不授权业务代码、数据库迁移、部署或运行验收。
|
||||
|
||||
## 1. 目标与背景
|
||||
|
||||
当前 RDM 已有项目级“笔记树 / 文档树 / 追溯 / 操作记录”读取入口,`RdmAuditWorkspace` 可以按树节点加载详情和关系。但这些入口仍以逐项查询为主,不能在进入项目后回答“项目文档完成到哪里、哪里缺内容、哪些来源未核实、哪些地方冲突、最近发生了什么”。本次目标是为文档内容建立一个项目级可视化驾驶舱:它是文档工作的聚合读取和审阅界面,不是目录列表,也不是另一个文档编辑器。
|
||||
|
||||
设计基线来自已确认的方向:
|
||||
|
||||
- 默认进入结构全景;全景和阅读器共享同一项目上下文、筛选条件和选中节点。
|
||||
- 结构全景用于整体关系、完成度、风险和影响面;文档阅读器用于连续阅读和审阅正文。
|
||||
- 两种视图消费同一个服务器权威聚合快照,不各自拼接一套状态。
|
||||
- 个人视图偏好只决定恢复哪种视图,不扩大项目或文档权限。
|
||||
- 思维导图式关系画布是后续模式,不作为第一期主界面;第一期仍采用可扫描的结构树和局部关系展开。
|
||||
|
||||
## 2. 用户与成功标准
|
||||
|
||||
主要用户是项目成员、文档作者、审阅者和项目管理员。用户进入项目后的前 10 秒内应能判断:
|
||||
|
||||
1. 项目有哪些受控文档及其完成度。
|
||||
2. 哪些章节/段落为空、待确认、来源不足或存在冲突。
|
||||
3. 最近哪些内容被谁修改,以及修改是否已核实。
|
||||
4. 选中一个节点后,正文、来源、历史和影响对象是否可在同一屏继续阅读。
|
||||
|
||||
成功标准不是“显示更多信息”,而是减少用户在多个列表、弹窗和导出报告之间来回拼接上下文的次数。默认层只显示结论和下一步,原始来源、差异和工具记录按需展开。
|
||||
|
||||
## 3. 范围与非目标
|
||||
|
||||
### 3.1 本次范围
|
||||
|
||||
- 项目级文档聚合读取模型(Document Cockpit Read Model)。
|
||||
- 文档→章节→小节→段落的结构树,带状态徽标和更新时间。
|
||||
- 结构全景与文档阅读器两种视图,以及两者之间的定位跳转。
|
||||
- 内容来源、核实状态、置信度、冲突、影响关系和历史摘要的统一展示。
|
||||
- 按来源类型、状态、负责人、风险和最近更新的筛选。
|
||||
- 个人视图/密度/展开状态的恢复;权限仍由服务器按项目和资源判定。
|
||||
- 空数据、部分数据、过期快照、无权限和读取失败的诚实展示。
|
||||
|
||||
### 3.2 非目标
|
||||
|
||||
- 本阶段不增加文档生成、提交、审签、审批或导出动作。
|
||||
- 不替换现有 RDM 事件日志、关系存储、文档正文存储或权限系统。
|
||||
- 不把私人对话、上传原件或个人草稿直接公开到项目驾驶舱。
|
||||
- 不引入第三种主布局、独立“后台任务页”或全局关系图。
|
||||
- 不声称真实模型、真实浏览器、部署或运行环境已经验收。
|
||||
|
||||
## 4. 设计原则
|
||||
|
||||
1. **结论先行。** 顶部统计和节点摘要先给可行动结论;原始命令、内部 ID、隐藏推理和长日志默认不占据阅读层。
|
||||
2. **一份事实,多种投影。** 全景、阅读器、右侧依据面板都来自同一快照和同一 `snapshotRevision`。
|
||||
3. **来源可追溯但不越权。** 展示来源类型、摘要、验证状态和可见定位;私人原文依权限字段级隐藏。
|
||||
4. **不把未知显示成成功。** 未读取、被截断、冲突未决和权限过滤都必须有明确状态。
|
||||
5. **渐进式密度。** 紧凑总览适合扫描,完整内容适合审阅;展开使用现有 `@ui` `Collapsible` 原语。
|
||||
6. **视觉克制。** 遵守 `DESIGN.md` 和 `@ui/tokens.css`:灰白层级、单色主操作、清晰留白、语义色只表达语义,不自造颜色或动效。
|
||||
|
||||
## 5. 总体架构
|
||||
|
||||
```text
|
||||
RDM 文档/章节/段落存储
|
||||
RDM 来源与关系存储
|
||||
RDM 原子事件与历史
|
||||
RDM 项目/成员/职责授权
|
||||
|
|
||||
v
|
||||
Document Cockpit Read Service
|
||||
- scope + authorization
|
||||
- node aggregation
|
||||
- source normalization
|
||||
- completeness/conflict/impact projection
|
||||
- snapshot revision + truncation
|
||||
|
|
||||
+--> cockpit overview snapshot
|
||||
+--> tree page / node detail
|
||||
+--> source/history/impact panels
|
||||
+--> local refresh / event invalidation
|
||||
|
|
||||
v
|
||||
Frontend cockpit shell
|
||||
- overview header
|
||||
- panorama view
|
||||
- reader view
|
||||
- shared selection/filter state
|
||||
```
|
||||
|
||||
读取服务只聚合已有领域事实。它可以建立可重建的读模型或查询投影,但不成为新的写入权威。任何写入(正文、来源核实、冲突裁定、职责变更)仍走现有领域命令和权限检查,并通过事件使读模型失效或刷新。
|
||||
|
||||
## 6. 核心对象
|
||||
|
||||
### 6.1 文档节点
|
||||
|
||||
节点层级固定为 `document -> section -> subsection -> paragraph`。若现有数据缺少某一层,读取服务返回实际层级和 `structuralGap`,前端不虚构空节点。每个节点至少有:
|
||||
|
||||
- 稳定引用:`projectId`、`nodeRef {kind,id,version}`;UI 不显示内部 ID。
|
||||
- 可读标题、路径、父节点和子节点计数。
|
||||
- `contentState`: `complete | partial | empty | inaccessible | unavailable`。
|
||||
- `verificationState`: `verified | mixed | unverified | disputed | not_applicable`。
|
||||
- `sourceCount`、`conflictCount`、`impactCount`、`missingChildCount`。
|
||||
- `lastChangedAt`、`lastChangedBy`、`contentRevision`。
|
||||
- `visibility`: `full | redacted | metadata_only`。
|
||||
|
||||
### 6.2 来源
|
||||
|
||||
来源类型统一为 `conversation | file | web | tool | agent | human | derived`。来源记录包含来源摘要、采集时间、核实人/时间、置信度、定位信息和可见性;不能展示的私人原文只返回 `redactedReason` 和可审计的元数据。
|
||||
|
||||
### 6.3 冲突
|
||||
|
||||
冲突不是简单的“有两个来源”。只有当两个可见断言对同一节点/字段在同一有效范围内给出不兼容结论时才生成 `conflict`。记录冲突两侧的来源引用、差异摘要、发现时间、当前状态(`open | acknowledged | resolved | superseded`)和裁定依据引用。
|
||||
|
||||
### 6.4 影响对象
|
||||
|
||||
影响对象可为 `requirement | document | section | risk | task | trace_link`。关系带方向、类型、强度、状态和来源。默认只显示一跳;继续展开必须明确请求深度和上限,并返回 `truncated`。
|
||||
|
||||
## 7. 视图职责
|
||||
|
||||
### 7.1 结构全景
|
||||
|
||||
默认入口。左侧显示可展开结构树;中央显示当前项目或选中文档的章节概览、完成度和异常分布;右侧显示选中节点的来源、历史、影响和冲突。全景不把长正文铺满画布,而是显示摘要和可定位的内容片段。
|
||||
|
||||
### 7.2 文档阅读器
|
||||
|
||||
用于连续阅读。左侧目录保持当前位置;中央按章节渲染正文、段落状态和版本差异;右侧沿用同一个依据与影响面板。选中段落时,全景和阅读器的 `selectedNodeRef` 同步;切换视图后保留滚动锚点、筛选条件和权限范围。
|
||||
|
||||
### 7.3 个人偏好
|
||||
|
||||
只保存 `lastView`、`density`、`expandedNodeRefs`、`rightPanelTab` 和阅读锚点。偏好按用户和项目隔离,服务端不得把偏好当作授权依据。新用户默认 `panorama + compact`;进入项目后恢复最近一次视图。
|
||||
|
||||
## 8. 一致性与刷新
|
||||
|
||||
- 每次读取返回 `snapshotRevision`、`asOfSeq`、`generatedAt` 和各自的 `truncated` 标志。
|
||||
- 页面内异步请求必须绑定 `projectId`、筛选哈希、`snapshotRevision` 和请求代次;旧响应不得覆盖新上下文。
|
||||
- 领域事件到达时只使受影响节点和统计失效,不自动改变用户正在阅读的滚动位置;显示“有更新”提示,由用户刷新或在安全点合并。
|
||||
- 历史读取只能落在已提交操作批次的结束序号;落在批次中间时服务端拒绝或规范化到批次末尾。
|
||||
- 聚合失败时保留上一个可识别快照并显示其时间和过期状态,不把缓存当成当前事实。
|
||||
|
||||
## 9. 权限与隐私
|
||||
|
||||
服务端以项目为隔离根执行:项目访问、文档可见性、职责/资源 ACL 和字段级披露共同决定返回内容。客户端隐藏入口不构成授权。私人对话、上传原件和个人草稿默认不进入共享摘要;若某个受控文档引用了它们,只返回经授权的来源摘要和稳定定位。管理员能力不自动等同于作者、审阅者或批准者能力。
|
||||
|
||||
## 10. 分期边界
|
||||
|
||||
- V1:聚合快照、双视图、来源/历史/影响/冲突只读展示、筛选、权限和刷新一致性。
|
||||
- V1.1:局部关系展开、版本对照、来源核实入口(复用已有命令,另行授权)。
|
||||
- 后续:关系画布、批量审阅、文档导出和更多领域插件。
|
||||
|
||||
## 11. 需求与验收 ID
|
||||
|
||||
| ID | 要求 | 验收判定 |
|
||||
|---|---|---|
|
||||
| DV-R01 | 首屏显示项目级完成度、缺项、冲突、未核实来源、待确认变更和最近更新 | 有真实快照时六项均可定位;缺数据时显示原因而非 0 值冒充 |
|
||||
| DV-R02 | 结构树覆盖实际文档层级并显示节点状态 | 展开、选择、分页和空子节点均可用;不泄漏内部 ID |
|
||||
| DV-R03 | 全景和阅读器共享选中节点、筛选和项目 | 双向切换后定位同一 `nodeRef` 和章节锚点 |
|
||||
| DV-R04 | 来源、历史、影响、冲突可从选中节点继续展开 | 每个面板显示计数、权限状态、来源时间和截断状态 |
|
||||
| DV-R05 | 快照具有可核验一致性 | 旧响应、乱序事件和历史中间序号不会覆盖当前状态 |
|
||||
| DV-R06 | 私有数据和字段级披露受服务端授权保护 | 未授权读取返回拒绝/脱敏;客户端绕过入口不能得到原文 |
|
||||
| DV-R07 | 窄屏、键盘、大字和减少动效可用 | 320/390/736/1024/1440 宽度无横向溢出,核心操作不依赖隐藏面板 |
|
||||
| DV-R08 | 诚实处理过期、部分、冲突和失败 | UI 不生成虚假百分比、ETA、来源核实或完成结论 |
|
||||
|
||||
## 12. 当前状态
|
||||
|
||||
本设计基于 Dev `9edb011e63ab9bf104360379e52c30075bd2f344` 的源代码和既有规划进行整理。设计文档、实现、业务测试、真实浏览器验收、CI、部署和生产数据验证均不在本文件中宣称完成。
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
# 文档驾驶舱聚合读取模型与接口契约 r1
|
||||
|
||||
状态:待评审;只定义读取契约,不授权实现或迁移。
|
||||
|
||||
## 1. 契约定位
|
||||
|
||||
本契约把 RDM 已有树、正文、来源、关系和事件事实投影成一个面向 UI 的只读模型。它不替代 RDM 领域实体,也不允许前端根据多个旧接口自行拼装出第二套事实。所有接口都必须带项目上下文并在服务端完成授权。
|
||||
|
||||
## 2. 公共约定
|
||||
|
||||
```ts
|
||||
type NodeKind = 'document' | 'section' | 'subsection' | 'paragraph'
|
||||
type NodeRef = { kind: NodeKind; id: string; version?: string }
|
||||
type ViewMode = 'panorama' | 'reader'
|
||||
type Density = 'compact' | 'full'
|
||||
type SourceKind = 'conversation' | 'file' | 'web' | 'tool' | 'agent' | 'human' | 'derived'
|
||||
type ContentState = 'complete' | 'partial' | 'empty' | 'inaccessible' | 'unavailable'
|
||||
type VerificationState = 'verified' | 'mixed' | 'unverified' | 'disputed' | 'not_applicable'
|
||||
|
||||
interface SnapshotMeta {
|
||||
schemaVersion: 'document-cockpit.v1'
|
||||
projectId: string
|
||||
snapshotRevision: string
|
||||
asOfSeq: number
|
||||
generatedAt: string
|
||||
expiresAt?: string
|
||||
truncated: boolean
|
||||
truncationReasons: string[]
|
||||
}
|
||||
|
||||
interface TreePage {
|
||||
meta: SnapshotMeta
|
||||
items: TreeNode[]
|
||||
nextCursor?: string
|
||||
hasMore: boolean
|
||||
}
|
||||
```
|
||||
|
||||
`projectId` 是服务端解析后的项目定位,不是授权令牌。客户端提交的节点 ID、来源 ID 和 cursor 必须在同一项目范围重新解析。
|
||||
|
||||
## 3. 读取资源
|
||||
|
||||
### 3.1 项目概览
|
||||
|
||||
`GET /api/rdm/projects/{projectId}/document-cockpit/overview`
|
||||
|
||||
返回项目统计、最近变化和顶层文档节点。统计字段必须区分“确实为 0”和“无法计算”:
|
||||
|
||||
```ts
|
||||
interface CockpitOverview {
|
||||
meta: SnapshotMeta
|
||||
project: { title: string; visibility: 'member' | 'restricted' }
|
||||
stats: {
|
||||
documentCount: number | null
|
||||
completion: { known: number; total: number; state: 'known' | 'partial' | 'unavailable' }
|
||||
emptyNodeCount: number | null
|
||||
unverifiedSourceCount: number | null
|
||||
conflictCount: number | null
|
||||
pendingChangeCount: number | null
|
||||
updatedAt?: string
|
||||
// 任一统计为 null 时,必须在本表给出该字段名的 unavailableReason
|
||||
// (如 forbidden_source / projection_lag / upstream_error),见 §6。
|
||||
statReasons: Record<string, string>
|
||||
}
|
||||
documents: TreeNode[]
|
||||
recentChanges: ChangeSummary[]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 树分页
|
||||
|
||||
`GET /api/rdm/projects/{projectId}/document-cockpit/tree?parent=&cursor=&limit=&filter=`
|
||||
|
||||
返回 `TreePage { meta, items: TreeNode[], nextCursor?, hasMore }`。服务端排序稳定为“文档顺序 / 章节顺序 / 最近更新时间”,不得按数据库内部 ID 作为用户可见排序。`filter` 是服务端解析后的来源、状态、负责人、风险和时间条件,未知过滤值拒绝而不是忽略。
|
||||
|
||||
```ts
|
||||
interface TreeNode {
|
||||
ref: NodeRef
|
||||
title: string
|
||||
path: string[]
|
||||
parent?: NodeRef
|
||||
childCount: number
|
||||
state: {
|
||||
content: ContentState
|
||||
verification: VerificationState
|
||||
sourceCount: number
|
||||
conflictCount: number
|
||||
impactCount: number
|
||||
missingChildCount: number
|
||||
// 现有层级不足以表达契约层级时为 true(v1:文档树只有 document -> section,
|
||||
// 章节即叶节点;subsection/paragraph 枚举值保留给后续层级扩展)。
|
||||
structuralGap: boolean
|
||||
}
|
||||
lastChangedAt?: string
|
||||
lastChangedBy?: ActorSummary
|
||||
visibility: 'full' | 'redacted' | 'metadata_only'
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 节点详情
|
||||
|
||||
`GET /api/rdm/projects/{projectId}/document-cockpit/nodes/{kind}/{id}?version=`
|
||||
|
||||
返回正文和面板摘要。正文必须区分 `contentState` 与 `body` 缺失;被权限过滤不能返回空字符串冒充空内容。
|
||||
|
||||
```ts
|
||||
interface NodeDetail {
|
||||
meta: SnapshotMeta
|
||||
node: TreeNode
|
||||
body?: ContentBlock[]
|
||||
parent?: NodeRef
|
||||
children: TreeNode[]
|
||||
sources: SourceSummaryPage
|
||||
history: HistorySummaryPage
|
||||
impacts: ImpactPage
|
||||
conflicts: ConflictPage
|
||||
availableActions: string[]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 面板分页
|
||||
|
||||
- `GET .../nodes/{kind}/{id}/sources`
|
||||
- `GET .../nodes/{kind}/{id}/history`
|
||||
- `GET .../nodes/{kind}/{id}/impacts?depth=1&cursor=`
|
||||
- `GET .../nodes/{kind}/{id}/conflicts`
|
||||
|
||||
每个分页资源返回同一 `SnapshotMeta`、`items`、`nextCursor`、`hasMore`、`truncated` 和 `redactions`。关系查询默认 `depth=1`、带服务端上限;超过上限只能返回明确的 `truncated=true`。
|
||||
|
||||
## 4. 内容与来源字段
|
||||
|
||||
```ts
|
||||
interface SourceSummary {
|
||||
ref: { kind: SourceKind; id: string }
|
||||
label: string
|
||||
excerpt?: string
|
||||
locator?: { conversationId?: string; filePath?: string; url?: string; toolName?: string }
|
||||
capturedAt?: string
|
||||
verifiedAt?: string
|
||||
verifiedBy?: ActorSummary
|
||||
confidence: 'high' | 'medium' | 'low' | 'unknown'
|
||||
verification: VerificationState
|
||||
visibility: 'full' | 'redacted' | 'metadata_only'
|
||||
redactedReason?: 'private' | 'forbidden' | 'expired' | 'not_loaded'
|
||||
}
|
||||
```
|
||||
|
||||
来源摘要不是来源原文缓存。`excerpt` 只有在当前用户拥有对应字段披露权限时返回;否则只返回标签、类型、时间和 `redactedReason`。
|
||||
|
||||
## 5. 变化与冲突
|
||||
|
||||
```ts
|
||||
interface ChangeSummary {
|
||||
node: NodeRef
|
||||
title: string
|
||||
changedAt: string
|
||||
actor?: ActorSummary
|
||||
kind: 'created' | 'content_changed' | 'source_added' | 'verification_changed' | 'conflict_opened' | 'conflict_resolved'
|
||||
summary: string
|
||||
version?: string
|
||||
}
|
||||
|
||||
interface AssertionSummary {
|
||||
node: NodeRef
|
||||
claim: string
|
||||
sourceRef?: { kind: SourceKind; id: string }
|
||||
visibility: 'full' | 'redacted' | 'metadata_only'
|
||||
redactedReason?: 'private' | 'forbidden' | 'expired' | 'not_loaded'
|
||||
}
|
||||
|
||||
interface ConflictSummary {
|
||||
id: string
|
||||
node: NodeRef
|
||||
state: 'open' | 'acknowledged' | 'resolved' | 'superseded'
|
||||
left: AssertionSummary
|
||||
right: AssertionSummary
|
||||
detectedAt: string
|
||||
resolvedAt?: string
|
||||
resolutionRef?: string
|
||||
}
|
||||
```
|
||||
|
||||
v1 冲突投影(冻结于实施计划 §7.3):领域无持久化冲突实体,适配器只转换现有碰撞检测视图与 `supersedes` 裁决边;`acknowledged` 首期不产生,一侧受限时对应 `AssertionSummary` 降为 `redacted` 并给出 `redactedReason`。
|
||||
|
||||
历史查询和导出只能使用已提交批次结束序号。读服务不得把正在写入的中间事件投影为“最近变化”。
|
||||
|
||||
## 6. 筛选、排序和缓存
|
||||
|
||||
- 筛选表达式必须序列化为稳定哈希 `filterHash`,并回显在响应中,防止旧筛选响应覆盖当前结果。
|
||||
- `ETag`/`If-None-Match` 可用于只读缓存,但缓存键必须包含用户可见范围、项目、筛选、版本和字段披露策略。
|
||||
- 允许短时缓存统计和树页;正文、来源和权限变化后必须以事件或 TTL 失效。缓存命中返回 `generatedAt` 和 `expiresAt`。
|
||||
- 任何 `null` 统计都必须伴随 `unavailableReason`,例如 `forbidden_source`、`projection_lag` 或 `upstream_error`。
|
||||
|
||||
## 7. 错误契约
|
||||
|
||||
| 场景 | HTTP/状态 | UI 处理 |
|
||||
|---|---|---|
|
||||
| 项目不存在或不可见 | 404(不泄露存在性) | 显示项目不可访问,不重试节点请求 |
|
||||
| 节点属于其他项目 | 404 | 丢弃本地选择并刷新项目快照 |
|
||||
| 权限允许元数据但禁止正文 | 200 + `metadata_only` | 显示标题/状态,正文和原文标为受限 |
|
||||
| 快照过期 | 200 + `expired=true` 或 409 | 保留旧内容,显示刷新入口,不静默当当前事实 |
|
||||
| cursor/过滤器非法 | 400 | 显示可理解的筛选错误,保留上一次有效筛选 |
|
||||
| 上游读取失败 | 503/领域错误码 | 显示局部不可用和重试;不清空其他成功面板 |
|
||||
| 关系超限 | 200 + `truncated=true` | 显示已截断及继续展开的明确上限 |
|
||||
|
||||
## 8. 事件与前端状态
|
||||
|
||||
读模型可以通过现有项目事件/SSE 通知失效,事件只携带受影响 `projectId`、`nodeRef`、`seq` 和 `reason`。前端维护一个异步所有者:
|
||||
|
||||
- `contextKey = projectId + filterHash + selectedNodeRef + viewMode`。
|
||||
- 每次请求拥有 `requestGeneration`;响应不匹配当前 generation 或 contextKey 时丢弃。
|
||||
- 每个事件流按 `seq` 严格递增应用;旧事件丢弃,缺口触发只读重拉而不是猜测中间状态。
|
||||
- 任何视图只读取同一快照缓存,不自行维护正文、统计或权限的第二份副本。
|
||||
|
||||
## 9. 版本兼容
|
||||
|
||||
响应顶层带 `schemaVersion`。新增字段向后兼容;状态枚举扩展必须先让旧客户端落入 `unknown` 安全分支。删除字段或改变字段语义必须提升版本并经过组合验证。契约初版不要求迁移旧 RDM 存储,读取服务通过适配器把既有 `rdm.inspect.tree/object/relations/events/history` 事实映射到新 DTO。
|
||||
|
||||
## 10. 安全验收
|
||||
|
||||
- 同一节点 ID 换项目提交时不得返回另一项目数据。
|
||||
- 仅有项目管理权而无正文/来源职责时,不得获得被保护原文。
|
||||
- `metadata_only`、`redacted` 和 `inaccessible` 三种状态在接口和 UI 中可区分。
|
||||
- 历史序号位于未提交批次时不得读取半个操作。
|
||||
- 导出、下载和关系展开沿用相同 scope/ACL 检查;本契约不新增绕过入口。
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# 文档驾驶舱双视图交互规格 r1
|
||||
|
||||
状态:待评审;这是界面与交互规格,不是实现稿。
|
||||
|
||||
## 1. 信息架构
|
||||
|
||||
```text
|
||||
项目文档驾驶舱
|
||||
├── 顶部:项目名 / 视图切换 / 密度 / 全局筛选 / 刷新状态
|
||||
├── 项目统计带:完成度、空缺、未核实、冲突、待确认、最近更新
|
||||
├── 左栏:文档结构树(文档→章节→小节→段落)
|
||||
├── 中栏:
|
||||
│ ├── 全景:项目/文档概览、章节状态、关系摘要
|
||||
│ └── 阅读器:目录定位、正文、段落状态和版本变化
|
||||
└── 右栏:依据、历史、影响、冲突(同一选中节点)
|
||||
```
|
||||
|
||||
不新增第四栏。窄屏时三栏变为同一工作区内的单栏导航:树、内容、依据面板依次进入,始终提供明确返回按钮和当前节点标题。
|
||||
|
||||
## 2. 顶部统计带
|
||||
|
||||
统计卡只展示数值和一句解释,不做装饰性大卡片。每个统计项可点击,点击后只改变共享筛选:
|
||||
|
||||
- 完成度:已知完成节点 / 已知节点;数据不足时显示“部分计算”。
|
||||
- 空缺段落:内容为空或结构缺失的叶节点。
|
||||
- 未核实来源:有来源但验证状态不是 `verified` 的节点数。
|
||||
- 冲突:开放或待裁定冲突数。
|
||||
- 待确认变更:最近变化中需要人工确认的变更数。
|
||||
- 最近更新:最近一次可见变更时间和操作者。
|
||||
|
||||
点击统计不得直接执行写入或裁定;它只定位待处理内容。
|
||||
|
||||
## 3. 左侧结构树
|
||||
|
||||
### 默认显示
|
||||
|
||||
每行显示标题、层级缩进、内容状态、来源数、冲突/待确认徽标和最近更新时间。内部 ID、数据库类型名和技术状态码不显示。文档节点可以展开,章节和段落按需加载;加载失败只影响当前分支并保留重试。
|
||||
|
||||
### 交互
|
||||
|
||||
- 单击节点:更新共享 `selectedNodeRef`,中央和右侧同步加载。
|
||||
- 展开箭头:只加载子节点,不改变选中内容。
|
||||
- 键盘:方向键移动,Enter 选择,Space 展开,左/右折叠/展开。
|
||||
- 搜索:按标题、路径和可见摘要检索;搜索结果仍受项目权限和当前筛选约束。
|
||||
- 状态徽标:可作为筛选入口,但不隐藏结构树的其他节点。
|
||||
|
||||
## 4. 结构全景
|
||||
|
||||
### 中央内容
|
||||
|
||||
未选中节点时显示项目/文档概览:文档列表、章节完成度条、缺项摘要、最近变化和风险分布。选中节点时显示:
|
||||
|
||||
1. 节点标题和路径。
|
||||
2. 一句话状态总结(内容、验证、冲突、影响)。
|
||||
3. 当前可见正文摘要或章节概览。
|
||||
4. 子节点状态表,可按缺项/冲突/负责人排序。
|
||||
5. “在阅读器中打开”按钮,带同一 `nodeRef` 和阅读锚点。
|
||||
|
||||
### 关系摘要
|
||||
|
||||
只在选中节点附近显示来源数量、影响对象数量和冲突数量;关系详情在右栏展开。大规模网络图不是默认内容。
|
||||
|
||||
## 5. 文档阅读器
|
||||
|
||||
### 中央内容
|
||||
|
||||
阅读器按章节连续渲染正文,段落之间显示轻量状态线:来源类型、验证状态、最近修改人/时间和冲突标记。版本变化默认以“当前版本 + 前一版本摘要”呈现,完整差异使用 `Collapsible` 展开。被权限过滤的段落显示“内容受限”,而不是空白。
|
||||
|
||||
### 阅读行为
|
||||
|
||||
- 从全景进入阅读器时定位到选中节点并保留章节滚动锚点。
|
||||
- 从对话卡片或来源跳转时,若目标是关系解释,进入全景;若目标是交付正文,进入阅读器。
|
||||
- 切换筛选后保留选中节点;若节点被筛掉,显示“当前节点不在筛选范围”并提供清除筛选。
|
||||
- 后台更新不抢占滚动位置;仅在标题旁显示“内容已更新”,用户选择刷新。
|
||||
|
||||
## 6. 右侧依据与影响面板
|
||||
|
||||
右侧使用四个标签,默认打开“内容来源”。每个标签显示数量和状态,详情按需展开。
|
||||
|
||||
### 内容来源
|
||||
|
||||
显示来源类型图标/文字、摘要、采集时间、核实状态、置信度和可见定位。私人来源只显示脱敏元数据;不展示隐藏原文或内部提示词。
|
||||
|
||||
### 修改历史
|
||||
|
||||
以自然语言时间线显示创建、正文修改、来源变化、验证变化和冲突状态变化。每条记录显示操作者、时间、版本和差异摘要;完整 diff 折叠。
|
||||
|
||||
### 影响对象
|
||||
|
||||
显示受影响要求、文档、风险、任务和追溯关系。默认一跳,显示关系类型、方向、状态和置信度;继续展开前提示数量上限。
|
||||
|
||||
### 冲突与风险
|
||||
|
||||
显示冲突双方摘要、各自来源、发现时间和当前裁定状态。没有权限看到一侧原文时仍显示“另一侧受限”,不把冲突误判成单方事实。
|
||||
|
||||
## 7. 状态与空态
|
||||
|
||||
| 状态 | 文案方向 | 禁止行为 |
|
||||
|---|---|---|
|
||||
| 加载中 | 加载项目文档概览 / 加载依据 | 不显示虚假的 0 统计 |
|
||||
| 空项目 | 暂无受控文档 | 不显示导入或生成按钮,除非另有已批准入口 |
|
||||
| 部分加载 | 已显示已读取内容,部分依据暂不可用 | 不把部分数据标为完整 |
|
||||
| 受限 | 你可以看到节点状态,但正文受权限限制 | 不泄露原文存在性以外的私密信息 |
|
||||
| 过期 | 内容来自某时间的快照,刷新以获取最新状态 | 不静默自动改写用户正在阅读的正文 |
|
||||
| 失败 | 该面板暂时不可用,可重试 | 不清空其它已成功面板 |
|
||||
| 截断 | 已显示前 N 条,继续展开有上限 | 不假装显示全部关系 |
|
||||
|
||||
## 8. 视觉与可访问性门禁
|
||||
|
||||
- 颜色、圆角、字号只消费 `@ui/tokens.css`;字号使用 `--fs-ui-*`。
|
||||
- 折叠只使用 `@ui` `Collapsible`,动效只使用 `@ui/motion.css` 的 `mk-*` 类。
|
||||
- 主操作采用单色反色按钮;状态色只表达成功、警告、错误、等待和差异语义。
|
||||
- 320/390/736/1024/1440 宽度下不横向溢出;18px UI 字号下标题、按钮和徽标不重叠。
|
||||
- 所有图标按钮有可访问名称;树节点和标签页有键盘焦点;减少动效时只保留状态变化。
|
||||
- 不把三栏做成互相嵌套的卡片墙;页面区域使用无框布局,重复来源/变化项才使用轻量条目容器。
|
||||
|
||||
## 9. 视图切换规则
|
||||
|
||||
| 触发来源 | 默认视图 | 定位 |
|
||||
|---|---|---|
|
||||
| 第一次进入项目 | 结构全景 | 项目根节点 |
|
||||
| 用户上次有偏好 | 上次视图 | 上次项目/节点锚点(仍需重新授权) |
|
||||
| 对话解释关系 | 结构全景 | 目标关系节点 |
|
||||
| 对话交付正文 | 文档阅读器 | 目标章节/段落 |
|
||||
| 来源或冲突跳转 | 当前视图保持 | 选中节点 + 右栏对应标签 |
|
||||
| 节点无正文但有关系 | 结构全景 | 节点摘要和影响面板 |
|
||||
|
||||
## 10. 交互验收场景
|
||||
|
||||
1. 进入有多个文档的项目,首屏看到统计和树,不需要逐个打开弹窗。
|
||||
2. 在全景点选段落,切换阅读器后正文和右栏仍是同一段落。
|
||||
3. 从阅读器打开来源,返回后保持滚动位置和筛选。
|
||||
4. 一个来源被撤回或标为未核实,统计、树徽标、正文状态和来源面板一致变化。
|
||||
5. 两个来源冲突时,冲突面板显示双方摘要;无权限的一侧只显示脱敏状态。
|
||||
6. 读取超时或断线后,保留旧快照并明确显示过期,不出现空白页面。
|
||||
7. 在窄屏和键盘操作下,树、正文和依据面板都可进入和返回。
|
||||
|
||||
Reference in New Issue
Block a user