[SEN] 修复独立纵切验收脚本的源码隔离、产物清理与启动诊断 #145

Closed
opened 2026-08-29 19:25:41 +08:00 by ila · 3 comments
Owner

状态

已完成(2026-08-29,PR #146 已合入 dev)

基本信息

  • 类型:缺陷修复 / 测试与交付
  • 主项目:Sense
  • 主 agent:Sense agent
  • 所属 Epic:#7
  • 所属 MVP:#8
  • 前置工单:#71(已验收);产品纵切本身已在 #8 本轮验收通过
  • 并行:否;修复后直接恢复 #8 的最后一个未通过验收项
  • 独立运行:验收期间不启动或调用 Brain、Bell

原始需求与证据

  • 来源:用户于 2026-08-29 执行“三项目独立纵切集成验收”后,明确要求建立 Sense 缺陷工单修复验收脚本。
  • 目的摘要:让 Sense 文档中的默认独立 E2E 命令在正常开发工作区可重复运行、失败可诊断、结束后不污染源码工作区。
  • 复现基线:dev@6702b8a5b9bc0c6383e707904074b9885eeb3661。
  • #8 验收证据:Sense 静态回归、当前源码 Windows 构建和 prepared-package 产品 E2E 均通过;失败集中在验收脚本自身。

已确认缺陷

  1. 默认命令 pwsh -NoProfile -File Sense/tests/e2e/run-isolated-e2e.ps1 使用 Copy-Item -Recurse 复制整个 Sense/。当 Sense/ui/node_modules 存在时,pnpm 深层路径复制失败,产品 E2E 尚未开始。
  2. 使用 -PreparedPackageRoot Sense/dist/sense-windows-amd64 时,浏览器脚本被生成到 Sense/ui/sense-browser-smoke.cjs,导致测试后出现未跟踪源码文件。
  3. prepared-package 首次运行曾在 Sense HTTP 根地址就绪检查超时,第二次完整通过;当前超时信息只有 URL,缺少足以区分进程提前退出、日志报错和启动较慢的安全诊断。

目标

  1. 默认隔离 E2E 只复制构建所需的受控源码,不复制 node_modules、dist、本地配置、缓存、日志或其他忽略产物。
  2. prepared-package 与默认模式的浏览器脚本、截图、日志和运行数据全部写入本次系统临时目录,不写源码树。
  3. Sense HTTP 就绪失败时,输出可定位且脱敏的进程退出状态与有限日志摘要;保持明确超时和非零退出码。
  4. 所有路径无论成功、失败或超时都执行所属进程树和临时产物清理;-KeepTemporary 仅显式保留当前隔离目录并提示敏感边界。
  5. 修复后从存在 Sense/ui/node_modules 与 Sense/dist 的正常开发工作区执行文档默认命令,完整产品纵切通过且 Git 工作区前后 clean。

非目标

  • 不修改登录/RBAC、设备、ONVIF/RTSP、MediaMTX、实时监看、区域配置或其他产品语义。
  • 不修改 Sense/Bell GoAdmin 冻结基线、工具链版本或上游参考仓库。
  • 不修改 Brain、Bell、contracts/、根级部署或跨项目协议。
  • 不引入生产凭据、真实摄像机数据或客户数据。
  • 不以延长无限等待时间掩盖进程提前退出或真实启动失败。

精确 write_paths

  • Sense/tests/e2e/run-isolated-e2e.ps1
  • Sense/tests/e2e/browser-smoke.cjs(仅当需要调整脚本输入/输出位置;不得改变产品交互验收范围)
  • Sense/tests/compatibility/**(仅新增或调整本缺陷的脚本静态回归)
  • Sense/ACCEPTANCE.md(仅同步真实可复制命令、临时目录与排错说明)

禁止写:Sense 业务实现目录、Sense/ui/src/**、Sense/server/**、Sense/scripts/build/**、Brain/**、Bell/**、contracts/**、docs/**、根级配置。

已确认方案

受控源码隔离

  • 不再递归复制整个 Sense/。
  • 从 Git 当前任务树取得受版本控制的 Sense 文件清单,或使用等价的显式 allowlist 复制,保持相对目录结构。
  • 明确拒绝复制 node_modules、dist、.env、本地数据库、缓存、日志、凭据和未跟踪文件。
  • 临时副本必须能从当前任务提交独立构建;不得复用未知来源或过期包。

临时产物与清理

  • 浏览器 smoke 脚本始终从仓库已跟踪位置读取,在系统临时目录创建运行副本或直接通过参数执行;生成截图/状态/日志只能写隔离目录。
  • finally 只停止本次脚本启动且可证明归属的进程树,然后清理本次临时目录。
  • 默认运行成功或失败均不在源码树新增、修改或删除文件;-KeepTemporary 只保留隔离目录,不影响进程清理。

启动就绪与诊断

  • 等待循环同时观察 HTTP 就绪和 Sense 启动进程状态;进程提前退出时立即失败,不等待完整 HTTP 超时。
  • 超时或提前退出时仅输出退出码、阶段、日志文件位置及经过秘密过滤和长度限制的日志摘要。
  • 保持动态端口、现有安全环境变量和随机凭据;不得在诊断中打印数据库连接串、密码、JWT/credential key 或 Cookie。
  • 不因一次已通过复跑就忽略首轮超时;增加可重复的回归覆盖,证明启动等待逻辑既不会假通过也能给出可行动失败。

验收标准

  • Sense/tests/compatibility/run-static-regression.ps1 通过,并覆盖禁止整树复制、禁止源码树生成运行产物、进程提前退出诊断与敏感字段过滤。
  • 在 Sense/ui/node_modules 和 Sense/dist 均存在时,直接运行文档默认命令,不再发生 pnpm 深层路径复制错误。
  • 默认入口从当前源码构建全新包并完成完整 Sense 隔离 E2E。
  • -PreparedPackageRoot 模式完成同一产品 E2E,源码树不产生 sense-browser-smoke.cjs 或其他未跟踪运行文件。
  • 模拟 Sense 进程提前退出和 HTTP 不就绪时快速返回非零,诊断可定位且不泄露任何随机凭据或连接串。
  • 成功、失败、超时三条路径均无残留 Sense、MediaMTX、PostgreSQL、ffmpeg、浏览器或 fixture 进程。
  • 默认模式测试前后 git status --short 一致且 clean;git diff --check 通过。
  • python dev_scripts/harness.py check --strict 与 python -m unittest discover -s tests -v 通过。
  • 修复后回到 #8,仅重跑 Sense 默认入口及仓库 clean 检查即可恢复 MVP 最后一项验收。

风险与回退

  • 风险:受控复制漏掉构建输入、误把用户未跟踪文件纳入测试、清理未知进程、诊断泄露运行时秘密、过短超时造成偶发失败。
  • 控制:Git/allowlist 来源、临时根目录校验、进程归属记录、日志脱敏与长度限制、显式超时和失败注入回归。
  • 回退:回退本工单对验收脚本、静态回归和 ACCEPTANCE 文档的提交;不修改产品数据、数据库结构或生产部署。

设计与文档影响

  • 非 UI 产品变更,不需要新原型;复用 #71 已确认的 Sense 产品验收流程和 #8 的真实失败证据。
  • 长期影响 Sense 独立验收命令、临时目录和排错说明;更新 Sense/ACCEPTANCE.md。
  • 不修改 Wiki/根 docs/:本缺陷不改变产品架构、配置、业务规则或部署入口;若实施后命令语义发生长期变化,再由协调任务更新对应 Wiki。
## 状态 已完成(2026-08-29,PR #146 已合入 dev) ## 基本信息 - 类型:缺陷修复 / 测试与交付 - 主项目:Sense - 主 agent:Sense agent - 所属 Epic:#7 - 所属 MVP:#8 - 前置工单:#71(已验收);产品纵切本身已在 #8 本轮验收通过 - 并行:否;修复后直接恢复 #8 的最后一个未通过验收项 - 独立运行:验收期间不启动或调用 Brain、Bell ## 原始需求与证据 - 来源:用户于 2026-08-29 执行“三项目独立纵切集成验收”后,明确要求建立 Sense 缺陷工单修复验收脚本。 - 目的摘要:让 Sense 文档中的默认独立 E2E 命令在正常开发工作区可重复运行、失败可诊断、结束后不污染源码工作区。 - 复现基线:`dev@6702b8a5b9bc0c6383e707904074b9885eeb3661`。 - #8 验收证据:Sense 静态回归、当前源码 Windows 构建和 prepared-package 产品 E2E 均通过;失败集中在验收脚本自身。 ## 已确认缺陷 1. 默认命令 `pwsh -NoProfile -File Sense/tests/e2e/run-isolated-e2e.ps1` 使用 `Copy-Item -Recurse` 复制整个 `Sense/`。当 `Sense/ui/node_modules` 存在时,pnpm 深层路径复制失败,产品 E2E 尚未开始。 2. 使用 `-PreparedPackageRoot Sense/dist/sense-windows-amd64` 时,浏览器脚本被生成到 `Sense/ui/sense-browser-smoke.cjs`,导致测试后出现未跟踪源码文件。 3. prepared-package 首次运行曾在 Sense HTTP 根地址就绪检查超时,第二次完整通过;当前超时信息只有 URL,缺少足以区分进程提前退出、日志报错和启动较慢的安全诊断。 ## 目标 1. 默认隔离 E2E 只复制构建所需的受控源码,不复制 `node_modules`、`dist`、本地配置、缓存、日志或其他忽略产物。 2. prepared-package 与默认模式的浏览器脚本、截图、日志和运行数据全部写入本次系统临时目录,不写源码树。 3. Sense HTTP 就绪失败时,输出可定位且脱敏的进程退出状态与有限日志摘要;保持明确超时和非零退出码。 4. 所有路径无论成功、失败或超时都执行所属进程树和临时产物清理;`-KeepTemporary` 仅显式保留当前隔离目录并提示敏感边界。 5. 修复后从存在 `Sense/ui/node_modules` 与 `Sense/dist` 的正常开发工作区执行文档默认命令,完整产品纵切通过且 Git 工作区前后 clean。 ## 非目标 - 不修改登录/RBAC、设备、ONVIF/RTSP、MediaMTX、实时监看、区域配置或其他产品语义。 - 不修改 Sense/Bell GoAdmin 冻结基线、工具链版本或上游参考仓库。 - 不修改 Brain、Bell、`contracts/`、根级部署或跨项目协议。 - 不引入生产凭据、真实摄像机数据或客户数据。 - 不以延长无限等待时间掩盖进程提前退出或真实启动失败。 ## 精确 write_paths - `Sense/tests/e2e/run-isolated-e2e.ps1` - `Sense/tests/e2e/browser-smoke.cjs`(仅当需要调整脚本输入/输出位置;不得改变产品交互验收范围) - `Sense/tests/compatibility/**`(仅新增或调整本缺陷的脚本静态回归) - `Sense/ACCEPTANCE.md`(仅同步真实可复制命令、临时目录与排错说明) 禁止写:Sense 业务实现目录、`Sense/ui/src/**`、`Sense/server/**`、`Sense/scripts/build/**`、`Brain/**`、`Bell/**`、`contracts/**`、`docs/**`、根级配置。 ## 已确认方案 ### 受控源码隔离 - 不再递归复制整个 `Sense/`。 - 从 Git 当前任务树取得受版本控制的 Sense 文件清单,或使用等价的显式 allowlist 复制,保持相对目录结构。 - 明确拒绝复制 `node_modules`、`dist`、`.env`、本地数据库、缓存、日志、凭据和未跟踪文件。 - 临时副本必须能从当前任务提交独立构建;不得复用未知来源或过期包。 ### 临时产物与清理 - 浏览器 smoke 脚本始终从仓库已跟踪位置读取,在系统临时目录创建运行副本或直接通过参数执行;生成截图/状态/日志只能写隔离目录。 - `finally` 只停止本次脚本启动且可证明归属的进程树,然后清理本次临时目录。 - 默认运行成功或失败均不在源码树新增、修改或删除文件;`-KeepTemporary` 只保留隔离目录,不影响进程清理。 ### 启动就绪与诊断 - 等待循环同时观察 HTTP 就绪和 Sense 启动进程状态;进程提前退出时立即失败,不等待完整 HTTP 超时。 - 超时或提前退出时仅输出退出码、阶段、日志文件位置及经过秘密过滤和长度限制的日志摘要。 - 保持动态端口、现有安全环境变量和随机凭据;不得在诊断中打印数据库连接串、密码、JWT/credential key 或 Cookie。 - 不因一次已通过复跑就忽略首轮超时;增加可重复的回归覆盖,证明启动等待逻辑既不会假通过也能给出可行动失败。 ## 验收标准 - [x] `Sense/tests/compatibility/run-static-regression.ps1` 通过,并覆盖禁止整树复制、禁止源码树生成运行产物、进程提前退出诊断与敏感字段过滤。 - [x] 在 `Sense/ui/node_modules` 和 `Sense/dist` 均存在时,直接运行文档默认命令,不再发生 pnpm 深层路径复制错误。 - [x] 默认入口从当前源码构建全新包并完成完整 Sense 隔离 E2E。 - [x] `-PreparedPackageRoot` 模式完成同一产品 E2E,源码树不产生 `sense-browser-smoke.cjs` 或其他未跟踪运行文件。 - [x] 模拟 Sense 进程提前退出和 HTTP 不就绪时快速返回非零,诊断可定位且不泄露任何随机凭据或连接串。 - [x] 成功、失败、超时三条路径均无残留 Sense、MediaMTX、PostgreSQL、ffmpeg、浏览器或 fixture 进程。 - [x] 默认模式测试前后 `git status --short` 一致且 clean;`git diff --check` 通过。 - [x] `python dev_scripts/harness.py check --strict` 与 `python -m unittest discover -s tests -v` 通过。 - [x] 修复后回到 #8,仅重跑 Sense 默认入口及仓库 clean 检查即可恢复 MVP 最后一项验收。 ## 风险与回退 - 风险:受控复制漏掉构建输入、误把用户未跟踪文件纳入测试、清理未知进程、诊断泄露运行时秘密、过短超时造成偶发失败。 - 控制:Git/allowlist 来源、临时根目录校验、进程归属记录、日志脱敏与长度限制、显式超时和失败注入回归。 - 回退:回退本工单对验收脚本、静态回归和 ACCEPTANCE 文档的提交;不修改产品数据、数据库结构或生产部署。 ## 设计与文档影响 - 非 UI 产品变更,不需要新原型;复用 #71 已确认的 Sense 产品验收流程和 #8 的真实失败证据。 - 长期影响 Sense 独立验收命令、临时目录和排错说明;更新 `Sense/ACCEPTANCE.md`。 - 不修改 Wiki/根 `docs/`:本缺陷不改变产品架构、配置、业务规则或部署入口;若实施后命令语义发生长期变化,再由协调任务更新对应 Wiki。
ila added the kind/taskproject/sensescope/independentpriority/p0 labels 2026-08-29 19:25:41 +08:00
Author
Owner

从干净且与远端一致的 dev@6702b8a5b9bc0c6383e707904074b9885eeb3661 创建 feature/145-sense-e2e-isolation-cleanup。当前会话未提供 codebase-memory 图工具,按仓库规则回退到对工单授权 PowerShell/Markdown 文件的本地只读检查;不读取或修改 Sense 业务实现。

从干净且与远端一致的 `dev@6702b8a5b9bc0c6383e707904074b9885eeb3661` 创建 `feature/145-sense-e2e-isolation-cleanup`。当前会话未提供 codebase-memory 图工具,按仓库规则回退到对工单授权 PowerShell/Markdown 文件的本地只读检查;不读取或修改 Sense 业务实现。
Author
Owner

最终实施证据(2026-08-29)

状态:待验收;提交已推送,PR #146(feature/145-sense-e2e-isolation-cleanup → dev)可合并。

最终差异

  • 默认 E2E 根据 git ls-files -- Sense 复制当前跟踪源码并在临时仓库提交,排除 node_modules、dist、本地配置、日志和所有未跟踪文件。
  • prepared-package 先复制到本次临时目录;浏览器脚本直接从跟踪位置执行,cwd、截图和日志均在临时目录。
  • HTTP 等待同时监测启动进程,提前退出立即失败;超时/退出诊断包含阶段、状态、日志位置和最多 2000 字符的脱敏摘要。
  • WebRTC UDP 端口使用真实 UDP socket 探测。临时包内 MediaMTX/config 在 Sense managed 启动前预检并完全停止,避免 Windows 首次扫描与错误 UDP 端口被误报为 Sense 超时。
  • Sense/ACCEPTANCE.md 已同步真实隔离、诊断、清理、预检和协议级端口规则。

验证

  • Sense/tests/compatibility/run-static-regression.ps1:31 assertions 通过。
  • Harness 失败注入:跟踪复制、UDP bind、进程提前退出、HTTP 超时、秘密脱敏全部通过。
  • prepared-package 完整 E2E:通过;原包/源码树未产生 sense-browser-smoke.cjs 或其他运行文件,无残留进程。
  • 最终提交 1c6b30fac014913457086fe8910ce6d8c47872ab 后,从 clean 工作区运行文档默认 E2E:全新源码构建、包审计、PostgreSQL、登录/RBAC、中文设备、Digest ONVIF/RTSP、凭据隔离、MediaMTX、实时监看、区域重校准、Chrome GoAdmin 外壳、冷启动和停止全部通过。
  • 默认 E2E 后临时目录不存在,无验收所属进程,Git 工作区仍 clean。
  • python dev_scripts/harness.py check --strict:通过。
  • python -m unittest discover -s tests -v:48 passed。
  • git diff --check 与精确写路径检查:通过;仅修改工单授权的 3 个 Sense 文件。

实施中定位并闭环的原始偶发超时

  • 新诊断首次捕获 Sense 因 MediaMTX readiness timeout 提前退出。
  • MediaMTX 预检随后捕获 WebRTC UDP 地址 bind ... forbidden by access permissions;根因是旧脚本以 TCP 空闲结果选择 UDP 端口。
  • 改为 UDP 实际绑定探测并增加包/config 预检后,prepared 与默认模式均完整通过;未修改产品运行时或延长产品超时。

提交与文档

  • 提交:1c6b30fac014913457086fe8910ce6d8c47872ab。
  • PR:#146。
  • 长期命令说明已更新 Sense/ACCEPTANCE.md;无产品架构、配置、业务规则或部署入口变化,不修改 Wiki/根 docs/。

等待用户验收;验收前不合并、不关闭。

## 最终实施证据(2026-08-29) 状态:待验收;提交已推送,PR #146(`feature/145-sense-e2e-isolation-cleanup` → `dev`)可合并。 ### 最终差异 - 默认 E2E 根据 `git ls-files -- Sense` 复制当前跟踪源码并在临时仓库提交,排除 `node_modules`、`dist`、本地配置、日志和所有未跟踪文件。 - prepared-package 先复制到本次临时目录;浏览器脚本直接从跟踪位置执行,cwd、截图和日志均在临时目录。 - HTTP 等待同时监测启动进程,提前退出立即失败;超时/退出诊断包含阶段、状态、日志位置和最多 2000 字符的脱敏摘要。 - WebRTC UDP 端口使用真实 UDP socket 探测。临时包内 MediaMTX/config 在 Sense managed 启动前预检并完全停止,避免 Windows 首次扫描与错误 UDP 端口被误报为 Sense 超时。 - `Sense/ACCEPTANCE.md` 已同步真实隔离、诊断、清理、预检和协议级端口规则。 ### 验证 - `Sense/tests/compatibility/run-static-regression.ps1`:31 assertions 通过。 - Harness 失败注入:跟踪复制、UDP bind、进程提前退出、HTTP 超时、秘密脱敏全部通过。 - prepared-package 完整 E2E:通过;原包/源码树未产生 `sense-browser-smoke.cjs` 或其他运行文件,无残留进程。 - 最终提交 `1c6b30fac014913457086fe8910ce6d8c47872ab` 后,从 clean 工作区运行文档默认 E2E:全新源码构建、包审计、PostgreSQL、登录/RBAC、中文设备、Digest ONVIF/RTSP、凭据隔离、MediaMTX、实时监看、区域重校准、Chrome GoAdmin 外壳、冷启动和停止全部通过。 - 默认 E2E 后临时目录不存在,无验收所属进程,Git 工作区仍 clean。 - `python dev_scripts/harness.py check --strict`:通过。 - `python -m unittest discover -s tests -v`:48 passed。 - `git diff --check` 与精确写路径检查:通过;仅修改工单授权的 3 个 Sense 文件。 ### 实施中定位并闭环的原始偶发超时 - 新诊断首次捕获 Sense 因 `MediaMTX readiness timeout` 提前退出。 - MediaMTX 预检随后捕获 WebRTC UDP 地址 `bind ... forbidden by access permissions`;根因是旧脚本以 TCP 空闲结果选择 UDP 端口。 - 改为 UDP 实际绑定探测并增加包/config 预检后,prepared 与默认模式均完整通过;未修改产品运行时或延长产品超时。 ### 提交与文档 - 提交:`1c6b30fac014913457086fe8910ce6d8c47872ab`。 - PR:#146。 - 长期命令说明已更新 `Sense/ACCEPTANCE.md`;无产品架构、配置、业务规则或部署入口变化,不修改 Wiki/根 `docs/`。 等待用户验收;验收前不合并、不关闭。
Author
Owner

验收结论(2026-08-29)

  • 用户明确确认:#145通过。
  • PR #146 已合入 dev。
  • 实现提交:1c6b30fac014913457086fe8910ce6d8c47872ab。
  • dev 合并提交:19c0868c5d1719f2554b275f23e0fd714dd17b3b。
  • 已核对实现提交属于远端 origin/dev 历史。
  • 验收结论:通过,工单关闭。

Sense 项目内长期验收说明已更新;无 Wiki/根 docs/ 变化。

## 验收结论(2026-08-29) - 用户明确确认:`#145通过`。 - PR #146 已合入 `dev`。 - 实现提交:`1c6b30fac014913457086fe8910ce6d8c47872ab`。 - `dev` 合并提交:`19c0868c5d1719f2554b275f23e0fd714dd17b3b`。 - 已核对实现提交属于远端 `origin/dev` 历史。 - 验收结论:通过,工单关闭。 Sense 项目内长期验收说明已更新;无 Wiki/根 `docs/` 变化。
ila closed this issue 2026-08-29 20:15:57 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ila/yovision#145