Bläddra i källkod

docs(cockpit): T28 结票(100%)并确立「真实启动路径是 yarn dev」的环境口径

- 票 28:验收由「predev 演示环境」改框到真实启动路径(`yarn dev` / `fes build`),
  维护者明确 predev 只用于预览插件、真实应用环境不使用它启动服务;predev 那条几何
  改作「宿主套壳」的等价复现手段留在证据里。5 项验收全部勾上,进度 100%。
- map.md:Notes 写明环境口径(yarn dev 真实路径、predev 不是产品路径);
  Decisions so far 追加票 28 的 gist。
- 票 06:把过时的 npm 措辞改为 yarn,并记下这条口径。
- verify/t28-fill-container.mjs:脚本头注释同步口径(不再把 predev 当验收环境)。

注:本次一并提交的 map.md 还带票 27 会话写的状态行与 gist(27 已由其会话关闭)。
其中「yarn dev 走查 20/20」与我实测不一致——服务停之前我最后一次跑是 19/20,
A15 的 widgetChrome=1 为红(cesiumEngine.js 最后修改 15:41,早于该次实测,
也早于 27 的关闭时间 16:05),已反馈维护者,待 27 会话复跑确认。
Kazerin 1 månad sedan
förälder
incheckning
7e433255fd

+ 2 - 2
.scratch/cockpit-shell-panel-layout/issues/06-cockpit-static-assets.md

@@ -63,7 +63,7 @@ Labels: ready-for-agent
 同一份代码在两次走查里 A12「页面铺满视口」先红后绿,差异来自**开发环境的布局配置**,不是代码:
 
 - 红的那次:外壳 `y=54`、`main.bottom=992 > vh=950`。页面顶部有 TvT 演示菜单「📀 预览演示 / 📜 源码地址 / 📚 说明文档」,而这些菜单只存在于 `.fes.predev.js` 与 `.fes.predev.one.js`(`layout.navigation: 'top'` + `isFixedHeader: true`)。Fes 布局 `src/.fes/plugin-layout/views/BaseLayout.vue` 走 `'top'` 分支渲染 54px 固定页头,把内容区顶到 `top: 54px`,外壳再按 `100vh` 铺就被挤出容器底部。
-- 绿的那次(本次):`pageHeaderH: 0`、外壳 `y=0 h=950`、`main.bottom=938 ≤ 950`。服务跑的是 `.fes.js` 环境(`layout.navigation: null`),`BaseLayout.vue` 落到最后的 `<template v-else>`,只渲染 `<FMain><router-view /></FMain>`,**没有页头**。`npm run dev` 与 `npm run build` 都是这个环境。
+- 绿的那次(本次):`pageHeaderH: 0`、外壳 `y=0 h=950`、`main.bottom=938 ≤ 950`。服务跑的是 `.fes.js` 环境(`layout.navigation: null`),`BaseLayout.vue` 落到最后的 `<template v-else>`,只渲染 `<FMain><router-view /></FMain>`,**没有页头**。真实启动路径 `yarn dev` 与产品构建 `yarn build` 都是这个环境。维护者 2026-09-16 明确:**真实应用环境不使用 predev 启动服务**,故 predev 那条红与产品无关。
 - 票 06 未触及布局、路由与任何 `.fes*` 配置;把顶栏高度还原成改动前的 56 设计像素,`main.bottom` 仍是 992,即失败量与本次改动无因果关系。
 
-已做的加固:走查脚本头部写明「必须用 `npm run dev`,别用 `pre.dev` / `pre.dev.one`」的前置条件,A12 证据新增 `pageHeaderH`(null 布局为 0、predev 演示布局为 54),下次一眼可辨是环境还是回归。另立票 28,让外壳填满所在容器而不是硬用 `100vh`——这样在 predev 演示站或将来 qiankun 主应用带页头的壳里,驾驶舱也照样铺满可用区域。
+已做的加固:走查脚本头部写明「用 `yarn dev`,别用 `yarn pre.dev` / `pre.dev.one`」并注明维护者这条环境口径;A12 证据新增 `pageHeaderH`(null 布局为 0、predev 演示布局为 54),下次一眼可辨是环境还是回归。另立票 28,让外壳填满所在容器而不是硬用 `100vh`——这样在宿主套壳(预演站或将来 qiankun 主应用带页头的壳)时,驾驶舱也照样铺满可用区域。

+ 26 - 16
.scratch/cockpit-shell-panel-layout/issues/28-shell-fill-container.md

@@ -1,48 +1,58 @@
 # 28: 外壳填满所在容器,而不是硬用 100vh
 
-**What to build:** `.cockpit-shell` 原先写死 `height: 100vh`。宿主布局一旦在页面顶部留出固定页头(`npm run pre.dev` 的 TvT 演示站是 54px;将来 qiankun 主应用也可能套壳),外壳就被挤出容器底部 54px:底部内容看不见,容器还多出一条纵向滚动条。改成填满**可用容器**,让驾驶舱在任何宿主布局下都铺满可用区域。
+**What to build:** `.cockpit-shell` 原先写死 `height: 100vh`。宿主布局一旦在页面顶部留出页头、或把 `/cockpit` 放进比视口矮的容器里(预演站是 54px 页头;将来 qiankun 主应用也可能套壳),外壳就被挤出容器底部 54px:底部内容看不见,容器还多出一条纵向滚动条。改成填满**可用容器**,让驾驶舱在任何宿主下都铺满可用区域。
 
 Blocked by: 01
 
-Status: claimed
+Status: resolved
 Labels: ready-for-agent
 
+> 请勿据标签重复接单:本票已完成并有验证记录,`Labels` 保留只是为了让面板不把它退化成 `needs-triage`。
+
+## 环境口径(维护者 2026-09-16 澄清)
+
+**真实启动路径是 `yarn dev`**(= `fes dev` → `.fes.js`:`layout.navigation: null`,页面无页头);**真实应用环境不使用 predev 启动服务**。`yarn pre.dev` / `pre.dev.one` 是 TvT 预演站布局(`navigation: 'top'` + `isFixedHeader`,顶部多 54px 固定页头),只用于预览插件,不是产品路径。
+
+本票最初把验收写成「predev 演示环境下……」,那是**框错了环境**:验收改以真实路径为准(见下),predev 那条几何只作为「宿主套壳」的等价复现手段保留在证据里。本票的剩余价值因此落在两点:真实路径下不得有回归;将来 `/cockpit` 被 qiankun 主应用或别的前端壳包住时,外壳仍要铺满可用区域而不是溢出。
+
 ## 依赖与事实
 
-- 走查 A12(铺满视口)在 predev 环境下红、在 `.fes.js`(`npm run dev` / `fes build`)环境下绿;两次走查数据与根因定位见 [06](06-cockpit-static-assets.md) 的「关于走查 A12 的环境差异」。
+- 走查 A12(铺满视口)在预演站环境下红、在 `.fes.js`(`yarn dev` / `yarn build`)环境下绿;两次走查数据与根因定位见 [06](06-cockpit-static-assets.md) 的「关于走查 A12 的环境差异」。
 - 页头来源:`.fes.predev.js` / `.fes.predev.one.js` 的 `layout.navigation: 'top'` + `isFixedHeader: true`;`.fes.js` 是 `navigation: null`,`src/.fes/plugin-layout/views/BaseLayout.vue` 落到 `v-else`,只渲染 `<FMain><router-view /></FMain>`。
-- 走查脚本已加 `pageHeaderH` 字段与「必须用 `npm run dev`」的前置条件说明,可用它判断当前跑在哪个环境。
+- 走查脚本已加 `pageHeaderH` 字段与「用 `yarn dev`,别用 `yarn pre.dev`」的前置条件说明,可用它判断当前跑在哪个环境。
 
 ## 验收
 
-- [ ] predev 演示环境(`npm run pre.dev`)下页面无纵向滚动、外壳底部不被裁切:`main.bottom <= 视口高`。
-      → 等价验证已过(见下),**真实 predev 环境待人工确认**,故本票未 close。
-- [x] `.fes.js` 环境(`npm run dev`)下 A12 仍绿:外壳铺满视口、中央一张图吃掉剩余宽高。
+- [x] **真实启动路径 `yarn dev`**(产品构建为 `fes build`)下:页面无纵向滚动、外壳铺满视口、`main.bottom <= 视口高`、中央一张图吃掉剩余宽高。
+- [x] 宿主套壳(顶部有页头,例如将来 qiankun 主应用的前端壳)时外壳跟着容器变矮、底部不被裁切——用等价复现验证(见证据 B)。
+- [x] `.fes.js` 环境(`yarn dev`)下走查 A12 仍绿。
 - [x] 改动落在驾驶舱模块内,不靠全局路由配置改布局(`.fes.js` 的 `router.routes` 会关掉整套文件路由,见票 01 的约束)。
 - [x] 窗口 resize 后仍贴合,不得只在挂载时算一次。
-- [x] 走查 A12 绿、`pageHeaderH` 与几何自洽(本轮走查 19/20:唯一红的 A15 是票 27 会话同一时间新加的 `widgetChrome` 断言,与本票无关)。
+- [x] 走查 A12 绿、`pageHeaderH` 与几何自洽。
 
-## 进度:95%
+## 进度:100%
 
 ### 已实施
 
 `src/modules/cockpit/CockpitShell.vue` 两处,**只动这一个文件**(没碰路由、`.fes.js` 或宿主布局):
 
-- `.cockpit-shell`:`position: relative; width: 100%; height: 100vh` → `position: absolute; inset: 0`。贴着最近的定位容器:宿主留了页头时容器矮,外壳就跟着矮;没有定位祖先时按规范落回初始包含块(=视口),所以普通 dev 下仍是铺满视口。resize 由 CSS 自己跟随,**没有**挂载时测量、也没有 resize 监听(驾驶舱模块内 grep 无 `innerHeight` / `clientHeight`)。
+- `.cockpit-shell`:`position: relative; width: 100%; height: 100vh` → `position: absolute; inset: 0`。贴着最近的定位容器:宿主留了页头时容器矮,外壳就跟着矮;没有定位祖先时按规范落回初始包含块(=视口),所以 `yarn dev` 下仍是铺满视口。resize 由 CSS 自己跟随,**没有**挂载时测量、也没有 resize 监听(驾驶舱模块内 grep 无 `innerHeight` / `clientHeight`)。
 - `.cockpit-shell__atmosphere`:`fixed` → `absolute`,氛围底只铺驾驶舱自己的范围,不再盖到宿主页头那一带。
 
 ### 验收证据
 
-`node .scratch/cockpit-shell-panel-layout/verify/t28-fill-container.mjs` → **7/7 通过**。脚本把 `#tvt-app` 临时改成「有定位 + top:54px + 高度 = 视口 - 54px + 滚动容器」,在当前真实页面上复刻 predev 那条几何链路(predev 实测的定位容器是 `section.fes-layout.is-fixed`:absolute、top 54px、高 896),再对比新旧实现:
+真实路径(`yarn dev`,服务在 8000):外壳 `position: absolute`、`y=0 h=950`(= 视口高)、底边贴合、链上无可滚动祖先、地图铺满主体;走查 A12(铺满视口)保持绿。
+
+`node .scratch/cockpit-shell-panel-layout/verify/t28-fill-container.mjs` → **7/7 通过**。脚本把 `#tvt-app` 临时改成「有定位 + top:54px + 高度 = 视口 - 54px + 滚动容器」,复刻「宿主套壳」那条几何链路(预演站里实测到的定位容器是 `section.fes-layout.is-fixed`:absolute、top 54px、高 896),再对比新旧实现:
 
-- `A-real-host` 普通 dev(无页头):外壳 `y=0 h=950`(= 视口高)、底边贴合、链上无可滚动祖先、地图铺满主体。
-- `B1-reproduce-old` **复现**:带 54px 页头的宿主 + 旧实现(`position: static; height: 100vh`)→ 外壳 `y=54 h=950`、底边 1004 > 视口 950、宿主容器多出纵向滚动。与票 06 走查在 predev 实测到的 `y=54 / main.bottom=992` 是同一现象。
+- `A-real-host` 真实宿主(无页头):外壳铺满视口、底边贴合、无可滚动祖先、地图铺满主体。
+- `B1-reproduce-old` **复现**:套壳宿主 + 旧实现(`position: static; height: 100vh`)→ 外壳 `y=54 h=950`、底边 1004 > 视口 950、宿主容器多出纵向滚动。与票 06 走查在预演站实测到的 `y=54 / main.bottom=992` 是同一现象。
 - `B2-fixed` 修复后:外壳高 = 容器高 896、底边 = 视口底 950、`main.bottom <= 视口高`、无纵向滚动、地图仍铺满主体。
 - `B3-atmosphere-scoped`:氛围底范围与外壳完全一致,不越界到页头那一带。
 - `B4-follows-container` + `C-real-viewport-resize`:容器再变矮 66px、以及把视口**真的**改成 1280x720,外壳都跟着缩(666 = 720 - 54)并保持底边贴合、无滚动条——证明是 CSS 跟随,不是一次性测量。
 
-回归:`t06-assets.mjs` 15/15、`t01-panel-catalog.mjs` 通过、走查 A12 仍绿(本轮 19/20,唯一红的 A15 属票 27 会话在改的断言)。
+回归:`t06-assets.mjs` 15/15、`t01-panel-catalog.mjs` 通过、走查 A12 仍绿。
 
-### 下一步(待确认什么,故未 close)
+### 环境口径的由来
 
-验收第 1 条写的是「`npm run pre.dev` 演示环境下」。我没有起服务(项目规则要求不得自行起 dev/serve),上面是复刻该环境几何链路的等价验证。请你在真实 `npm run pre.dev` 下看一眼 `/cockpit`(或授权我在别的端口起一次 predev 复跑走查):外壳应贴着演示页头、底部不被裁、页面无纵向滚动。确认后本票置 100% 并 close。
+本票原先的验收第 1 条写的是「`npm run pre.dev` 演示环境下」,属于**框错了环境**:维护者 2026-09-16 明确真实启动路径是 `yarn dev`、真实应用环境不使用 predev 启动服务。上面的证据全部落在真实路径,宿主套壳那条用等价复现覆盖;走查脚本头部与 `map.md` 的 Notes 也同步了这条口径,免得后人再去追 predev。

+ 5 - 3
.scratch/cockpit-shell-panel-layout/map.md

@@ -3,7 +3,7 @@
 Status: open
 Labels: wayfinder:map
 
-本目录是 `/to-spec` + `/to-tickets` 的产物,不是 wayfinder effort:`spec.md` 是规格,`issues/01`–`23` 是实现票(01、02、06 已关闭),`issues/24`–`28` 是调研、待人工处理项与后续新增票(24 调研已关闭;25 待人工;26 watcher 崩溃已修复;**27 接入 Cesium 常驻 Viewer**,是票 03 的前置,实施中;28 外壳填满容器,由 06 的环境差异派生)。
+本目录是 `/to-spec` + `/to-tickets` 的产物,不是 wayfinder effort:`spec.md` 是规格,`issues/01`–`23` 是实现票(01、02、06 已关闭),`issues/24`–`28` 是调研、待人工处理项与后续新增票(24 调研已关闭;25 待人工;26 watcher 崩溃已修复;**27 接入 Cesium 常驻 Viewer**,是票 03 的前置,已关闭;28 外壳填满容器已关闭)。
 本 `map.md` 的唯一作用是把这个 effort 暴露给 issue tracker 面板——面板只枚举含 `map.md` 的 `.scratch/<effort>/`,没有 `map.md` 的目录连同它的票都不会被列出。
 `Labels: wayfinder:map` 在这里只用于让面板按**地图视图**渲染本 effort 的子票状态、进度与依赖分层;不代表本 effort 由 `/wayfinder` 驱动——推进仍走 `/implement`。
 
@@ -17,8 +17,8 @@ Labels: wayfinder:map
 - `issues/24`(resolved)是 AFK 调研,产物在 `research/panel-field-coverage.md`,不改业务代码。
 - `issues/25`(ready-for-human)是后端补契约与业务定义缺口,需要人或后端负责人处理;不阻塞 `01`–`23` 的 mock 阶段。
 - `issues/26`(resolved)是 dev server watcher 的 EBUSY 崩溃修复:忽略清单须同时覆盖 `.scratch` 面板原子写与 DSH 编辑审阅临时文件。
-- `issues/27`(ready-for-agent)是新增的引擎接入票:装 `cesium` + 静态资源/`CESIUM_BASE_URL` + 服务层创建唯一 Viewer;**票 03 依赖它**(相机契约必须落在真实引擎上)。
-- **走查必须在 `npm run dev` 下跑**(`.fes.js` → `layout.navigation: null`,无页头)。`npm run pre.dev` / `pre.dev.one` 是 TvT 演示站点布局(`navigation: 'top'` + `isFixedHeader`),页面顶部多 54px 固定页头,外壳按 `100vh` 铺就溢出容器底部——A12 会红但那是环境差异。A12 证据里的 `pageHeaderH` 就是用来分辨这一点的(见票 28)。
+- `issues/27`(resolved)是引擎接入票:装 `cesium` + 静态资源/`CESIUM_BASE_URL` + 服务层创建唯一 Viewer;**票 03 依赖它**(相机契约必须落在真实引擎上)。已关闭,验证证据与遗留(本工作区 `fes build` 因两个未跟踪插件缺依赖而跑不完)见票面。
+- **真实启动路径是 `yarn dev`**(= `fes dev` → `.fes.js`:`layout.navigation: null`,无页头);**真实应用环境不使用 predev 启动**(维护者 2026-09-16 明确)。`yarn pre.dev` / `pre.dev.one` 是 TvT 预演站布局(`navigation: 'top'` + `isFixedHeader`,顶部多 54px 固定页头),那里出现的布局异常(如 A12 红)属环境差异。A12 证据里的 `pageHeaderH` 用来分辨这一点(见票 28)。
 - 相关技能:`implement`、`tdd`、`code-review`;TvT.js 侧基线是 `skills/tvt-js-plugin-builder/`。
 - 验收清单就在每张票正文里,完成时勾上并同步该票的 `Status:` 行。
 
@@ -31,6 +31,8 @@ Labels: wayfinder:map
 - [26: Dev server 文件监视被 `.scratch` 面板原子写击穿](issues/26-devserver-watch-scratch-crash.md) — 已修复(含重开补验):`.fes.js` 的 dev server watch 忽略 `**/.scratch/**` 与 `**/.dsh-*`(Vite 默认 ignore 合并不覆盖);两个触发源——面板原子写与 DSH 编辑审阅临时文件——均实测不再击穿。
 - [02: MapCanvas 常驻挂载](issues/02-mapcanvas-persistent-mount.md) — 已关闭:新增 `services/mapService.js` 持有实例生命周期(幂等挂载、尺寸上报、离开才销毁)+ 常驻宿主组件 `MapCanvas.vue`;逻辑单测 + 走查 A14 证明「切模式与收放面板都不重建」。
 - [06: 驾驶舱自有静态资产与视觉占位](issues/06-cockpit-static-assets.md) — 已关闭:token 唯一来源 `styles/tokens.css` 挂 `.cockpit-shell`(不挂 `:root`,免漏插件样式)、`public/cockpit/` 自持资产、占位/图标/状态标签三件套(`PanelPlaceholder` / `icons.js`+`CockpitIcon` / `statusTones.js`+`StatusTag`,标签带文字不吃纯色);零依赖脚本 15/15 + 走查 19/19。副产:查清 A12「铺满」的 predev 环境差异(并立票 28),走查脚本加 `pageHeaderH` 与前置条件说明。
+- [27: 接入 Cesium 常驻 Viewer](issues/27-cesium-viewer-integration.md) — 已关闭:`cesium@1.145.0` 固定版本(不进 federation `shared`、进 `manualChunks` 单独分包)+ `src/common/cesiumStaticPlugin.js`(dev/pre.dev 中间件与 build 拷贝四个静态目录,`pre.dev.one` 的 `copyPublicDir:false` 同样生效)+ `services/cesiumAssets.js`(`CESIUM_BASE_URL` 在 import 之前写入,取 `publicPath: './'` / qiankun 注入路径)+ `services/cesiumEngine.js`(唯一 Viewer:控件与默认相机输入全关、`baseLayer:false` 不伪造配准)+ `mapService` 持有引擎生命周期与宿主状态浮标;`yarn dev` 走查 20/20(含强制失败的兜底断言)、`pre.dev.one` 19/20(仅 A12 环境差异红)、`yarn pre.build.one` 日志证明四目录进产物。遗留:本工作区 `fes build` 被两个未跟踪插件缺依赖挡住(`@takram/three-3d-tiles-support`、`leaflet`),cesium 分包暂无产物证据。
+- [28: 外壳填满所在容器,而不是硬用 100vh](issues/28-shell-fill-container.md) — 已关闭:`.cockpit-shell` 由 `height: 100vh` 改为 `absolute + inset: 0`,贴着最近的定位容器(没有定位祖先时按规范落回初始包含块=视口);氛围层同步由 `fixed` 改 `absolute`,不再盖到宿主页头那一带。零依赖脚本 7/7(旧实现复现「越界 54px + 宿主滚动条」,交付实现容器等高、底边贴合、真·视口 resize 跟随),走查 A12 仍绿。附带确立:真实启动路径是 `yarn dev`,predev 预演站不是真实应用环境。
 
 ## Not yet specified
 

+ 9 - 10
.scratch/cockpit-shell-panel-layout/verify/t28-fill-container.mjs

@@ -1,18 +1,17 @@
 /**
  * T28 检查:外壳填满**所在容器**,而不是按 100vh 铺。
  *
- * 背景(票 28):宿主布局在页面顶部留页头时(`npm run pre.dev` 的 TvT 演示站是 54px
- * 固定页头,将来 qiankun 主应用也可能套壳),容器比视口矮,`height: 100vh` 会把外壳
- * 顶出容器底部——底部被裁、滚动容器还会多出一条纵向滚动条。
+ * 背景(票 28):外壳不能只认视口高度。真实启动路径是 `yarn dev`(`.fes.js` →
+ * `layout.navigation: null`,页面无页头,外壳贴初始包含块=铺满视口);但 `/cockpit` 一旦被
+ * 别的前端壳包住(例如将来 qiankun 主应用),容器的定位盒会比视口矮,`height: 100vh`
+ * 就会把外壳顶出容器底部:底部被裁、滚动容器还多一条纵向滚动条。
+ * 维护者已明确:**真实应用环境不使用 predev 启动服务**,所以这里不依赖 predev 服务。
  *
- * 为什么用「模拟宿主页头」而不是真的起 predev 服务:项目规则(AGENTS.md)要求不得自行
- * 起 dev/serve;而两种环境真正的差异只有一条——外壳的**定位容器**比视口矮 54px
- * (predev 下是 `section.fes-layout.is-fixed`:absolute + top:54px + 高 896;普通 dev 下
- * 没有定位祖先,外壳直接贴初始包含块=整个视口)。脚本把现有的 `#tvt-app` 临时改成
- * 「有定位 + top:54px + 高度 = 视口 - 54px + 滚动容器」,复刻那条几何链路,
- * 再对比「旧实现(position: static + height:100vh)」与「交付实现(absolute + inset:0)」。
+ * 做法:在当前真实页面里把 `#tvt-app` 临时改成「有定位 + top:54px + 高度 = 视口 - 54px +
+ * 滚动容器」,复刻「宿主套壳」那条几何链路(预演站里实测的定位容器是
+ * `section.fes-layout.is-fixed`:absolute、top 54px、高 896),再对比旧实现与交付实现。
  *
- * 运行(需先起 npm run dev,服务在 http://localhost:8000/):
+ * 运行(需先起 `yarn dev`,服务在 http://localhost:8000/):
  *   node .scratch/cockpit-shell-panel-layout/verify/t28-fill-container.mjs
  */
 import { join } from 'node:path'