docs(task): record T-014 16-stream baseline
Harness governance / validate (push) Has been cancelled
Harness governance / validate (pull_request) Has been cancelled

This commit is contained in:
QiuSW
2026-08-10 23:16:12 +08:00
parent d029067aa7
commit b9e21a95d1
8 changed files with 172 additions and 11 deletions
+16
View File
@@ -138,3 +138,19 @@ Linux amd64 使用同版 `mediamtx_v1.19.3_linux_amd64.tar.gz`,SHA-256 为 `a7
``` ```
`ip_camera.env` 必须保持在 Git 忽略范围内。调试时可把 `-ObservationMinutes` 降为 1;正式 T-006 证据必须使用默认 30 分钟,且最终 `maximum_unconverged`、`final_unconverged` 都为 0。 `ip_camera.env` 必须保持在 Git 忽略范围内。调试时可把 `-ObservationMinutes` 降为 1;正式 T-006 证据必须使用默认 30 分钟,且最终 `maximum_unconverged`、`final_unconverged` 都为 0。
## T-014 本地 16 路容量基线
T-014 不访问摄像头或客户网络。脚本使用隔离 PostgreSQL v5、真实 Control API、两套 MediaMTX 和 16 个独立的 FFmpeg `-c copy` 合成 publisher,验证 17 路配额拒绝、三轮批量启停、`16 → 0 → 16` Path 收敛、固定四路故障隔离/恢复,以及 30 分钟稳定性和资源观测。
从仓库根目录执行预检、短窗口调试和正式验收:
```powershell
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -PreflightOnly
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -ObservationMinutes 1 -OutputPath (Join-Path $env:TEMP 'yovision-t014-smoke.json')
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -OutputPath (Join-Path $env:TEMP 'yovision-t014-formal.json')
```
只有默认不少于 30 分钟且输出 `formal_eligible=true` 的单次完整运行可作正式证据;调试窗口固定标记为 false。脚本要求 PostgreSQL 17.10、MediaMTX v1.19.3、FFmpeg 8.1.2 和 `Sense/` 模块的 Go 1.26.5,只使用随机回环端口,运行后清理临时媒体、二进制、PGDATA 和秘密文件。结果 JSON 不含 token、DSN、端口、设备 ID 或流地址。
2026-08-10 正式结果为 `1800.1 s / 180` 个 10 秒样本,最大/最终 `unconverged=0`、最终在线 Path 16、帧错误 0;完整版本、资源数据、失败记录和适用边界见 [`../docs/research/sense-16-stream-capacity.md`](../docs/research/sense-16-stream-capacity.md)。该结果只是本机低码率合成负载的软件基线,不代表真实 16 摄像头、客户网络、录像、AI/GPU、64/128 路或生产 SLA。
+4 -2
View File
@@ -40,13 +40,13 @@ MVP 以默认 16 路跑通一个场景的端到端闭环;架构、数据和 UI
## 当前阶段 ## 当前阶段
当前为 **M0 指定型号实机准入与 M1 Sense 五路混合源集成均已完成,M2 正在补齐生产接入边界**。后续本地开发统一使用已准入的一台海康样机,多路软件闭环使用独立合成 RTSP 源补足;真实多设备证据延后到客户/借用/租赁条件具备时执行。 当前为 **M0 指定型号实机准入、M1 Sense 五路混合源集成和 M2 本地 16 路软件基线均已完成,正在转入 M3 的 Bell/Brain 最小闭环**。后续本地开发统一使用已准入的一台海康样机,多路软件闭环使用独立合成 RTSP 源补足;真实多设备证据延后到客户/借用/租赁条件具备时执行。客户网络尚未提供,T-013 WireGuard 继续后置,不阻塞 Bell 事件存储与审计 relay 边界设计。
优先路径: 优先路径:
1. M0:已用一台真实样机完成首期指定“型号 + 硬件版本 + 固件”ONVIF/RTSP 准入;结论不外推为多品牌兼容,真实断网恢复证据按负责人豁免留痕。 1. M0:已用一台真实样机完成首期指定“型号 + 硬件版本 + 固件”ONVIF/RTSP 准入;结论不外推为多品牌兼容,真实断网恢复证据按负责人豁免留痕。
2. M1:只在 `Sense/` 建立 MediaMTX 生产接入骨架,以 1 路准入实机 + 至少 4 路独立合成源完成五路自动建 path、探活和断线重建。 2. M1:只在 `Sense/` 建立 MediaMTX 生产接入骨架,以 1 路准入实机 + 至少 4 路独立合成源完成五路自动建 path、探活和断线重建。
3. M2:Control API、多租户投影、调和 fencing、孤儿安全闸已完成;下一步是隧道和至少一个站点的 16 路全流程。 3. M2:Control API、多租户投影、调和 fencing、孤儿安全闸和本地 16 路批量收敛/30 分钟稳定基线已完成;WireGuard 等客户网络条件具备后补验。
4. M3:Brain + Bell 起步,默认 16 路端到端事件、预警、ack 与误报反馈。 4. M3:Brain + Bell 起步,默认 16 路端到端事件、预警、ack 与误报反馈。
5. M4–M5:64/128 路分片、管理端和第二/第三场景包。 5. M4–M5:64/128 路分片、管理端和第二/第三场景包。
@@ -92,3 +92,5 @@ go -C Sense build ./...
``` ```
日常优先运行根目录 `./init.ps1` 或 `./init.sh`,它会执行上述治理、生成、测试、静态检查和构建门禁。Sense 本地启动为 `go -C Sense run ./cmd/sense-api`;默认只监听回环地址,具体配置、MediaMTX 版本与校验方法见 [`03-tech-stack.md`](03-tech-stack.md) 和 [`../Sense/README.md`](../Sense/README.md)。 日常优先运行根目录 `./init.ps1` 或 `./init.sh`,它会执行上述治理、生成、测试、静态检查和构建门禁。Sense 本地启动为 `go -C Sense run ./cmd/sense-api`;默认只监听回环地址,具体配置、MediaMTX 版本与校验方法见 [`03-tech-stack.md`](03-tech-stack.md) 和 [`../Sense/README.md`](../Sense/README.md)。
本机 16 路软件容量基线使用 `./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17`;正式证据必须使用默认 30 分钟窗口,且只证明固定低码率合成负载。结果与限制见 [`research/sense-16-stream-capacity.md`](research/sense-16-stream-capacity.md)。
+3 -1
View File
@@ -54,6 +54,8 @@ T-011 复用同一套冻结的 Go、PostgreSQL、pgx 与 `oapi-codegen`,未增
T-012 同样未增加第三方依赖:PostgreSQL v5 使用数据库时钟租约和 fencing token 协调多实例调和/孤儿扫描;MediaMTX Path 枚举继续使用同版生成客户端。`/metrics` 由 Go 标准库输出 Prometheus 文本格式,只包含固定结果枚举、构建/实例信息和汇总 gauge/counter,不使用 tenant、Site、device 或 Path 标签。孤儿处置是 PostgreSQL 专用本地命令,默认周期任务只报告、不自动删除。 T-012 同样未增加第三方依赖:PostgreSQL v5 使用数据库时钟租约和 fencing token 协调多实例调和/孤儿扫描;MediaMTX Path 枚举继续使用同版生成客户端。`/metrics` 由 Go 标准库输出 Prometheus 文本格式,只包含固定结果枚举、构建/实例信息和汇总 gauge/counter,不使用 tenant、Site、device 或 Path 标签。孤儿处置是 PostgreSQL 专用本地命令,默认周期任务只报告、不自动删除。
T-014 没有增加生产依赖。Windows 容量脚本冻结并核对 Sense 模块 Go 1.26.5、PostgreSQL 17.10、MediaMTX v1.19.3 与 FFmpeg 8.1.2;MediaMTX Windows amd64 ZIP 使用上表官方 SHA-256,解压后 `mediamtx.exe` 另固定为 `1cda85249312cb9463f9f94c5a712b9f160c9af3fd9490f0d4723911d7880e05`。FFmpeg 只生成无人物夹具并以 16 个独立 `-c copy` 进程发布,不进入生产镜像或 Go module。正式本机结果与限制见 [`research/sense-16-stream-capacity.md`](research/sense-16-stream-capacity.md)。
## 2. 外部项目边界 ## 2. 外部项目边界
- MiBeeNvr:只用于 M0 隔离实验室、ONVIF兼容性和交互参考,不作为生产依赖。 - MiBeeNvr:只用于 M0 隔离实验室、ONVIF兼容性和交互参考,不作为生产依赖。
@@ -115,6 +117,6 @@ python scripts/validate_harness_governance.py
| PostgreSQL schema/repository | `python -m unittest discover -s tests -p "test_postgres_contract.py"`;Windows 本机再运行 `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17` | migration、权限、配额判定或 PostgreSQL driver 变化 | 不需要摄像头;必须核对临时集群未使用现有 data 目录,现有 5432 listener 前后不变 | | PostgreSQL schema/repository | `python -m unittest discover -s tests -p "test_postgres_contract.py"`;Windows 本机再运行 `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17` | migration、权限、配额判定或 PostgreSQL driver 变化 | 不需要摄像头;必须核对临时集群未使用现有 data 目录,现有 5432 listener 前后不变 |
| Brain Python | 单元测试、类型/格式检查(命令待项目脚手架冻结) | mapper、判定状态机、模型接口变化 | 命中模型任务时用冻结数据集和目标硬件 | | Brain Python | 单元测试、类型/格式检查(命令待项目脚手架冻结) | mapper、判定状态机、模型接口变化 | 命中模型任务时用冻结数据集和目标硬件 |
| Bell Go/Web | 后端测试 + 前端 lint/test/build(命令待脚手架冻结) | schema、RBAC、预警状态机或公共 UI 变化 | P0 流程由产品/值班角色验收 | | Bell Go/Web | 后端测试 + 前端 lint/test/build(命令待脚手架冻结) | schema、RBAC、预警状态机或公共 UI 变化 | P0 流程由产品/值班角色验收 |
| 容量/分片 | 任务内基准脚本 | 16/64/128 路里程碑 | 目标网络、媒体和 GPU 硬件必需 | | 容量/分片 | 任务内基准脚本;本地 16 路入口为 `./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17` | 默认 16 路软件基线,以及后续 64/128 路分片里程碑 | 本地 16 路控制面可用独立合成源;真实多路、生产 SLA、64/128 路、AI/GPU、网络与存储必须使用目标环境分别验收 |
代码脚手架落地时必须把真实命令同步到本文、`init.ps1`/`init.sh`、`00-ai-start-here.md` 和 `current-state.md`。 代码脚手架落地时必须把真实命令同步到本文、`init.ps1`/`init.sh`、`00-ai-start-here.md` 和 `current-state.md`。
+3 -1
View File
@@ -79,6 +79,8 @@ Sense ── 视频流/触发信号 ──> Brain
- 单分片故障不能扩散到其他分片。 - 单分片故障不能扩散到其他分片。
- 管理端默认查看 16 路,但按 128 路设计分页、虚拟列表、筛选和批量操作。 - 管理端默认查看 16 路,但按 128 路设计分页、虚拟列表、筛选和批量操作。
T-014 已在单台 Windows 主机上用隔离 PostgreSQL、真实 Control API、单个生产 MediaMTX 和 16 个独立低码率合成 publisher 完成 `16 → 0 → 16` 批量收敛、四路发布故障隔离/恢复和 `1800.1 s / 180` 样本稳定观察,最大/最终 `unconverged=0`。这只证明默认 16 路的本地软件控制面与拉流基线,不改变上述分片架构:`media_shard.max_streams=32` 仍是待 64/128 路目标环境压测的初始建议,不能从 T-014 推导单机、真实摄像头、AI/GPU、存储或生产 SLA。完整证据见 [`research/sense-16-stream-capacity.md`](research/sense-16-stream-capacity.md)。
## 7. 一致性与失败处理 ## 7. 一致性与失败处理
- PostgreSQL `sense` schema 是生产期望态真相源;SQLite 只保留为 M1 本地开发/回归路径。MediaMTX、推理 worker 和对象存储是可对账的实际态。 - PostgreSQL `sense` schema 是生产期望态真相源;SQLite 只保留为 M1 本地开发/回归路径。MediaMTX、推理 worker 和对象存储是可对账的实际态。
@@ -120,7 +122,7 @@ Sense 脚手架和 PostgreSQL `001`~`011` 已实现;Brain/Bell 应用目录
- M0 不写生产代码。 - M0 不写生产代码。
- M1 只动 Sense,以 1 路 T-001 准入实机 + 至少 4 路独立合成 RTSP 源完成五路接入骨架与 MediaMTX;设备模型从此时起保持模态/能力可扩展,但不提前实现非视频适配器。真实多设备现场门禁移到 T-007,阻塞生产试点但不阻塞本地开发。 - M1 只动 Sense,以 1 路 T-001 准入实机 + 至少 4 路独立合成 RTSP 源完成五路接入骨架与 MediaMTX;设备模型从此时起保持模态/能力可扩展,但不提前实现非视频适配器。真实多设备现场门禁移到 T-007,阻塞生产试点但不阻塞本地开发。
- M2 仍以 Sense 为主,完成 16 路开通/停用、对账、多租户投影与隧道。 - M2 仍以 Sense 为主;Control API、对账、多租户投影和本地 16 路开通/停用基线已完成,隧道等待客户网络条件后补验。
- M3 Brain 与 Bell 同时起步,事件契约首次被真实使用。 - M3 Brain 与 Bell 同时起步,事件契约首次被真实使用。
- M4/M5 再做 64/128 路分片、完整管理端和多个场景包;M6 接入雷达、门磁、按钮和可穿戴等非视频适配器。 - M4/M5 再做 64/128 路分片、完整管理端和多个场景包;M6 接入雷达、门磁、按钮和可穿戴等非视频适配器。
+1 -1
View File
@@ -28,7 +28,7 @@
- T-011:按 T-008 契约实现认证 tenant 上下文、7 个设备/operation handler、PostgreSQL 幂等收据、ETag/HMAC cursor、最多 128 项批量操作和停用精确 path 收敛;公共控制 API 默认关闭且只在 PostgreSQL 路径启用。 - T-011:按 T-008 契约实现认证 tenant 上下文、7 个设备/operation handler、PostgreSQL 幂等收据、ETag/HMAC cursor、最多 128 项批量操作和停用精确 path 收敛;公共控制 API 默认关闭且只在 PostgreSQL 路径启用。
- T-012:以 PostgreSQL 数据库时钟租约和 fencing token 防止多实例重复调和;增加可证明的 Path 历史归属、默认只读孤儿报告、15 分钟二次确认、10% 不可绕过安全闸和低基数 `/metrics`。 - T-012:以 PostgreSQL 数据库时钟租约和 fencing token 防止多实例重复调和;增加可证明的 Path 历史归属、默认只读孤儿报告、15 分钟二次确认、10% 不可绕过安全闸和低基数 `/metrics`。
- T-013(后置,尚未创建):WireGuard 边缘隧道与断网恢复;等待客户网络拓扑、地址规划和部署权限,不阻塞本地软件开发。 - T-013(后置,尚未创建):WireGuard 边缘隧道与断网恢复;等待客户网络拓扑、地址规划和部署权限,不阻塞本地软件开发。
- T-014:使用隔离 PostgreSQL、真实 Control API 和 16 个独立本地合成 publisher,完成批量开通/停用、局部故障恢复和资源观测;只形成实验室软件基线,不替代 T-007/T-013 或生产 SLA。 - T-014:使用隔离 PostgreSQL、真实 Control API 和 16 个独立本地合成 publisher,完成批量开通/停用、局部故障恢复和资源观测;正式基线为 `1800.1 s / 180` 样本、最大/最终 `unconverged=0`,仍只形成实验室软件证据,不替代 T-007/T-013 或生产 SLA。
## M3:首个 16 路端到端 MVP ## M3:首个 16 路端到端 MVP
+15 -5
View File
@@ -1,11 +1,11 @@
# 当前实现状态 # 当前实现状态
> 快照日期:2026-08-07。只记录仓库现实与 blocker;任务实时状态到 Gitea Issue 查看。 > 快照日期:2026-08-10。只记录仓库现实与 blocker;任务实时状态到 Gitea Issue 查看。
## 当前阶段 ## 当前阶段
- 阶段:M0 指定摄像头型号准入已完成;M1 的“一实机 + 四合成源”实验室软件闭环已通过;M2 已完成 Control API、Site/Area 准入、本地审计事务、多实例调和 fencing 和孤儿受控处置基础,但 WireGuard、16 路容量出口、五条独立真实上游和生产 SLA 尚未验收。 - 阶段:M0 指定摄像头型号准入、M1“一实机 + 四合成源”软件闭环和 M2 本地 16 路批量收敛/稳定基线已通过;客户网络尚未提供,WireGuard T-013 后置,五条独立真实上游和生产 SLA 仍未验收。下一开发重点转向 M3 的 Bell 事件存储与审计 relay 边界。
- 生产代码:Sense 已包含可构建进程、SQLite/PostgreSQL repository、Site/Area 准入、设备操作 Outbox、标准 ONVIF SOAP/WS-Security adapter、凭据引用、MediaMTX 生成客户端、Control API v1、对账/探活、数据库租约、孤儿只读扫描/受控命令和低基数指标;Bell 管理服务/JWT、Outbox relay、WireGuard 和完整生产部署仍未实现。 - 生产代码:Sense 已包含可构建进程、SQLite/PostgreSQL repository、Site/Area 准入、设备操作 Outbox、标准 ONVIF SOAP/WS-Security adapter、凭据引用、MediaMTX 生成客户端、Control API v1、对账/探活、数据库租约、孤儿只读扫描/受控命令、低基数指标和可重复 16 路容量脚本;Bell 管理服务/JWT、Outbox relay、WireGuard 和完整生产部署仍未实现。
- 默认容量:16 路;单站点本阶段上限 128 路,必须横向分片。 - 默认容量:16 路;单站点本阶段上限 128 路,必须横向分片。
## 仓库现实 ## 仓库现实
@@ -18,6 +18,7 @@
- MediaMTX 固定为独立二进制 `v1.19.3`,官方 OpenAPI 已按 SHA-256 vendoring,并由固定 `oapi-codegen v2.8.0` 生成客户端;手写薄封装有 create/read/delete、幂等 ensure、探活和只返回名称的受限分页枚举测试。 - MediaMTX 固定为独立二进制 `v1.19.3`,官方 OpenAPI 已按 SHA-256 vendoring,并由固定 `oapi-codegen v2.8.0` 生成客户端;手写薄封装有 create/read/delete、幂等 ensure、探活和只返回名称的受限分页枚举测试。
- T-003 对账进度与指数退避持久化,覆盖取消和 SQLite 重启恢复;T-006 增加真实 ONVIF adapter、RTSP router、实验室播种/状态工具、故障代理和五路自动验收。T-012 的普通调和不枚举孤儿;独立 PostgreSQL 扫描默认只报告,未知归属永不删除。 - T-003 对账进度与指数退避持久化,覆盖取消和 SQLite 重启恢复;T-006 增加真实 ONVIF adapter、RTSP router、实验室播种/状态工具、故障代理和五路自动验收。T-012 的普通调和不枚举孤儿;独立 PostgreSQL 扫描默认只报告,未知归属永不删除。
- T-006 正式使用 1 台准入实机和 4 个独立合成 publisher 连续观察 `1806.6 s` / 180 次采样,四类恢复均通过,最大与最终 `unconverged` 均为 0;详细证据见 `docs/research/sense-5-stream-integration.md`。 - T-006 正式使用 1 台准入实机和 4 个独立合成 publisher 连续观察 `1806.6 s` / 180 次采样,四类恢复均通过,最大与最终 `unconverged` 均为 0;详细证据见 `docs/research/sense-5-stream-integration.md`。
- T-014 正式使用隔离 PostgreSQL、真实 Control API、两套 MediaMTX 和 16 个独立低码率合成 publisher,完成 17 路配额拒绝、三轮 `16 → 0 → 16` 批量收敛和固定四路故障恢复;稳定观察 `1800.1 s` / 180 次采样,最大与最终 `unconverged` 均为 0、最终在线 Path 16、帧错误 0。证据见 `docs/research/sense-16-stream-capacity.md`;不外推到真实 16 机、网络、录像、AI/GPU、64/128 路或生产 SLA。
- `docs/raw/01`~`08` 已记录需求、分析、方案、客户场景、事件比对和三系统职责。 - `docs/raw/01`~`08` 已记录需求、分析、方案、客户场景、事件比对和三系统职责。
- `docs/raw/contracts/event-v0.1.schema.json` 已冻结,并有多份示例与语义说明。 - `docs/raw/contracts/event-v0.1.schema.json` 已冻结,并有多份示例与语义说明。
- `docs/contracts/sense-control-v1.openapi.json` 的 7 个站点作用域/operation endpoint 已由 T-011 实现:外部静态 SHA-256 主体注册表、tenant/Site scope、HMAC cursor、ETag、PostgreSQL 24 小时幂等收据和最多 128 项 batch operation 均有代码与隔离集成测试。默认 SQLite 只暴露运维探针与低基数 `/metrics`,不注册业务路由;Bell 管理服务、JWT/OIDC 和 Outbox relay 尚未实现。 - `docs/contracts/sense-control-v1.openapi.json` 的 7 个站点作用域/operation endpoint 已由 T-011 实现:外部静态 SHA-256 主体注册表、tenant/Site scope、HMAC cursor、ETag、PostgreSQL 24 小时幂等收据和最多 128 项 batch operation 均有代码与隔离集成测试。默认 SQLite 只暴露运维探针与低基数 `/metrics`,不注册业务路由;Bell 管理服务、JWT/OIDC 和 Outbox relay 尚未实现。
@@ -56,6 +57,15 @@ python scripts/validate_harness_governance.py
./scripts/test_postgres.ps1 -PgRoot D:\pgsql17 ./scripts/test_postgres.ps1 -PgRoot D:\pgsql17
``` ```
本机 16 路软件容量预检与正式验证:
```powershell
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -PreflightOnly
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -OutputPath (Join-Path $env:TEMP 'yovision-t014-formal.json')
```
只有默认 30 分钟且输出 `formal_eligible=true` 的单次完整运行可作正式证据;`-ObservationMinutes 1` 只用于 smoke。
Sense 默认监听 `127.0.0.1:8080`,提供 `/healthz`、`/readyz` 运维探针和低基数 `/metrics`;探针不代表摄像头或 M1 里程碑健康。MediaMTX 获取、校验和独立启动方法见 `Sense/README.md`。 Sense 默认监听 `127.0.0.1:8080`,提供 `/healthz`、`/readyz` 运维探针和低基数 `/metrics`;探针不代表摄像头或 M1 里程碑健康。MediaMTX 获取、校验和独立启动方法见 `Sense/README.md`。
## 当前 blocker / 待确认 ## 当前 blocker / 待确认
@@ -67,12 +77,12 @@ Sense 默认监听 `127.0.0.1:8080`,提供 `/healthz`、`/readyz` 运维探针
- 人脸方向已延后至 M5 的 S4 成人园区候选试点;必要性/PIP 影响评估、单独同意与替代方式、合法底库来源和删除流程未完成,阻塞人脸能力上线。 - 人脸方向已延后至 M5 的 S4 成人园区候选试点;必要性/PIP 影响评估、单独同意与替代方式、合法底库来源和删除流程未完成,阻塞人脸能力上线。
- 短信/语音具体供应商未选;生产前必须选定两条独立投递路径并验证故障切换。 - 短信/语音具体供应商未选;生产前必须选定两条独立投递路径并验证故障切换。
- Python/Savant 的精确版本、目标硬件和 Bell 前端栈尚未冻结;Sense M1 的 Go、SQLite driver、MediaMTX、生成器及生成运行时版本已在 T-003 冻结,PostgreSQL/pgx 版本已在 T-009 冻结。 - Python/Savant 的精确版本、目标硬件和 Bell 前端栈尚未冻结;Sense M1 的 Go、SQLite driver、MediaMTX、生成器及生成运行时版本已在 T-003 冻结,PostgreSQL/pgx 版本已在 T-009 冻结。
- 本机现有 PostgreSQL 5432 实例使用 SCRAM 且当前开发进程没有管理员密码;T-009~T-012 不绕过认证,自动验收使用隔离临时集群。向共享/生产实例安装 migration 前仍需管理员私下提供专用数据库、登录角色、外部 Control API 安全文件与备份方案。 - 本机现有 PostgreSQL 5432 实例使用 SCRAM 且当前开发进程没有管理员密码;T-009~T-014 不绕过认证,自动验收使用隔离临时集群。向共享/生产实例安装 migration 前仍需管理员私下提供专用数据库、登录角色、外部 Control API 安全文件与备份方案。
- 代码知识图谱在无业务代码阶段可能为空;工具不可用时使用 `rg` 处理文档与配置。 - 代码知识图谱在无业务代码阶段可能为空;工具不可用时使用 `rg` 处理文档与配置。
## 下一步 ## 下一步
下一项建议先冻结并实施 WireGuard 边缘隧道与断网恢复,再创建 16 路批量开通/停用和分维度容量基准任务;T-012 完成不等于 M2 容量出口。客户授权、借用或租赁条件具备后再执行 T-007 五条独立真实上游现场门禁。T-006 的合成结果不解除 T-007,也不形成容量或生产 SLA 承诺。 客户网络仍未提供,T-013 WireGuard 继续后置。下一项建议拆分并冻结 M3 的 Bell 不可变事件接收/存储,以及 Sense 设备操作 Outbox 到 Bell 全局审计的幂等 relay 协议与实现;两者不要在一个任务中混写。客户授权、借用或租赁条件具备后再执行 T-007 五条独立真实上游现场门禁。T-014 只解除本地默认 16 路软件基线缺口,不解除 T-007/T-013,也不形成真实多路或生产 SLA 承诺。
## 已知风险 ## 已知风险
+109
View File
@@ -0,0 +1,109 @@
# Sense 本地 16 路容量与批量收敛基线
> T-014 正式证据,运行日期:2026-08-10。本文只证明固定主机、固定版本和低码率合成负载下的本地软件基线,不是生产 SLA。
## 1. 结论
在 24 个逻辑处理器、15.78 GiB 内存的 Windows 主机上,提交 `d029067aa750ad75a2d79ef8e6c51b6bad55096d` 使用隔离 PostgreSQL、真实 Sense Control API、两套独立 MediaMTX 和 16 个独立 FFmpeg publisher 完成正式验收:
- 16 个 disabled 视频设备创建后,三轮 16 项批量操作全部成功,生产 MediaMTX 配置 Path 数按 `16 → 0 → 16` 收敛。
- 16 路 enabled 后,第 17 路 enabled 创建稳定返回 `quota_exceeded`,设备台账仍为 16 项;disabled 项不冒充已占用视频通道。
- 同时停止固定第 5~8 路后,精确 4 路受影响、其余 12 路保持在线;恢复后 5.1 秒回到 16 路在线和 `unconverged=0`。
- 正式稳定窗口为 1800.1 秒,每 10 秒绝对节拍采样,共 180 个样本;最大与最终未收敛数均为 0,最终在线 Path 为 16,入站帧错误增量为 0。
因此,默认 16 路的 Sense/PostgreSQL/MediaMTX 控制面与拉流闭环具备可重复的本地软件基线。该结论不证明 16 台真实摄像头、客户网络、录像、下游观看、AI 解码/推理、GPU、64/128 路分片或生产 SLA,也不解除 T-007/T-013。
## 2. 固定环境与负载
| 项目 | 正式值 |
| --- | --- |
| 仓库提交 | `d029067aa750ad75a2d79ef8e6c51b6bad55096d` |
| Sense 二进制 SHA-256 | `e6fa01991152cf7e9f2a1e420422a12d474dfe7be10530ff2924671d46cc7871` |
| Go | `go1.26.5 windows/amd64`(在 `Sense/` 模块上下文读取) |
| PostgreSQL | `17.10`,单次运行隔离临时集群 |
| MediaMTX | `v1.19.3` |
| MediaMTX Windows amd64 ZIP SHA-256 | `5d82148d1032a6a190d9909a2997d9989457aaadf49af87dd02cd4512d31bebe` |
| MediaMTX EXE SHA-256 | `1cda85249312cb9463f9f94c5a712b9f160c9af3fd9490f0d4723911d7880e05` |
| FFmpeg | `8.1.2-full_build-www.gyan.dev` |
| 主机 | Windows,24 logical processors,15.78 GiB memory |
| 单路夹具 | 640×360、10 fps、H.264、无音频、无人物 |
| 发布方式 | 16 个独立 FFmpeg 进程,各自循环预编码夹具并以 `-c copy` 发布独立 RTSP Path |
预编码 copy 发布是为了不把 16 路软件编码负载混入 Sense/MediaMTX 基线。它仍产生 16 个可独立停止和恢复的发布进程,但不能代表真实摄像头编码器、复杂 GOP、高码率、音频或公网抖动。
## 3. 运行方法与安全边界
从仓库根目录执行:
```powershell
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -PreflightOnly
./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -OutputPath (Join-Path $env:TEMP 'yovision-t014-formal-final.json')
```
调试可显式传入 `-ObservationMinutes 1`,但输出固定标记 `formal_eligible=false`,不能作为正式验收。
脚本在系统临时目录生成媒体、Sense 二进制、凭据文件和 PGDATA,只绑定随机回环端口;migration 读取 `001`~`011` 并重复回放,不读取或修改 `D:\pgsql17\data`。结果 JSON 不包含 token、DSN、临时端口、设备 ID、Path/source URI 或凭据引用。正式退出后复查 session、FFmpeg、MediaMTX 和 Sense 数量均为 0,本机现有 5432 listener 前后未变化。
## 4. 功能与时序结果
| 门禁 | 正式结果 |
| --- | ---: |
| 16 个独立 publisher 就绪 | 7.6 s |
| 首轮 enable batch | `succeeded`,16 项,请求 0.041 s |
| 首轮 enable 收敛 | 3.1 s |
| 第 17 路 enabled | 拒绝,`quota_exceeded` |
| disable batch | `succeeded`,16 项,请求 0.015 s |
| disable 收敛 | 1.0 s |
| 第二轮 enable batch | `succeeded`,16 项,请求 0.046 s |
| 第二轮 enable 收敛 | 3.1 s |
| 配置 Path | `16 → 0 → 16` |
| 四路故障检测 | 1.0 s,影响 4 路,其余 12 路在线 |
| 四路恢复 | 5.1 s,最终未收敛 0 |
批量启停使用真实 `/api/v1/sites/{site_id}/devices:batchDesiredState`,每轮提交前重新读取各设备最新 ETag;不能用创建响应中的旧 ETag 与后台调和竞速。每轮 operation 必须为 `succeeded` 且 16 个逐项结果全部成功。
## 5. 30 分钟稳定性与资源观测
| 指标 | 正式结果 |
| --- | ---: |
| 观察时长 | 1800.1 s |
| 采样节拍 / 样本 | 10 s / 180 |
| 最大未收敛数 | 0 |
| 最终未收敛数 | 0 |
| 最终在线 Path | 16 |
| 聚合入站码率 | 15.443 Mbps |
| 入站帧错误增量 | 0 |
| Sense CPU 总时间 | 5.594 s |
| Sense working set 峰值 | 69.99 MiB |
| Sense private bytes 峰值 | 57.58 MiB |
| Sense handle 峰值 | 228 |
| 生产 MediaMTX CPU 总时间 | 26.812 s |
| 生产 MediaMTX working set 峰值 | 45.27 MiB |
| 生产 MediaMTX private bytes 峰值 | 79.23 MiB |
| 生产 MediaMTX handle 峰值 | 295 |
| PostgreSQL 业务库连接峰值 | 3 |
| PostgreSQL 数据库大小 | 8.90 MiB |
归一化 CPU 平均值与峰值在 24 逻辑处理器主机上四舍五入到三位小数后为 0.000%,因此报告保留进程 CPU 总秒数作为低负载证据;不能据此推导通用硬件下限。
## 6. 失败记录与工具修正
正式结论只取最后一次完整成功运行。研发过程中保留以下失败,不拼接为成功证据:
1. MediaMTX 发布 ZIP 与解压后 EXE 的 SHA-256 不同,脚本分别冻结并校验两者。
2. disabled 设备不消耗视频通道;第 17 路门禁改为在 16 路 enabled 后创建 enabled 设备,符合实际配额语义。
3. PowerShell 读取 `application/problem+json` 时可能得到 byte array;脚本显式按 UTF-8 解码后校验稳定错误码。
4. 把 `pg_ctl start` 接入 PowerShell 输出管道会让 PostgreSQL 继承管道句柄并阻塞;启动改为直接执行并检查退出码。
5. Windows 退出时 `sense-api.exe` 曾短暂持有文件锁;清理改为共享截止时间内终止全部进程、完成异步输出读取、释放 `Process` 句柄并重试删除。
6. “固定睡 10 秒再查询”会把查询耗时累计进采样间隔,30 分钟不足 180 个样本;改为按绝对时间点调度第 1~180 个样本。
7. 根目录 Go launcher 为 1.23.0,但 `Sense/go.mod` 冻结并实际构建使用 1.26.5;版本证据改为在 `Sense/` 模块上下文读取。
8. 首轮 batch 曾复用创建响应 ETag,与后台调和的资源版本更新竞速;现在三轮 batch 都在提交前读取最新 ETag,失败诊断只输出状态/错误码计数。
每次失败都没有生成正式成功 JSON,且相关临时 PostgreSQL、媒体和 Sense 进程已停止,单次 session 已清理。
## 7. 后续验收
- T-007 仍需至少 5 条独立真实摄像头上游与现场网络,才能形成真实多路故障隔离和生产试点证据。
- T-013 等客户网络拓扑、地址规划和部署权限具备后,再验证 WireGuard 与断网补传。
- 64/128 路必须在后续任务中分别验证媒体分片、带宽、解码、AI/GPU、证据存储和单分片故障域;本报告不外推这些结论。
- 进入 M3 前应优先冻结并实现 Bell 事件不可变存储,以及 Sense Outbox 到 Bell 全局审计的 relay 边界。
+21 -1
View File
@@ -3,7 +3,7 @@ id: T-014
title: 建立 Sense 本地 16 路批量收敛与容量基线 title: 建立 Sense 本地 16 路批量收敛与容量基线
phase: 2 phase: 2
deps: [T-012] deps: [T-012]
status: DOING status: DONE
created: 2026-08-08 created: 2026-08-08
issue: 47 issue: 47
context_ref: 8ebb8ced492c614106e766192c59b7f13fb4ad0f context_ref: 8ebb8ced492c614106e766192c59b7f13fb4ad0f
@@ -74,6 +74,26 @@ T-006 已证明一台准入实机与四条独立合成源可以完成五路实
## 执行记录 ## 执行记录
### 2026-08-10 正式 16 路基线
- 在提交 `d029067aa750ad75a2d79ef8e6c51b6bad55096d` 执行 `./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -OutputPath (Join-Path $env:TEMP 'yovision-t014-formal-final.json')`,成功输出 `formal_eligible=true`。固定环境为 Go 1.26.5、PostgreSQL 17.10、MediaMTX v1.19.3、FFmpeg 8.1.2;主机为 24 logical processors / 15.78 GiB。
- 16 个独立 publisher 在 `7.6 s` 就绪;三轮 16 项 batch 均 `succeeded`,请求分别为 `0.041 s / 0.015 s / 0.046 s`,收敛分别为 `3.1 s / 1.0 s / 3.1 s`,配置 Path 为 `16 → 0 → 16`。16 路 enabled 后第 17 路 enabled 返回 `quota_exceeded`。
- 固定停止第 5~8 路后 `1.0 s` 检测到精确 4 路受影响,其余 12 路在线;恢复 `5.1 s` 后回到 16 路在线。稳定窗口 `1800.1 s`、10 秒绝对节拍、180 个样本,最大/最终 `unconverged=0`,聚合入站 `15.443 Mbps`,帧错误 0。
- 资源记录:Sense CPU 总计 `5.594 s`、working set 峰值 `69.99 MiB`、private 峰值 `57.58 MiB`、handle 峰值 228;生产 MediaMTX 分别为 `26.812 s / 45.27 MiB / 79.23 MiB / 295`;PostgreSQL 连接峰值 3,数据库 `8.90 MiB`。详细边界与失败记录见 `docs/research/sense-16-stream-capacity.md`。
- 正式退出后复查 T-014 session、FFmpeg、MediaMTX 和 Sense 数量均为 0;结果不含 token、DSN、端口、设备 ID、Path/source URI 或客户信息。本机现有 5432 listener 未被停止或修改。
### 2026-08-10 完整门禁
- PowerShell parser 与 `python -m unittest discover -s tests -p "test_sense_capacity_contract.py" -v` 通过,T-014 静态契约 6/6 通过。
- `./init.ps1` 通过:58 个 Python 测试成功,MediaMTX/Control API 生成漂移检查、全部 Sense Go 包测试、`go vet` 与 `go build` 均成功。
- `./scripts/test_postgres.ps1 -PgRoot D:\pgsql17` 通过:PostgreSQL 17.10 隔离集群重放 `001`~`011`,权限断言与 `yovision/sense/internal/store` 真实 PostgreSQL 测试成功,临时端口和 PGDATA 已清理。
- `python scripts/validate_agent_context.py`、`python -m unittest discover -s tests -p "test_*.py"`(58 项)、`python scripts/validate_harness_governance.py` 与 `git diff --check` 均通过。生成文件只有现有 LF→CRLF 提示,没有内容漂移或任务范围外修改。
### 2026-08-08~2026-08-10 基准工具失败与修正
- 正式结论没有拼接失败样本。依次修复并回归:MediaMTX ZIP/EXE 双指纹、disabled 不占配额、problem+json byte array 解码、`pg_ctl start` 管道句柄继承、Windows EXE 文件锁与进程句柄释放、固定 sleep 导致 30 分钟不足 180 样本、根目录 Go launcher 与 Sense 1.26.5 工具链口径不一致,以及首轮 batch 复用创建 ETag 的调和竞速。
- 中断或失败运行均未输出正式成功 JSON;已核验并停止临时 PostgreSQL,清除精确的单次 session。最终脚本按绝对 10 秒节拍取得 180 个样本,三轮 batch 提交前都读取最新 ETag,清理使用共享截止时间并释放异步输出/进程句柄。
### 2026-08-08 一分钟端到端 smoke ### 2026-08-08 一分钟端到端 smoke
- `./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -ObservationMinutes 1` 通过并输出 `formal_eligible=false`:16 个独立 publisher 全部在线,三轮 16 项 batch 均 `succeeded`,配置 Path 为 `16 → 0 → 16`,第 17 路 enabled 返回 `quota_exceeded` 且台账仍为 16 项。 - `./Sense/scripts/t014-capacity.ps1 -PgRoot D:\pgsql17 -ObservationMinutes 1` 通过并输出 `formal_eligible=false`:16 个独立 publisher 全部在线,三轮 16 项 batch 均 `succeeded`,配置 Path 为 `16 → 0 → 16`,第 17 路 enabled 返回 `quota_exceeded` 且台账仍为 16 项。