Clone
43
Local-Development-and-Verification
ila edited this page 2026-09-01 12:07:17 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

本地开发与验证

环境要求

工具 当前用途 检查命令
Git 版本和工作区保护 git --version
Python 3 Harness 脚本和测试 python --version
Gitea 工单与 Wiki 浏览仓库或调用 MCP
Gitea PAT Wiki 写入 仅由 MCP 或 GITEA_TOKEN 提供,不打印

Sense/Bell 的 Go、Node 与 pnpm 基线已冻结并记录于下文;Brain 的 Python/PyTorch 基线也已由骨架工单固定。PostgreSQL、MediaMTX 的交付版本仍按各产品工单与部署环境冻结,旧仓库环境不自动成为新项目事实。

Windows PowerShell 与 UTF-8

  • Windows 环境优先使用当前已配置的 PowerShell;可选择时优先 PowerShell 7 pwsh.exe,不为设置编码重复启动一层 PowerShell。
  • 文本文件读写在命令支持时显式指定 UTF-8。文件解码与控制台输出分别处理,只有出现真实乱码或已知宿主非 UTF-8 时才调整当前进程输出编码或 Python UTF-8 环境变量。
  • 不默认使用 -ExecutionPolicy Bypass。只有可信脚本确实被策略阻止且没有更小替代方案时,才对该次进程使用并在工单记录原因。

第一次运行

  1. 检查工作区:

    git status --short --branch
    

    预期:显示 main 和本任务创建的引导文件,没有来源不明改动。

  2. 检查 Harness:

    python dev_scripts/harness.py check --strict
    

    预期:输出“DevHarness 检查通过”。

  3. 运行 Harness 测试:

    python -m unittest discover -s tests -v
    

    预期:全部测试为 ok。

  4. 对照 Wiki:

    python dev_scripts/harness.py sync --check
    

    预期:全部映射一致。

子项目命令状态

项目 构建 测试 运行 当前状态
Sense cd Sense/server; go build ./...、cd Sense/ui; corepack pnpm@9.15.1 build:prod go test ./...、go vet ./...、前端 lint/单测、独立 E2E sense server -c <仓库外配置> GoAdmin 产品骨架与独立纵切已于 2026-08-27 通过验收
Brain Brain\.venv\Scripts\python.exe -m pip install -e "Brain[dev]" python -m pytest Brain/tests/test_package.py -q、CPU/CUDA smoke python -m yovision_brain --runtime-info Python/PyTorch 骨架已于 2026-08-27 通过验收;CPU 已验证,CUDA 未验证
Bell cd Bell/server; go build ./...、cd Bell/ui; corepack pnpm@9.15.1 build:prod go test ./...、go vet ./...、前端 lint/单测 go run . server -c config/settings.yml 冻结 GoAdmin 产品骨架已于 2026-08-27 通过验收

不得复制旧仓库命令来填空。每个骨架工单必须同时建立 README、可复制命令和最小测试。

常用调试方式

  • Harness 语法:python -m compileall -q dev_scripts tests。
  • 单测:python -m unittest tests.test_harness_docs -v。
  • 查看差异:git diff --check、git diff。
  • 查看 Wiki 配置:只查看 wiki-docs.json,不得打印 token。
  • 跨项目问题先验证契约,再分别验证生产者和消费者,不直接修改两端猜测修复。

测试数据与日志

  • 只使用合成或脱敏事件、合成 RTSP 和明确授权的实验室设备。ONVIF 自动化测试需覆盖 Basic、Digest challenge、Media 服务发现、跨主机地址归一化、拒绝地址凭据和禁止重定向。
  • 不提交真实视频、客户名称、地址、手机号、摄像头密码或通知凭据;真实设备验证只记录状态与 Profile 数量,不记录设备地址、Authorization 或 Stream URI。
  • 日志必须可按 request/event/alert ID 追踪,但不得记录 Authorization、Cookie 或连接密钥。

完成修改前

python -m unittest discover -s tests -v
python dev_scripts/harness.py check --strict
python dev_scripts/harness.py sync --check
git diff --check
git status --short

业务工单还必须运行其声明的子项目测试;跨契约工单必须运行所有受影响项目的契约测试。未执行部分写入工单。

Sense/Bell 固定工具链与只读参考源

根 goadmin-baseline.json 是机器可读基线。开始 Sense/Bell 骨架或升级工作前,先核对:

Get-Content .\goadmin-baseline.json

git -C D:\github\goadmin\go-admin rev-parse HEAD
git -C D:\github\goadmin\go-admin-ui rev-parse HEAD
git -C D:\github\goadmin\go-admin-doc rev-parse HEAD

go version
node --version
pnpm --version

D:\github\goadmin 下三个仓库只允许读取和核对,不允许在其中开发或提交 yovision 产品代码。本机路径不是跨机器事实;缺少该路径时,应从清单中的上游 URL 检出相同 commit 到仓库外目录。

截至 2026-08-12,系统 Go 1.23.0 仍不满足基线;开发机已在仓库外安装并校验隔离 Go 1.26.5,并通过 Corepack 使用 pnpm 9.15.1。Sense、Bell 的后端测试/构建与前端 lint/build 已在该隔离工具链完成。隔离目录是开发机临时事实,不得写入部署配置;其他机器应从官方来源安装相同精确版本。

go-admin-doc 只用于理解上游框架;项目自己的架构、开发规则和版本事实仍以 yovision Wiki、Agent 规则与 goadmin-baseline.json 为准。

Sense 本地构建与验证

Sense 后端与前端已从冻结源码建立。先确认 Go 1.26.5、Node 22.22.1 和 pnpm 9.15.1,再执行:

cd Sense/server
go test ./...
go vet ./...
go build ./...

cd ../ui
corepack pnpm@9.15.1 install --frozen-lockfile
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

数据库固定为 PostgreSQL。复制 Sense/server/config/settings.yml 到仓库外,填写连接串和至少 32 个字符的随机 JWT 密钥;仓库模板本身不可直接启动生产服务。首次运行先执行 sense migrate -c <配置路径>,再通过只存在于当前进程的高熵令牌启动服务并创建首位管理员:

$env:SENSE_BOOTSTRAP_TOKEN = Read-Host "输入至少 32 个字符的一次性初始化令牌"
sense server -c <配置路径>

# 在另一个 PowerShell 中输入相同令牌;不要把真实值写入脚本或命令历史
$bootstrapToken = Read-Host "输入一次性初始化令牌"
$bootstrapBody = @{
  username = "admin"
  password = Read-Host "输入至少 6 个字符的管理员密码"
  nickname = "系统管理员"
} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:<端口>/api/v1/bootstrap" -Headers @{ "X-Sense-Bootstrap-Token" = $bootstrapToken } -ContentType "application/json" -Body $bootstrapBody
Remove-Variable bootstrapToken, bootstrapBody

初始化成功后停止服务,从启动环境中执行 Remove-Item Env:SENSE_BOOTSTRAP_TOKEN,再按正常生产方式启动。已有任一用户时初始化接口会拒绝请求。Sense 在 production、test、dev 模式均只提交账号和密码,不显示、不请求也不校验验证码;/api/v1/captcha 暂时保留作上游兼容接口,但登录页和登录 API 不依赖它。登录成功、错误密码和未认证拒绝仍必须写入脱敏身份审计,密码继续执行 6–72 字节策略。

Sense 默认登录有效期为固定 30 天。仓库配置和 Windows 运行脚本生成的 jwt.timeout 均为 2592000 秒,前端 Sense-Admin-Token Cookie 使用 30 天持久化期限。更新该版本后必须重新登录,已有 Token 不会自动延长。该有效期不是滑动续期;退出登录会删除本机 Cookie,但当前无状态 JWT 架构不提供服务端单 Token 撤销。如需立即使全部已签发 Token 失效,应在受控维护窗口轮换仓库外 JWT secret,并明确通知所有用户重新登录。

身份回归至少覆盖:admin 可管理账户及查看审计;implementation_operator 只能查看实施所需日志和字典支撑数据;site_admin 可维护账户并读取角色、部门、岗位、字典,但不能修改角色或菜单;viewer 不能访问管理接口。还要验证配置/接口管理路由返回 404、短密码被拒绝、6 位全小写密码可用,以及登录/登出/改密/拒绝审计中不含密码、令牌、Cookie 或验证码。身份审计直接写入 PostgreSQL,不依赖通用操作日志数据库开关。

详细来源与安全约束见 Sense/LICENSES/SOURCES.md 和 Sense/README.md。

设备台账启用凭据写入前,还必须在服务进程环境提供独立随机密钥;示例文件 Sense/server/config/credential.env.example 只保留空值:

# 生成一次随机 32 字节密钥并以 Base64 形式注入当前进程;不要打印或写入仓库
$keyBytes = New-Object byte[] 32
[System.Security.Cryptography.RandomNumberGenerator]::Fill($keyBytes)
$env:SENSE_CREDENTIAL_KEY = [Convert]::ToBase64String($keyBytes)
[Array]::Clear($keyBytes, 0, $keyBytes.Length)

缺少或格式错误的密钥时,普通设备台账仍可读写,但凭据更新返回服务不可用且不得产生部分写入。设备回归至少覆盖:中文名称与位置、未知 JSON 字段拒绝、版本冲突返回 409、非视频设备显示适配器未就绪、viewer 只读、凭据响应/操作日志不含明文,以及 PostgreSQL 迁移重复执行不增加菜单或权限记录。

视频接入还需在仓库外配置 SENSE_ONVIF_DISCOVERY_IP(获准的本机网卡 IP)和 SENSE_ONVIF_ALLOWED_CIDRS(逗号分隔的获准摄像头网段)。不要使用 0.0.0.0/0 代替授权清单。

协议回归位于 app/sense/onvif、app/sense/rtsp、app/sense/admission;隔离 PostgreSQL 重启恢复测试通过 SENSE_ADMISSION_TEST_DATABASE_URL 显式启用。验证至少覆盖 Digest/Basic、无配置发现提示、URL 凭据和敏感查询拒绝、目标网段、重定向、Media/Stream 主机归一化、主子码流、失败重探保留已验证 Profile,以及 viewer 只读权限。 MediaMTX 保持仓库外独立二进制。运行前在进程环境设置:

$env:SENSE_MEDIAMTX_BINARY = '<MediaMTX 可执行文件>'
$env:SENSE_MEDIAMTX_CONFIG = '<仓库外 mediamtx.yml>'
$env:SENSE_MEDIAMTX_API = 'http://127.0.0.1:9997'

配置文件不存在时 Sense 只生成 loopback API 和空 paths: {} 的无凭据基础配置;模板位于 Sense/server/config/mediamtx/mediamtx.yml.example。Control API 不允许非回环地址。真实集成验证使用:

$env:SENSE_MEDIAMTX_TEST_BINARY = '<MediaMTX 可执行文件>'
go test ./tests/media -run TestRealMediaMTXControlLifecycle -v

$env:SENSE_MEDIA_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./tests/media -run TestPostgresColdStartRestoresDesiredRoute -v

$env:SENSE_MEDIA_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestMediaMigrationOnPostgres -v

测试必须使用隔离端口和数据库;结束后停止测试进程。不得输出连接串或摄像头凭据。

Sense 实时监看

浏览器直接访问 Sense 所在主机且 MediaMTX 使用默认 WebRTC 端口 8889 时无需额外变量。反向代理、HTTPS 或端口映射部署必须在 Sense 进程环境提供浏览器可达的基础地址;值只能是无用户信息、查询和片段的 HTTP(S) origin:

$env:SENSE_MEDIAMTX_WEBRTC_PUBLIC_BASE = 'http://<浏览器可达主机>:8889'

不要填写 RTSP 地址、Control API 地址、摄像头凭据或服务器内部文件路径。HTTPS 页面不得嵌入 HTTP 视频地址;应为 MediaMTX WebRTC 配置 HTTPS 或受控同源代理后填写对应 HTTPS origin。

定向与回归验证:

cd Sense/server
go test -race ./app/sense/liveview
go test ./...
go vet ./...
go build ./...

$env:SENSE_LIVEVIEW_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestLiveviewMigrationOnPostgres -count=1 -v

cd ../ui
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

真实 smoke 使用隔离端口、MediaMTX 和合成 RTSP:浏览器打开 WebRTC 播放地址后必须取得非零视频尺寸和可播放 readyState,并确认任一时刻只存在一个播放器。结束后停止测试 MediaMTX/FFmpeg/浏览器并删除临时目录。客户真实摄像机与现场网络仍需获得授权后验证,记录状态而不记录地址、URI 或凭据。

Brain 本地环境与验证

Brain 固定使用 CPython 3.11.15、pip 26.2.1、setuptools 80.9.0、pytest 8.4.2、NumPy 2.3.3 和 PyTorch 2.12.1。CPU 与 CUDA wheel 必须使用不同虚拟环境,不能混装:

uv python install 3.11.15
uv venv --python 3.11.15 Brain/.venv
Brain\.venv\Scripts\python.exe -m pip install pip==26.2.1 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install -e "Brain[dev]" --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install numpy==2.3.3 --index-url https://pypi.org/simple
Brain\.venv\Scripts\python.exe -m pip install torch==2.12.1 --index-url https://download.pytorch.org/whl/cpu

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/test_package.py -q
Brain\.venv\Scripts\python.exe -m yovision_brain --runtime-info
Brain\.venv\Scripts\python.exe -m yovision_brain --smoke cpu

NVIDIA 环境将最后一个索引替换为 https://download.pytorch.org/whl/cu126,再执行 --smoke cuda。本轮只验证了 CPU wheel 与 CPU tensor smoke;不得在未执行真实 CUDA smoke 时声明 GPU 可用。

Bell 本地构建与验证

Bell 已从冻结 GoAdmin 基线独立派生。运行前只在进程环境提供独立的 BELL_DATABASE_URL、至少 32 字符的 BELL_JWT_SECRET,以及仅首次迁移使用的 BELL_BOOTSTRAP_USERNAME / BELL_BOOTSTRAP_PASSWORD;不得提交真实值。

Set-Location Bell/server
$env:GOTOOLCHAIN='go1.26.5'
go test ./...
go vet ./...
go build ./...
go run . migrate -c config/settings.yml
go run . server -c config/settings.yml

Set-Location ../../Bell/ui
corepack pnpm@9.15.1 install --frozen-lockfile
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

默认监听为 127.0.0.1:18090,可用 BELL_HOST / BELL_PORT 覆盖。当前已验证隔离 PostgreSQL 17 的迁移、健康检查、登录、未认证拒绝和 RBAC 菜单;浏览器级前后端登录、生产 PostgreSQL 部署与发布打包尚未验证。

Sense 独立端到端验收

从仓库根目录执行:

& Sense\tests\compatibility\run-static-regression.ps1
& Sense\tests\e2e\run-isolated-e2e.ps1

详细矩阵见 Sense/ACCEPTANCE.md。隔离 E2E 默认需要 PostgreSQL 17 工具目录、已审核的 MediaMTX、FFmpeg 与 Chrome;路径不同时用参数显式指定。所有运行数据、随机凭据、数据库、日志、截图和构建副本位于系统临时目录,只有排错时才使用 -KeepTemporary,并须把保留目录当作敏感数据及时清理。

PowerShell 7 调用入口时会自动转入 Windows PowerShell 5.1 执行本地 HTTP 回归,源码打包仍显式使用 PowerShell 7。这是当前 Windows 交付宿主边界。现场真机、客户新主机、16 路长稳、硬件解码及 Brain/Bell 跨项目链路不在本验收覆盖内。

Sense Windows 打包与验证

在仓库根目录使用冻结工具链构建:

Sense\scripts\build\build-windows.ps1 -MediaMTXPath D:\approved\mediamtx.exe

构建脚本严格检查 Go 1.26.5、Node 22.22.1 和 pnpm 9.15.1,执行前端生产构建与 Windows 后端构建,并生成 Sense\dist\sense-windows-amd64\ 和同名 ZIP。未传 -MediaMTXPath 时只生成占位说明,交付前必须另外提供已审核的 Windows amd64 MediaMTX。构建末尾会执行包审计,并清理源码目录的 Sense/ui/node_modules 与 Sense/ui/dist。

提交前验证:

cd Sense\server
go test ./...
go vet ./...
go build ./...
go test -race ./app/sense/media ./cmd/api

cd ..\..
Sense\scripts\build\test-package.ps1 -PackageRoot Sense\dist\sense-windows-amd64

包内验证从解压目录执行:

check-sense.bat
start-sense.bat
stop-sense.bat

检查项至少覆盖配置解析与进程环境优先级、特殊字符不被执行、production/demo 数据库隔离、迁移失败不启动服务、首页 SPA fallback、/healthz、MediaMTX Control API、包外工作目录启动与停止、PostgreSQL custom-format 备份及恢复到独立数据库。真实摄像机、目标客户数据库账号、目标浏览器与干净客户机器仍须在授权交付环境验收。

GoAdmin 派生前置检查

每个 Sense/Bell 骨架或基础能力工单在修改前必须:

  1. 核对 goadmin-baseline.json 中三个完整 commit。
  2. 核对本机只读副本或重新检出的上游仓库 HEAD。
  3. 阅读任务相关的 go-admin-doc 主题/文件,并把参考项记录到工单。
  4. 记录计划继承的 go-admin/go-admin-ui 路径、计划隐藏/禁用的模块和许可证处理。
  5. 验证最终产品树确实包含上游派生结构;只使用 Go、Vue、Element Plus 或相似视觉不算通过。

Sense 区域与警戒线验证

后端定向与全量验证:

cd Sense/server
go test ./app/sense/area ./app/sense/admission
go test -race ./app/sense/area ./app/sense/admission
go test ./...
go vet ./...
go build ./...

使用隔离 PostgreSQL 验证迁移和真实并发;连接值只放当前进程环境,不写入仓库或日志:

$env:SENSE_AREA_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestAreaMigrationOnPostgres -count=1 -v

$env:SENSE_AREA_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./app/sense/area -run TestConcurrentUpdateOnPostgresReturnsConflict -count=1 -v

前端验证:

cd Sense/ui
corepack pnpm@9.15.1 install --frozen-lockfile
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

浏览器 smoke 至少覆盖:鼠标添加和拖动顶点;键盘 Enter 添加、方向键移动、Delete 删除;错误文字可见并具有 aria-live/alert 语义;刷新后版本、启停和重新校准状态仍可追溯。真实摄像机校准只使用明确授权设备,不记录地址、URI、凭据或视频内容。Brain、Bell 不启动时必须能独立保存、读取和预览。

Sense 本机 Supervisor 托管

本机开发/演示环境可由 D:\supervisor 托管已经构建的 Sense Windows 交付包。实例配置位于仓库外的 D:\supervisor\programs\yovision.conf,实例名为 yovision-sense;工作目录固定为 D:\OPC\yovision\Sense\dist\sense-windows-amd64。

Supervisor 配置只调用包内 scripts\runtime\start-sense.ps1,运行参数继续从包内 config\sense.env 读取。不得把数据库连接、JWT 密钥、摄像头凭据或其他秘密复制到 Supervisor 配置或工单。

常用命令:

D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf status yovision-sense
D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf restart yovision-sense
D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf stop yovision-sense
D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf start yovision-sense
Get-Content D:\supervisor\logs\yovision-sense.log -Tail 100

新增或修改 programs/*.conf 后执行:

D:\supervisor\supervisord.exe ctl /c D:\supervisor\supervisord.conf reload

当前 Go Supervisor 的 reload 会重新读取独立配置;实际受影响实例必须以命令输出和 reload 前后 PID 为准。切换托管前先停止占用 Sense 端口的非 Supervisor 实例,防止自动启动进入 Backoff。验证至少包含 Supervisor 状态为 Running、http://127.0.0.1:18080/health 与首页返回 200,以及受控重启后 Sense 和受管 MediaMTX PID 均更新。

Sense 本地事件验证

合成数据通过 local_event.SeedSyntheticFixture 在测试中显式装载,不存在生产自动开关,也不要求 Brain 或 Bell 进程。定向及回归命令:

cd Sense/server
go test -race ./app/sense/local_event
go test ./...
go vet ./...
go build ./...

cd ../ui
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

PostgreSQL 迁移测试使用独立 schema;连接值只放当前进程环境,不写入仓库或日志:

$env:SENSE_LOCAL_EVENT_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestLocalEventMigrationOnPostgres -count=1 -v

验证应覆盖:candidate/confirmed 与 pending/success/failed 的独立组合、分页和时间/状态/关键词筛选、详情及保留提示、viewer/实施/站点管理员只读权限、操作审计,以及 Brain/Bell 均未启动时的合成候选 smoke。没有可用 PostgreSQL 测试连接时必须明确记录为未验证,不得以 SQLite 单测替代 PostgreSQL 结论。

Sense 运维中心验证

定向验证:

cd Sense/server
go test -race ./app/sense/operations
go test ./app/admin/router ./cmd/migrate/migration/version
go test ./...
go vet ./...
go build ./...

cd ../ui
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

合成 smoke 应覆盖设备认证失败、设备时间漂移、媒体退避、孤儿路由、本地推理 unavailable、筛选分页、详情、设备同步探测重试、媒体排队重试、版本冲突、在途防重和脱敏审计。Brain/Bell 不应启动或成为测试依赖。真实摄像头与 MediaMTX 故障恢复仍须在获准环境验证,日志不得记录设备地址、Stream URI 或凭据。

Sense 边缘节点验证

定向验证:

cd Sense/server
go test -race ./app/sense/edge_node
go test ./cmd/migrate/migration/version -run EdgeNode
go test ./...
go vet ./...

cd ../ui
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

PostgreSQL 迁移测试只在提供隔离连接时执行:

$env:SENSE_EDGE_NODE_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestEdgeNodeMigrationOnPostgres -count=1 -v

验证应覆盖在线、超过 90 秒的离线、心跳恢复但通道未收敛、最后已知状态与陈旧时长、负载和回填队列、不可变状态事件、只读权限、脱敏读取审计,以及 Brain/Bell 不运行时的独立性。合成节点只能由测试或显式开发调用;没有隔离 PostgreSQL 连接时必须记录迁移真库测试未执行。

Sense MediaMTX 分片验证

定向与全量验证:

cd Sense/server
go test -race ./app/sense/media ./app/sense/media_shard ./cmd/migrate/migration/version
go test ./...
go vet ./...

cd ../ui
corepack pnpm@9.15.1 lint
corepack pnpm@9.15.1 test:unit
corepack pnpm@9.15.1 build:prod

cd ../..
powershell.exe -NoProfile -File .\Sense\tests\package\run-tests.ps1

使用真实本机 MediaMTX 二进制验证两个独立测试实例;测试会分配临时回环端口并在结束时停止其自有进程:

cd Sense/server
$env:SENSE_MEDIAMTX_TEST_BINARY = '<mediamtx.exe 的绝对路径>'
go test ./tests/media -run 'TestTwoRealMediaMTXShardsAreIndependentlyUsable|TestRealMediaMTXControlLifecycle' -count=1 -v

PostgreSQL 迁移测试仅使用专用隔离连接:

$env:SENSE_MEDIA_SHARD_MIGRATION_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./cmd/migrate/migration/version -run TestMediaShardMigrationOnPostgres -count=1 -v

验证应覆盖任意配置容量、稳定重复分配、容量耗尽、分片故障后归属不变、设备/Profile/路径影响范围、只读迁移预检、只读 RBAC、Control API 不出现在响应,以及 Brain/Bell 均不运行。没有专用 PostgreSQL 连接时必须记录真库迁移测试未执行。

Sense Outbox 本地验证

从 Sense/server 运行完整后端测试:

go test ./...

PostgreSQL 多 worker 集成测试必须使用专用隔离数据库,不得指向开发或生产库:

$env:SENSE_OUTBOX_TEST_DATABASE_URL = '<隔离 PostgreSQL 连接>'
go test ./app/sense/outbox -run TestPostgresConcurrentWorkersDoNotClaimSameMessage -count=1 -v

前端从 Sense/ui 运行:

pnpm lint
pnpm test:unit -- --runInBand
pnpm build:prod

验证至少覆盖:领域记录与 outbox 原子回滚、并发 claim/lease、租约恢复、退避与 dead、人工重新排队及操作人、永久幂等收据、production 禁用测试 sink、只读/恢复权限、API 不泄露 payload,以及 Brain/Bell 均不运行时页面可观察。无专用 PostgreSQL 连接时必须明确记录真库并发测试未执行。

Sense 运维告警验证

从后端目录运行:

cd Sense/server
go test ./app/sense/ops_alert ./app/admin/router ./cmd/migrate/migration/version
go test ./...

从前端目录运行:

cd Sense/ui
pnpm lint
pnpm test:unit -- --runInBand
pnpm build:prod

故障注入至少覆盖六类来源、相同源版本重复刷新、健康恢复、5 分钟观察门槛、观察期复发、恢复后再次发生、旧版本并发冲突、viewer 只读权限和脱敏操作审计。Brain/Bell 不启动。隔离启动 smoke 必须验证 2026082816000_ops_alert.go 迁移、菜单和 API 注册;不得把开发或生产数据库当作破坏性故障注入库。

Brain 合成与本地输入验证

从仓库根目录使用 Brain 的隔离 CPython 3.11 环境执行:

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/input Brain/tests/config -q
Brain\.venv\Scripts\python.exe -m pytest Brain/tests -q

定向测试覆盖固定种子与时间基准、Profile/分辨率和规则配置、EOF、取消、文件不存在、非法配置、凭据字段拒绝及安全错误文本。测试只使用运行时生成的小型匿名字节文件,不启动 Sense/Bell,不连接摄像头或网络服务。

Brain 视频解码验证

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/decode -q
Brain\.venv\Scripts\python.exe -m pytest Brain/tests -q

定向测试使用运行时生成的匿名 YUV4MPEG2 字节流,覆盖跨输入分块解码、顺序与时间戳、Profile/分辨率、RGB24 尺寸变化、正常 EOF、主动取消、截断帧、不支持格式/色度和配置尺寸不匹配。该结果不证明生产 RTSP、硬件解码、GPU 或多路性能。

Brain 匿名检测与跟踪验证

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/vision -q
Brain\.venv\Scripts\python.exe -m pytest Brain/tests -q
Brain\.venv\Scripts\python.exe -m yovision_brain --smoke cpu

定向测试覆盖空帧、目标出现/移动、短暂遮挡、消失、轨迹结束、会话 ID 边界及 PyTorch CPU 后端。合成几何帧不含人脸或客户数据;结果只证明链路可运行,不是效果评估。

Brain 区域与方向越线验证

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/rules -q
Brain\.venv\Scripts\python.exe -m pytest Brain/tests -q

定向测试覆盖区域外/进入/内部、边界点、正反方向、贴线 deadband、无效多边形/警戒线、重复 ID 和 Profile/分辨率不匹配;只使用合成归一化几何与匿名轨迹。

Brain 独立纵切运行与验证

Brain\.venv\Scripts\python.exe -m pytest Brain/tests/events Brain/tests/app -q
Brain\.venv\Scripts\python.exe -m pytest Brain/tests -q
Brain\.venv\Scripts\python.exe -m yovision_brain.app --config Brain\tests\fixtures\events\area.json --output -

CLI 将内部事件 JSON Lines 写入 stdout,并把 completed/cancelled、帧数、检测数和事件数摘要写入 stderr。配置文件必须显式提供,当前使用 JSON;无命中正常返回零事件,读取/配置/模块失败返回非零且不回显机器路径。命令不启动 Sense/Bell、不连接摄像头或网络。

Sense↔Brain v1 契约验证

源/规则配置契约:

pwsh -NoProfile -File contracts/tests/source-config-v1/run.ps1

脚本在系统临时目录创建隔离虚拟环境,按固定依赖运行 Schema、跨字段语义、JCS/SHA-256、版本/重校准和秘密拒绝测试,结束后清理所属临时目录。

运行状态契约不需要第三方包:

python contracts/tests/runtime-status-v1/test_contract.py

测试覆盖六态运行状态、30 秒未来时间偏差、90 秒陈旧边界、空/多配置流、四种配置应用状态、重复 config_id、integer revision mismatch、倒序消息、未知主版本、回退保留和敏感字段拒绝。

仓库级复核:

python -m unittest discover -s tests -v
python dev_scripts/harness.py check --strict
git diff --check

这些命令本身只验证冻结契约;#152 产品 adapter、持久 replay、停用/超时/恢复由本页后续 connector 测试覆盖,真实部署网络与端到端链路仍由 #154/#155 验证。

标准事件与证据 v1 契约验证

两组测试均只使用 Python 标准库:

python contracts/tests/events-v1/test_contract.py
python contracts/tests/evidence-v1/test_contract.py

事件测试覆盖匿名危险区域/方向越线样例、Brain producer→Sense relay→Bell consumer mapper fixture、RFC 8785/SHA-256 幂等向量、重复/冲突、未知版本、敏感字段拒绝和 OpenAPI 引用。

证据测试覆盖 pending/processing/success/failed 状态约束、success 完整性、失败降级、旧 available 状态拒绝、敏感访问材料拒绝和证据 API 响应引用。

仓库级复核:

python -m unittest discover -s tests -v
python dev_scripts/harness.py check --strict
git diff --check

这些命令本身只验证冻结契约;#153 产品 mapper/relay/ingress、机器身份、持久 replay、断线补投与证据降级由本页后续 connector 测试覆盖,真实证据存储、生产网络和跨项目 E2E 仍由 #154/#155 验证。

机器身份与安全传输 v1 验证

从仓库根目录执行隔离契约测试:

pwsh -NoProfile -File contracts/tests/machine-identity-v1/run.ps1

脚本在系统临时目录建立虚拟环境,按固定 cryptography==50.0.1 和 jsonschema==4.25.1 验证封闭 Schema、Go/Python 固定 Ed25519 向量、请求绑定、Bearer-only、错 audience/scope、过期、重放、轮换、吊销和 TLS policy,结束后删除所属临时目录。

三端定向验证:

cd Sense/server
go test -race ./app/sense/integration/machine_identity

cd ../../Bell/server
go test -race ./app/bell/integration/machine_identity

cd ../..
Brain\.venv\Scripts\python.exe contracts\tests\machine-identity-v1\test_contract.py

这些测试只证明 #151 身份和传输基础。#152/#153 已覆盖业务 adapter/endpoint、断网补投和持久 replay 重启恢复;真实客户 PKI/网络、现场时钟漂移与最终故障隔离仍由 #154/#155 验证,不得用进程内 replay store替代生产结论。

#152/#153 connector 验证

使用冻结 CPython 3.11.15 与 Go 1.26.5。从仓库根目录按受影响范围执行:

$env:PYTHONPATH = (Resolve-Path Brain/src)
Brain\.venv\Scripts\python.exe -m pytest Brain/tests/integration/sense_control Brain/tests/integration/event_export Brain/tests/app/test_event_export_connector.py -q

cd Sense/server
go test ./...
go vet ./...
go test -race ./app/sense/integration/brain_control ./app/sense/integration/bell_connector ./app/sense/local_event ./cmd/api ./cmd/migrate/migration/version

cd ../../Sense/tests/integration/brain_control
go test -race ./...
cd ../bell_connector
go test -race ./...

cd ../../../../Bell/server
go test ./...
go vet ./...
go test -race ./app/bell/integration/event_ingress ./cmd/api ./cmd/migrate/migration/version
cd tests/integration/event_ingress
go test -race ./...

冻结契约与仓库检查:

pwsh -NoProfile -File contracts/tests/source-config-v1/run.ps1
python contracts/tests/runtime-status-v1/test_contract.py
python contracts/tests/events-v1/test_contract.py
python contracts/tests/evidence-v1/test_contract.py
pwsh -NoProfile -File contracts/tests/machine-identity-v1/run.ps1
python -m unittest discover -s tests -v
python dev_scripts/harness.py check --strict
git diff --check

#152 覆盖 revision 幂等、last-known-good、单调状态、陈旧/离线/恢复、持久 replay、停用、超时和退避。#153 覆盖 Brain mapper、Sense 同事务 Outbox、Bell 永久 Receipt/Event、重复/冲突、证据降级、持久 replay、重启、断线恢复和多数据库默认库选择。

工单验收未使用客户 PKI、生产 PostgreSQL、真实三端网络或生产流量;这些结果只能由 #154 部署和 #155 E2E 补充。Sense 本地候选原子 Outbox 当前没有生产创建 caller,也不得据此声明本地产生链已完整接通。

根级编排本地验证

工单 #154 的编排验证只使用仓库外临时目录和假交付包,不需要真实密码、数据库或客户 PKI。先运行清单和脚本验证:

pwsh -NoProfile -File scripts/runtime/coordination/start-yovision.ps1 -Manifest C:\YoVision\config\coordination.json -ValidateOnly
pwsh -NoLogo -NoProfile -File deploy/coordination/tests/coordination-smoke.ps1

冒烟测试必须返回 0,并覆盖 Sense、Brain、Bell 分别启动/状态/停止、Brain+Bell 选择性组合、停止单端不影响另一端、单端启动失败隔离、端口占用与重复端口拒绝、重复数据库身份拒绝、无归属 PID 保护、清单漂移诊断、退出码和状态清理。测试创建的目录必须解析在系统临时目录内,结束时只清理该测试目录。

仓库闭环验证:

python dev_scripts/harness.py check --strict
python -m unittest discover -s tests -v
python dev_scripts/harness.py sync --check
git diff --check

这些测试证明编排和隔离控制,不证明真实产品包、生产 PostgreSQL、客户 PKI、真实摄像头/GPU、供应商服务、容量或长稳表现。真实契约闭环与 Brain/Bell 离线、重启、重复/冲突及证据降级由后续 E2E 工单验证。

三项目协调 E2E 验证

从仓库根目录执行唯一默认验收入口:

pwsh scripts/e2e/coordination/run-coordination-e2e.ps1

可复制的工具参数:

pwsh scripts/e2e/coordination/run-coordination-e2e.ps1 -PostgresBin D:\pgsql17\bin -Python Brain\.venv\Scripts\python.exe

默认完整运行按以下阶段串行收敛:

  1. 创建动态 loopback 端口的临时 PostgreSQL,为 Sense/Bell 建立不同的随机 owner/database,并执行 Bell 正式迁移。
  2. 在一次性 Python venv 中验证 source-config、runtime-status、machine-identity、events、evidence 五类冻结 v1 契约。
  3. 验证 Sense 配置/状态、Brain 事件接入/证据/Outbox 与 PostgreSQL 并发恢复。
  4. 验证 Brain 配置/状态 connector、匿名事件导出和持久重放。
  5. 串行验证 Bell ingress/evidence、Rule/Alert 投影和 ack/close 生命周期。共享有状态 Bell 数据库的包不得并行运行。
  6. 默认重新运行 Sense isolated E2E、Brain 全套测试和 Bell isolated E2E。
  7. 核对 Sense/Bell database owner/database 不同、随机秘密未进入临时日志、所属端口/进程已停止,并安全清理专属临时目录。

#155 的完整通过记录为:source-config 11 项、runtime-status 14 项、machine-identity 10 项、events 7 项、evidence 4 项;Brain connector/event export 25 项、Brain 全套 74 项;Sense/Bell connector 与独立 isolated E2E 均通过。不同提交必须以当次真实输出为准,不复用这些数量冒充新结果。

只有默认完整入口退出码为 0、末行出现 COORDINATION_E2E passed、三端独立回归均成功并且工作区无计划外改动,才满足协调 E2E 技术验收。-SkipIndependentProductE2E 仅供 harness 调试,不能作为 #155/MVP 验收。-KeepTemporary 仅用于失败诊断,保留内容不得提交或共享。

仓库级闭环继续执行:

python dev_scripts/harness.py check --strict
python -m unittest discover -s tests -v
python dev_scripts/harness.py sync --check
git diff --check

已验证范围不包含真实 GPU/生产模型、真实摄像头、通知供应商、生产迁移、16 路长稳和客户现场效果;这些项目必须在对应环境和独立工单中验收。

验证 Bell 联系人与值班排班

后端与 PostgreSQL 集成验证:

Set-Location Bell/server
$env:GOTOOLCHAIN = 'go1.26.5'
go test ./... -count=1
pwsh ./tests/bell_contact_schedule/run-postgres.ps1

前端验证:

Set-Location Bell/ui
corepack pnpm lint
corepack pnpm build:prod

联系人通道加密需要在运行进程中配置 BELL_CONTACT_CHANNEL_KEY。它必须是 Base64 编码的 32 字节随机值,不得提交到 Git、Wiki、工单或日志。仅为当前 PowerShell 进程生成测试密钥:

$keyBytes = [Security.Cryptography.RandomNumberGenerator]::GetBytes(32)
$env:BELL_CONTACT_CHANNEL_KEY = [Convert]::ToBase64String($keyBytes)

PostgreSQL 脚本会验证密文保存、写接口不回显地址、验证与启用状态分离、过期版本冲突、完整周覆盖、已发布历史不可修改、临时替班不重叠、不可变事实约束、操作员只读权限,以及操作日志不含通道明文。当前范围不连接真实外部消息提供商。