diff --git a/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.1_Task_Report.md b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.1_Task_Report.md new file mode 100644 index 00000000..642d0b1d --- /dev/null +++ b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.1_Task_Report.md @@ -0,0 +1,24 @@ +# R2.1 任务报告 + +完整只读审计见 [UniDesk #1869](https://github.com/pikasTech/unidesk/issues/1869#issuecomment-4952486744),执行任务为 qt_c4072b7278ed409f94dc271d69f39540。 + +## 需求与失效边界 + +- 架构已从 #891 的单一 24 小时 dry-run 演进为多 runner、全局 latest/history、Dashboard、cadence freshness 与 OTel;#1861 是执行到 record/index 断点的局部实证,不是唯一架构依据。 +- 当前 monitorRoot 只是选择某个 sentinel 的 public root,不是中心聚合服务。 +- 每 runner 私有 SQLite 在单实例可用,但跨 runner 必然产生多权威、fan-out、部分失败和不同 latest 语义。 +- monitor-web 绑定当前 runner API,并对历史 run 发出 N+1 detail 请求;聚合留在 UI 会使 CLI、页面和服务看到不同事实。 +- runner 服务同时持有执行、索引、查询和前端,已越过可维护边界。 + +## 必须满足 + +- 配置、Host PG role/database/export/Secret consumer、迁移与切换状态全部 YAML-first。 +- 每 sentinel 只有一个 cadence/CronJob 调度权威,并明确区分业务 cadence 与 heartbeat。 +- runner 负责 observe/analyze 与不可变 artifact;中心 Monitor 拥有全局 durable index/read model。 +- global latest/history/finding/artifact locator 由同一中心 API 选择,CLI 与 monitor-web 共用。 +- 复用 NC01 Host PG;一次性迁移可计数、校验、切换、回滚,完成后无永久双写、SQLite fallback 或第二索引。 +- 近 3000 行 service 按执行、持久化、查询和 UI 边界拆分。 + +## 方案选择 + +拒绝 runner API fan-out 聚合与共享 runner/PVC/SQLite。采用中心 Monitor service + NC01 Host PG;runner 保留执行与 artifact owner,monitor-web 只读中心 API。artifact 文件是否迁移由 R2.2 冻结。 diff --git a/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.2_Task_Report.md b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.2_Task_Report.md new file mode 100644 index 00000000..98e0f1e7 --- /dev/null +++ b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.2_Task_Report.md @@ -0,0 +1,31 @@ +# R2.2 任务报告 + +完整只读审计见 [UniDesk #1871](https://github.com/pikasTech/unidesk/issues/1871#issuecomment-4952489758),执行任务为 qt_aef9f6210a0b4b76bb6a84d99cbf8cc4。 + +## 实测基线 + +- 当前已部署 NC01 SQLite 为 1,277,952 bytes,228 runs、242 findings、234 metadata;全部 run 为 blocked。 +- 仅 2 个 run 有 state_dir/report SHA 和 locator,合计 5 个 artifact。 +- 历史 runtime YAML 声明多个私有 SQLite/PVC,但不能在未观测运行实例时把它们伪装为现役迁移源。 +- SQLite 无 TTL;artifact bytes 不在数据库中,仍由 PVC/stateDir 与 web-observe GC 管理。 + +## 目标持久化模型 + +- 复用 config/platform-db/postgres-nc01.yaml 的 NC01 Host PostgreSQL,新建 Monitor 专用 role/database/export/Secret consumer。 +- PG 保存 runner identity、run、finding、run payload、artifact locator 和必要 timeline;时间使用 timestamptz,JSON 使用 jsonb,定义 FK、唯一约束和 scope 索引。 +- artifact bytes 继续留 runner PVC;PG 保存 node/lane/PVC/stateDir/relativePath/SHA/size 等不可变定位信息。 +- latest 明确定义为所选 scope 内 updated_at DESC、run_id DESC;不再扇出多个 SQLite。 +- 迁移工具只导出/导入已有事实,不合成缺失 run、finding、report 或 artifact。 + +## 切换 + +1. 从 resolved YAML registry 生成真实迁移源清单并记录 SQLite fingerprint/integrity/schema/rows。 +2. 在受控短停写窗口做一致快照和 artifact existence/SHA 枚举。 +3. 每 source 单 PG transaction 幂等导入,冲突即失败。 +4. 校验行数、关键字段、latest 与 locator 可达性。 +5. 一次发布把 writer/query 切到 PG,并拒绝 SQLite fallback。 +6. 回滚只允许在接管确认前回到冻结 snapshot;确认后不再写回或服务 SQLite。 + +## 前置阻塞 + +受控只读状态显示 NC01 Host PG 服务和既有对象存在,但已有应用凭据 SCRAM 认证失败。实施前必须通过 owning YAML/Secret 流程修复并验证,禁止手改密码或复用其它应用凭据。 diff --git a/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.3_Task_Report.md b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.3_Task_Report.md new file mode 100644 index 00000000..ba2cc75d --- /dev/null +++ b/docs/MDTODO/details/web-sentinel-runtime-reliability/R2.3_Task_Report.md @@ -0,0 +1,23 @@ +# R2.3 任务报告 + +完整只读审计见 [UniDesk #1870](https://github.com/pikasTech/unidesk/issues/1870#issuecomment-4952485516),执行任务为 qt_1e8f647f10ce4030ace2ba8e6ac16fe3。 + +## 关键发现 + +- 当前 2998 行 sentinel service 同时负责 runner 私有 SQLite、scheduler metadata、CronJob 触发、终态写入、latest/runs/findings/report 查询、artifact 解析和 monitor-web 资产。 +- 仓库没有 /api/root 或 /api/aggregate;monitor root 实际是 runner-served-bridge,前端只读当前 runner 同源 API,切换 sentinel 只是跳转。 +- 当前不存在真正全局 latest;入口 runner/PVC/SQLite 不可用时,该实例历史和页面一起不可读。把前端改成 HTTP fan-out 只会放大故障。 +- plan、实际 CronJob 执行和 record 终态不是清晰的中心事务链,scheduler heartbeat 不能证明新 run 已完成或 latest 已更新。 + +## 冻结边界 + +- runner 只执行既有 observe/analyze、生成不可变 artifact,并提交一次终态与 locator。 +- owning YAML/CronJob 保持每 sentinel 唯一调度权威,不新建第二 scheduler。 +- 中心 Monitor 持久化与查询服务通过 NC01 Host PG 提供唯一结构化写入/读取权威。 +- monitor-web 只消费中心 bounded API,不聚合 runner、不读取私有 SQLite/PVC。 +- artifact 实体可暂留 runner PVC;中心只保存不可变 locator、hash、摘要和可达性。 +- 禁止 runner fan-out、永久双写、SQLite fallback 和扫描 PVC/SQLite 补洞。 + +## 后续 + +结合 R2.1、R2.2 决定最小 ingest 方式、schema、切换窗口与回滚;先更新 P0 SPEC,再进入实现。 diff --git a/docs/MDTODO/web-sentinel-runtime-reliability.md b/docs/MDTODO/web-sentinel-runtime-reliability.md index f080ba38..b1ce53d6 100644 --- a/docs/MDTODO/web-sentinel-runtime-reliability.md +++ b/docs/MDTODO/web-sentinel-runtime-reliability.md @@ -28,18 +28,18 @@ PR 合并后只等待自动发布链,使用受控 Web sentinel 原入口产生 推进 [UniDesk #1868](https://github.com/pikasTech/unidesk/issues/1868):按当前多 runner、全局查询与 Dashboard 复杂度重构 Monitor 平台,评估并实施分散 SQLite 到 NC01 YAML-first Host PostgreSQL 的统一迁移;P0 先冻结架构、数据模型和切换边界,再实现、自动发布和原入口验收,不以迁移掩盖 [#1861](https://github.com/pikasTech/unidesk/issues/1861),不保留永久双写或第二权威,完成任务后将详细报告写入[任务报告](./details/web-sentinel-runtime-reliability/R2_Task_Report.md)。 -### R2.1 [in_progress] +### R2.1 [completed] 完成 [#1869](https://github.com/pikasTech/unidesk/issues/1869) 的需求演进、组件职责与复杂度失效边界审计,形成目标架构 must/should/out-of-scope 和候选方案,完成任务后将详细报告写入[任务报告](./details/web-sentinel-runtime-reliability/R2.1_Task_Report.md)。 -### R2.2 [in_progress] +### R2.2 [completed] 完成 [#1871](https://github.com/pikasTech/unidesk/issues/1871) 的 SQLite 实例、schema、数据规模与生命周期盘点,设计 NC01 Host PG schema、YAML role/database/export、一次性迁移、校验、切换和回滚,完成任务后将详细报告写入[任务报告](./details/web-sentinel-runtime-reliability/R2.2_Task_Report.md)。 -### R2.3 [in_progress] +### R2.3 [completed] 完成 [#1870](https://github.com/pikasTech/unidesk/issues/1870) 的 service/scheduler/runner API/monitor-web 调用链审计,冻结中心 Monitor 服务拆分、唯一写入/查询权威和故障隔离边界,完成任务后将详细报告写入[任务报告](./details/web-sentinel-runtime-reliability/R2.3_Task_Report.md)。 -### R2.4 +### R2.4 [in_progress] 由主代理汇总 R2.1-R2.3 冻结 [#1868](https://github.com/pikasTech/unidesk/issues/1868) 架构规格,再按规格拆实施 issue/PR,迁移已有数据,等待自动 CI/CD,并用 CLI、Monitor 页面和 Web Sentinel 原入口完成一致性验收及旧 SQLite 权威退役,完成任务后将详细报告写入[任务报告](./details/web-sentinel-runtime-reliability/R2.4_Task_Report.md)。 diff --git a/project-management/PJ2026-01/specs/PJ2026-010605-observability-monitoring.md b/project-management/PJ2026-01/specs/PJ2026-010605-observability-monitoring.md index fb8dcf51..318a40f7 100644 --- a/project-management/PJ2026-01/specs/PJ2026-010605-observability-monitoring.md +++ b/project-management/PJ2026-01/specs/PJ2026-010605-observability-monitoring.md @@ -97,7 +97,7 @@ | PJ2026-01060505 | Workbench性能 | [PJ2026-01060505 Workbench性能](PJ2026-01060505-workbench-performance.md) | Web 工作台用户可感知性能、RUM、AgentRun event visible latency 和 Prometheus 指标口径 | Web工作台、Agent编排、API契约 | 平台运维、客户端和性能回归调查 | | PJ2026-01060506 | Metrics接入 | 本规格 6.6 | metrics endpoint、scrape target 和 label 口径 | 各 L1 服务健康指标 | Prometheus 查询 | | PJ2026-01060507 | Rolling恢复观测 | 本规格 6.7 | active runner、reconciler backlog、terminal retry、projection lag 和不可恢复 blocker 的查询口径 | AgentRun核心、HWLAB接入、Workbench唯一投影、发布Lane | rolling 发布判定、故障收口 | -| PJ2026-01060508 | Web哨兵 | [PJ2026-01060508 Web哨兵](PJ2026-01060508-web-probe-sentinel.md) | `web-probe observe` 的 YAML-first 生产哨兵、持续 canary、报告视图、dashboard 分析工作台和发布恢复验证 | Web工作台、Workbench唯一投影、YAML运维、公开入口、发布流水 | 平台值守、CI/CD targetValidation、用户入口恢复判定 | +| PJ2026-01060508 | Web哨兵 | [PJ2026-01060508 Web哨兵](PJ2026-01060508-web-probe-sentinel.md) | `web-probe observe` 的 YAML-first 生产哨兵、独立 runner、中心 Monitor/Host PG、报告视图、dashboard 分析工作台和发布恢复验证 | Web工作台、Workbench唯一投影、YAML运维、公开入口、发布流水 | 平台值守、CI/CD targetValidation、用户入口恢复判定 | | PJ2026-01060509 | 出站诊断 | 本规格 6.9 | provider egress TCP tunnel、受控 relay、async job/server lifecycle 的阶段化日志、低噪声摘要和诊断入口 | provider-gateway、backend-core、YAML运维、发布流水 | D601/G14 runtime 出站排障、OpenFGA/Postgres/OA Event Flow 链路验收 | ## 6. 原子需求 @@ -271,7 +271,9 @@ rolling recovery 相关 span 应能用 OTel trace id/request id 关联 `sessionI 运维监控应提供 YAML-first Web 哨兵能力,把现有 `web-probe observe start/status/command/collect/analyze` 服务化为生产可用的持续 canary、报告视图和发布恢复验证入口。该能力只 wrap 现有 observe runner、control queue、artifact JSONL、`collect` 渲染和 `observe analyze` 报告,不新增第二套 Playwright runner、offline analyzer、finding classifier、dashboard 事实源或 Workbench 状态机。 -Web 哨兵配置必须通过 node/lane root YAML 的 `observability.webProbe.sentinel.enabled/configRefs` 引用 runtime、scenario、promptSet、reportView、publicExposure、CI/CD 和 Secret owning YAML。parser 只校验引用、形状、类型和冲突;cadence、采样间隔、轮次、profile、prompt source、report view、retention、public exposure、maintenance 和 Secret 参数以 YAML 为准。 +Web 哨兵配置必须通过 node/lane root YAML 的 `observability.webProbe.sentinels[]` 引用各 runner owning YAML,并通过 `observability.webProbe.monitor.configRef` 引用中心 runtime、publicExposure、persistence、CI/CD 和 Secret owning YAML。parser 只校验引用、形状、类型和冲突;cadence、采样间隔、轮次、profile、prompt source、report view、retention、public exposure、maintenance 和 Secret 参数以 YAML 为准。 + +Web 哨兵多 runner 的结构化状态必须由中心 Monitor 服务写入 NC01 YAML-first Host PostgreSQL,并通过同一 bounded API 向 CLI 与 monitor-web 提供 global/scoped latest、history、finding 和 artifact locator。runner 只负责 observe/analyze 与不可变 artifact;禁止跨 runner HTTP fan-out、永久 SQLite 双写/fallback、第二 scheduler 或由页面合并全局事实。artifact bytes 可以保留在独立 runner PVC,但 locator、hash、owner 和可达性必须进入中心索引。 Web 哨兵 dashboard 应作为平台值守和问题分析工作台展示同一 observe/analyze 事实:首屏健康摘要、scheduler/maintenance、latest run、finding severity、runs history、run detail、turn-summary 和 trace-frame。Dashboard 不得新增采样器、analyzer、截图保存源或 Workbench 状态仲裁;自动刷新只能读取 bounded/redacted API。 diff --git a/project-management/PJ2026-01/specs/PJ2026-01060508-web-probe-sentinel.md b/project-management/PJ2026-01/specs/PJ2026-01060508-web-probe-sentinel.md index c83d9984..4e6d063c 100644 --- a/project-management/PJ2026-01/specs/PJ2026-01060508-web-probe-sentinel.md +++ b/project-management/PJ2026-01/specs/PJ2026-01060508-web-probe-sentinel.md @@ -22,8 +22,9 @@ | 实现引用版本 | draft-2026-06-25-p0-web-probe-sentinel; draft-2026-06-27-p0-workbench-read-model-rootcause | | Dashboard 实现引用版本 | draft-2026-06-26-p8-web-probe-sentinel-recovery | | 多实例实现引用版本 | draft-2026-06-26-p9-multi-web-probe-sentinel | -| Monitor Web 聚合实现引用版本 | draft-2026-06-26-p10-monitor-web-aggregation | +| 历史 Monitor Web 聚合实现引用版本 | draft-2026-06-26-p10-monitor-web-aggregation(由 P17 取代) | | Monitor Web 观察面板治理实现引用版本 | draft-2026-06-27-p11-monitor-web-observability-dashboard; draft-2026-06-27-p12-cadence-scheduler-monitor-web | +| Monitor 中心持久化实现引用版本 | draft-2026-07-12-p17-monitor-central-persistence | | Cadence/OTel 稳定性实现引用版本 | draft-2026-07-01-p15-cadence-otel | | CI/CD source snapshot 实现引用版本 | draft-2026-07-01-p16-cicd-source-snapshot | | 需求规格模板 | [ISO/IEC/IEEE 29148 需求规格模板](../../templates/iso-iec-ieee-29148-requirements-spec-template.md) | @@ -46,8 +47,8 @@ Web哨兵必须遵循 UniDesk YAML-first ops。目标 node/lane、public origin ### 2.2 范围内 - `web-probe observe` CLI 的 wrapper/adapter 边界,使常驻服务能够稳定调用 start/status/command/collect/analyze。 -- YAML `observability.webProbe.sentinel.enabled/configRefs` 的 legacy 单实例入口,以及 `observability.webProbe.sentinels[]` 多实例 registry 与每个 sentinel 管理 YAML 的引用图。 -- 常驻 TypeScript 单 Pod wrapper 服务、scheduler、scenario runner、PVC/SQLite index、health、metrics、maintenance API 和 dashboard。 +- YAML `observability.webProbe.sentinels[]` 多实例 registry、`observability.webProbe.monitor.configRef` 中心服务入口,以及各自 owning YAML 的引用图。 +- 独立 sentinel runner、scheduler、scenario runner、artifact PVC、中心 Monitor ingest/query 服务、Host PostgreSQL、health、metrics、maintenance API 和 dashboard。 - `sentinel plan|apply|status|validate|report|maintenance` 与 `sentinel image|control-plane` 等受控 CLI 入口。 - 发布流水 maintenance start/stop、quick verify、targetValidation、GitOps/Argo/git-mirror closeout 和 public exposure 验证。 - 哨兵自身 CI/CD 的 k8s git-mirror source snapshot、PipelineRun source acquisition、GitOps publish 和 selected/latest closeout。 @@ -64,8 +65,8 @@ Web哨兵必须遵循 UniDesk YAML-first ops。目标 node/lane、public origin - API path、错误 envelope、route policy 和用户身份语义归 [PJ2026-010403 API契约](PJ2026-010403-api-contract.md)。 - 第一阶段不交付分布式压测;loadtest 只保留同镜像、同 wrapper 的配置和命令扩展点。 - in-cluster 哨兵不是外部公网监控节点。若后续需要真正外网用户路径监控,应另行定义外部或边缘哨兵,不把当前服务伪装成外部观测点。 -- 多实例 Web 哨兵不得用一个 Pod、一个 PVC 或一个 SQLite index 伪装隔离。共享 dashboard domain 可以按 route prefix 暴露,但 runtime Deployment、Service、PVC、SQLite、GitOps path、Argo Application、metrics label 和 report index 必须按 sentinel id 独立。 -- SQLite index、dashboard、metrics 和 maintenance 状态不得替代 `samples.jsonl`、`control.jsonl`、network/artifact JSONL 或 `analysis/report.json` 成为探针事实源。 +- 多实例 Web 哨兵不得用一个 Pod 或一个 PVC 伪装执行隔离。runtime Deployment/Job、Service、artifact PVC、GitOps path、Argo Application 和 metrics label 必须按 sentinel id 独立;结构化 run/finding/locator 则统一进入中心 Monitor Host PostgreSQL。 +- 中心 Monitor 索引、dashboard、metrics 和 maintenance 状态不得替代 `samples.jsonl`、`control.jsonl`、network/artifact JSONL 或 `analysis/report.json` 成为探针事实源。 - Dashboard 不负责修复 Workbench projection、trace timing、runner/envreuse 或 git mirror 慢路径;它只把 observe/analyze 已采集事实组织成可读的值守和分析入口。 - Web 哨兵不得通过降低 Playwright/Chromium 启动资源、禁用浏览器能力或自动刷新页面来规避 Workbench 卡死和内存膨胀;浏览器进程 RSS 是诊断证据,阻塞判定必须优先使用页面级 baseline 后的有效内存、CDP/Playwright 响应性和 YAML policy。 @@ -89,14 +90,15 @@ Web哨兵必须遵循 UniDesk YAML-first ops。目标 node/lane、public origin | synthetic prompt set | YAML 管理的合成 prompt 集。报告默认只展示 prompt id、hash、字节数和轮次编号,不展示原文。 | | maintenance window | 发布或维护期间的哨兵状态:继续采样和记录,但暂停告警;结束时触发 quick verify 和 analyze。 | | quick verify | 由 maintenance stop 或 CI/CD targetValidation 触发的一次短巡检,底层仍使用 `web-probe observe` CLI 和 `observe analyze`。 | -| SQLite index | PVC 上的轻量索引,只保存 run、scenario、finding、report hash、artifact 摘要和 dashboard 分页信息;它不是业务或探针事实源。 | +| Monitor 中心索引 | NC01 Host PostgreSQL 中由中心 Monitor 服务唯一写入和查询的结构化 run、finding、report payload、artifact locator 与必要状态时间线;它不是业务或探针事实源。 | +| legacy SQLite index | 切换前 runner PVC 上的历史轻量索引,只能作为一次性迁移输入和有界回滚快照,不能继续提供运行时读写或 fallback。 | | dashboard workbench | 面向平台值守和问题分析的 Web 哨兵监控工作台,按 overview、runs、findings、run detail、trace-frame 等视图组织同一 report/index 数据。 | | trace-frame viewer | Dashboard 内的第二层 trace 阅读视图,只从已有采样帧和 report view 渲染单帧文字版 trace,不另存截图或另造 analyzer。 | | auto refresh | Dashboard 的受控刷新能力;刷新只读 API/report/index,不发送 control command、不启动采样、不制造第二事实源。 | | public exposure | YAML 声明的 `monitor.pikapython.com` HTTPS 暴露,通过共享 PK01 Caddy + FRP managed-block helper 到达 ClusterIP Service。 | | targetValidation | 发布流水中的目标验证结果;对 HWLAB Web 恢复的判定必须来自 observe/analyze 对 public origin 的观察,不得只看 Argo green。 | | source snapshot | 哨兵自身 CI/CD 触发时由 k8s git-mirror 解析出的不可变源码快照,绑定 selected commit、mirror ref、PipelineRun、GitOps revision 和 runtime image。 | -| monitor-web | 独立于 sentinel-runner 的 Vue 3 + TypeScript + Vite 展示和聚合层,承载 `monitor.pikapython.com` root、多哨兵总览、趋势曲线、时间线、单哨兵详情和受控截图验收。 | +| monitor-web | 独立于 sentinel-runner 的 Vue 3 + TypeScript + Vite 展示层,只消费中心 Monitor bounded API,承载 `monitor.pikapython.com` root、多哨兵总览、趋势曲线、时间线、单哨兵详情和受控截图验收。 | | cadence freshness | 根据 YAML cadence、scheduler heartbeat、latest run age、active/planned run 和 analyzed report 更新时间计算的运行新鲜度;它默认是非阻塞值守告警,只有真正导致 run/report 不产生或业务链路不可用时才升级为 blocker。 | | env reuse | CI/CD 复用既有 env image、依赖缓存、BuildKit 层和未受影响服务的发布产物,以避免无关重建;小范围变更应在 status/closeout 中暴露 build/reuse 摘要。 | | 页面内存 baseline | web-probe 在每个 Playwright page/page epoch 上采集的初始浏览器运行指标;浏览器启动、空页和未加载目标 URL 前的基础成本只作为 baseline,不计入该页有效内存预算。 | @@ -108,7 +110,7 @@ Web哨兵必须遵循 UniDesk YAML-first ops。目标 node/lane、public origin | --- | --- | | 外部使用者 | 平台值守人员、发布操作人员、Workbench owner、CI/CD targetValidation、问题调查 agent。 | | 外部输入 | YAML configRefs、Secret sourceRef presence、HWLAB Web public origin、scenario cadence、maintenance 操作、observe artifacts、analyze reports、GitOps/Argo 状态。 | -| 受控资源 | Web哨兵 Deployment、Service、PVC、ServiceAccount、NetworkPolicy、ConfigMap、publicExposure、SQLite index、dashboard 和 Prometheus metrics。 | +| 受控资源 | Sentinel runner Deployment/Job、Service、artifact PVC、中心 Monitor Deployment/Service、Host PostgreSQL database/role/export/Secret consumer、ServiceAccount、NetworkPolicy、ConfigMap、publicExposure、dashboard 和 Prometheus metrics。 | | 外部输出 | sentinel status、health、metrics、dashboard overview、run history、finding analysis、run detail、report summary、turn-summary、trace-frame、maintenance 状态和 targetValidation 结果。 | | 用户接口 | `bun scripts/cli.ts web-probe sentinel ...`、`https://monitor.pikapython.com` dashboard、CI/CD maintenance 调用和受控 GitOps/control-plane CLI。 | | 系统边界 | Web哨兵只生产运行监控和发布恢复证据;不定义业务成功,不写第二套 Workbench 状态,不直接修复 Web,不读取或打印 Secret/prompt/provider payload。 | @@ -119,16 +121,16 @@ Web哨兵必须遵循 UniDesk YAML-first ops。目标 node/lane、public origin | --- | --- | --- | --- | --- | --- | | PJ2026-0106050801 | Wrapper边界 | 本规格 6.1 | 只 wrap 现有 observe CLI,禁止第二 runner/analyzer | web-probe observe、Workbench唯一投影 | 服务化入口、人工排障 | | PJ2026-0106050802 | YAML配置 | 本规格 6.2 | configRefs、owning YAML、parser 校验和 redacted plan | YAML运维、公开入口、Secret分发 | plan/status、部署渲染 | -| PJ2026-0106050803 | 常驻服务 | 本规格 6.3 | scheduler、scenario runner、PVC/SQLite、health、metrics、maintenance API | Wrapper边界、YAML配置 | dashboard、CI/CD | +| PJ2026-0106050803 | 常驻服务 | 本规格 6.3 | scheduler、scenario runner、artifact PVC、中心 ingest/query、Host PG、health、metrics、maintenance API | Wrapper边界、YAML配置 | dashboard、CI/CD | | PJ2026-0106050804 | 报告视图 | 本规格 6.4 | CLI/report API 渐进读取、分页、redaction、trace-frame | observe collect/analyze、Workbench唯一投影 | issue evidence、dashboard | | PJ2026-0106050805 | 发布集成 | 本规格 6.5 | CI/CD、GitOps、Argo、maintenance、targetValidation、publicExposure | 发布流水、源码同步、公开入口 | 发布恢复判定 | | PJ2026-0106050806 | Canary验收 | 本规格 6.6 | dsflash-go 十轮工具调用、24 小时 dry-run 和 profile 结构化失败边界 | Agent编排、Workbench、web-probe | 生产巡检收口 | | PJ2026-0106050807 | 安全隔离 | 本规格 6.7 | Secret/prompt/provider redaction、NetworkPolicy、public dashboard auth | 用户管理、平台运维 | 安全 closeout | | PJ2026-0106050808 | 代码引用 | 本规格 6.8 | SPEC 头部标注和生成/配置追溯 | 规格治理 | 后续 PR 审计 | | PJ2026-0106050809 | Dashboard工作台 | 本规格 6.9 | overview、runs、findings、run detail、trace-frame viewer、前端分层 | 报告视图、常驻服务、Workbench性能 | 平台值守和问题分析 | -| PJ2026-0106050810 | 多实例与账号切换 | 本规格 6.10 | sentinel registry、实例隔离、账号切换 command、route prefix 和 report label | YAML配置、Wrapper边界、安全隔离 | 多哨兵巡检、账号链路值守 | -| PJ2026-0106050811 | Monitor Web 聚合 | 本规格 6.11 | runner/web 职责拆分、单 monitor-web 聚合、Kubernetes discovery、Vue+TS 前端和 public exposure 收敛 | 多实例与账号切换、Dashboard工作台、发布集成 | `monitor.pikapython.com` 统一值守入口 | -| PJ2026-0106050812 | Monitor Web 观察面板治理 | 本规格 6.12 | 趋势曲线、运行时间线、固定视口三栏、cadence freshness、Vue CI/CD/env reuse/git mirror | Monitor Web 聚合、Dashboard工作台、发布集成、源码同步 | 可滚动上线和值守的统一观察面板 | +| PJ2026-0106050810 | 多实例与账号切换 | 本规格 6.10 | sentinel registry、runner 隔离、账号切换 command、中心 API scope 和 report label | YAML配置、Wrapper边界、安全隔离 | 多哨兵巡检、账号链路值守 | +| PJ2026-0106050811 | Monitor 中心服务与 Web | 本规格 6.11 | runner/中心服务/Web 职责拆分、Host PG 唯一索引、中心 API、Vue+TS 前端和 public exposure 收敛 | 多实例与账号切换、Dashboard工作台、发布集成 | `monitor.pikapython.com` 统一值守入口 | +| PJ2026-0106050812 | Monitor Web 观察面板治理 | 本规格 6.12 | 趋势曲线、运行时间线、固定视口三栏、cadence freshness、Vue CI/CD/env reuse/git mirror | Monitor 中心服务与 Web、Dashboard工作台、发布集成、源码同步 | 可滚动上线和值守的统一观察面板 | | PJ2026-0106050814 | 哨兵 CI/CD 可见性 | 本规格 6.14 | publish 阶段耗时、env reuse、docker cache、超时诊断、git mirror/Argo/runtime 收敛下一步 | 发布集成、源码同步、Monitor Web 观察面板治理 | 小改动滚动上线可诊断、可续跑、可验收 | | PJ2026-0106050815 | Cadence/OTel 稳定性 | 本规格 6.15 | Kubernetes CronJob 周期巡检、状态缺口故障码、monitor-web cadence 可见性和 sentinel OTel span 合同 | Monitor Web 观察面板治理、发布集成、OTel、YAML运维 | JD01/v03 周期巡检恢复和后续防回归 | @@ -154,18 +156,26 @@ flowchart LR Mgmt --> Secrets end - subgraph Sentinel[Web哨兵 Pod] + subgraph Sentinel[Per-sentinel runner] Scheduler[Scheduler] Adapter[observe CLI wrapper adapter] - Index[(SQLite index on PVC)] - API[/api overview status runs report views maintenance] + ArtPVC[(Immutable artifact PVC)] + RunnerAPI[/health trigger artifact access] Metrics[/metrics] - Dash[Dashboard workbench] Scheduler --> Adapter - Scheduler --> Index - API --> Index - Dash --> API - Metrics --> Index + Adapter --> ArtPVC + Scheduler --> Metrics + RunnerAPI --> ArtPVC + end + + subgraph Monitor[Central Monitor] + Ingest[Ingest API] + Store[(NC01 Host PostgreSQL)] + Query[Bounded query API] + Dash[monitor-web] + Ingest --> Store + Store --> Query + Query --> Dash end subgraph Observe[Existing web-probe observe] @@ -189,7 +199,8 @@ flowchart LR Scenario --> Scheduler Adapter --> Runner Adapter --> Control - Analyze --> Index + Analyze --> ArtPVC + Analyze --> Ingest Runner --> Web Dash -. HTTPS .-> Exposure ``` @@ -198,22 +209,27 @@ flowchart LR ```mermaid flowchart TD - Root[config/hwlab-node-lanes.yaml
lanes.v03.targets.D601.observability.webProbe.sentinels[]] --> Entry[id/enabled/configRef] + Root[config/hwlab-node-lanes.yaml
targets.node.observability.webProbe] --> Entry[id/enabled/configRef] + Root --> MonitorRef[monitor service configRef] Entry --> Mgmt[sentinel management YAML#sentinel] Mgmt --> Refs[configRefs] Refs --> Runtime[runtime.d601-v03.yaml#sentinel.runtime] Refs --> Scenarios[scenarios.workbench.yaml#sentinel.scenarios] Refs --> PromptSets[prompt-set.dsflash-go.yaml#sentinel.promptSet] Refs --> ReportViews[report-views.yaml#sentinel.reportViews] - Refs --> PublicExposure[public-exposure.d601-v03.yaml#sentinel.publicExposure] Refs --> Cicd[cicd.d601-v03.yaml#sentinel.cicd] Refs --> SecretRefs[secrets.d601-v03.yaml#sentinel.secrets] + MonitorRef --> MonitorRuntime[Monitor runtime owning YAML] + MonitorRuntime --> PublicExposure[Monitor publicExposure owning YAML] + MonitorRuntime --> PlatformDB[config/platform-db/postgres-nc01.yaml] + PlatformDB --> MonitorSecret[Monitor DB export / Secret consumer] Scenarios --> PromptSets Scenarios --> ReportViews Scenarios --> AnalyzeThresholds[hwlab-node-lanes.yaml#...observe.analysisThresholds] PublicExposure --> Edge[PK01 Caddy + FRP managed block] SecretRefs --> Runtime Cicd --> Runtime + MonitorSecret --> MonitorRuntime ``` 配置引用图必须保持单向:root YAML 只保存 enable 与 ref;具体数值在 owning YAML;parser 只解析、校验和报告,不写合并后的新 source of truth。 @@ -232,17 +248,18 @@ flowchart TD Artifacts --> Analyze[observe analyze] Analyze --> ReportJson[analysis/report.json] Analyze --> ReportMd[analysis/report.md] - ReportJson --> Index[SQLite index] - ReportMd --> Index - ReportJson --> ViewApi[bounded report view API] - Index --> ReportCli[sentinel report] - Index --> Dashboard[Dashboard] - ViewApi --> Dashboard - Index --> Metrics[Prometheus metrics] - Index --> Validation[targetValidation] + ReportJson --> Ingest[Monitor ingest] + ReportJson --> ArtifactPVC[Runner artifact PVC] + ReportMd --> ArtifactPVC[Runner artifact PVC] + Ingest --> Store[(NC01 Host PostgreSQL)] + Store --> ViewApi[bounded Monitor query API] + Store --> ReportCli[sentinel report] + ViewApi --> Dashboard[monitor-web] + Store --> Metrics[Prometheus metrics] + Store --> Validation[targetValidation] ``` -`ReportCli`、dashboard、metrics 和 targetValidation 只能读取 artifact/report/index 摘要。它们不得重新访问 Workbench、重新采样页面、重排 trace 行、重新分类 finding 或从 SQLite 推导业务事实。 +`ReportCli`、dashboard、metrics 和 targetValidation 只能读取中心 Monitor 索引及其引用的 artifact/report 摘要。它们不得重新访问 Workbench、重新采样页面、重排 trace 行、重新分类 finding 或从 PostgreSQL 推导业务事实。 ### 5.4 常规巡检时序图 @@ -253,7 +270,7 @@ sequenceDiagram participant Obs as observe runner participant Web as HWLAB Web public origin participant Ana as observe analyze - participant Idx as SQLite/PVC index + participant Mon as Monitor ingest / Host PG Sch->>CLI: observe start with YAML scenario CLI->>Obs: start sampler/stateDir @@ -263,7 +280,7 @@ sequenceDiagram Obs->>Web: official UI/API action Sch->>CLI: observe status until terminal/window end Sch->>Ana: observe analyze stateDir - Ana-->>Idx: report SHA and findings summary + Ana-->>Mon: terminal run, report SHA, findings and locator ``` ### 5.5 发布 maintenance 时序图 @@ -271,20 +288,23 @@ sequenceDiagram ```mermaid sequenceDiagram participant CI as CI/CD Pipeline - participant Sen as Sentinel API + participant Mon as Monitor API + participant Run as Sentinel runner participant CP as Runtime control-plane participant CLI as observe wrapper participant Ana as observe analyze - CI->>Sen: maintenance/start release id - Sen-->>CI: sampling continues, alert muted + CI->>Mon: maintenance/start release id + Mon-->>CI: sampling continues, alert muted CI->>CP: rollout / Argo sync CP-->>CI: runtime healthy summary - CI->>Sen: maintenance/stop - Sen->>CLI: quick verify observe start/command/status - CLI-->>Sen: observer/run/stateDir - Sen->>Ana: analyze quick verify artifact - Ana-->>CI: report SHA, findings, targetValidation status + CI->>Mon: maintenance/stop + Mon->>Run: trigger selected quick verify + Run->>CLI: observe start/command/status + CLI-->>Run: observer/run/stateDir + Run->>Ana: analyze quick verify artifact + Ana->>Mon: terminal ingest + Mon-->>CI: report SHA, findings, targetValidation status ``` ### 5.6 哨兵自身 rollout 时序图 @@ -294,18 +314,18 @@ sequenceDiagram participant CP as Sentinel control-plane participant GitOps as GitOps repo participant Argo as ArgoCD - participant Pod as Sentinel Pod + participant Run as Sentinel runner + participant Mon as Monitor service participant Val as sentinel validate CP->>GitOps: publish digest-pinned manifests - Argo->>Pod: sync Deployment/Service/PVC - Val->>Pod: /api/health - Val->>Pod: /metrics - Val->>Pod: dashboard/public exposure probe - Pod-->>Val: scheduler heartbeat and PVC writable + Argo->>Run: sync runner Deployment/Job/Service/PVC + Argo->>Mon: sync Monitor Deployment/Service + Val->>Run: /health, /metrics, artifact PVC + Val->>Mon: /health, Host PG schema/query, monitor-web assets ``` -哨兵自身 rollout 只验证哨兵服务健康、配置装载、PVC/SQLite 可写、metrics、dashboard 和调度循环;它不能把另一个哨兵当作 HWLAB Web 业务观察对象,也不能因为 HWLAB 业务 quick verify blocked 就把哨兵自身发布状态标成失败。 +哨兵自身 rollout 只验证 runner 与中心 Monitor 服务健康、配置装载、artifact PVC 可写、Host PG 可查询、metrics、dashboard 和调度循环;它不能把另一个哨兵当作 HWLAB Web 业务观察对象,也不能因为 HWLAB 业务 quick verify blocked 就把哨兵自身发布状态标成失败。 ### 5.7 哨兵不可用结构化失败时序图 @@ -345,12 +365,13 @@ Dashboard 首屏必须先呈现当前值守判断,再允许 drill-down。用 ```mermaid flowchart LR - Index[(SQLite index)] --> OverviewApi[/api/overview] - Index --> RunsApi[/api/runs filters cursor] - Index --> FindingsApi[/api/findings aggregate] - Report[analysis/report.json] --> DetailApi[/api/runs/:id] - Report --> ViewApi[/api/runs/:id/views] - Artifacts[observe artifacts] --> ViewApi + Store[(NC01 Host PostgreSQL)] --> OverviewApi[/api/overview] + Store --> RunsApi[/api/runs filters cursor] + Store --> FindingsApi[/api/findings aggregate] + Store --> DetailApi[/api/runs/:id] + Store --> ViewApi[/api/runs/:id/views] + ArtifactLocator[artifact locator] --> ViewApi + Artifacts[runner observe artifacts] --> ArtifactLocator OverviewApi --> Dashboard RunsApi --> Dashboard FindingsApi --> Dashboard @@ -470,7 +491,7 @@ Web哨兵必须只编排现有顶层 `web-probe observe start/status/command/col | --- | --- | --- | --- | | OPS-SENTINEL-REQ-002 | YAML配置 | PJ2026-0106050802 YAML配置 | [YAML运维](PJ2026-010603-yaml-first-ops.md)、[公开入口](PJ2026-010604-public-entry.md)、[源码同步](PJ2026-010602-source-sync.md) | -Web哨兵 legacy 单实例配置可通过 node/lane root YAML 的 `observability.webProbe.sentinel.enabled/configRefs` 进入;多实例配置必须通过 `observability.webProbe.sentinels[]` registry 进入。registry 项只能声明 `id`、`enabled` 和 `configRef`,再由 sentinel 管理 YAML 引用 runtime、workflow/scenario、promptSet、reportView、publicExposure、CI/CD 和 Secret owning YAML。root YAML 不得承载所有 runtime/scenario/report/Secret 数值,也不得生成合并后的超级配置作为第二 source of truth。 +Web 哨兵多实例配置必须通过 node/lane root YAML 的 `observability.webProbe.sentinels[]` registry 进入,中心服务通过 `observability.webProbe.monitor.configRef` 进入。sentinel registry 项只能声明 `id`、`enabled` 和 `configRef`,再由 sentinel 管理 YAML 引用 runtime、workflow/scenario、promptSet、reportView、CI/CD 和 Secret owning YAML;Monitor 管理 YAML 独立引用 runtime、publicExposure、persistence、CI/CD 和 Secret owning YAML。旧单实例 `sentinel` 与 `monitorRoot` 在 P17 切换时删除,不作为兼容入口保留。 parser 只负责解析 `path/to/file.yaml#object.path` 或规格确认的等价引用,校验文件存在、路径存在、字段形状、类型、枚举键名、必填字段和重复事实冲突。registry id 与 sentinel 管理 YAML 内的 id 必须一致;多实例 registry 下的非 config 操作必须显式选择 `--sentinel `,避免误操作默认实例。缺失字段应报告 YAML path 和下一步 drill-down;不得用代码默认值补 namespace、image、cadence、timeout、threshold、profile、Secret、public URL、report view 或 retention。 @@ -482,13 +503,13 @@ parser 只负责解析 `path/to/file.yaml#object.path` 或规格确认的等价 | --- | --- | --- | --- | | OPS-SENTINEL-REQ-003 | 常驻服务 | PJ2026-0106050803 常驻服务 | [发布流水](PJ2026-010601-controlled-release.md)、[Workbench性能](PJ2026-01060505-workbench-performance.md) | -Web哨兵服务应以 TypeScript/Node.js 实现,默认单 Pod 单副本。服务负责 scheduler、scenario runner、PVC/SQLite index、health、metrics、maintenance API 和 dashboard 静态资源;它不得直接写第二套 DOM 采样、网络采样、截图、Workbench 读取逻辑或 finding 分类。 +Web 哨兵必须拆成 per-sentinel runner 与中心 Monitor 服务。runner 负责编排既有 observe/analyze、生成不可变 artifact、暴露执行健康/受控触发/locator 访问;中心 Monitor 服务负责 ingest、Host PostgreSQL 持久化、bounded query API、metrics 和 monitor-web 静态资源。两者都不得复制第二套 DOM/网络采样、截图、Workbench 读取逻辑或 finding 分类。 -PVC 保存 SQLite index 和原始 `.state/web-observe` artifact。SQLite 只索引 run、scenario、finding、report hash、artifact 摘要、maintenance 状态和分页游标;它不得替代 JSONL/report 事实源,不参与 Workbench lifecycle、trace 顺序、final response 或业务状态仲裁。 +每个 runner 的 PVC 只保存 `.state/web-observe` artifact 和切换前冻结的 legacy SQLite 快照。NC01 Host PostgreSQL 保存 runner identity、run、finding、report payload、artifact locator 和必要状态时间线;只有中心 Monitor 服务持有数据库连接并写入。结构化索引不得替代 JSONL/report 事实源,不参与 Workbench lifecycle、trace 顺序、final response 或业务状态仲裁。 -`/api/health` 必须覆盖 scheduler loop、SQLite/PVC 可写、最近 heartbeat、analyze 可执行性和必要配置装载。SQLite/PVC 不可写、scheduler 停摆、最近 heartbeat 超时或 analyzer 失败时,health 应非健康。`/metrics` 至少暴露 run 成功率、最近 finding 数、采样延迟、active observer 数和 maintenance 状态。 +终态 ingest identity 固定为 `(sentinelId,node,lane,runId)`;相同 identity 与相同 payload hash 必须幂等,相同 identity 与不同 payload hash 必须结构化拒绝。runner 在 analyze 后同步提交已有 report/finding/locator,并对瞬时失败做 YAML 声明的有界重试;最终失败必须显示 `monitor-ingest-failed` 或等价语义,允许用同一不可变 artifact 显式重提,禁止写本地 SQLite fallback、永久 outbox 或第二索引。 -Pod 重建后应从 PVC 恢复 index 与最近 artifact 摘要;进行中 run 可以标记 `interrupted` 并重新调度,不能静默假绿。 +runner `/health` 必须覆盖配置装载、scheduler/CronJob 观察、artifact PVC 可写、analyze 可执行性和中心 ingest 可达性;中心 Monitor `/health` 必须覆盖配置、Host PG 连接/schema、ingest/query 和前端资产。Pod 重建不能靠扫描 PVC 或补造历史恢复中心索引;进行中 run 可以按已有执行事实标记 `interrupted` 并重新调度,不能静默假绿。 ### 6.4 OPS-SENTINEL-REQ-004 报告视图和 dashboard @@ -516,7 +537,7 @@ P8 恢复判定必须把 Workbench 业务失败继续 drill-down 到运行面依 | --- | --- | --- | --- | | OPS-SENTINEL-REQ-005 | 发布集成 | PJ2026-0106050805 发布集成 | [发布流水](PJ2026-010601-controlled-release.md)、[源码同步](PJ2026-010602-source-sync.md)、[公开入口](PJ2026-010604-public-entry.md) | -Web哨兵自身必须纳入受控且独立的 sentinel control-plane:source 来自 UniDesk `master`,镜像、GitOps path、Argo Application、publicExposure 和 targetValidation 由 Web 哨兵 owning YAML 声明。D601/v03 当前可通过 `web-probe sentinel image|control-plane` 的独立 publish Job 实现构建、推送、GitOps 写回和 Argo 收敛;后续也可以切换到 Tekton Pipeline,但 builder 类型必须来自 YAML,不得依赖 operator 本地 dirty worktree。 +Web 哨兵自身必须纳入受控且独立的 sentinel control-plane:source 来自 UniDesk `master`,runner 与中心 Monitor 的镜像、GitOps path、Argo Application、中心 publicExposure 和 targetValidation 分别由对应 owning YAML 声明。builder 类型必须来自 YAML,不得依赖 operator 本地 dirty worktree。 哨兵自身 CI/CD 的 source identity 必须来自 k8s git-mirror source snapshot。`trigger-current` 应先通过 YAML 声明的 git-mirror cache/service 在 k8s 内解析并同步 selected commit,再把同一 source snapshot 注入 publish PipelineRun、GitOps 写回、status 和 closeout。operator host 上的 `git ls-remote`、`git fetch`、`git clone`、`git rev-parse HEAD` 和固定 host worktree 读写不得参与正式 source selection。 @@ -584,6 +605,8 @@ P10/P11 monitor-web 范围内新增或修改的 Vue/TypeScript/Vite 前端、typ P15 cadence/OTel 范围内新增或修改的 CronJob renderer/status probe、runner health/overview、quick verify record path、monitor-web cadence 展示和 OTel emitter 源码文件头部必须标注 `SPEC: PJ2026-01060508 Web哨兵 draft-2026-07-01-p15-cadence-otel`。 +P17 中心持久化范围内新增或修改的 Monitor ingest/query、Host PG store/schema、SQLite export/import、runner terminal submit、monitor-web API client、CLI report/status、YAML renderer 和 cutover 工具源码文件头部必须标注 `SPEC: PJ2026-01060508 Web哨兵 draft-2026-07-12-p17-monitor-central-persistence`。 + 实现文件不得只写 issue 编号、`latest`、`current` 或“按最新方案”作为规格引用。自动生成文件、第三方 vendored 文件、纯 YAML/config、锁文件和无法承载注释头的二进制产物不要求加源码头部,但对应生成器、渲染器、owning YAML 或 CLI 入口必须能追溯到本 SPEC。 后续 P1-P6 阶段如果改变稳定需求、观察对象、数据流、接口、部署边界或验收口径,应先更新本规格和上级 [PJ2026-010605 运维监控](PJ2026-010605-observability-monitoring.md),再更新执行 issue。 @@ -606,7 +629,7 @@ Dashboard 前端架构应借鉴 Sub2API 监控面板的分层方式:typed API Dashboard 自动刷新只能读取 bounded API,不得发送 `observe command`、不启动新采样、不重新 analyze、不保存额外截图。页面 hidden、loading 或上一次请求未完成时应暂停或跳过刷新,避免监控 UI 自身制造额外压力。 -P11 起,长期权威观察面板是 Vue `monitor-web`,不是 runner 内置 vanilla dashboard。迁移前 runner dashboard 可以继续承担单哨兵兼容、短修和回归对照,但趋势曲线、固定视口三栏、运行时间线、多哨兵聚合、cadence freshness 和 root cause 默认可见性必须在 `monitor-web` 中设计和验收。 +长期权威观察面板是 Vue `monitor-web`,不是 runner 内置 dashboard。切换前 runner 页面只允许用于迁移对照,切换发布必须删除其查询和展示入口;趋势曲线、固定视口三栏、运行时间线、多哨兵聚合、cadence freshness 和 root cause 默认可见性统一在中心 `monitor-web` 中设计和验收。 P8 中文运维页面必须以中文为默认用户可见语言:主标题、状态、筛选、运行历史、finding 分组、run detail、trace-frame、Final Response、空态、错误态、自动刷新和下一步动作均使用中文。原始英文 code、status 枚举、CLI 命令和 report SHA 可作为机器对照保留,但不得要求用户阅读英文 finding 才能判断 HWLAB 是否可用、卡在哪一层、下一步运行什么命令。 @@ -616,41 +639,49 @@ P8 中文运维页面必须以中文为默认用户可见语言:主标题、 | --- | --- | --- | --- | | OPS-SENTINEL-REQ-010 | 多实例与账号切换 | PJ2026-0106050810 多实例与账号切换 | [YAML运维](PJ2026-010603-yaml-first-ops.md)、[用户管理](PJ2026-0105-user-management.md)、[公开入口](PJ2026-010604-public-entry.md) | -Web 哨兵多实例必须以 node/lane root YAML 的 `observability.webProbe.sentinels[]` 为唯一 registry。每个 registry 项必须通过 `configRef` 指向独立 sentinel 管理 YAML,管理 YAML 再声明 runtime、workflow/scenario、promptSet、reportViews、publicExposure、cicd 和 secrets configRefs。legacy `observability.webProbe.sentinel` 只能作为单实例兼容入口;当同一 node/lane 存在多个 sentinel 时,除 `plan/status` registry 总览外,image、control-plane、validate、maintenance、report 和服务启动都必须显式携带 `--sentinel `。 +Web 哨兵多实例必须以 node/lane root YAML 的 `observability.webProbe.sentinels[]` 为唯一 runner registry。每个 registry 项必须通过 `configRef` 指向独立 sentinel 管理 YAML,管理 YAML 再声明 runtime、workflow/scenario、promptSet、reportViews、cicd 和 secrets configRefs;中心 Monitor 由独立 `observability.webProbe.monitor.configRef` 声明。对 runner 的 image、control-plane、validate 和执行操作必须显式携带 `--sentinel `;全局 report/overview 默认走中心 API,并支持显式 scope。 -每个 sentinel 必须拥有独立的 Deployment、ServiceAccount、Service、PVC、SQLite path、GitOps path、Argo Application、FRP Secret/Deployment、metrics label、report index namespace 和 dashboard/report route label。不同 sentinel 可以共享同一 public hostname,但必须通过 YAML `routePrefix` 或等价 publicExposure 声明区分路径;不得共享同一个 PVC/SQLite 后再用 scenario id 伪装实例隔离。 +每个 sentinel 必须拥有独立的 runner Deployment/Job、ServiceAccount、ClusterIP Service、artifact PVC、GitOps path、Argo Application、metrics label 和稳定 `(sentinelId,node,lane)` identity;不得共享一个执行 Pod/PVC 后再用 scenario id 伪装隔离。结构化 run/finding/locator 统一写入中心 Host PG,并以稳定 identity、FK 和 scope 索引隔离,不再声明 per-sentinel SQLite path 或 report index namespace。 `workbench-dsflash-go-tool-call-10x` 是保留的生产 canary,迁移到多实例 registry 后其 observe/analyze、report view、dashboard root 和 targetValidation 语义不得回退。迁移 closeout 必须证明旧实例 `sentinel plan --sentinel workbench-dsflash-go-tool-call-10x` 仍能解析原 runtime/scenario/prompt/report/publicExposure/cicd/secrets 引用。 `workbench-auth-session-switch-2users` 是账号切换链路哨兵。账号 A/B 的用户名、密码或 token 只能来自 Secret sourceRef 和 targetKey;CLI、服务日志、dashboard、report 和 issue evidence 只能展示 account id、sourcePurpose、presence、fingerprint 或 redacted 摘要。workflow 必须通过同一 `web-probe observe command` 控制队列支持 `loginAccount`、`logout`、`listSessions` 和 `switchSessions` 命令;submit 或命令失败必须作为结构化失败解决和上报,不能只写到备注里。 -账号切换 report view 至少要给出账号 A/B login/logout 成败、session 列表可见性、切换前后 active session/account id、trace/final 可见性、blocked finding 和同一 observer/run/report SHA。`auth-session-switch-summary` 视图只读取已有 artifact/report/index,不重新访问 Workbench、不保存第二套截图、不打印账号凭据。 +账号切换 report view 至少要给出账号 A/B login/logout 成败、session 列表可见性、切换前后 active session/account id、trace/final 可见性、blocked finding 和同一 observer/run/report SHA。`auth-session-switch-summary` 视图只读取中心索引及其引用的已有 artifact/report,不重新访问 Workbench、不保存第二套截图、不打印账号凭据。 -多实例 public exposure 复测必须通过受控 `web-probe screenshot` 或沉淀后的 command 远程截图能力完成,并把 PNG 保存到调用者 `/tmp` 下用于人工布局分析。修复 dashboard 布局问题后,复测截图必须覆盖 root dashboard 和至少一个 sentinel route prefix。 +公网只暴露中心 monitor-web;runner Service 不按 sentinel 单独公开。多实例 public exposure 复测必须通过受控 `web-probe screenshot` 或沉淀后的 command 远程截图能力完成,并把 PNG 保存到调用者 `/tmp` 下用于人工布局分析。修复 dashboard 布局问题后,复测截图必须覆盖 root dashboard 和至少一个中心 API 驱动的 sentinel detail route。 -### 6.11 OPS-SENTINEL-REQ-011 Monitor Web 聚合 +### 6.11 OPS-SENTINEL-REQ-011 Monitor 中心服务与 Web | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | -| OPS-SENTINEL-REQ-011 | Monitor Web 聚合 | PJ2026-0106050811 Monitor Web 聚合 | [公开入口](PJ2026-010604-public-entry.md)、[YAML运维](PJ2026-010603-yaml-first-ops.md)、Dashboard工作台、多实例与账号切换 | +| OPS-SENTINEL-REQ-011 | Monitor 中心服务与 Web | PJ2026-0106050811 Monitor 中心服务与 Web | [公开入口](PJ2026-010604-public-entry.md)、[YAML运维](PJ2026-010603-yaml-first-ops.md)、Dashboard工作台、多实例与账号切换 | -P10 起,Web 哨兵运行面必须区分 `sentinel-runner` 与 `monitor-web`。`sentinel-runner` 继续以每个 sentinel id 一套 Deployment、Service、PVC、SQLite index、scheduler、observe wrapper、report API、health 和 metrics 的形态存在;它只负责采样、分析、索引和提供单哨兵渐进读取 API。`monitor-web` 是独立的展示和聚合层,负责 `monitor.pikapython.com` root、所有 enabled sentinel 的 registry 总览、聚合 overview/runs/findings、单哨兵 detail route、受控截图/验证入口和人类值守信息架构。runner 不得因为聚合需求而回退到共享 Pod、共享 PVC 或共享 SQLite。 +P17 起,Web 哨兵运行面必须区分 `sentinel-runner`、中心 `monitor-service` 与 `monitor-web`。runner 只负责采样、分析、不可变 artifact、执行健康和终态提交;中心 service 是 Host PG 唯一 writer/query authority,负责 global overview/runs/findings/detail、maintenance/cadence 结构化状态与 locator;monitor-web 只负责展示和人类值守信息架构。禁止把 monitor-web 继续挂在任一 runner 上作为 `runner-served-bridge`。 -`monitor-web` 配置必须是 YAML-first。node/lane、namespace、Deployment、Service、publicExposure、runner discovery label selector、read timeout、聚合 API、静态资源托管方式、RBAC、NetworkPolicy 和 Secret sourceRef 都必须来自 owning YAML 或 configRef。root `observability.webProbe.sentinels[]` 仍是 enabled sentinel registry;`monitor-web` 可以读取该 registry 与 Kubernetes Service/EndpointSlice discovery 结果做一致性校验,但不得把发现结果写回成第二 source of truth。 +中心 Monitor 配置必须是 YAML-first。node/lane、namespace、Deployment、Service、publicExposure、Host PG database/role/export/Secret consumer、ingest/query timeout、静态资源托管方式、RBAC、NetworkPolicy 和 migration/cutover mode 都必须来自 owning YAML 或 configRef。root `observability.webProbe.sentinels[]` 仍是 enabled sentinel registry;数据库或 Kubernetes discovery 只能与 registry 做一致性校验,不能写回第二 source of truth。 -Runner discovery 优先使用 Kubernetes 原生对象:runner Service/Pod 必须带 `unidesk.ai/web-probe-sentinel-id`、node、lane、workspace 和 component label;`monitor-web` 使用 Service list/watch 或 EndpointSlice list/watch 按 label selector 发现 ClusterIP runner endpoint。Prometheus/ServiceMonitor 只用于低基数 metrics scrape,不承载 report drill-down,也不替代 runner HTTP API。runner Service 默认 ClusterIP;公网只暴露 `monitor-web`,不逐个暴露 runner。 +Runner Service/Pod 必须带 `unidesk.ai/web-probe-sentinel-id`、node、lane、workspace 和 component label,供中心控制面做健康、触发与 artifact locator 可达性检查。中心 query 绝不能按请求 fan-out runner API、读取 runner SQLite 或扫描 PVC;runner 不可用时,已经进入 Host PG 的历史仍必须可查,只有对应 artifact locator 显示不可达。Prometheus/ServiceMonitor 只用于低基数 metrics scrape,不承载 report drill-down。 -`monitor-web` 前端目标技术栈为 Vue 3 + TypeScript + Vite,并与 HWLAB Cloud Web 的组件拆分、typed API client、状态管理、加载/空态/错误态、Markdown/代码块渲染和样式约定对齐。旧 `scripts/assets/web-probe-sentinel-dashboard/dashboard.js` vanilla `innerHTML` 实现只允许作为迁移前的短修和对照,不再作为 monitor-web 新能力的长期承载面。迁移前的短修仍必须保留 P8/P9 三栏、高信息密度、中文运维页面、渐进披露和 trace-frame 入口。 +`monitor-web` 前端目标技术栈为 Vue 3 + TypeScript + Vite,并与 HWLAB Cloud Web 的组件拆分、typed API client、状态管理、加载/空态/错误态、Markdown/代码块渲染和样式约定对齐。前端只能消费中心 bounded API,不允许 N+1 拉取 runner detail 或客户端合并 global latest。旧 runner 内置 dashboard/静态资产在切换完成后删除,不作为兼容入口保留。 P10 dashboard 受控验收必须沉淀为 CLI 入口。`web-probe sentinel dashboard verify|screenshot` 或等价命令必须从 selected sentinel 的 YAML `publicExposure.publicBaseUrl` 解析 URL,通过远程浏览器执行 JS、采集 pageerror/console/requestfailed/DOM 行数/布局溢出和截图 SHA。`validate` 中的 public dashboard 200 只证明 HTML/CSS/JS 静态资源可达,不能替代浏览器渲染验收。 -`monitor.pikapython.com` root 的目标首屏必须展示所有 enabled sentinels 的 latest status、latest run、red/amber/info 摘要、freshness、runner degraded 状态和 drill-down 链接;`/sentinels/` 必须展示单哨兵 runs/findings/detail/trace-frame。删除或重启一个 runner 只能让对应 sentinel 显示 degraded,不得让 root 变成空白或阻断其他 runner 数据。聚合 API 必须 bounded、分页、redacted,不打印 Secret、prompt 原文、provider payload、cookie、完整 stdout/stderr 或完整 report。 +`monitor.pikapython.com` root 必须展示所有 enabled sentinels 的 latest status、latest run、red/amber/info 摘要、freshness、runner degraded 状态和 drill-down 链接;`/sentinels/` 必须从同一中心 API 展示单哨兵 runs/findings/detail/trace-frame。删除或重启一个 runner 只能让对应 execution/artifact 可达性显示 degraded,不得清空已持久历史或阻断其他 runner 数据。所有 API 必须 bounded、分页、redacted,不打印 Secret、prompt 原文、provider payload、cookie、完整 stdout/stderr 或完整 report。 + +Host PG 首版数据模型必须至少包含 runner identity、run、finding、run payload、artifact locator、timeline event、schema migration 和 import manifest。run identity 使用 `(sentinelId,node,lane,runId)` 唯一约束;finding 和 payload 以 run FK 关联;artifact locator 保存 owner node/lane/PVC、stateDir、relative path、SHA、size 和 kind,不保存 artifact blob。全局及 scoped latest 统一按 `updatedAt DESC, runId DESC` 选择,所有列表使用稳定 cursor,不允许各 runner 自己定义 latest。 + +中心 ingest 首版使用同步 HTTP 提交,不引入 Kafka、第二数据库或长期 outbox。runner 只提交已有 analyze/report 事实;中心在一个 PG transaction 内写入 run、finding、payload、locator 和 timeline。提交失败时 run 执行结果与 `monitor-ingest-failed` 必须同时可见;对同一不可变 report 的显式重提属于恢复同一事实,不得修改 payload、补造 report 或把失败 run 静默标成已记录。 + +SQLite 到 Host PG 的迁移必须先恢复并验证 YAML 声明的 Host PG role/database/export/Secret consumer,再从 resolved registry 生成实际 source 清单。受控 cutover 依次执行:暂停新 run 并等待 active run 结束、对每库记录 fingerprint/integrity/schema/row count、创建一致只读快照、单 source transaction 导入、校验行数/关键字段/latest/locator SHA 与可达性、切换 runner writer 和中心 query、恢复 cadence。切换前允许回到冻结快照;PG 接管新写入后不得回写或重新服务 SQLite。 + +实现可以分两次自动发布:第一次交付 PG capable 的中心 service、store 和迁移工具,但生产读写仍保持旧权威且不得双写;第二次在迁移校验成功后一次性切换 writer/query/UI/CLI,并删除 runner SQLite/query/dashboard 路径。PR 合并后只能观察自动 GitHub webhook → Gitea mirror → PaC → CI/CD → GitOps/Argo 链路,自动链路不通时修自动链路,禁止手工补触发。 ### 6.12 OPS-SENTINEL-REQ-012 Monitor Web 观察面板与 CI/CD 治理 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | -| OPS-SENTINEL-REQ-012 | Monitor Web 观察面板治理 | PJ2026-0106050812 Monitor Web 观察面板治理 | Monitor Web 聚合、Dashboard工作台、[源码同步](PJ2026-010602-source-sync.md)、[发布流水](PJ2026-010601-controlled-release.md) | +| OPS-SENTINEL-REQ-012 | Monitor Web 观察面板治理 | PJ2026-0106050812 Monitor Web 观察面板治理 | Monitor 中心服务与 Web、Dashboard工作台、[源码同步](PJ2026-010602-source-sync.md)、[发布流水](PJ2026-010601-controlled-release.md) | `monitor-web` 首屏信息架构必须把值守判断放在最前:顶部状态与全局操作之后,先显示哨兵入口,再在哨兵入口正下方展示运行趋势曲线。趋势曲线至少展示最近运行窗口内 red finding count、warning/amber finding count 和 total finding count;当前选中 run、maintenance window、缺失 report、stale run 和 runner degraded 必须有可见标记。 @@ -660,33 +691,33 @@ P10 dashboard 受控验收必须沉淀为 CLI 入口。`web-probe sentinel dashb cadence freshness 必须成为 `monitor-web` 的一等状态。每个 sentinel 应显示 YAML expected cadence、scheduler heartbeat age、latest run age、latest analyzed report age、active run、planned/next run 和 stale 倍数。cadence stale 默认是非阻塞告警;只有 scheduler 停摆、run/report 长时间不产生、submit/command 失败、采样样本缺失、或 Code Agent 多轮业务链路不可继续时,才升级为 blocker。面板不得把 timing warning、terminal-boundary elapsed correction 或单纯超时预算告警伪装成业务 blocker。 -P12 runner-served-bridge 形态下,sentinel runner Pod 可以只承载 API、PVC/SQLite index、health、metrics 和 dashboard 静态资源;若 Pod 内没有完整 repo 配置、`trans`、Chromium 或 observe 依赖,不得让 Pod 自行 SSH/回调宿主机触发巡检。周期巡检必须由受控宿主控制面调度器读取同一 YAML registry、scenario/workflow cadence、publicExposure 和 targetValidation timeout,按 stale 窗口触发现有 `web-probe sentinel validate --quick-verify --confirm --wait` 路径。该调度器只负责 due 判断、互斥锁、timeout、命令执行和 JSONL 事件日志,不实现第二套采样、analyze、finding 分类或 report 写入。 +P17 删除 `runner-served-bridge`。sentinel runner Pod/Job 只承载执行 adapter、artifact PVC、health、metrics 和中心 ingest client;若运行单元没有完整 repo 配置、`trans`、Chromium 或 observe 依赖,不得自行 SSH/回调宿主机触发巡检。周期巡检仍由受控 node/lane CronJob 读取同一 YAML registry、scenario/workflow cadence 和 targetValidation timeout,并触发现有 `web-probe sentinel validate --quick-verify --confirm --wait` 语义;它不实现第二套采样、analyze、finding 分类或 report 写入。 -宿主控制面调度器必须由目标 node/lane 的 k3s CronJob/GitOps 或等价受控入口周期调用,默认 tick 间隔不得替代 YAML cadence;每次 tick 必须输出 sentinel id、cadence、latest run age、due、trigger status、latest run id 和下一步 drill-down。触发失败要区分业务 finding、命令 submit/control 失败、overview/API 不可达、lock-held 和 timeout;业务 finding 已产生新 run 时不得把 scheduler 本身标为 infra blocker。`monitor-web` 应继续把 stale run 作为非阻塞告警展示,但 run/report 持续不更新或 submit/control 失败必须能在面板和 CLI 中直接看到根因。 +调度器必须由目标 node/lane 的 k3s CronJob/GitOps 受控入口周期调用,默认 tick 间隔不得替代 YAML cadence;due 判断读取中心 Monitor 的 latest 与 YAML cadence,不读取 runner 私有索引。每次 tick 必须输出 sentinel id、cadence、latest run age、due、trigger status、latest run id 和下一步 drill-down。触发失败要区分业务 finding、命令 submit/control 失败、中心 query/ingest 不可达、lock-held 和 timeout;业务 finding 已产生并成功 ingest 新 run 时不得把 scheduler 本身标为 infra blocker。 `monitor-web` 前端必须使用 Vue 3 + TypeScript + Vite,并与 HWLAB Cloud Web/Sub2API 运维图表的组件化方式对齐:typed API client、format composable、auto refresh composable、chart component、timeline component、run table、detail tabs、finding groups、loading/empty/error 状态和深链路由。图表库不是前置结论;可选 Chart.js、ECharts 或原生 SVG/canvas,但 SPEC/PR 必须说明包体、构建耗时、交互能力和维护成本取舍。 -Vue `monitor-web` 的 CI/CD 必须和架构一起交付。YAML 必须声明 source、build context、Node/Bun/Vite 构建环境、env image、dependency cache、registry image、GitOps path、Argo Application、Service、publicExposure、runner discovery selector 和 screenshot 验收命令。CI 读源码必须优先走 node/lane 声明的 git mirror read URL;触发 PipelineRun 前做受控 pre-sync,GitOps promotion 后做受控 post-flush,并在 status/closeout 中输出 `pendingFlush`、`githubInSync`、source commit、GitOps revision 和 PipelineRun 名称。 +Vue `monitor-web` 与中心 Monitor service 的 CI/CD 必须和架构一起交付。YAML 必须声明 source、build context、Node/Bun/Vite 构建环境、env image、dependency cache、registry image、GitOps path、Argo Application、Service、publicExposure、Host PG Secret consumer、runner control-plane discovery selector 和 screenshot 验收命令。CI 读源码必须优先走 node/lane 声明的 git mirror read URL;PR 合并后只允许自动链路完成 mirror、PaC、PipelineRun、GitOps 和 Argo 收敛。 Vue `monitor-web` 构建必须利用 env reuse、CI tools/env image、依赖缓存和镜像层缓存。未修改 runner/backend/API 时不得重建无关运行面;纯 SPEC、CLI、文档或无需 runtime 重建的提交应在 status 中呈现 `build=0 reuse=` 或等价 reuse 证据。Vue `monitor-web` CI/CD 总耗时或单个 build TaskRun 超过两分钟时,必须先从 env reuse、依赖缓存、git mirror pre-sync、镜像层缓存和无关服务重建方向优化,再继续 UI 功能实现;不得死等长 PipelineRun 后只记录超时。 -发布成功判据不能只看 legacy `dashboard.js` 静态资源 200。Vue `monitor-web` closeout 必须记录 Vite 产物内容 hash、asset 200/字节数/SHA、HTML 引用一致性、`/health`、root 聚合页 browser render、至少一个 `/sentinels/` 详情页 render、远程 PNG localPath/SHA、DOM 摘要、overflow 结果、Argo/runtime/source/GitOps/git mirror alignment 和 runner degraded 降级行为。所有触发、rollout、status、git mirror sync/flush 和截图验收必须走 UniDesk 受控 CLI。 +发布成功判据必须同时覆盖中心 `/health`、Host PG schema/read-write probe、Vue assets 和 browser render,不能只看静态资源 200。closeout 必须记录 Vite 产物 hash、中心 API、root 与至少一个 `/sentinels/` 详情页、远程 PNG localPath/SHA、DOM/overflow、Argo/runtime/source/GitOps alignment,以及停一个 runner 后历史仍可读而 locator 显示 degraded。禁止手工触发 mirror、PipelineRun、Argo sync/refresh 或补做 CI/CD。 ### 6.13 OPS-SENTINEL-REQ-013 D518 多 runner 强边界与 OTel 根因收敛 | 编号 | 短名 | 主责模块 | 关联模块 | | --- | --- | --- | --- | -| OPS-SENTINEL-REQ-013 | D518 多 runner 强边界 | PJ2026-0106050813 D518 多 runner 强边界 | 多实例与账号切换、Monitor Web 聚合、OTel、AgentRun、YAML运维 | +| OPS-SENTINEL-REQ-013 | D518 多 runner 强边界 | PJ2026-0106050813 D518 多 runner 强边界 | 多实例与账号切换、Monitor 中心服务与 Web、OTel、AgentRun、YAML运维 | 本阶段执行 issue 为 [#1206](https://github.com/pikasTech/unidesk/issues/1206),阶段子 issue 为 P0 [#1208](https://github.com/pikasTech/unidesk/issues/1208)、P1 [#1209](https://github.com/pikasTech/unidesk/issues/1209)、P2 [#1210](https://github.com/pikasTech/unidesk/issues/1210)、P3 [#1211](https://github.com/pikasTech/unidesk/issues/1211)、P4 [#1212](https://github.com/pikasTech/unidesk/issues/1212)、P5 [#1213](https://github.com/pikasTech/unidesk/issues/1213)、P6 [#1214](https://github.com/pikasTech/unidesk/issues/1214)、P7 [#1215](https://github.com/pikasTech/unidesk/issues/1215) 和 P8 [#1216](https://github.com/pikasTech/unidesk/issues/1216)。 -D518/v03 不允许再以“多个 sentinel 配置入口共享一个 runner Deployment/Service/PVC/SQLite/FRP/Caddy owner”的形式上线。每个 sentinel 必须有独立 runtime configRef,至少独立声明 Deployment、Service、ServiceAccount、PVC、stateRoot、SQLite path、CronJob、FRP Deployment、FRP Secret、httpProxy name、remotePort、GitOps path 和 Argo Application。`observeWrapperRef` 不得使用 `sentinels[0]` 这类位置索引;必须由 selected sentinel id 解引用或用等价稳定 id 绑定。 +D518/v03 不允许多个 sentinel 配置入口共享一个 runner Deployment/Service/artifact PVC。每个 sentinel 必须有独立 runtime configRef,至少独立声明 runner Deployment/Job、Service、ServiceAccount、PVC、stateRoot、CronJob、GitOps path 和 Argo Application;公网 FRP/Caddy 只属于中心 monitor-web。`observeWrapperRef` 不得使用 `sentinels[0]` 这类位置索引,必须由 selected sentinel id 解引用或用等价稳定 id 绑定。 -runner API 的边界必须是硬约束。`/api/overview`、`/api/runs`、`/api/findings`、`/api/runs/:id` 和 `/api/report` 只能返回当前 runner `sentinelId`、node、lane 下的数据;SQLite schema 至少包含 `sentinelId/scenarioId/observerId/runId`,并对 runs/findings 建立 sentinel 维度索引。route sentinelId 与服务实例 sentinelId 不一致时,API 必须返回结构化 `sentinel-route-mismatch` blocker,不允许 fallback 到其他 sentinel 的 latest run,也不允许前端过滤后继续展示。 +runner API 只保留 health、受控 trigger 与 artifact locator 访问,不再提供 overview/runs/findings/report。中心 API 必须按 `sentinelId`、node、lane、scenario、run identity 做显式 scope 与排序;route scope 与 registry/数据库 identity 不一致时返回结构化 `sentinel-route-mismatch`,不允许 fallback 到其他 sentinel 的 latest,也不允许前端过滤后继续展示。 状态语义必须区分 latest selected run 与 historical trend。latest run 的 `blocked/failed/error/timeout` 可以驱动当前状态为 blocker;历史趋势里的 red/error 样本只能作为趋势或历史风险展示,不能把一个已选 latest run 误标为当前阻塞。timing budget 超过 YAML `targetValidation.maxSeconds` 但已采集到 durable completed business turn 时,默认是非阻塞 timing warning;只有 submit/control 失败、样本缺失、报告未生成或 Code Agent 多轮业务链路不可继续时才升级为 blocker。 -dashboard verify/screenshot 必须断言 selected sentinel 的 route 和 API 返回一致:远程浏览器脚本必须检查 DOM bootstrap `data-sentinel-id`、`/api/overview.sentinelId`、`/api/runs.sentinelId`、runs rows 的 `sentinelId` 和 public URL routePrefix。任何 dsflash route 返回 fake-echo 数据、fake-echo route 返回空 body 或 root route 绑定单 runner 的情况都必须失败并给出有界证据。 +dashboard verify/screenshot 必须断言 selected sentinel 的 route 和中心 API 返回一致:远程浏览器脚本必须检查 DOM selected sentinel、overview scope、runs rows 的 `sentinelId` 和 public URL route。任何 dsflash route 返回 fake-echo 数据、detail route 返回空 body、root 绑定单 runner 或页面绕过中心 API 的情况都必须失败并给出有界证据。 OTel 根因契约必须与应用内 report/index 分工清楚。sentinel report/index 负责 latest、history、finding、artifact、timeline、availability 和 runner heartbeat;OTel/Tempo 负责跨服务根因链路。D518 `diagnose-code-agent` 的 AgentRun namespace/lane 必须从 `config/hwlab-node-lanes.yaml` 解析到实际 `agentrun-v02`,不得硬编码 `agentrun-v01`。HWLAB cloud-api、AgentRun manager 和 AgentRun runner 的 span 必须能通过 trace context 串联;缺失任一段时标为 instrumentation blocker 或 instrumentation gap,不得静默跳过。 @@ -718,7 +749,7 @@ Web 哨兵周期巡检必须由目标 node/lane 的 Kubernetes CronJob/GitOps `web-probe sentinel control-plane status` 必须把 CronJob 作为独立 observed check,而不是只相信 Argo `Synced/Healthy`。当 YAML 启用 cadenceScheduler 但线上缺 CronJob 时,状态必须 blocked,故障码固定为 `sentinel-cadence-cronjob-missing`;schedule 不一致使用 `sentinel-cadence-cronjob-schedule-mismatch`;CronJob suspend 使用 `sentinel-cadence-cronjob-suspended`。状态输出至少展示 CronJob name、namespace、schedule/expectedSchedule、lastScheduleTime、lastSuccessfulTime、active job count、jobCount 和 latest job name。 -`monitor-web` 必须把 cadence freshness 作为一等状态:显示 YAML expected cadence、scheduler heartbeat age、latest run age、latest analyzed report age、active runs、planned runs、stale multiple、CronJob 观察状态和 OTel coverage/gap。runner API 不直接查询 Kubernetes CronJob 时,页面必须显式显示 `control-plane-status-required`,不得让用户误以为 CronJob 已观察通过。 +`monitor-web` 必须把 cadence freshness 作为一等状态:显示 YAML expected cadence、scheduler heartbeat age、latest run age、latest analyzed report age、active runs、planned runs、stale multiple、CronJob 观察状态和 OTel coverage/gap。中心 API 未取得 Kubernetes CronJob observed fact 时,页面必须显式显示 `control-plane-status-required`,不得让用户误以为 CronJob 已观察通过。 Web 哨兵必须向平台 OTel 后端发出有界、脱敏的 span 或在状态中显式标记 instrumentation gap。P15 span 名称固定为:`web_probe_sentinel.scheduler.heartbeat`、`web_probe_sentinel.cadence.expected`、`web_probe_sentinel.cadence.cronjob_rendered`、`web_probe_sentinel.cadence.cronjob_observed`、`web_probe_sentinel.quick_verify.job_start`、`web_probe_sentinel.quick_verify.job_finish`、`web_probe_sentinel.record_run`、`web_probe_sentinel.scheduler_gap.detected`。属性至少包含 node、lane、sentinelId、scenarioId、runId、cronJobName、jobName、podName、namespace、cadence、status、exitCode、failureKind、gitopsRevision、sourceCommit、imageDigest 和 valuesRedacted;不存在的属性可以省略但不得打印 Secret、prompt、cookie、provider payload 或完整 stdout/stderr。 @@ -738,16 +769,18 @@ P8 哨兵恢复执行 issue 为 [#971](https://github.com/pikasTech/unidesk/issu P8-P8 起,targetValidation 的 availability blocker 与 Workbench timing 架构治理必须分层。若同一 trace 在 terminal 前最后一帧仍为 running,随后 terminal commit 的 sealed `durationMs` 把可见 `totalElapsed` 小幅校正到更短值,且 drop 不超过 YAML `turnTimingSampleSlackSeconds`、final response 与完成行均已可见,则该现象作为 terminal-boundary timing correction 证据保留,不生成 `turn-timing-total-elapsed-decrease` red blocker。归零、running/running 下降、terminal 后增长、完成耗时与卡片耗时超出 slack、trace 乱序和完成行非最后仍保持 red;根因治理继续归 [HWLAB #2055](https://github.com/pikasTech/HWLAB/issues/2055) 和 [HWLAB #2125](https://github.com/pikasTech/HWLAB/issues/2125),不得在 UI、CLI renderer 或 analyzer 中做读侧 repair。 -P9 多实例巡检与账号切换链路执行 issue 为 [#1017](https://github.com/pikasTech/unidesk/issues/1017)。P9 closeout 必须回写:SPEC P9 引用、registry 和两条 sentinel drill-down、旧 dsflash canary 迁移验证、账号切换 workflow/Secret sourceRef 验证、独立 Deployment/PVC/Service/SQLite/GitOps/Argo/public route prefix 证据、submit/command 失败处理、非阻塞计时告警证据、远程 PNG 截图布局复测,以及未完成阶段是否已拆出后续 issue。 +P9 多实例巡检与账号切换链路执行 issue 为 [#1017](https://github.com/pikasTech/unidesk/issues/1017)。P9 closeout 必须回写:SPEC P9 引用、registry 和两条 sentinel drill-down、旧 dsflash canary 迁移验证、账号切换 workflow/Secret sourceRef 验证、独立 runner Deployment/PVC/Service/GitOps/Argo 与中心索引 scope 证据、submit/command 失败处理、非阻塞计时告警证据、远程 PNG 截图布局复测,以及未完成阶段是否已拆出后续 issue。 -P10 monitor-web 聚合执行 issue 为 [#1056](https://github.com/pikasTech/unidesk/issues/1056)。P10 closeout 必须回写:SPEC P10 引用、runner/web 职责拆分状态、Vue+TS monitor-web 迁移边界或短修边界、root 与至少一个 route prefix 的 browser render 证据、`web-probe sentinel dashboard verify|screenshot` 证据、publicExposure 和 runtime provenance、单哨兵 API 兼容性、未完成 monitor-web 架构项是否拆出后续 issue,以及 `unidesk-monitor` skill 是否记录当前操作面。 +P10 monitor-web 聚合执行 issue 为 [#1056](https://github.com/pikasTech/unidesk/issues/1056)。P10 的 runner fan-out/runner-served-bridge 方案已由 P17 取代;后续 closeout 只保留可复用的 Vue 信息架构、browser render、dashboard verify/screenshot、publicExposure 和 runtime provenance 证据,不再以单哨兵查询 API 兼容性作为门禁。 P11 monitor-web 观察面板治理执行 issue 为 [#1112](https://github.com/pikasTech/unidesk/issues/1112)。P11 的第一阶段必须先完成本 SPEC 收敛;SPEC 未合并前不得推进 Vue `monitor-web` 实现、CI/CD、GitOps、publicExposure 或部署代码。P11 实现 PR closeout 必须回写:SPEC P11 引用、Vue monitor-web 源码和 CI/CD 文件头部追溯、趋势曲线和运行时间线截图、固定视口三栏 overflow 摘要、cadence freshness 状态、env reuse/buildServices 证据、git mirror pre-sync/post-flush 证据、PipelineRun/Argo/GitOps/source alignment、root 与至少一个 sentinel detail 远程截图 localPath/SHA,以及超过两分钟 CI/CD 耗时是否已先从 env reuse/git mirror 方向优化。 P12 cadence 调度和 monitor-web 交互修复执行 issue 为 [#1123](https://github.com/pikasTech/unidesk/issues/1123)。P12 closeout 必须回写:SPEC P12 引用、两个 10m cadence sentinel 的 stale 证据、k3s CronJob/GitOps 调度器 due 判断和触发记录、auth sentinel Argo/source alignment、趋势曲线 hover 数值和时间截图/DOM 证据、三栏 sticky header 遮盖复测、远程 PNG localPath/SHA、k3s CronJob 状态、以及两个目标 sentinel 最新 run 已刷新到当前窗口的证据。 -P13 D518 多 runner 强边界与 OTel 根因收敛执行 issue 为 [#1206](https://github.com/pikasTech/unidesk/issues/1206)。P13 closeout 必须回写:SPEC P13 引用、[#1208](https://github.com/pikasTech/unidesk/issues/1208)-[#1216](https://github.com/pikasTech/unidesk/issues/1216) 阶段状态、D518 双 sentinel 独立 Deployment/Service/PVC/CronJob/GitOps/Argo/public route 证据、route/API sentinelId 强断言、report/index 不串线证据、dashboard verify/screenshot localPath/SHA、k3s CronJob 调度证据、latest selected run 与 historical trend 状态分层证据、以及 OTel AgentRun namespace/trace gap 是否已解除或拆入后续 issue。 +P13 D518 多 runner 强边界与 OTel 根因收敛执行 issue 为 [#1206](https://github.com/pikasTech/unidesk/issues/1206)。P13 closeout 必须回写:SPEC P13 引用、[#1208](https://github.com/pikasTech/unidesk/issues/1208)-[#1216](https://github.com/pikasTech/unidesk/issues/1216) 阶段状态、D518 双 sentinel 独立 runner Deployment/Service/PVC/CronJob/GitOps/Argo 证据、中心 route/API scope 强断言、report/index 不串线证据、dashboard verify/screenshot localPath/SHA、k3s CronJob 调度证据、latest selected run 与 historical trend 状态分层证据,以及 OTel AgentRun namespace/trace gap。 P14 Web 哨兵 CI/CD 可见性执行 issue 为 [#1285](https://github.com/pikasTech/unidesk/issues/1285)。P14 closeout 必须回写:SPEC P14 引用、source commit、PR/merge commit、JD01/v03 `jd01-web-probe-sentinel` publish job、digest、GitOps revision、git mirror flush 状态、Argo/runtime observed alignment、`validate`、dashboard screenshot、latest report,以及超过 YAML 等待预算时的结构化阶段归因和可续跑命令。 P15 Cadence 调度稳定性与 OTel 覆盖执行 issue 为 [#1372](https://github.com/pikasTech/unidesk/issues/1372)。P15 closeout 必须回写:SPEC P15 引用、[#1374](https://github.com/pikasTech/unidesk/issues/1374)-[#1378](https://github.com/pikasTech/unidesk/issues/1378) 阶段状态、JD01/v03 `jd01-web-probe-sentinel` CronJob manifest/GitOps/Argo/runtime observed 证据、`sentinel-cadence-cronjob-missing` 防回归状态、monitor-web cadence/OTel coverage 显示、OTel trace search 或 instrumentation-gap 证据、受控 rollout/publish job、GitOps revision、source commit、dashboard/health 验收,以及 CI/CD 门禁仍只验证 `/health` 的证据。 + +P17 Monitor 中心持久化与架构重构执行 issue 为 [#1868](https://github.com/pikasTech/unidesk/issues/1868),P0 调研为 [#1869](https://github.com/pikasTech/unidesk/issues/1869)、[#1870](https://github.com/pikasTech/unidesk/issues/1870) 和 [#1871](https://github.com/pikasTech/unidesk/issues/1871)。P17 必须按“Host PG 前置健康、中心 store/ingest/query、runner terminal submit、一次性迁移与原子切换、monitor-web/CLI 中心读取、自动发布与原入口验收”顺序推进。closeout 必须记录 SQLite 冻结 fingerprint/行数、PG 导入校验、global latest 规则、artifact locator 可达性、runner 停机后历史可读、旧 SQLite 与 runner dashboard 已退出读写路径,以及 PR 合并后的自动 CI/CD 证据。