docs(raw): archive prototype review sources
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
# 三系统职责划分:Sense / Brain / Bell
|
||||
|
||||
> 本文档回答一个问题:**一段代码该写进哪个目录。**
|
||||
> 划分依据来自《03-通用场景应用方案》的 L0–L5 分层与组件选型,本文档只是把它按三个可独立开发的系统重新切分。
|
||||
> 定稿:2026-08-03
|
||||
> ⚠️ 有 8 条待裁决的修订建议涉及本文档(§1.1、§1.2、§2.2、§2.3、§3 边界 7、§5),见《13-架构评审与修订建议》汇总表。**裁决前本文内容全部有效。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 三系统总表
|
||||
|
||||
| | **Sense** | **Brain** | **Bell** |
|
||||
| --- | --- | --- | --- |
|
||||
| 中文 | 感知系统 | 推理系统 | 管理系统 |
|
||||
| 小学生版 | 感觉到 | 想一想 | 打铃叫人 |
|
||||
| 对应层 | L1 接入 | L2 流水线 + L3 算法 | L4 业务 + L0 基座 |
|
||||
| 语言 | Go | Python / CUDA | Go + 前端 |
|
||||
| 有无状态 | 有(设备台账) | **无状态** | 有(事件、告警) |
|
||||
| DB schema | `sense` | 无 | `bell` |
|
||||
| 契约角色 | 供流与信号 → Brain | **产出**事件 | **消费**事件 |
|
||||
| 首次交付 | M1 | M3 | M3(最小)→ M4(完整) |
|
||||
|
||||
### 1.1 各自装什么
|
||||
|
||||
**Sense —— 把现场的流和信号稳定地拿进来并管住**
|
||||
|
||||
- 设备台账(`devices`,含 `modality`:video / radar / contact / button / wearable)
|
||||
- ONVIF 客户端:连接、GetProfiles、GetStreamUri、SetSystemDateAndTime
|
||||
- mediamtx API 客户端(**自行用 oapi-codegen 从其 OpenAPI 生成**,不依赖第三方 SDK)
|
||||
- **对账器**:水平触发、`sync_state`、独立信号量、10% 孤儿删除安全闸、只收敛不回滚
|
||||
- 探活与断线重建
|
||||
- WireGuard 控制面隧道
|
||||
- mediamtx 鉴权回调(401 + 踢流是四种停用粒度之一)
|
||||
- 容量配额执行:设备新增/启用时读取 Bell 的站点配额,只拒绝超额变更;配额服务暂时不可用时不影响已有流
|
||||
- 流绑定与媒体分片调度:维护 `mtx_instance`,默认 16 路交付;扩到 128 路时按 `media_shard.max_streams` 横向分片
|
||||
- 边缘节点 agent:推流、本地环形缓冲、断网续传
|
||||
- **设备型触发源**:雷达、门磁、按钮、ONVIF 事件订阅
|
||||
- 非视频传感器的信号接收(signal plane,不走 mediamtx)
|
||||
|
||||
**Brain —— 看画面、出判定**
|
||||
|
||||
- Savant 流水线与适配器(ZeroMQ 边界,适配器故障隔离,实时模式丢帧)
|
||||
- 模型:检测 / 姿态 / 跟踪 / ReID(`anon_id`)/(M5)人脸
|
||||
- **`Detector` 与 `PoseEstimator` 接口解耦**——这是 AGPL 逃生通道的前提,换 YOLOX + RTMPose 时判定算法不动
|
||||
- 判定内核:几何证据 + 时间窗状态机(从 silver_pose 抽取,两边共用)
|
||||
- 事件 mapper:判定结果 → 事件契约 v0.1
|
||||
- **像素级**运动侦测触发(要解码,所以在这里)
|
||||
- 推理 worker 注册与分片:单逻辑推理分片默认最多 16 路;64/128 路由多个 worker 承担,路由变更不改判定代码
|
||||
|
||||
**Bell —— 记录、派发、追到人确认**
|
||||
|
||||
- 事件接收与校验(schema 校验 + 契约 README §5 那六条代码级断言 + 生成 ULID)
|
||||
- 事件存储:**不可变**,误判只改 `outcome`
|
||||
- 规则引擎 + 场景包加载
|
||||
- 告警状态机:升级链、ack、抑制、静默(**≤4h,无永久选项**)
|
||||
- 投递:push / 短信 / 语音,**双供应商**
|
||||
- 误报反馈闭环:`outcome` 回写 Brain
|
||||
- 多租户 RBAC、`tenant_features`(人脸授权开关:未授权时能力在 API 与 UI 中**不可见**,不是禁用)
|
||||
- 审计日志
|
||||
- 站点容量配额的唯一真相源:`site.max_video_channels` 默认 16、上限 128;提供版本化内部读取接口/投影给 Sense 执行
|
||||
- 管理后台前端 + 大屏:按 128 路设计分页/虚拟列表、筛选与批量操作,不一次性加载全部视频
|
||||
|
||||
### 1.2 不属于任何一个目录的东西
|
||||
|
||||
| 组件 | 说明 |
|
||||
| --- | --- |
|
||||
| **mediamtx** | 独立二进制,外部依赖。Sense 管它的配置与生命周期,`Sense/deploy/` 放基线配置 |
|
||||
| **PostgreSQL / MinIO / Prometheus** | 基础设施,独立部署清单 |
|
||||
| **silver_pose** | 独立仓库,是 Brain 判定内核的来源与单机演示形态。**不改名、不合并**——它现在能卖,Brain 还不能 |
|
||||
| **`_reference/`** | 只读参考源码(如 MiBeeNvr)。按《03》§1.4 白名单借鉴 ONVIF、IP 自愈、健康检测、测试组织与 UI 交互;禁止复制媒体内核、SQLite 真相源、AI/用户体系,禁止整仓进生产或加入 go.mod |
|
||||
|
||||
---
|
||||
|
||||
## 2. 目录结构
|
||||
|
||||
### 2.1 Sense(Go)
|
||||
|
||||
```
|
||||
Sense/
|
||||
├── cmd/
|
||||
│ ├── sense-api/ 控制面服务:设备台账、鉴权回调、对账器
|
||||
│ └── sense-agent/ 边缘节点:推流、环形缓冲、隧道
|
||||
├── internal/
|
||||
│ ├── device/ 设备台账(devices,含 modality)
|
||||
│ ├── onvif/ 连接、GetProfiles、GetStreamUri、SetSystemDateAndTime
|
||||
│ ├── mtx/ oapi-codegen 生成的 mediamtx 客户端 + 薄封装
|
||||
│ ├── reconcile/ 对账循环(幂等 + 退避 + 安全闸)
|
||||
│ ├── probe/ 探活
|
||||
│ ├── trigger/ 设备型触发源(雷达/门磁/按钮/ONVIF 事件)
|
||||
│ ├── tunnel/ WireGuard 控制面
|
||||
│ ├── authcb/ mediamtx 鉴权回调
|
||||
│ └── store/ M1 先 SQLite,schema 与生产 Postgres 保持一致
|
||||
├── deploy/
|
||||
│ └── mediamtx.yml 基线配置
|
||||
└── api/openapi.yaml
|
||||
```
|
||||
|
||||
### 2.2 Brain(Python / CUDA)
|
||||
|
||||
```
|
||||
Brain/
|
||||
├── pipeline/ Savant 流水线定义与适配器
|
||||
├── models/
|
||||
│ ├── detector/ Detector 接口 + YOLO / YOLOX 实现
|
||||
│ ├── pose/ PoseEstimator 接口 + YOLO-pose / RTMPose 实现
|
||||
│ ├── tracker/ ByteTrack / BoT-SORT
|
||||
│ └── reid/ 匿名同一性,产出 anon_id
|
||||
├── judge/
|
||||
│ ├── evidence.py 几何证据(躯干角、髋部下坠比)
|
||||
│ └── state.py 时间窗状态机 NORMAL/SUSPECT/CONFIRMED/RECOVERING
|
||||
├── emit/
|
||||
│ ├── mapper.py 判定结果 → 契约 v0.1
|
||||
│ └── publisher.py 投递(HTTP 起步 → ZeroMQ);**失败落本地队列重试,不阻塞主链路**
|
||||
├── trigger/ 像素级运动侦测
|
||||
└── contracts/ ← 与 Bell/contracts/ 逐字节相同
|
||||
```
|
||||
|
||||
### 2.3 Bell(Go + 前端)
|
||||
|
||||
```
|
||||
Bell/
|
||||
├── cmd/bell-api/
|
||||
├── internal/
|
||||
│ ├── ingest/ 接收事件、schema 校验、六条断言、生成 ULID
|
||||
│ ├── event/ 事件存储(不可变,只允许追加 outcome)
|
||||
│ ├── rule/ 规则引擎 + 场景包加载
|
||||
│ ├── alert/ 告警状态机、升级链、ack、静默
|
||||
│ ├── deliver/ push / 短信 / 语音,双供应商
|
||||
│ ├── feedback/ 误报回流,outcome 回写 Brain
|
||||
│ ├── tenant/ 多租户 RBAC、tenant_features
|
||||
│ ├── audit/ 审计日志
|
||||
│ └── store/ Postgres(schema: bell)
|
||||
├── web/ 管理后台前端
|
||||
├── packs/ 场景包(**纯配置** —— M5 架构验收点)
|
||||
└── contracts/ ← 与 Brain/contracts/ 逐字节相同
|
||||
```
|
||||
|
||||
> `contracts/` 只在 Brain 与 Bell 各存一份(生产者与消费者),**Sense 不需要**——它不碰事件契约。
|
||||
|
||||
---
|
||||
|
||||
## 3. 七条边界(不写死就会漂)
|
||||
|
||||
| # | 边界 | 定论 |
|
||||
| --- | --- | --- |
|
||||
| 1 | mediamtx 二进制归谁 | 独立进程。**Sense** 管配置与生命周期,部署清单放 `Sense/deploy/` |
|
||||
| 2 | 触发源归谁 | 按性质切:**设备型**(雷达/门磁/按钮/ONVIF 事件)→ Sense,它们本来就是设备;**像素级**运动侦测 → Brain,它要解码 |
|
||||
| 3 | pre-roll 证据切片谁裁 | 录制在 Sense(mediamtx),事件在 Brain 产出。**Bell 发起回捞**(它拥有事件),Sense 提供切片接口 |
|
||||
| 4 | ULID 谁生成 | **Bell**。Brain 只填 `source_event_id`。见契约 README §4 |
|
||||
| 5 | 一个 PostgreSQL 还是三个 | **一个实例,schema 分离**(`sense` / `bell`),Brain 无 schema。"DB 是唯一真相源"是对账器成立的前提,拆库即失效 |
|
||||
| 6 | 16 路与 128 路分别指什么 | **16 路是默认交付规格,128 路是本阶段单逻辑站点上限**,都不是“单进程/单服务器保证值”。媒体与推理必须横向分片;单机承载量由分辨率、码率、帧率、模型和硬件基准测试决定 |
|
||||
| 7 | 站点配额谁拥有、谁执行 | **Bell 拥有 `sites.max_video_channels`,Sense 在设备新增/启用写路径执行**。通过版本化内部 API 或只读投影同步,不允许 Sense 直接写 Bell schema;依赖暂时不可用时拒绝新变更,但已有视频链路继续运行 |
|
||||
|
||||
第 2、3、6、7 条是本文档新定的,若实施中发现更合适的切法,改这里并同步《02》《03》。
|
||||
|
||||
> ⚠️ **边界 7(站点配额)有一条待裁决的修订建议**:既然已定"一个 PostgreSQL 实例、schema 分离",跨系统读一个整数不必走版本化 API,可改为同库只读视图 `bell.site_quota_v1`。见《13-架构评审与修订建议》A-2。裁决前本表内容仍然有效。
|
||||
|
||||
---
|
||||
|
||||
## 4. 标识符约定
|
||||
|
||||
```
|
||||
仓库/目录 Sense Brain Bell
|
||||
镜像 yov/sense:x.y yov/brain:x.y yov/bell:x.y
|
||||
日志/指标前缀 sense_ brain_ bell_
|
||||
三字母码 SEN BRN BEL
|
||||
DB schema sense — bell
|
||||
```
|
||||
|
||||
**命名规则:系统名不得是该系统领域模型里的实体名。**
|
||||
`bell` 域内有 `alerts` 表 → 系统不能叫 Alert(`alert.alerts` 无法读,且撞 Prometheus 内置的 `ALERTS` 序列)。另两个同样干净:`sense` 域内是 `devices`/`streams`,`brain` 域内是 `models`/`detections`。
|
||||
|
||||
---
|
||||
|
||||
## 5. 里程碑与目录的对应
|
||||
|
||||
| 阶段 | 动哪个目录 |
|
||||
| --- | --- |
|
||||
| **M0** 摄像头兼容性验证 | 无生产代码;可直接运行 MiBeeNvr 等 `_reference/` 项目作为隔离实验室测试台,产物允许丢弃 |
|
||||
| **M1** 5 路接入骨架 + mediamtx | **仅 Sense**;MediaMTX 正式进入,完整 MiBeeNvr 不得替代生产媒体数据面 |
|
||||
| **M2** 对账器 + 多租户 + 隧道 + 16 路开通 | **仅 Sense**;至少一个站点验证默认 16 路配额与全流程 |
|
||||
| **M3** 默认 16 路推理 + 规则引擎 + 事件预警 | **Brain + Bell 同时起步**,契约在此首次被真实使用 |
|
||||
| **M4** 64 路分片 + 灰度 + 管理系统 | Sense 与 Brain 完成横向分片,Bell 完成 128 路规模下的列表与批量交互;验证单分片故障隔离 |
|
||||
| **M5** 128 路容量验收 + 第二三场景包 + 触发式推理 + 人脸 | Sense/Brain 验证扩容不改业务代码;Bell 的 `packs/`(**纯配置**)+ Brain 的模型与触发 |
|
||||
| **M6** 异构传感器 + 两级判定 | Sense 的 `trigger/` 与 `device/`(modality 扩展)+ Brain 两级判定 |
|
||||
|
||||
> M3 是契约第一次被真实使用的时刻。**在此之前契约允许原地修订,之后版本递增规则绝对生效**(契约 README §1)。
|
||||
@@ -0,0 +1,150 @@
|
||||
# Sense 原型评审 → IX 条目草稿
|
||||
|
||||
> 来源:`yovision-T-004/docs/design/sense/index.html`(codex,2026-08-04)
|
||||
> 用途:补齐原型枚举缺口对应的交互清单条目,供并入 `docs/08-interaction-checklist.md`
|
||||
> **写入约束**:T-004 的 `write_paths` 只含 `docs/tasks/T-004.md`、`docs/design/sense/index.html`、`docs/design/bell/index.html`,且唯一写入者为 codex。本文件是草稿输入,**由 08 文件的所有者合入**,不要由本会话直接改那个 worktree。
|
||||
> 状态:全部条目标【待确认】,按 `docs/design/README.md` 工作流第 5 步逐条人工确认。
|
||||
|
||||
---
|
||||
|
||||
## 0. 先纠正一条
|
||||
|
||||
原评审列的「128 路列表缺分页」**不需要新条目**——`IX-003` 已覆盖「分页/筛选/批量选择;128 路不一次加载所有视频和详情」。那是**原型漏画**,回原型补即可,清单无需改动。
|
||||
|
||||
因此新增 **5 条**(IX-014 ~ IX-018),另有 2 处全局章节需要收紧。
|
||||
|
||||
---
|
||||
|
||||
## 1. 新增条目(可直接贴入主表)
|
||||
|
||||
```markdown
|
||||
| IX-014 | 设备模态与准入 | 设备台账按 modality(video/radar/contact/button/wearable)建模;列表、筛选、添加流程不得以"摄像头"为唯一形态;非成像设备无画面、无 Profile、无分片,其详情页不展示视频相关页签 | US-001 | M2/M6 |
|
||||
| IX-015 | 停用与踢流 | 停用需展示影响范围(是否中断在途会话、是否影响推理)并二次确认;停用后期望态与实际态分别收敛,实际态不得立即伪装为"已停止";重新启用为幂等操作 | US-001、US-002 | M2 |
|
||||
| IX-016 | 隐私区域设备准入 | 标记为隐私区域的位置只接受非成像模态;选择该位置时成像类设备不可选并说明原因;越过前端的写请求由后端拒绝并回显同一措辞 | US-006 | M2 |
|
||||
| IX-017 | 检测区域几何编辑 | 多边形与方向警戒线的绘制、撤销、清空、闭合;警戒线必须渲染方向箭头;键盘坐标输入与鼠标绘制等效;画面参数变化后既有区域标记为待校准且不静默失效 | US-005 | M3 |
|
||||
| IX-018 | 草稿与跨系统上下文 | 存在未保存几何草稿时,离开页面(导航、面包屑、切换绘制工具、跳转 Bell)必须拦截并确认;Sense↔Bell 深链双向携带摄像头与区域上下文,返回后草稿不丢失 | US-005 | M3 |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. P0 条目详情展开
|
||||
|
||||
### IX-014 设备模态与准入
|
||||
|
||||
**为什么是 P0**:原型把「摄像头」写进了导航名、表名、添加对话框标题和协议下拉(只有 ONVIF/RTSP)。《08-三系统职责划分》§1.1 已定 `devices` 含 `modality`,且隐私区域约束现在按模态判定。信息架构一旦以摄像头为唯一形态定稿,接入雷达时是整页重做而非加字段——这与事件契约 v0.1 在 2026-08-03 因同一假设被迫原地修订是同构问题。
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| 取值 | `video` / `radar` / `contact` / `button` / `wearable` / `other` |
|
||||
| 列表 | 模态是可筛选维度;设备图标按模态区分,不复用摄像头图标 |
|
||||
| 添加流程 | 先选模态,再按模态渲染字段。`radar`/`contact` 无 Profile、无码流、无分片绑定 |
|
||||
| 详情页 | 非成像模态**不展示**「画面与检测区域」「流与健康」页签,而非展示为禁用 |
|
||||
| 命名 | 一级导航不叫「摄像头」。建议「设备」,摄像头作为模态筛选项 |
|
||||
| 阶段 | 建模与命名在 M2 落地;雷达等真实接入在 M6。**建模不能等到 M6** |
|
||||
|
||||
**状态覆盖**:模态不支持该操作 / 模态与站点策略冲突 / 老数据无 modality 的迁移默认值。
|
||||
|
||||
### IX-015 停用与踢流
|
||||
|
||||
**为什么是 P0**:原型的「期望态」列有"停用"这个**值**,但没有停用**动作**,也没有任何关于"停用会不会踢掉正在观看的流"的表达。这是 Sense 最有运维后果的行为,且《03》§2.1 定义了四种粒度(卸载推理源 / 踢会话 / 鉴权回调 401 + 踢流 / DELETE path),标准组合是**先踢再拒**。原型不画,IX 就不会生成,实现时会退化成一个静默的布尔开关。
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| 确认前必须说明 | 是否中断当前在途会话、是否影响正在运行的推理、是否影响录制与证据回捞 |
|
||||
| 期望态与实际态 | 点击停用后期望态立即变更,实际态由对账器收敛;**实际态不得立即显示"已停止"** |
|
||||
| 收敛可见 | 停用中的设备计入「待收敛项」,收敛超时有明确提示 |
|
||||
| 幂等 | 重复停用/启用不产生副作用,不生成重复审计条目 |
|
||||
| 批量 | 批量停用逐项结果可见,部分失败可重试 |
|
||||
|
||||
**状态覆盖**:正在被其他人观看时停用 / 对账器不可达时停用 / 停用后又被上游策略重新启用。
|
||||
|
||||
### IX-016 隐私区域设备准入
|
||||
|
||||
**为什么是 P0**:这是**代码级**硬约束(《01》RQ-S1-05、《02》NFR-CMP-05、《03》§3.2)。原型的「区域」下拉只是普通选项,没有任何拒绝路径。合规约束在 UI 上不可见时,实现者不会知道它存在。
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| 判定依据 | 按 `modality` 判定,**不按设备类型名判定**。`privacy_flag = true` 的位置允许 `radar`/`contact`/`button`/`wearable`,拒绝 `video` |
|
||||
| 前端 | 成像模态在隐私位置**不可选**,并就地说明原因,而非提交后报错 |
|
||||
| 后端 | 绕过前端的写请求必须拒绝,措辞与前端一致 |
|
||||
| 位置属性变更 | 已有成像设备的位置被改标为隐私区域时,必须走显式处置流程,不允许静默留存 |
|
||||
|
||||
**状态覆盖**:位置属性读取失败时默认按最严处理(拒绝成像)。
|
||||
|
||||
### IX-017 检测区域几何编辑
|
||||
|
||||
**为什么是 P0**:原型的草稿层(`drawDraft`)把警戒线画成无向线段,但**方向是警戒线唯一的语义**——越线方向决定是否触发。静态示例 SVG 里画了箭头,草稿里没有,说明这是实现遗漏而非设计取舍。
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| 方向 | 警戒线草稿与已保存态**都**必须渲染方向箭头;提供反转方向的操作 |
|
||||
| 最小点数 | 多边形 ≥3,警戒线 =2;不足时保存被拒并说明 |
|
||||
| 闭合交互 | 双击闭合**不得先追加顶点**(原型 534–535 行:dblclick 前两次 click 会多加 2 个点) |
|
||||
| 键盘等效 | 坐标输入(0–100%)与鼠标绘制完全等效,含撤销与删除单点 |
|
||||
| 待校准 | 画面分辨率/旋转变化后既有区域标记为待校准,**不静默失效也不自动改坐标** |
|
||||
| 版本 | 区域版本与告警规则版本是不同对象;保存区域不发布规则 |
|
||||
|
||||
### IX-018 草稿与跨系统上下文
|
||||
|
||||
**为什么是 P0**:T-004 任务书自己写明"后端系统边界不得迫使用户丢失当前摄像头或规则草稿上下文"。实测原型有三条路径会静默丢弃草稿:面包屑返回(502 行)、侧栏导航(493 行)、**切换绘制工具**(536 行 `points.length = 0`)。而 `clearPoints` 与 `discardDraft` 都有 `confirm`——同一类破坏性操作,三处有确认、三处没有。
|
||||
|
||||
| 项 | 约定 |
|
||||
| --- | --- |
|
||||
| 拦截范围 | 页内导航、面包屑、切换绘制工具、跳转 Bell、关闭标签页 |
|
||||
| 一致性 | 所有丢弃草稿的路径使用**同一个**确认组件与措辞 |
|
||||
| 深链 | Sense→Bell 与 Bell→Sense **双向**携带 `camera` + `zone`;原型目前只有 Bell→Sense 带 `return` 参数,反向缺失 |
|
||||
| 返回 | 从 Bell 返回后草稿仍在;若期间区域被他人保存,提示冲突而非覆盖 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 全局章节需要收紧的两处
|
||||
|
||||
### 3.1 「无障碍与安全」——把对比度写成可验证的数字
|
||||
|
||||
现文:「文本和关键状态满足可读对比度」。建议改为:
|
||||
|
||||
```markdown
|
||||
- 正文与关键状态对比度 ≥ 4.5:1,大字号(≥18.66px 粗体或 ≥24px)≥ 3:1;**主操作按钮同样受此约束**。
|
||||
```
|
||||
|
||||
**实测依据**(对原型配色计算,非估计):
|
||||
|
||||
| 用途 | 前景/背景 | 实测 | 判定 |
|
||||
| --- | --- | --- | --- |
|
||||
| `.btn-primary` 主 CTA | `#ffffff` / `#0ea5e9` | **2.77:1** | ❌ 深浅两个主题都不过(浅色主题未覆盖 `--primary-strong`) |
|
||||
| 浅色主题 `--subtle` | `#718096` / `#ffffff` | **4.02:1** | ❌ 用于 `.nav-label`、搜索图标 |
|
||||
| 其余抽查 6 项 | — | 4.6–16.3:1 | ✅ |
|
||||
|
||||
主按钮那条影响最大:「添加摄像头」「保存区域版本」「保存为待激活」全是它。修法是把 `--primary-strong` 压到 `#0369a1` 一带(≈5.9:1),或主按钮改深底浅字。
|
||||
|
||||
### 3.2 「无障碍与安全」——补三条可测项
|
||||
|
||||
原型实测出的问题,与其修原型不如钉进清单(生产要重写):
|
||||
|
||||
```markdown
|
||||
- 当前导航项使用 `aria-current="page"`;不得用空值属性表达(空串等于 false)。
|
||||
- 图标按钮在任何断点下都必须保留可访问名;隐藏文字标签时须提供 aria-label。
|
||||
- 采用 tab 模式时必须完整:`role="tabpanel"` + `aria-controls` 关联 + 方向键导航,不做半套。
|
||||
```
|
||||
|
||||
对应原型位置:`aria-current` 见 489 行 `toggleAttribute`;图标按钮见 236 行 `≤1180px` 隐藏 `.nav span`;tab 半套见 372–377 与 503–507 行。
|
||||
|
||||
---
|
||||
|
||||
## 4. 不进清单、但要回原型补的
|
||||
|
||||
| # | 内容 | 处理 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 设备列表分页控件 | IX-003 已覆盖,仅原型漏画 |
|
||||
| 2 | 「推理绑定 16/16」画成 100% 满格紫条 | 正常态显示成满载,易误读为告警。换表现,不进清单 |
|
||||
| 3 | 分片容量 `8/32` 的 **32** 无出处 | 《08》只定义站点 16 默认 / 128 上限,未定义单分片容量。**要么把 `media_shard.max_streams` 补进《08》§3,要么原型改用文档里的数**——两个分片 ×32 = 64,与站点上限 128 也对不齐 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议的落地顺序
|
||||
|
||||
1. IX-014(模态)先定——它影响导航命名与表结构,**建议整页重生成原型而非打补丁**
|
||||
2. IX-015 / IX-016 补进原型(停用动作 + 隐私区域拒绝态),二者都只是加控件与一个拒绝态
|
||||
3. IX-017 / IX-018 可以只写清单不改原型——都是行为约定,生产实现时按清单做
|
||||
4. §3 两处全局收紧直接合入
|
||||
5. §4 第 3 条的分片容量需要一个数字决定,然后同步《08》
|
||||
@@ -0,0 +1,136 @@
|
||||
# Sense 原型第二轮评审
|
||||
|
||||
> 基准:`yovision-T-004/docs/design/sense/index.html`(codex,2026-08-04 09:55,78 KB)
|
||||
> 对标:`02-requirements`、`04-architecture`、`07-user-stories`、`08-interaction-checklist`(均于 09:41 更新)、`routes.md`、`api.md`
|
||||
> 前置:《09-Sense原型评审-IX草稿》《10-Sense原型-功能模块缺口》
|
||||
> 日期:2026-08-04
|
||||
|
||||
---
|
||||
|
||||
## 0. 结论
|
||||
|
||||
| 轮次 | 内容 | 状态 |
|
||||
| --- | --- | --- |
|
||||
| 《09》行为缺口 | IX-014~018 + 无障碍三条 + 对比度 | ✅ **基本全部落地**,且清单版本比我的草稿更好 |
|
||||
| 《10》模块缺口 | 6 个 P0 模块 | ❌ **0 / 6 落地**,导航仍是 5 项 |
|
||||
| 本轮新增 | 由 modality/capabilities 模型带来的新问题 | ⚠️ **5 处**,见 §3 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 已落地的(有证据,不必再提)
|
||||
|
||||
| 项 | 证据 |
|
||||
| --- | --- |
|
||||
| 一级入口改名「设备」,`modality` 成为一等公民 | 原型内 `modality` 出现 29 次;筛选含 `onvif`/`radar`/`mqtt` |
|
||||
| `capabilities` 驱动详情页签 | 「能力」11 次;页签改为「连接与健康」而非「流与健康」 |
|
||||
| 隐私区域准入 | `updatePrivacyAdmission()`;区域筛选含 `privacy`;导入文案含「区域隐私策略」 |
|
||||
| **三种停用粒度**(IX-015) | `operationDialog`:暂停推理 / 停用接入 / 断开当前会话,每项带影响说明 + 幂等声明 + 审计声明 |
|
||||
| tab 模式补完整 | `aria-controls` + `aria-selected` + roving `tabindex` |
|
||||
| 草稿自动保存(IX-018) | 检出自动保存逻辑 |
|
||||
|
||||
清单侧的 IX-015 拆成三粒度、IX-018 改成"自动保存 + 只在破坏性动作时拦截",都比我原草稿准确。
|
||||
|
||||
---
|
||||
|
||||
## 2. 《10》的模块缺口:一处未动
|
||||
|
||||
导航仍是 `运行总览 · 实时监控 · 设备 · 接入任务 · 系统状态`。逐项核对:
|
||||
|
||||
| 《10》 | 缺口 | 本轮 | 关键词实测 |
|
||||
| --- | --- | --- | --- |
|
||||
| §1.2 | **对账器运维视图** | 未动 | 「孤儿」0 次、「退避」0 次;待收敛项仍不可下钻 |
|
||||
| §1.5 | **权限与角色** | 未动 | 「角色」「只读」「权限」各 **0** 次 |
|
||||
| §1.1 | 站点与 Area 管理 | 未动 | 「站点」仅顶栏 1 次;无 Area 增删改 |
|
||||
| §1.3 | 待激活闭环 | 未动 | 筛选仍无「待激活」 |
|
||||
| §1.4 | 凭据更新 | 未动 | 仍只有「已安全保存,页面不可见」,无写入路径 |
|
||||
| §1.6 | 配额降级态 | 未动 | 状态演示仍是 normal/loading/empty/error 四态 |
|
||||
| §2.1 | 边缘节点与隧道 | 未动 | 「隧道」0 次、「补传」0 次 |
|
||||
| §2.3/2.4 | 主子码流切换 / 分片迁移 | 未动 | 「主码流」0 次、「迁移」0 次 |
|
||||
| — | 设备列表分页(IX-003 明确要求) | 未动 | 「分页」0 次 |
|
||||
|
||||
不重复推导,理由见《10》。**优先级不变:对账器视图 > 权限 > 站点与 Area。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 本轮更新新产生 / 新暴露的 5 处
|
||||
|
||||
### 3.1 `capabilities` 成了一等公民,却没有产生它的流程 ⚠️ P0
|
||||
|
||||
`capabilities` 现在决定详情页显示哪些页签——这是正确的设计。但**谁写入 capabilities?**
|
||||
|
||||
原型的「测试连接」仍然只是一次性反馈("2 个 Profile,时间漂移 +0.4s"),结果没有落地成设备的持久属性。于是 `capabilities` 变成一个没有来源的字段。
|
||||
|
||||
而且它会**变化**:固件升级后可能新支持 ONVIF 事件订阅,换 Profile 后分辨率变化会让检测区域待校准(IX-017 已覆盖后半段,但没覆盖能力本身的变化)。
|
||||
|
||||
| 需要什么 |
|
||||
| --- |
|
||||
| 探测结果落地为设备的 `capabilities`,详情页「设备能力」区可见 |
|
||||
| **重新探测**动作,以及探测结果与既有 `capabilities` 的**差异提示** |
|
||||
| 能力降级的处置:原本支持事件订阅、现在探测不到了,依赖它的设备型触发怎么办 |
|
||||
| 与采购白名单关联(US-007 要求形成白名单,现在白名单和设备台账没有连接) |
|
||||
|
||||
### 3.2 modality 可选 radar,但适配器 M6 才有 ⚠️ P0
|
||||
|
||||
`02-requirements` §3.1 写明:
|
||||
|
||||
> M1~M5 只完整实现 video 适配器,M6 再接入非视频设备,但不得因此把数据模型和一级信息架构写死为摄像头。
|
||||
|
||||
原型的模态下拉已经能选 `radar`/`mqtt`。**那么现在选了会怎样?** 如果能一路添加成功,原型就在承诺一个 M6 才有的能力;如果直接不可选,又违背了"信息架构不写死为摄像头"。
|
||||
|
||||
正解是第三种状态:**模态已建模、适配器未就绪**——可以录入、进台账、占位、参与隐私准入校验,但明确标注"适配器 M6 交付,当前不建立连接"。这个态现在不存在。
|
||||
|
||||
### 3.3 「暂停推理」的措辞与实际机制不符 ⚠️ P1
|
||||
|
||||
对话框写:
|
||||
|
||||
> **暂停推理**:保留媒体接入与实时预览,只停止新推理任务
|
||||
|
||||
但《03》§2.1 的机制是**卸载推理 source**,而且原文特别警告:
|
||||
|
||||
> `sourceOnDemand: yes` 的语义是「有 reader 才拉流」,而**推理 source 挂上去就是一个 reader**。因此「暂停分析」必须通过**卸载 source** 实现,不能只在推理插件里 `return`——后者会让 mediamtx 持续拉流、带宽白烧,而监控上看起来一切正常。
|
||||
|
||||
「停止新推理任务」这个措辞暗示的正是被明令禁止的那种实现(在推理侧跳过)。原型是 IX 的输入物,措辞会直接变成实现者的心智模型。
|
||||
|
||||
**建议改为**:「解除推理侧对该路的订阅;无其他观看者时上游自动停止拉流」——同时把"是否仍在拉流"作为可观察结果显示,这正是那条血泪教训要防的。
|
||||
|
||||
### 3.4 Area 策略可校验,但没有地方修改策略 ⚠️ P1
|
||||
|
||||
隐私准入在**添加**路径上做对了。但 IX-016 还要求:
|
||||
|
||||
> 已有设备遇到区域策略变化时进入**显式处置流程**,不静默留存或停用
|
||||
|
||||
这个流程的**触发点**——把某个 Area 从 `video_allowed` 改成 `non_imaging_only`——在 UI 上不存在,因为 Area 根本不可管理(《10》§1.1)。等于规则写好了但没有触发它的按钮。
|
||||
|
||||
同理,IX-016 的「策略读取失败时拒绝新变更并告警」也需要一个降级态,与《10》§1.6 的配额降级是同类问题:**读故障 vs 写故障表现完全不同**,而状态演示仍只有四态。
|
||||
|
||||
### 3.5 `api.md` 缺一行:Sense → Bell 的审计投递 ⚠️ P1(文档缺口,非原型缺口)
|
||||
|
||||
原型现在多处承诺审计:「每次请求均审计」、执行操作后「已记录本次审计」。
|
||||
|
||||
但架构 §2 定 Bell 是审计真相源,而 `api.md` §2「待冻结的内部接口」表只有五行:
|
||||
|
||||
```
|
||||
Sense → Bell 读取站点视频配额
|
||||
Bell → Sense 请求事件证据 / pre-roll 切片
|
||||
Bell → Brain outcome / 误报反馈
|
||||
Sense → Brain 流绑定与设备型触发
|
||||
Worker → 控制面 注册、心跳、容量
|
||||
```
|
||||
|
||||
**没有 Sense → Bell 的审计投递。** 于是原型承诺的审计要么落在 Sense 本地(架构说不行,Bell 才是真相源),要么走一条没定义的接口。这行需要补进 `api.md`,并明确:异步还是同步、Bell 不可达时 Sense 的操作是否仍然执行(我的建议:**执行,审计落本地队列重传**,与 Brain 投递失败的处理一致)。
|
||||
|
||||
---
|
||||
|
||||
## 4. 建议顺序
|
||||
|
||||
| 顺序 | 做什么 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 1 | **对账器运维视图**(《10》§1.2) | 两轮未动,仍是单点最大缺口。Sense 的存在理由在 UI 上等于不存在 |
|
||||
| 2 | **权限与角色**(《10》§1.5) | 决定页面上有没有按钮,是 IA 问题;两轮为 0 |
|
||||
| 3 | **capabilities 的产生流程**(§3.1) | 本轮新引入的字段没有来源,会变成永远为空的装饰 |
|
||||
| 4 | **站点与 Area 管理**(《10》§1.1 + §3.4) | 现在有了明确触发点:改 `capture_policy` 需要显式处置流程 |
|
||||
| 5 | 「暂停推理」措辞(§3.3) | 一句话的改动,但防的是一个会烧带宽且监控看不出来的实现错误 |
|
||||
| 6 | `api.md` 补审计接口行(§3.5) | 文档改动,不影响原型 |
|
||||
| 7 | 模态适配器未就绪态(§3.2)、配额/策略降级态、分页 | 补齐 |
|
||||
|
||||
> 第 1、2、4 项都是**改信息架构**,建议合并进同一次原型重生成。这是第二次提出——分次打补丁的成本会持续累积。
|
||||
@@ -0,0 +1,255 @@
|
||||
# Sense 原型待办清单(合并 09 / 10 / 11)
|
||||
|
||||
> 合并来源:《09-Sense原型评审-IX草稿》《10-Sense原型-功能模块缺口》《11-Sense原型-第二轮缺口》
|
||||
> 基准:`yovision-T-004/docs/design/sense/index.html`(2026-08-04 09:55)
|
||||
> 用途:给 codex 的单一执行清单。理由与推导见来源文档,本文只给**做什么 + 依据 + 验收**。
|
||||
> 日期:2026-08-04
|
||||
|
||||
---
|
||||
|
||||
## 0. 使用说明
|
||||
|
||||
- 编号 `S-xx` 稳定,后续讨论只引用编号。
|
||||
- **A 组必须一次重生成**,不要逐项打补丁——三项都改信息架构,分次改的返工成本已经累积两轮。
|
||||
- **写入范围**:T-004 的 `write_paths` 只含 `docs/tasks/T-004.md`、`docs/design/sense/index.html`、`docs/design/bell/index.html`。标记「⚠️ 超出 write_paths」的条目**需另开任务**,不要在本任务内改。
|
||||
- 优先级:**P0** = M2 出口必需;**P1** = M2 内补齐;**P2** = 只留信息架构位,不实现。
|
||||
|
||||
---
|
||||
|
||||
## 1. 已完成(核对用,不执行)
|
||||
|
||||
第一轮《09》的全部条目已落地,实测确认:
|
||||
|
||||
| 项 | 验证方式 | 结果 |
|
||||
| --- | --- | --- |
|
||||
| IX-014 modality 建模与「设备」改名 | `modality` 出现 29 次;筛选含「视频 / 雷达」,添加对话框可选「视频设备 / 毫米波雷达」 | ✅ |
|
||||
| IX-014 capabilities 驱动页签 | 页签改为「连接与健康」 | ✅ |
|
||||
| IX-015 三种停用粒度 | `operationDialog`:暂停推理 / 停用接入 / 断开会话,各带影响说明 + 幂等 + 审计声明 | ✅ |
|
||||
| IX-016 隐私准入(新增路径) | `updatePrivacyAdmission()`;区域筛选含 privacy | ✅ |
|
||||
| IX-017 警戒线方向 | 检出 marker / 反转相关实现 | ✅ |
|
||||
| IX-018 草稿自动保存 | 检出自动保存逻辑 | ✅ |
|
||||
| a11y:tab 模式 | `aria-controls` + `aria-selected` + roving `tabindex` | ✅ |
|
||||
| **对比度:主按钮** | `--primary-strong` 改为 `#0369a1` / `#075985` | ✅ **5.93:1 / 7.56:1**(原 2.77:1) |
|
||||
|
||||
---
|
||||
|
||||
## 2. A 组 · 信息架构级(P0,一次重生成)
|
||||
|
||||
导航从 5 项扩到 8 项:
|
||||
|
||||
```
|
||||
运行总览 · 实时监控 · 设备 · 接入任务 · 【站点与区域】 · 【运维】 · 系统状态 · 【审计】
|
||||
顶栏补:站点切换器 · 当前用户与角色
|
||||
```
|
||||
|
||||
### S-01 运维视图:对账队列 · P0
|
||||
|
||||
**两轮未动,单点最大缺口。** 总览的「待收敛项」目前不可下钻;对账器是 Sense 区别于普通 NVR 的全部理由,UI 上等于不存在。
|
||||
|
||||
| 必须包含 | 依据 |
|
||||
| --- | --- |
|
||||
| 未收敛项列表,逐项显示**期望态 vs 实际态的具体差异** | 架构 §7「PostgreSQL 是期望态真相源」 |
|
||||
| 每项的重试次数、当前退避间隔、下次重试时间 | 架构 §7「幂等、指数退避、限制并发」 |
|
||||
| **孤儿资源列表 + 10% 安全闸触发告警** | 架构 §7「孤儿删除必须有 10% 安全闸和人工可观察指标」 |
|
||||
| 单项手动触发收敛(现有「立即对账」是全局的,粒度过粗) | — |
|
||||
| 收敛持续失败的升级路径:多久算异常、通知谁 | 需求 §3.5 运维告警独立 |
|
||||
|
||||
**验收**:从总览「待收敛项 N」可点击进入;任选一项能看到差异、退避与下次重试时间;孤儿列表与安全闸状态可见。
|
||||
|
||||
### S-02 权限与角色 · P0
|
||||
|
||||
**两轮为 0。**「角色」「只读」「权限」在原型中各出现 0 次。权限决定页面上**有没有**按钮,是信息架构问题,不是加一层。
|
||||
|
||||
| 必须包含 | 依据 |
|
||||
| --- | --- |
|
||||
| 顶栏显示当前用户与角色 | 需求 §3.5 五角色 RBAC |
|
||||
| 只读角色下:添加 / 停用 / 删除 / 更新凭据**不出现**(不是置灰) | `routes.md` 路由守卫 |
|
||||
| 越权深链的统一拒绝态 | `routes.md`「深链打开无权限或已删除资源时给出统一、安全的反馈」 |
|
||||
| 站点管理员只能看到自己站点 | 需求 §3.5 |
|
||||
| 角色切换器(原型演示用,同状态演示下拉的做法) | — |
|
||||
|
||||
**验收**:切到「只读」角色后,设备页所有写操作控件消失;越权深链显示统一拒绝态。
|
||||
|
||||
### S-03 站点与区域(Area)管理 · P0
|
||||
|
||||
实体链 `Tenant → Site → Area/Device` 目前断了两级:Site 是顶栏一行静态字,Area 只是一个下拉选项。
|
||||
|
||||
| 必须包含 | 依据 |
|
||||
| --- | --- |
|
||||
| 站点列表:配额已用/上限、在线率、未收敛数、边缘节点状态 | `routes.md` `/sites` |
|
||||
| 顶栏站点切换器,切换后所有列表按站点过滤 | 架构 §3 SaaS-ready 边界 |
|
||||
| 配额只读展示 + 标注「由 Bell 持有」 | 架构 §5 第 7 条 |
|
||||
| **Area 增删改,含 `capture_policy = video_allowed \| non_imaging_only` 的编辑** | 需求 §3.1;架构 §8 |
|
||||
| **改 `capture_policy` 时的显式处置流程**(该 Area 已有成像设备怎么办) | IX-016「不静默留存或停用」——规则已写,触发点当前不存在 |
|
||||
|
||||
**验收**:能新建 Area 并设为 `non_imaging_only`;把一个已有摄像头的 Area 改成该策略时,出现显式处置流程而非静默通过。
|
||||
|
||||
### S-04 审计入口 · P1
|
||||
|
||||
原型多处承诺「每次请求均审计」,但没有查询入口。
|
||||
|
||||
**必须包含**:设备操作审计列表(时间 / 操作 / 对象 / 执行人 / 结果),可按设备、操作类型、时间筛选;标注真相源在 Bell。
|
||||
**验收**:从设备详情「操作记录」可跳到全局审计页并保留该设备筛选。
|
||||
|
||||
---
|
||||
|
||||
## 3. B 组 · 页内新增(不改 IA)
|
||||
|
||||
### S-05 capabilities 的产生流程 · P0
|
||||
|
||||
本轮新引入的 `capabilities` 决定页签显示,但**没有写入它的流程**——「测试连接」仍只是一次性 toast,结果不落地。
|
||||
|
||||
| 必须包含 |
|
||||
| --- |
|
||||
| 探测结果落地为设备持久属性,详情页「设备能力」区可见(厂商、型号、固件、认证方式、Profile 列表、是否支持校时、**是否支持 ONVIF 事件订阅**) |
|
||||
| **重新探测**动作 + 与既有 `capabilities` 的**差异提示** |
|
||||
| 能力降级处置:原本支持事件订阅、重探后不支持了,依赖它的设备型触发怎么办 |
|
||||
| 与采购白名单关联(US-007 要求形成白名单,当前白名单与台账无连接) |
|
||||
|
||||
**验收**:添加设备后「设备能力」区有内容;重新探测能显示"新增/消失了哪些能力"。
|
||||
|
||||
### S-06 模态适配器未就绪态 · P0
|
||||
|
||||
需求 §3.1:M1~M5 只完整实现 video 适配器,M6 才接非视频;但信息架构不得写死为摄像头。
|
||||
|
||||
现在模态下拉已能选 `radar`/`mqtt`——**选了会怎样没有定义**。能一路添加成功就是承诺 M6 能力;直接禁用又违背 IA 要求。
|
||||
|
||||
**需要第三态**:模态已建模、适配器未就绪——可录入、进台账、占位、参与隐私准入校验,但明确标注「适配器 M6 交付,当前不建立连接」,且不计入视频配额。
|
||||
**验收**:选 radar 添加后设备进入台账并显示该标注;实际态不显示为「在线」或「离线」,而是「适配器未就绪」。
|
||||
|
||||
### S-07 待激活闭环 · P0
|
||||
|
||||
需求 §3.1 明确的中间态,但设备表无待激活行、筛选无该项、无处置流程。
|
||||
|
||||
**必须包含**:待激活作为一级筛选项与独立计数;激活流程(重新探测 / 校时 / 配额复核);批量激活与逐项结果;长期待激活的过期策略。
|
||||
**验收**:筛选出待激活设备并完成一次激活,失败时可看到具体原因。
|
||||
|
||||
### S-08 凭据更新与认证失败恢复 · P0
|
||||
|
||||
详情页「凭据:已安全保存,页面不可见」——处理正确,但**只有读没有写**。现场改密码是最高频运维事件。
|
||||
|
||||
**必须包含**:单设备「更新凭据」(只写不读,不回显已存值);**认证失败作为独立实际态**(区别于「离线」,原因和处置都不同);批量更新凭据;更新后自动重试接入且结果可见。
|
||||
**验收**:认证失败设备在列表中可识别,能就地更新凭据并看到重试结果。
|
||||
|
||||
### S-09 降级态:配额不可读 / 区域策略不可读 · P0
|
||||
|
||||
状态演示仍是 `normal / loading / empty / error` 四态。缺的是**写故障**——与「边缘节点不可达」(读故障)表现完全不同:视频照常播、列表照常看,只有写操作被拒。
|
||||
|
||||
| 必须包含 | 依据 |
|
||||
| --- | --- |
|
||||
| 配额不可读:横幅说明「当前无法新增或启用设备,已有视频不受影响」,添加/激活按钮禁用并说明原因 | `api.md` §2;架构 §7 |
|
||||
| 区域策略不可读:拒绝新的成像设备变更并告警,已有链路不静默停用 | IX-016 |
|
||||
|
||||
**验收**:状态演示下拉新增这两态,切换后写操作被拒而视频与列表正常。
|
||||
|
||||
### S-10 边缘节点与隧道 · P1
|
||||
|
||||
侧栏底部只有一行 `sense-edge-01 · 在线`。但**控制面/数据面分离**是整个 NAT 方案的核心,UI 不体现等于白设计。
|
||||
|
||||
**必须包含**:边缘节点列表(版本、在线时长、隧道状态、承载设备数);**隧道断开但视频仍在推**的明确表达;本地缓存水位 + 断网恢复后的补传进度;节点升级/重启动作。
|
||||
**依据**:需求 §3.5「断网时边缘缓存事件,恢复后补传」。
|
||||
**验收**:能演示「隧道断开 / 视频正常」这个组合态,并显示补传队列长度。
|
||||
|
||||
### S-11 主 / 子码流切换 · P1
|
||||
|
||||
详情写死「子码流 704×576 · 5 FPS」,无切换动作。码流是容量的直接变量(架构 §6:`max_streams` 由码率决定),切换还会踢掉当前发布者,需影响范围提示。
|
||||
|
||||
### S-12 分片详情与设备迁移 · P1
|
||||
|
||||
分片健康只读。需要:分片详情(承载设备、实际码率、重连历史)、设备跨分片迁移(会中断该路,需确认)、单分片故障的影响范围展示(架构 §6「单分片故障不能扩散」)。
|
||||
|
||||
### S-13 批量任务列表与逐项结果 · P1
|
||||
|
||||
「当前任务」是单卡片,「查看逐项结果」是死按钮。IX-001 要求逐行错误、重复序列号、待激活、确认写入。
|
||||
|
||||
**必须包含**:任务列表(历史可查、可重试、可导出错误清单);逐项结果页(每行校验结果、失败原因、单行重试);上传前本地预校验结果页;部分成功语义(8 路里 5 成功 3 失败,成功的已生效)。
|
||||
|
||||
### S-14 Sense 运维告警列表 · P1
|
||||
|
||||
总览「今日设备告警 3」与「与业务预警分开」的说明写得对,但点不进去。
|
||||
|
||||
**必须包含**:运维告警列表(离线、时间漂移超阈、收敛失败、分片异常、隧道断开);运维侧的静默与通知配置(与 Bell 的业务静默是两套);明确标注「不会推给家属/值班员」。
|
||||
**依据**:需求 §3.4「业务预警与运维告警使用不同通道和值班配置」。
|
||||
|
||||
### S-15 设备列表分页 · P1
|
||||
|
||||
「分页」在原型中出现 0 次。IX-003 明确要求,阶段 M2/M4。含批量选择的跨页语义(「全选」到底选了当前页还是全部)。
|
||||
|
||||
### S-16 时间显示口径 · P1
|
||||
|
||||
系统内同时存在三个时钟:设备时间(可能漂 +3.8s)、服务器时间(期望态真相源)、浏览器本地时间。而「时间漂移」是原型自己列的一级指标,三者不区分会导致运维误判。
|
||||
|
||||
**约定**:统一显示服务器时间 + 时区标注;设备时间只出现在漂移列;相对时间悬停显示完整时间戳。
|
||||
|
||||
### S-17 租户维度 · P1
|
||||
|
||||
首期一客户一套私有实例,但架构 §3 要求「从第一版携带 `tenant_id` 并保持 SaaS-ready 边界」。不需要租户切换器,但需要当前租户可见、且所有列表按租户过滤这件事在 UI 上成立。
|
||||
|
||||
---
|
||||
|
||||
## 4. C 组 · 措辞与文档
|
||||
|
||||
### S-18 「暂停推理」措辞 · P0(一句话,但防的是重大实现错误)
|
||||
|
||||
现文:「只停止新推理任务」。这暗示的正是《03》§2.1 明令禁止的实现:
|
||||
|
||||
> `sourceOnDemand: yes` 的语义是「有 reader 才拉流」,而**推理 source 挂上去就是一个 reader**。因此「暂停分析」必须通过**卸载 source** 实现,不能只在推理插件里 `return`——后者会让 mediamtx 持续拉流、带宽白烧,**而监控上看起来一切正常**。
|
||||
|
||||
**改为**:「解除推理侧对该路的订阅;无其他观看者时上游自动停止拉流」。
|
||||
并把「是否仍在拉流」作为可观察结果显示——这正是那条教训要防的。
|
||||
|
||||
### S-19 `media_shard.max_streams` 标注 · P2
|
||||
|
||||
分片显示 `8/32`。架构 §6 写「初始建议 32,可按故障域降为 16,最终由压测确定」——数值有据,但 UI 需标注它是**可配置项**而非固定值,避免被当成硬上限。
|
||||
|
||||
### S-20 「推理绑定 16/16」的视觉 · P2
|
||||
|
||||
正常状态画成 100% 满格紫条,易被误读为告警/满载。换表现。
|
||||
|
||||
### S-21 ⚠️ 超出 write_paths:`api.md` 补审计投递接口 · P1
|
||||
|
||||
原型承诺「每次请求均审计」,架构 §2 定 Bell 是审计真相源,但 `api.md` §2 的五行内部接口**没有 Sense → Bell 的审计投递**。
|
||||
|
||||
需补一行并明确失败语义。**建议**:Bell 不可达时操作照常执行、审计落本地队列重传——与 Brain 投递失败的处理保持一致(架构 §7)。
|
||||
**处理方式**:另开任务,不在 T-004 内改。
|
||||
|
||||
---
|
||||
|
||||
## 5. D 组 · 只留信息架构位(P2,不实现)
|
||||
|
||||
避免 M3 时整页重做。三项各留一个导航位或详情页签占位即可:
|
||||
|
||||
| 编号 | 模块 | 依据 |
|
||||
| --- | --- | --- |
|
||||
| S-22 | 推理绑定视图(设备 ↔ worker 绑定、注册/心跳/容量、绑定失败态) | `api.md` §2「Worker → 控制面」 |
|
||||
| S-23 | pre-roll 切片运维(请求量、失败率、耗时) | 架构 §5 第 3 条 |
|
||||
| S-24 | 设备型触发源配置(雷达/门磁/按钮/ONVIF 事件订阅) | 《08》§3 边界 2;与 S-06 同源 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 执行顺序
|
||||
|
||||
| 批次 | 条目 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| **第 1 批** | S-01 · S-02 · S-03 · S-04 | **一次整页重生成**。四项都改信息架构,分次打补丁的返工成本已累积两轮 |
|
||||
| **第 2 批** | S-05 · S-06 · S-07 · S-08 · S-09 · S-18 | P0 页内新增 + 措辞。S-18 只是改文案,可随手带上 |
|
||||
| **第 3 批** | S-10 ~ S-17 | P1,M2 出口前补齐 |
|
||||
| **第 4 批** | S-19 · S-20 · S-22 · S-23 · S-24 | P2,留位与视觉 |
|
||||
| **独立任务** | S-21 | 超出 T-004 write_paths |
|
||||
|
||||
---
|
||||
|
||||
## 7. 总验收
|
||||
|
||||
第 1、2 批完成后应满足:
|
||||
|
||||
- [ ] 导航 8 项;顶栏有站点切换器、当前用户与角色
|
||||
- [ ] 「待收敛项」可下钻,能看到期望态/实际态差异、退避与孤儿资源
|
||||
- [ ] 切到只读角色,设备页所有写操作控件**消失**(非置灰)
|
||||
- [ ] 能新建 `non_imaging_only` 的 Area,并触发既有成像设备的显式处置流程
|
||||
- [ ] 「设备能力」区有内容,重新探测能显示能力差异
|
||||
- [ ] 选 radar 添加后进入台账,实际态为「适配器未就绪」,不计入视频配额
|
||||
- [ ] 待激活可筛选、可激活、失败有原因
|
||||
- [ ] 认证失败可识别、可就地更新凭据、可看到重试结果
|
||||
- [ ] 状态演示含「配额不可读」「区域策略不可读」,写操作被拒而视频与列表正常
|
||||
- [ ] 「暂停推理」措辞已改,且能观察到「是否仍在拉流」
|
||||
@@ -0,0 +1,165 @@
|
||||
# Bell 原型评审
|
||||
|
||||
> 基准:`yovision-T-004/docs/design/bell/index.html`(codex,2026-08-04 09:54,525 行 / 57 KB)
|
||||
> 对标:T-004 任务书方案 4 与不可变约束、`02-requirements` §3.3/§3.4/§8、`04-architecture` §8、IX-005~IX-013、`routes.md`
|
||||
> 日期:2026-08-04
|
||||
|
||||
---
|
||||
|
||||
## 0. 总评
|
||||
|
||||
**质量明显高于 Sense 第一版。** 七项导航(值班台 / 事件中心 / 规则策略 / 升级链 / 运营报表 / 站点与 Area / 审计)基本覆盖 `routes.md` 的页面职责,而且几处最容易做错的领域约束都做对了。
|
||||
|
||||
问题集中在三点:**投递事实少了一态**、**事件与 Alert 的关联无法双向导航**、**值班场景缺交接班**。另外 Area 的归属需要一次跨文档裁决——并且要修正我此前在《12》S-03 里的建议。
|
||||
|
||||
---
|
||||
|
||||
## 1. 做对的(点名保护,重写时别丢)
|
||||
|
||||
| 项 | 证据 |
|
||||
| --- | --- |
|
||||
| **静默对话框** | 4h 写死在选项里标「(上限)」、原因必填、到期自动恢复,且明确**排除 S1 高危事件与设备离线运维告警** |
|
||||
| **误报对话框** | 「这只会追加事件 outcome,不会修改原始事件事实和证据」;原因必填;进复核队列 |
|
||||
| **规则对话框** | 场景模板 / 继承与覆盖 / 摄像头 / **检测区域带版本号 `ZONE-007 · v7`** / 生效时段 / 持续时间;试运行复选框**默认勾选**;主按钮是「保存并开始试运行」而不是「保存」 |
|
||||
| 规则与区域解耦 | 「空间坐标由摄像头详情维护」「**区域版本变化不会绕过规则试运行或自动正式发布**」——精确回应 T-004 不可变约束 |
|
||||
| **人脸能力零出现** | 全文 `人脸` 出现 **0** 次。IX-013 要求未授权租户「能力不存在而非按钮置灰」,零出现就是正确实现 |
|
||||
| Area 策略对话框 | `capture_policy` 二选一、变更原因必填进审计、生成新策略版本;并写明「**Sense 投影同步前会显示旧版本,不允许绕过后端准入检查**」 |
|
||||
| 策略冲突处置 | `policyConflictDialog` = IX-016 要求的「已有设备遇策略变化的显式处置流程」 |
|
||||
| 弱网与权限状态 | 「结构化事件已到达,视频证据暂不可用」(渐进加载)、「没有查看此站点证据的权限」 |
|
||||
| 投递时间线 | 三级链、每级时间、当前级「已送达,未确认」、下一级「预计 23:16:10 · 尚未发送」 |
|
||||
|
||||
---
|
||||
|
||||
## 2. P0
|
||||
|
||||
### 2.1 「已发出」与「已送达」被合并了
|
||||
|
||||
**证据**:全文 `已发出` 出现 **0** 次,`已送达` 4 次,`已看到` 1 次。
|
||||
|
||||
**依据**:
|
||||
|
||||
- `02-requirements` §3.4:「区分**已发出、已送达、已看到**;**没有回执不能当成功**」
|
||||
- T-004 不可变约束:「Alert 的**首次投递、送达、看到、ack 和升级**必须分开展示」
|
||||
|
||||
**问题**:时间线目前只有「已送达」这一档,无法表达**发出了但没拿到回执**——而这恰恰是告警系统最重要的失败态。短信网关返回 `202 Accepted` 不等于用户手机收到;语音呼叫接通不等于有人听。把 sent 直接显示成 delivered,正是那句「没有回执不能当成功」要防的事。
|
||||
|
||||
**建议**:投递时间线每一级至少四态,且**未拿到回执时必须显式呈现**:
|
||||
|
||||
```
|
||||
已发出 23:14:10 → 已送达 23:14:12 → 已看到 23:14:31 → 已确认 23:14:40
|
||||
已发出 23:14:13 → ⚠ 未收到回执(已等待 42s)
|
||||
```
|
||||
|
||||
对应 IX-007「失败不能伪装成功」,建议把这条从抽象要求细化为四态时间线的明确规格。
|
||||
|
||||
### 2.2 事件与 Alert 的关联无法双向导航
|
||||
|
||||
**依据**:`04-architecture` §8 明写——
|
||||
|
||||
> Event 与 Alert 不合并:**一个事件可触发多次预警与投递,一次预警也可聚合多个事件**。
|
||||
|
||||
**问题**:原型有「事件中心」和「值班台(待处置预警)」两个入口,方向是对的。但看不到这一对多/多对一关系的表达:
|
||||
|
||||
- 从一条 Alert 打开,它聚合了哪几条 Event?
|
||||
- 从一条 Event 打开,它触发过几次 Alert、分别什么结局?
|
||||
|
||||
这是 Bell 最核心的数据模型。如果 UI 上表达不出来,实现时极易退化成 Event 与 Alert 一对一,而聚合、去重、已处置抑制全部依赖这个多对多关系。
|
||||
|
||||
**建议**:Alert 详情增加「关联事件」列表(含聚合原因:同设备冷却 / 同站点聚合 / 已处置抑制);Event 详情增加「触发的预警」列表(含每次的最终状态)。两边互为深链。
|
||||
|
||||
### 2.3 Area 的归属需要裁决 —— 并修正我此前的建议
|
||||
|
||||
**现状**:Bell 原型把 Area 的 CRUD 与 `capture_policy` 编辑放在「站点与 Area」页。
|
||||
|
||||
**我的判断:这个归属比我此前的建议更对。** 我在《12》S-03 里把「站点与 Area 管理」列为 Sense 的待办,那是错的——Area 是带合规策略的**组织实体**,而 Bell 拥有 Site(配额真相源)、租户、RBAC 和审计。Area 作为 Site 的子级归 Bell 一致性更好。
|
||||
|
||||
**但由此产生两个后果,必须一并处理**:
|
||||
|
||||
1. **《12》S-03 需改写**:Sense 侧应为 Area **只读** + 设备写路径的准入拒绝;CRUD 归 Bell。原文的「Area 增删改」要移出 Sense 待办
|
||||
2. **跨 schema 读从一处变成两处**(配额 + Area 策略)。Bell 原型自己写了「Sense 投影同步前会显示旧版本」——这个窗口期正是投影方案的固有代价。而《13》A-2 建议的同库只读视图**可以直接消除它**:视图无同步延迟,Sense 读到的永远是当前策略版本
|
||||
|
||||
A-2 的价值因此翻倍,建议提到裁决队列最前。
|
||||
|
||||
---
|
||||
|
||||
## 3. P1
|
||||
|
||||
### 3.1 缺交接班
|
||||
|
||||
`routes.md`「值班台/大屏」节明写:「声光提示、ack 与**交接班记录**」。全文 `交接班` 出现 **0** 次。
|
||||
|
||||
这是值班室最真实的场景:22:00 换班,上一班未处置的预警怎么移交、新一班如何确认接手。没有交接班,「有人负责」这个产品承诺在班次边界上断掉。
|
||||
|
||||
**建议**:值班台增加交接班动作——列出未关闭预警、交接人与接手人、接手确认进审计;交接期间的升级链不中断。
|
||||
|
||||
### 3.2 并发 ack 的结果未表达
|
||||
|
||||
IX-006 要求「并发 ack 有清晰结果」。两个值班员同时点 ack 会怎样,原型没有表达。
|
||||
|
||||
**建议**:明确为「先到者成为处置人,后到者收到明确提示并看到当前处置人」,而不是静默覆盖或双双成功。
|
||||
|
||||
### 3.3 重启续跑不可观测
|
||||
|
||||
`02-requirements` §3.4「进程重启后能续跑」、`04-architecture` §7「Alert 先落库再投递,进程重启恢复未完成升级链」。
|
||||
|
||||
这是一条很强的可靠性承诺,但 UI 上没有任何可验证的表达。运维无法确认它真的生效。
|
||||
|
||||
**建议**:升级时间线中标注「服务重启于 23:15:02,升级链已恢复」这类事件;系统状态页给出「待恢复升级链 N 条」的指标。
|
||||
|
||||
### 3.4 状态覆盖:多了两个好的,少了整组失败态
|
||||
|
||||
**实测状态演示**:`normal / loading / empty / denied / weak` —— 五态,比 Sense 的四态更好:
|
||||
|
||||
- `denied` 无权限 → 对应 IX-013
|
||||
- `weak` 结构化事件已到、视频证据暂不可用 → 对应 App 节「弱网下先显示结构化事件,再渐进加载抓拍/视频」
|
||||
|
||||
这两个是一等演示态,不只是文案。
|
||||
|
||||
**但一个失败态都没有。** IX 清单「全局状态」节要求每个页面至少评估:
|
||||
|
||||
> 初始、加载、空数据、成功、**部分成功、可重试失败、不可重试失败**;无权限、**会话过期、网络断开、后端超时、数据已被他人修改**。
|
||||
|
||||
Bell 覆盖了加载 / 空 / 无权限,缺整组失败语义。其中两个对 Bell 尤其关键:
|
||||
|
||||
| 缺失态 | 为什么对 Bell 关键 |
|
||||
| --- | --- |
|
||||
| **数据已被他人修改** | 正是 §3.2 并发 ack 的表现形式,也是规则版本冲突的表现形式。缺它,两个问题都没有落点 |
|
||||
| **可重试 / 不可重试失败** | 投递失败要区分「短信网关超时,会重试」与「号码无效,不会重试」。IX-007「失败不能伪装成功」的另一半 |
|
||||
|
||||
**建议**:状态演示补 `conflict`(数据已被他人修改)与 `error-retryable` / `error-final` 两类失败态。
|
||||
|
||||
### 3.5 事件中心与审计缺分页
|
||||
|
||||
全文 `分页` 出现 **0** 次。`routes.md` 对 `/events` 要求分页与筛选,对 `/audit` 要求「只读、分页、按权限脱敏」。与 Sense 是同一个问题。
|
||||
|
||||
---
|
||||
|
||||
## 4. P2
|
||||
|
||||
### 4.1 规则回滚偏薄
|
||||
|
||||
`回滚` 出现 1 次。IX-011 要求「支持取消/回滚」。试运行做得很扎实,但从「已正式发布」回退到「试运行」或「上一版本」的路径没有展开。
|
||||
|
||||
### 4.2 报表口径未对齐验收要求
|
||||
|
||||
`02-requirements` §8 规定:
|
||||
|
||||
> 效果指标**按规则分别报告召回率与每路每天误报数**;不使用跨场景统一「准确率」。
|
||||
|
||||
报表页目前是「近 7 日预警量」「处置结果」。这两个是运营口径,不是**验收口径**。而验收口径是要签进站点验收附件的,报表必须能直接出。
|
||||
|
||||
**建议**:报表页增加按规则维度的召回率与「每路每天误报数」,并显式标注「不提供跨场景统一准确率」——这句话本身就是对客户预期的管理。
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议顺序
|
||||
|
||||
| 顺序 | 条目 | 理由 |
|
||||
| --- | --- | --- |
|
||||
| 1 | §2.1 投递四态 | 需求原文的硬要求,且是告警系统最重要的失败态 |
|
||||
| 2 | §2.2 Event↔Alert 双向导航 | 核心数据模型,画不出来实现就会退化成一对一 |
|
||||
| 3 | §2.3 Area 归属裁决 + 修订《12》S-03 + 提前 A-2 | 一次裁决消掉三处不一致 |
|
||||
| 4 | §3.1 交接班 | 值班场景的真实断点 |
|
||||
| 5 | §3.4 状态覆盖 | 补 `conflict` 态可同时给 §3.2 并发 ack 和规则版本冲突一个落点,一处改动解两个问题 |
|
||||
| 6 | §3.2、§3.3、§3.5 | 并发 ack、重启续跑可观测、分页 |
|
||||
| 6 | §4.1、§4.2 | 回滚与报表口径 |
|
||||
Reference in New Issue
Block a user