完善 xyzbc-trt OPFS 与 AXIS 首屏等效

This commit is contained in:
mes123456
2026-07-02 10:10:54 -04:00
parent 1c8908e3ab
commit 52e54f8089
16 changed files with 925 additions and 28 deletions

View File

@@ -1,5 +1,51 @@
# 03-推进台账
## 2026-07-02 Web OPFS 强制与 AXIS 首屏等效实现轮次
### 本轮目标
接续用户要求“Web 的文件使用 OPFS 系统”,把浏览器端 machine files、session snapshot、tool table 保存链路从可 fallback 改为目标 app 默认强制 OPFS并完成 T-026 AXIS 首屏等效验收。
### 已做事项
- 修改 `app/src/runtime/linuxcnc-machine-file-staging.js`
- `saveMachineFileStagingPlan()` 的存储解析支持 `requireOpfs`
- 当目标 app 要求 OPFS 但浏览器缺少 `navigator.storage.getDirectory()` 或非安全上下文时直接报错,不再静默落到 memory fallback。
- 修改 `app/src/runtime/five-axis-session.js``app/src/runtime/tool-db-simulation.js`
- session snapshot 与 tool table 保存同样支持 `requireOpfs`
- 修改 `app/src/state/store.js``app/src/main.js`
- 浏览器 UI 默认对 machine file staging、session save/restore、tool DB save 启用 `requireOpfs=true`
- Node/测试显式传入 storage 时仍保留内存存储能力,用于非浏览器 smoke。
- 修改 `tests/browser/xyzbc_trt_browser_smoke.html`
- 断言启动 staging `storageMode=opfs`
- 从 OPFS 读回 `xyzbc_switchkins.ngc`,确认包含 `M428/M429`
- 保存并从 OPFS 读回 session snapshot确认包含 `machineProfile=xyzbc-trt`
- 保存并从 OPFS 读回 tool table确认包含 `T2/Z10`
- 断言 AXIS 首屏区域 dataset 和能力矩阵。
- 修改 `app/src/ui/gmoccapy-shell.js``app/src/styles/gmoccapy.css`
- 增加 AXIS 首屏等效状态带,覆盖 program、coordinates、status、MDI、switchkins、override、tool、preview、execution、axis-buttons。
- 各首屏区域输出 `data-axis-ui-section/profile/coordinates`,供浏览器验收。
- 修改 `tools/collect-web-xyzbc-trt-evidence.mjs``tools/compare-xyzbc-trt-evidence.mjs`
- 新增 `axisMainUi` evidence 和 compare 检查。
- Web evidence 中 Node 采集仍使用 memory storage真实浏览器 OPFS 以 `smoke:browser` 为准。
- 更新 `04-任务矩阵.md`
- T-006/T-014/T-016 增加真实 OPFS 验收描述。
- T-026 标记为完成。
### 验证情况
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node` 通过。
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build` 通过,输出 `gmoccapy_static_build=ok`
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser` 通过,输出 `xyzbc_trt_browser_smoke=ok`,其中已验证 OPFS 写入和读回。
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web` 通过。
- `npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare` 已生成真实失败报告:当前 20/25 通过;新增 AXIS 首屏检查通过,剩余 5 项仍来自 native preview/execution path 样本缺失。
### 下一步
1. 继续 T-019/T-037`/home/mes123456/cnc_wams/linuxcnc/scripts/rip-environment` 下重跑 native evidence使 native path 进入 20ms 可比状态。
2. 继续 T-028/T-030补 basic_sim 等效 task/HAL 细节和 Ngcgui/remap 子程序执行验收。
3. 继续 T-038基于真实 native 状态流复核 Web 按钮、HAL pin、路径和状态联锁。
## 2026-07-02 Tool table 到 tool-offset 闭环实现轮次
### 本轮目标

View File

@@ -7,7 +7,7 @@
| T-003 | 创建目标 Web app | 完成 | `web-rtcp-5axis-xyzbc-trt-sim-plan/app/index.html` 存在 |
| T-004 | 默认机型改为 `xyzbc-trt` | 完成 | `createSimulationStore().getState().machineProfile === "xyzbc-trt"` |
| T-005 | 接入 `xyzbc-trt` INI/profile | 完成 | profile 坐标为 `XYZBC`kinematics 为 `xyzbc-trt-kins` |
| T-006 | OPFS 路径隔离到目标项目 | 完成 | staged 文件 path 以 `web-rtcp-5axis-xyzbc-trt-sim-plan/machines/xyzbc-trt/` 开头 |
| T-006 | OPFS 路径隔离到目标项目 | 完成 | staged 文件 path 以 `web-rtcp-5axis-xyzbc-trt-sim-plan/machines/xyzbc-trt/` 开头;浏览器 smoke 断言 machine files/session/tool table 实际 `storageMode=opfs` 并可从 OPFS 读回 |
| T-007 | 默认加载 `xyzbc_switchkins.ngc` | 完成 | profile `machineFileStaging.defaultProgramFilename``xyzbc_switchkins.ngc` |
| T-008 | Stage remap/tool/PyVCP 文件 | 完成 | staging 包含 `428remap.ngc``429remap.ngc``430remap.ngc``xyzbc-trt.tbl``xyzbc-trt.xml` |
| T-009 | 增加目标 Node smoke | 完成 | `tests/node/verify_xyzbc_trt_web_app.mjs` 存在并通过 |
@@ -15,10 +15,10 @@
| T-011 | 完整 kinematics WASM 验证 | 完成 | `SKIP_KINEMATICS_BUILD=1 wasm-port/tests/wasm/node/verify_kinematics_wasm.sh` 通过,覆盖 `xyzbc-trt` |
| T-012 | 完整 interpreter/remap WASM 验证 | 完成 | `wasm-port/tests/wasm/node/verify_interp_wasm.sh` 通过,输出 `interp_wasm_node_smoke=ok` |
| T-013 | 完整 task/HAL WASM 验证 | 完成 | `SKIP_TASK_HAL_BUILD=1 wasm-port/tests/wasm/node/verify_task_hal_wasm.sh` 通过 |
| T-014 | 目标浏览器 smoke | 完成 | `npm run smoke:browser` 通过;页面默认显示 `xyzbc-trt`kinematics/interpreter/task-HAL worker runtime readycanvas 非空并暴露 Vismach dataset |
| T-014 | 目标浏览器 smoke | 完成 | `npm run smoke:browser` 通过;页面默认显示 `xyzbc-trt`kinematics/interpreter/task-HAL worker runtime readycanvas 非空并暴露 Vismach datasetWeb 文件强制使用 OPFS |
| T-015 | native 真实执行 JSON 采集 | 完成 | `native-xyzbc-trt-evidence.json` 记录真实执行事件,状态 completed |
| T-016 | Web OPFS/WASM readiness JSON 采集 | 完成 | `web-xyzbc-trt-evidence.json` 记录 Web profile/INI/staging/WASM readiness |
| T-017 | native/Web JSON 对比 | 部分完成 | `compare-xyzbc-trt-evidence.json` 已生成;当前 19/24 通过,剩余 5 项均为 native preview/execution path 样本缺失 |
| T-016 | Web OPFS/WASM readiness JSON 采集 | 完成 | `web-xyzbc-trt-evidence.json` 记录 Web profile/INI/staging/WASM readiness;真实浏览器 OPFS 由 `smoke:browser` 读回验证Node evidence 为内存采集 |
| T-017 | native/Web JSON 对比 | 部分完成 | `compare-xyzbc-trt-evidence.json` 已生成;当前 20/25 通过,剩余 5 项均为 native preview/execution path 样本缺失 |
| T-018 | WASM artifact 构建前置 | 完成 | 已生成 core/kinematics/tp/task-hal 所需 `.js/.wasm``web-xyzbc-trt-evidence.json.wasm.missing=[]` |
| T-019 | native 刀具预览路径 JSON 采集 | 待实现 | `native-xyzbc-trt-evidence.json.previewPath.samples` 使用 20ms 周期记录 LinuxCNC 预览刀路 |
| T-020 | native 刀具执行路径 JSON 采集 | 部分完成 | native 脚本已从 `stat()` 执行事件重采样为 20ms `executionPath`;需用新基线重跑生成证据 |
@@ -27,7 +27,7 @@
| T-023 | 刀路采样周期一致性检查 | 完成 | compare 检查 native/Web path `samplePeriodMs === 20`,否则 fail |
| T-024 | 刀路误差统计对比 | 完成 | compare 输出 preview/execution 的 TCP、joint、toolAxis 误差统计和缺样本清单 |
| T-025 | 全量对标追踪矩阵 | 完成 | `07-全量对标追踪矩阵.md` 逐项映射 `xyzbc-trt-runtime-files.md` 的运行功能 |
| T-026 | AXIS 主界面等效功能 | 待实现 | Web 首屏包含程序、坐标、状态、MDI/switchkins、override、工具和预览/执行区域 |
| T-026 | AXIS 主界面等效功能 | 完成 | Web 首屏包含程序、坐标、状态、MDI/switchkins、override、工具和预览/执行区域browser smoke 和 Web evidence `axisMainUi.ready=true` |
| T-027 | POSTGUI HAL/PyVCP 连接等效 | 完成 | Web evidence JSON 记录 `pyvcp.* -> halui.mdi-command-* -> M428/M429/M430` 和 multilabel 状态 |
| T-028 | basic_sim 等效 task/HAL | 待前置 | Web task/HAL runtime 覆盖模拟回零、manual toolchange、spindle、joint feedback |
| T-029 | Vismach 3D 模型 pin 对标 | 完成 | Web 3D 模型由 `table-x/saddle-y/spindle-z/tilt-b/rotate-c/tool-offset/x-offset/z-offset` 驱动;`web-xyzbc-trt-evidence.json.vismachEquivalent` 记录 pin 值、HAL net 和变换 |

View File

@@ -1,5 +1,58 @@
# 05-验收证据
## Web OPFS 与 AXIS 首屏等效验收
### 命令
```bash
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:node
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run build
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run smoke:browser
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:web
npm --prefix web-rtcp-5axis-xyzbc-trt-sim-plan/app run evidence:compare
```
### 结果
```text
xyzbc_trt_web_app_smoke=ok
gmoccapy_static_build=ok
xyzbc_trt_browser_smoke=ok
web_xyzbc_trt_evidence=.../working/evidence/web-xyzbc-trt-evidence.json
compare_xyzbc_trt_status=fail fail_count=5
```
### 浏览器 OPFS 断言
```text
machineFileSeedReady.save.storageMode = opfs
machineFileStaging.storageMode = opfs
machineFileStaging.storageCapability.opfsAvailable = true
OPFS readback xyzbc_switchkins.ngc contains M428/M429
saveSession().storageMode = opfs
OPFS readback session contains "machineProfile": "xyzbc-trt"
saveToolDb().storageMode = opfs
OPFS readback tool table contains T2 and Z10
```
### AXIS 首屏证据
```text
web.axisMainUi.ready = true
web.axisMainUi.profileId = xyzbc-trt
web.axisMainUi.coordinates = XYZBC
web.axisMainUi.missingCapabilities = []
web.coverage.axisMainUiEquivalent = true
compare.summary.passCount = 20
compare.summary.failCount = 5
```
结论:
- 目标 Web app 默认不再把 machine files、session、tool table 静默保存到 memory fallback浏览器路径强制 OPFS。
- `smoke:browser` 已从 OPFS 读回程序、会话和刀具表内容,证明不是仅生成 OPFS path。
- Node evidence 仍使用内存存储模拟文件内容,这是非浏览器采集限制;真实 Web 文件系统验收以 browser smoke 为准。
## Tool table 到 tool-offset 闭环验收
### 命令

View File

@@ -1,12 +1,12 @@
{
"apiName": "xyzbc-trt-native-web-evidence-comparison",
"status": "fail",
"comparedAt": "2026-07-02T13:36:36.368Z",
"comparedAt": "2026-07-02T13:57:49.317Z",
"nativePath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/native-xyzbc-trt-evidence.json",
"webPath": "/home/mes123456/cnc_wams/web-rtcp-5axis-xyzbc-trt-sim-plan/working/evidence/web-xyzbc-trt-evidence.json",
"summary": {
"checkCount": 24,
"passCount": 19,
"checkCount": 25,
"passCount": 20,
"failCount": 5,
"blockers": [],
"nativeStatus": "ok",
@@ -515,6 +515,201 @@
}
}
},
{
"category": "ui",
"requirement": "web AXIS first screen exposes program, coordinates, status, MDI/switchkins, override, tool, preview, and execution",
"status": "pass",
"evidence": {
"axisMainUi": {
"semanticBoundary": "xyzbc_trt_axis_first_screen_program_coordinates_status_mdi_switchkins_override_tool_preview_execution",
"firstViewport": "axis-equivalent-cnc-console",
"profileId": "xyzbc-trt",
"coordinates": "XYZBC",
"requiredSections": [
{
"id": "preview",
"section": "preview-toolpath-and-machine-model"
},
{
"id": "dro",
"section": "coordinates-dro"
},
{
"id": "gcode",
"section": "program-and-mdi"
},
{
"id": "status-sidebar",
"section": "status-mode-and-switchkins"
},
{
"id": "info-tabs",
"section": "execution-tool-and-runtime-state"
},
{
"id": "override",
"section": "feed-rapid-override"
},
{
"id": "spindle-coolant",
"section": "spindle-coolant"
},
{
"id": "bottom-controls",
"section": "run-jog-home-controls"
}
],
"capabilities": [
{
"id": "program",
"ready": true,
"evidence": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc"
},
{
"id": "coordinates",
"ready": true,
"evidence": {
"coordinates": "XYZBC",
"droAxes": [
"X",
"Y",
"Z",
"B",
"C"
]
}
},
{
"id": "status",
"ready": true,
"evidence": {
"taskState": "estop-reset",
"mode": "manual",
"runState": "idle"
}
},
{
"id": "mdi",
"ready": true,
"evidence": {
"command": "G0 X0 Y0 Z0",
"switchkinsMdi": [
"M429",
"M428",
"M430"
]
}
},
{
"id": "switchkins",
"ready": true,
"evidence": [
{
"value": 0,
"label": "identity",
"mdiCommand": "M429",
"webKinsType": "identity",
"remap": {
"code": "M429",
"modalGroup": 10,
"ngc": "429remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"switchkinsType": 0,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M429",
"halPin": "motion.switchkins-type"
},
{
"value": 1,
"label": "XYZBC TCP",
"mdiCommand": "M428",
"webKinsType": "tcp-xyzbc",
"remap": {
"code": "M428",
"modalGroup": 10,
"ngc": "428remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"switchkinsType": 1,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M428",
"halPin": "motion.switchkins-type"
},
{
"value": 2,
"label": "USERK",
"mdiCommand": "M430",
"webKinsType": "userk",
"remap": {
"code": "M430",
"modalGroup": 10,
"ngc": "430remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
"switchkinsType": 2,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M430",
"halPin": "motion.switchkins-type"
}
]
},
{
"id": "override",
"ready": true,
"evidence": {
"feedOverride": 100,
"rapidOverride": 100
}
},
{
"id": "tool",
"ready": true,
"evidence": {
"id": 2,
"pocket": 2,
"length": 10,
"diameter": 8
}
},
{
"id": "preview",
"ready": true,
"evidence": {
"samplePeriodMs": 20,
"sampleCount": 3074
}
},
{
"id": "execution",
"ready": true,
"evidence": {
"samplePeriodMs": 20,
"sampleCount": 569
}
},
{
"id": "axis-buttons",
"ready": true,
"evidence": {
"canRunAuto": false,
"canExecuteMdi": false,
"canJog": false,
"canHome": false
}
}
],
"missingCapabilities": [],
"ready": true
}
}
},
{
"category": "path-preview",
"requirement": "native and web preview path sample period is 20ms",

View File

@@ -1,7 +1,7 @@
{
"apiName": "xyzbc-trt-web-opfs-wasm-evidence",
"status": "ready-for-wasm-runtime",
"collectedAt": "2026-07-02T13:33:38.273Z",
"collectedAt": "2026-07-02T13:57:48.903Z",
"profile": {
"id": "xyzbc-trt",
"machineName": "sim-xyzbc-trt-kins (switchkins)",
@@ -117308,6 +117308,194 @@
],
"defaultActivationUsed": true
},
"axisMainUi": {
"semanticBoundary": "xyzbc_trt_axis_first_screen_program_coordinates_status_mdi_switchkins_override_tool_preview_execution",
"firstViewport": "axis-equivalent-cnc-console",
"profileId": "xyzbc-trt",
"coordinates": "XYZBC",
"requiredSections": [
{
"id": "preview",
"section": "preview-toolpath-and-machine-model"
},
{
"id": "dro",
"section": "coordinates-dro"
},
{
"id": "gcode",
"section": "program-and-mdi"
},
{
"id": "status-sidebar",
"section": "status-mode-and-switchkins"
},
{
"id": "info-tabs",
"section": "execution-tool-and-runtime-state"
},
{
"id": "override",
"section": "feed-rapid-override"
},
{
"id": "spindle-coolant",
"section": "spindle-coolant"
},
{
"id": "bottom-controls",
"section": "run-jog-home-controls"
}
],
"capabilities": [
{
"id": "program",
"ready": true,
"evidence": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc"
},
{
"id": "coordinates",
"ready": true,
"evidence": {
"coordinates": "XYZBC",
"droAxes": [
"X",
"Y",
"Z",
"B",
"C"
]
}
},
{
"id": "status",
"ready": true,
"evidence": {
"taskState": "estop-reset",
"mode": "manual",
"runState": "idle"
}
},
{
"id": "mdi",
"ready": true,
"evidence": {
"command": "G0 X0 Y0 Z0",
"switchkinsMdi": [
"M429",
"M428",
"M430"
]
}
},
{
"id": "switchkins",
"ready": true,
"evidence": [
{
"value": 0,
"label": "identity",
"mdiCommand": "M429",
"webKinsType": "identity",
"remap": {
"code": "M429",
"modalGroup": 10,
"ngc": "429remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/429remap.ngc",
"switchkinsType": 0,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M429",
"halPin": "motion.switchkins-type"
},
{
"value": 1,
"label": "XYZBC TCP",
"mdiCommand": "M428",
"webKinsType": "tcp-xyzbc",
"remap": {
"code": "M428",
"modalGroup": 10,
"ngc": "428remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/428remap.ngc",
"switchkinsType": 1,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M428",
"halPin": "motion.switchkins-type"
},
{
"value": 2,
"label": "USERK",
"mdiCommand": "M430",
"webKinsType": "userk",
"remap": {
"code": "M430",
"modalGroup": 10,
"ngc": "430remap",
"path": "configs/sim/axis/vismach/5axis/table-rotary-tilting/remap_subs/430remap.ngc",
"switchkinsType": 2,
"analogOutputIndex": 3,
"syncInputIndex": 0,
"requiresHalPinVars": true
},
"haluiCommand": "M430",
"halPin": "motion.switchkins-type"
}
]
},
{
"id": "override",
"ready": true,
"evidence": {
"feedOverride": 100,
"rapidOverride": 100
}
},
{
"id": "tool",
"ready": true,
"evidence": {
"id": 2,
"pocket": 2,
"length": 10,
"diameter": 8
}
},
{
"id": "preview",
"ready": true,
"evidence": {
"samplePeriodMs": 20,
"sampleCount": 3074
}
},
{
"id": "execution",
"ready": true,
"evidence": {
"samplePeriodMs": 20,
"sampleCount": 569
}
},
{
"id": "axis-buttons",
"ready": true,
"evidence": {
"canRunAuto": false,
"canExecuteMdi": false,
"canJog": false,
"canHome": false
}
}
],
"missingCapabilities": [],
"ready": true
},
"startupSequence": [
".desktop",
"rip-environment",
@@ -117649,6 +117837,7 @@
],
"uiEquivalence": {
"firstViewport": "axis-equivalent-cnc-console",
"semanticBoundary": "xyzbc_trt_axis_first_screen_program_coordinates_status_mdi_switchkins_override_tool_preview_execution",
"regions": [
"program",
"dro",
@@ -117658,6 +117847,18 @@
"tool",
"preview-execution"
],
"axisMainUiCapabilityIds": [
"program",
"coordinates",
"status",
"mdi",
"switchkins",
"override",
"tool",
"preview",
"execution",
"axis-buttons"
],
"activeProgram": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"selectedGcodeSourceRel": "configs/sim/axis/vismach/5axis/table-rotary-tilting/demos/xyzbc_switchkins.ngc",
"pyvcpPanelSchema": "xyzbc-trt-switchkins-pyvcp",
@@ -117911,6 +118112,7 @@
"axisJointLimitsCovered": true,
"previewPathAvailable": true,
"executionPathAvailable": true,
"axisMainUiEquivalent": true,
"toolTableToToolOffsetClosed": true,
"wasmArtifactsReady": true
},