dsh-engineering-ui 0.0.0-stage → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +772 -3
  3. package/engineering/plugins/dsh-engineering-ui/cordis.patch.yml +5 -0
  4. package/engineering/plugins/dsh-engineering-ui/icon.svg +14 -0
  5. package/engineering/plugins/dsh-engineering-ui/lib/client.js +8259 -0
  6. package/engineering/plugins/dsh-engineering-ui/lib/defense-sign.js +1552 -0
  7. package/engineering/plugins/dsh-engineering-ui/lib/index.js +5633 -0
  8. package/engineering/plugins/dsh-engineering-ui/lib/job-wait-guard.js +236 -0
  9. package/engineering/plugins/dsh-engineering-ui/lib/mem-guard.js +331 -0
  10. package/engineering/plugins/dsh-engineering-ui/lib/webots.js +114 -0
  11. package/engineering/plugins/dsh-engineering-ui/locale/en.json +6 -0
  12. package/engineering/plugins/dsh-engineering-ui/locale/zh.json +6 -0
  13. package/engineering/plugins/dsh-engineering-ui/preset-engineering.patch.yml +601 -0
  14. package/engineering/skills/assembly-orchestration/SKILL.md +651 -0
  15. package/engineering/skills/cad-workflow/SKILL.md +132 -0
  16. package/engineering/skills/mode-selection/SKILL.md +660 -0
  17. package/engineering/skills/physics-in-loop/SKILL.md +238 -0
  18. package/engineering/skills/physics-in-loop/references/feadocs.md +142 -0
  19. package/engineering/skills/solidworks-bridge/SKILL.md +445 -0
  20. package/engineering/skills/sw-design/SKILL.md +112 -0
  21. package/engineering/skills/sw-design/references/autocad-workflow.md +81 -0
  22. package/engineering/skills/sw-design/references/gbt-drafting.md +71 -0
  23. package/engineering/skills/sw-to-cad/SKILL.md +121 -0
  24. package/engineering/skills/webots-simulation/SKILL.md +58 -0
  25. package/engineering/tools/LICENSE.Auto-SolidWorks +21 -0
  26. package/engineering/tools/_plugin_paths.py +93 -0
  27. package/engineering/tools/_root.py +330 -0
  28. package/engineering/tools/_store.py +446 -0
  29. package/engineering/tools/ac_bridge.py +459 -0
  30. package/engineering/tools/ac_rules.json +21 -0
  31. package/engineering/tools/ac_validate.py +699 -0
  32. package/engineering/tools/ask_user.py +887 -0
  33. package/engineering/tools/build_arm1.py +46 -0
  34. package/engineering/tools/build_assembly.py +94 -0
  35. package/engineering/tools/build_base.py +57 -0
  36. package/engineering/tools/build_housing.py +70 -0
  37. package/engineering/tools/build_structural.py +43 -0
  38. package/engineering/tools/build_transmission.py +69 -0
  39. package/engineering/tools/cadx.lsp +128 -0
  40. package/engineering/tools/choice_contract.py +61 -0
  41. package/engineering/tools/conn_state.py +1671 -0
  42. package/engineering/tools/defense_gate.py +3374 -0
  43. package/engineering/tools/drawing_input.py +314 -0
  44. package/engineering/tools/env_check.py +467 -0
  45. package/engineering/tools/examples/build_axis.py +142 -0
  46. package/engineering/tools/examples/build_cup.py +56 -0
  47. package/engineering/tools/examples/build_plate.py +58 -0
  48. package/engineering/tools/examples/build_sphere.py +30 -0
  49. package/engineering/tools/examples/build_transition_duct.py +381 -0
  50. package/engineering/tools/gate_integrity.py +401 -0
  51. package/engineering/tools/mode2_flow.py +3589 -0
  52. package/engineering/tools/mode_checker.py +77 -0
  53. package/engineering/tools/mode_gate.py +8013 -0
  54. package/engineering/tools/part_registry.py +4266 -0
  55. package/engineering/tools/physics/__init__.py +50 -0
  56. package/engineering/tools/physics/_compat.py +12 -0
  57. package/engineering/tools/physics/design_state.py +142 -0
  58. package/engineering/tools/physics/domain_validator.py +751 -0
  59. package/engineering/tools/physics/fatigue.py +489 -0
  60. package/engineering/tools/physics/fea_solver.py +1163 -0
  61. package/engineering/tools/physics/feapy_solver.py +314 -0
  62. package/engineering/tools/physics/gb_materials.json +1228 -0
  63. package/engineering/tools/physics/geometry_gate.py +337 -0
  64. package/engineering/tools/physics/load_case.py +951 -0
  65. package/engineering/tools/physics/material_db.py +874 -0
  66. package/engineering/tools/physics/mesh_adapter.py +321 -0
  67. package/engineering/tools/physics/refine_rules.py +272 -0
  68. package/engineering/tools/physics/rules/gb_base_rules.json +377 -0
  69. package/engineering/tools/physics/rules/gb_drafting_rules.json +57 -0
  70. package/engineering/tools/physics/rules/gb_electrical_rules.json +25 -0
  71. package/engineering/tools/physics/rules/gb_fasteners_rules.json +73 -0
  72. package/engineering/tools/physics/rules/gb_housing_rules.json +41 -0
  73. package/engineering/tools/physics/rules/gb_manufacturing_rules.json +25 -0
  74. package/engineering/tools/physics/rules/gb_material_verify_rules.json +72 -0
  75. package/engineering/tools/physics/rules/gb_materials_rules.json +377 -0
  76. package/engineering/tools/physics/rules/gb_safety_rules.json +89 -0
  77. package/engineering/tools/physics/rules/gb_springs_rules.json +41 -0
  78. package/engineering/tools/physics/rules/gb_standards_registry.json +1646 -0
  79. package/engineering/tools/physics/rules/gb_structural_rules.json +201 -0
  80. package/engineering/tools/physics/rules/gb_surface_rules.json +25 -0
  81. package/engineering/tools/physics/rules/gb_transmission_rules.json +233 -0
  82. package/engineering/tools/physics/rules/housing_rules.json +48 -0
  83. package/engineering/tools/physics/rules/manifest.json +54 -0
  84. package/engineering/tools/physics/rules/mold_rules.json +48 -0
  85. package/engineering/tools/physics/rules/structural_rules.json +56 -0
  86. package/engineering/tools/physics/rules/transmission_rules.json +48 -0
  87. package/engineering/tools/physics/simulation_report.py +829 -0
  88. package/engineering/tools/physics_bridge.py +2685 -0
  89. package/engineering/tools/profile-manifest.ps1 +72 -0
  90. package/engineering/tools/run_regression.py +109 -0
  91. package/engineering/tools/settings.py +419 -0
  92. package/engineering/tools/solidworks-modeling.md +519 -0
  93. package/engineering/tools/sw_bridge.py +8215 -0
  94. package/engineering/tools/sw_guard.py +1066 -0
  95. package/engineering/tools/sw_surface.py +87 -0
  96. package/engineering/tools/swapi.py +14766 -0
  97. package/engineering/tools/verify_sync.py +218 -0
  98. package/engineering/tools/visual_check.py +2589 -0
  99. package/engineering/tools/webots_env.py +121 -0
  100. package/engineering/tools/webots_mcp/__init__.py +3 -0
  101. package/engineering/tools/webots_mcp/__main__.py +3 -0
  102. package/engineering/tools/webots_mcp/assembly.py +391 -0
  103. package/engineering/tools/webots_mcp/bootstrap.py +55 -0
  104. package/engineering/tools/webots_mcp/controller_worker.py +124 -0
  105. package/engineering/tools/webots_mcp/evidence.py +288 -0
  106. package/engineering/tools/webots_mcp/fake_worker.py +69 -0
  107. package/engineering/tools/webots_mcp/fault_resources.py +121 -0
  108. package/engineering/tools/webots_mcp/host.py +45 -0
  109. package/engineering/tools/webots_mcp/ledger.py +73 -0
  110. package/engineering/tools/webots_mcp/owned_job.py +70 -0
  111. package/engineering/tools/webots_mcp/physical_gate.py +187 -0
  112. package/engineering/tools/webots_mcp/physics.py +152 -0
  113. package/engineering/tools/webots_mcp/pipeline.py +108 -0
  114. package/engineering/tools/webots_mcp/recipes.py +129 -0
  115. package/engineering/tools/webots_mcp/repair.py +132 -0
  116. package/engineering/tools/webots_mcp/repair_trial.py +375 -0
  117. package/engineering/tools/webots_mcp/runtime.py +311 -0
  118. package/engineering/tools/webots_mcp/server.py +217 -0
  119. package/engineering/tools/webots_mcp/sw_export.py +509 -0
  120. package/engineering/tools/webots_mcp/transport.py +156 -0
  121. package/engineering/tools/workflow_gate.py +6134 -0
  122. package/package.json +64 -4
@@ -0,0 +1,71 @@
1
+ # GB/T 机械制图参考标准(DSH 工程模式)
2
+
3
+ > 来源:AutoCAD-skills mechanical-drafting-gbt / GBT 标准清单
4
+ > 用途:AI 生成或验证工程图时,作为尺寸标注、视图布局、线型规范的参考依据。
5
+
6
+ ## 核心标准清单
7
+
8
+ | 标准号 | 名称 |
9
+ |--------|------|
10
+ | GB/T 4457.4-2002 | 机械制图 图纸幅面和格式 图线 |
11
+ | GB/T 4458.4-2003 | 机械制图 尺寸注法 |
12
+ | GB/T 4458.5-2003 | 机械制图 公差与配合的注法 |
13
+ | GB/T 14689-2008 | 技术制图 图纸幅面和格式 |
14
+ | GB/T 14690-1993 | 技术制图 比例 |
15
+ | GB/T 14691-1993 | 技术制图 字体 |
16
+ | GB/T 14692-2008 | 技术制图 投影法 |
17
+ | GB/T 17451-1998 | 技术制图 视图 |
18
+ | GB/T 17452-1998 | 技术制图 剖视图和断面图 |
19
+ | GB/T 10609.1-2008 | 技术制图 标题栏 |
20
+ | GB/T 1182-2018 | 产品几何技术规范(GPS)几何公差 |
21
+ | GB/T 131-2006 | 产品几何技术规范 表面结构 轮廓法 |
22
+ | GB/T 1804-2000 | 一般公差 线性尺寸的未注公差 |
23
+
24
+ ## 实践规则
25
+
26
+ ### 线型层级
27
+
28
+ - **粗实线**:可见轮廓线、可见棱边
29
+ - **细实线**:尺寸线、尺寸界线、剖面线、指引线
30
+ - **细点画线**:轴线、对称中心线(需超出轮廓 2~5mm)
31
+ - **细虚线**:不可见轮廓线(剖面中减少可见性时用)
32
+ - **粗/细线比**:约 2:1,视觉区分明显即可
33
+
34
+ ### 视图与剖视
35
+
36
+ - 优先采用**第一角投影**(GB/T 默认),在标题栏注明投影方法
37
+ - 主视图、俯视图、右视图严格对齐:主俯同 X(长对正),主右同 Y(高平齐)
38
+ - 剖视图需要剖切符号和方向标记;位置明确时可省略
39
+ - 剖面线角度统一 45°,同一零件各视图剖面线方向和间距一致
40
+ - 螺纹孔、键槽、孔等标准件结构用简化画法,不画出每一个齿/旋棱
41
+
42
+ ### 标注规范
43
+
44
+ - 每个尺寸只注一次,不重复
45
+ - 最短尺寸靠近图形,外侧尺寸层层放大
46
+ - 直径标注在非圆视图上,加 Φ 符号;半径加 R
47
+ - 尺寸从功能基准(datum)出发,避免封闭尺寸链
48
+ - 轴类零件:直径在纵向视图标注,长度尺寸分层排列
49
+ - 文字统一水平方向,高度按选用的标题栏系列(常见 3.5mm)
50
+
51
+ ### 轴类零件专项
52
+
53
+ - 端倒角几何表示并标注一次(如 `2×45°`)
54
+ - 轴肩过渡需明确:圆角半径或退刀槽
55
+ - 轴承位和配合位注明公差带(如 `Φ50h6`);未确定时标 `TBD`
56
+ - 键槽宽度、深度、长度全部标注,`30×5` 单独出现时须说明约定
57
+ - 表面粗糙度附着在对应表面或作为总体要求,不可悬空装饰
58
+
59
+ ### 分级验证
60
+
61
+ **Pass 1 — 全图一致性**
62
+ - 闭合边界、零厚度材料、意外重叠、重复实体、相切断裂、同轴偏移
63
+ - 计算链长、半径/直径、对称偏移、角度、节距与显示尺寸交叉验证
64
+
65
+ **Pass 2 — 独立交叉视图重建**
66
+ - 从两个视图独立重建特征,预测第三视图位置并比对
67
+ - 每个剖视对照剖切面,剖面材料和孔洞前后关系正确
68
+
69
+ **Pass 3 — 发布检查**
70
+ - 检查修正冲突、高风险特征、功能基准、关键尺寸
71
+ - 最终导出为 PDF/DWG 后复查:字体丢失、裁剪、比例错误、线宽失效
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: sw-to-cad
3
+ description: >-
4
+ SolidWorks 零件一键转换为 CAD 工程图(DWG/PDF)。
5
+ 支持从 .sldprt 零件生成标准三视图工程图,并导出为 DWG(AutoCAD 可用)或 PDF。
6
+ whenToUse: >-
7
+ 当用户要求把 SolidWorks 零件转成 CAD 图纸、导出工程图、生成三视图、
8
+ 或需要 .dwg/.pdf 格式的图纸时使用。
9
+ source: engineering
10
+ provider: filesystem
11
+ ---
12
+
13
+ # SW → CAD 图纸转换指南
14
+
15
+ ## 功能概览
16
+
17
+ 将 SolidWorks 3D 零件(.sldprt)一键转换为:
18
+ - **工程图**(.slddrw):含标准三视图 + 等轴测
19
+ - **DWG**(.dwg):可直接用 AutoCAD 打开编辑
20
+ - **PDF**(.pdf):适合打印和分享
21
+
22
+ ## 使用方法
23
+
24
+ ### 命令格式
25
+
26
+ ```powershell
27
+ # 生成工程图
28
+ python "<包目录>\sw_bridge.py" drawing <零件路径> [输出路径]
29
+
30
+ # 生成 DWG(推荐用于 AutoCAD)
31
+ python "<包目录>\sw_bridge.py" dwg <零件路径> [输出路径]
32
+
33
+ # 导出 PDF(快速预览)
34
+ python "<包目录>\sw_bridge.py" export-pdf <输出路径>
35
+
36
+ # 展示当前窗口
37
+ python "<包目录>\sw_bridge.py" show
38
+ ```
39
+
40
+ ### 示例
41
+
42
+ ```powershell
43
+ # 从零件生成 DWG
44
+ python "C:\Users\...\tools\sw_bridge.py" dwg "C:\Users\...\DSH_法兰盘.sldprt" "C:\Users\...\DSH_法兰盘.dwg"
45
+
46
+ # 从零件生成工程图
47
+ python "C:\Users\...\tools\sw_bridge.py" drawing "C:\Users\...\DSH_法兰盘.sldprt"
48
+ ```
49
+
50
+ ## AI 调用流程
51
+
52
+ 当用户说"把这个零件转成 CAD 图纸"时:
53
+
54
+ ### 步骤 1:确认零件路径
55
+ ```powershell
56
+ python "sw_bridge.py" list
57
+ # 获取当前打开的零件列表
58
+ ```
59
+
60
+ ### 步骤 2:生成工程图
61
+ ```powershell
62
+ python "sw_bridge.py" drawing "<零件路径>"
63
+ ```
64
+ 输出:
65
+ - 自动创建三视图(前/俯/右)+ 等轴测
66
+ - 保存为 `.slddrw` 文件
67
+ - 返回截图路径
68
+
69
+ ### 步骤 3:导出 DWG(可选)
70
+ ```powershell
71
+ python "sw_bridge.py" dwg "<零件路径>" "<输出.dwg>"
72
+ ```
73
+ 输出:
74
+ - 自动转换为 DWG 格式
75
+ - 可直接用 AutoCAD 打开
76
+
77
+ ### 步骤 4:展示结果
78
+ ```powershell
79
+ python "sw_bridge.py" show
80
+ ```
81
+ 展示当前 SolidWorks 窗口截图给用户验收。
82
+
83
+ ## 技术原理
84
+
85
+ 1. **打开零件**:通过 COM 接口启动 SolidWorks 并打开零件
86
+ 2. **创建工程图**:使用 `NewDocument` 创建绘图文档
87
+ 3. **插入视图**:
88
+ - `CreateDrawViewFromModelView3` 插入标准视图
89
+ - 前视图居中,俯视图在下,右视图在右,等轴测在右上
90
+ 4. **保存**:`SaveAs3` 保存为 .slddrw
91
+ 5. **导出 DWG**:重新打开工程图,用 `SaveAs3` 导出为 DWG
92
+
93
+ ## 几何验证(CADX)
94
+
95
+ 生成 DWG/DXF 后,推荐使用 CADX 进行 7 项几何验证,确保图纸质量:
96
+
97
+ ```powershell
98
+ # 导出 DXF(SolidWorks 工程图 → DXF)
99
+ python "<工程模式根目录>\tools\sw_bridge.py" export-dxf "<输出.dxf>"
100
+
101
+ # 运行几何验证
102
+ python "<工程模式根目录>\tools\sw_bridge.py" cad-validate "<输出.dxf>"
103
+ ```
104
+
105
+ 验证项:未闭合多段线、重叠几何、尺寸过小、长宽比异常、墙厚不足、缺失元素、标注不一致。
106
+ 详见 `engineering/skills/sw-design/references/autocad-workflow.md`。
107
+
108
+ ## 已知限制
109
+
110
+ 1. **自动标注**:当前版本不自动添加尺寸标注,需要手动标注
111
+ 2. **图框**:使用默认 A3 图纸大小,不包含标题栏
112
+ 3. **复杂装配体**:仅支持单零件,装配体需要拆解后分别出图
113
+ 4. **模板**:自动探测绘图模板,如果找不到可能失败
114
+ 5. **AutoCAD 依赖**:CADX 验证需要已安装 AutoCAD(可选,非必需)
115
+
116
+ ## 后续改进方向
117
+
118
+ - 自动添加尺寸标注
119
+ - 自定义图纸大小(A4/A3/A2/A1/A0)
120
+ - 添加标题栏和材料明细表
121
+ - 支持直接导出 DXF 格式
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: webots-simulation
3
+ description: Use when an engineering task requests Webots simulation, robot drive or sensor experiments, simulation reports, collision evidence, or tracing a simulation issue to a SolidWorks assembly. Not for strength, fatigue, FEA or arbitrary 2D-to-3D reconstruction.
4
+ ---
5
+
6
+ # Webots simulation
7
+
8
+ This release supplies sol peripheral contracts, stored reports and bounded fixtures. Real execution, CAD conversion and safe return-to-SW cores A01–A04 are **not implemented**. Do not claim a completed engineering loop.
9
+
10
+ Read [integration-contract](../../docs/webots-mcp/integration-contract.md) for state/context and [report-viewer](../../docs/webots-mcp/report-viewer.md) for the live reader contract. Use [input-matrix](../../docs/webots-mcp/input-matrix.md) for supported input and [recipes-scenes](../../docs/webots-mcp/recipes-scenes.md) when preparing a bounded experiment.
11
+
12
+ 1. Discover the actual MCP server/tools; configured serverName is `webots` (`mcp__webots__sim_status`, `sim_report`, `sim_evidence`, `sim_job`). A missing tool is unavailable, never a prompt to emulate successful execution. Supply the **live authenticated** task/room binding and a request ID, not copied fixture IDs. The UI reader obtains it from `/dsh-engineering-ui/webots-context?sessionId=<live agent id>`; 403 `CONTEXT_UNAVAILABLE` means no authorized read. Never create a room or rewrite workflow state to bypass it.
13
+ 2. Read status and current owned reports first. The connection green light only proves installation/process availability. Keep `provenance`, `core_ready`, `execution_state`, `snapshot_at`, `stale`, `unsupported`, source revision and missing information visible. `fake`, `fixture`, `synthetic`, static validation, screenshots and empty contacts do not prove physical PASS or READY. `supported` describes support, not an experiment verdict.
14
+ 3. Use `sim_report` with `run_id` and one of `model_manifest`, `conversion_report`, `experiment_report`. Use `sim_evidence` for bounded worker-log pages: forward `next_offset` and the prior `sha256` as `expected_sha256`. A changed snapshot requires a fresh offset 0; do not concatenate different snapshots. Keep all candidate components and observed/derived/suspected evidence levels; a suspected or merged-body candidate is not a root cause.
15
+ 4. Prepare, rather than dispatch, currently unsupported experiments. Capture source/configuration/hash, model/world versions, units/frame sources, collision coverage, initial state, drive, sensor observations, seed/step and resource/stop budgets. Generated terrain worlds have no robot or calibrated physics. Missing mass, inertia, mapping or thresholds remain unknown, not invented defaults. Coordinate/inertia A01, joint/identity A02, attribution/SW changes A03 and physical/worker recovery A04 require their real implementation and verification.
16
+ 5. On `OUTCOME_UNKNOWN`, disconnect or action timeout, preserve operation/job/run/generation and the last confirmed progress; read status/job and evidence. Do **not** resend the action, even after reconnect. Cancellation acknowledgement does not prove rollback or process exit. Cleanup only verified session-owned processes; never terminate all Webots processes.
17
+
18
+ SW changes require current source revision and unique persistent instance identity, evidence-based attribution, authorized parameter scope, snapshot/rollback and same-condition retest. This version cannot satisfy that chain: report the missing core and stop automatic modification. A user request to investigate is not permission to select an arbitrary candidate or change gravity, mass, friction, collision switches or pass thresholds to manufacture improvement.
19
+
20
+ ## 与工程模式主流程的接口(D1 接通说明)
21
+ 上面那段是原交付自带的「S07 阶段」说明,保留作证据口径。下面是**本仓库实际接入**后的走法,
22
+ 两者冲突时以本节为准(本节描述的是已经落地的代码)。
23
+
24
+ ### 接口面
25
+ | 方向 | 接口 | 位置 |
26
+ |---|---|---|
27
+ | 模型进仿真 | `webots_mcp.pipeline publish-part` / `convert-part` | `engineering/tools/webots_mcp/` |
28
+ | 归属授权 | `resolveWebotsContext()` + `ctx.tools.guard` | `engineering/plugins/dsh-engineering-ui/lib/webots.js` |
29
+ | 只读证据 | `/dsh-engineering-ui/webots-context|-report|-evidence|-attribute` | 同上,复用 `guardRoute` |
30
+ | 设置页状态 | 连接区「Webots连接」(只显示安装/进程可用) | `lib/client.js` |
31
+ | 报告面板 | 组件 `EngWebotsPanel`(**已从设置页移除入口**,组件保留可复用) | `lib/client.js` |
32
+ | 人设约束 | persona 的「## 仿真(Webots,可选)」段 | `preset-engineering.patch.yml` |
33
+ | 模式入口 | mode-selection 的「🟦 Webots 仿真分支」 | `engineering/skills/mode-selection/SKILL.md` |
34
+
35
+ ### 三个必须记住的耦合点
36
+ 1. **身份不是猜的**:`task_id` 来自 `workflow_state.json`,`room_id` 来自
37
+ `mode_state.json` 里 `active=true` 且 `subagents[房间].id == 当前 agent.id` 的**唯一**房间。
38
+ 所以 —— 仿真必须发生在 `select` 之后、`room-end` 之前;房间已经收尾就没有合法身份了。
39
+ 2. **不抢 SW 锁**:仿真链路不调 `sw_bridge`,因此不会进 `mode_gate` 的 FIFO 队列。
40
+ 但**生成输入的那一步**(SW 导出)照旧要走原来的 SW 锁,不能借仿真名义绕开。
41
+ 3. **失败要说失败**:`RUNTIME_NOT_READY` / `CALIBRATION_REQUIRED` / `CONTEXT_UNAVAILABLE`
42
+ 都是**正常返回值**,不是异常。把它们改写成"成功"是本项目最严重的一类 bug。
43
+
44
+ ### 当前能力边界(2026-11-05 实测)
45
+ | 能做 | 不能做 |
46
+ |---|---|
47
+ | 离线把合成/真实零件捕获转成 URDF + PROTO(`urdf2webots 2025.0.0` 已跑通) | 原生 SW→URDF 的坐标系/惯量标定(A01) |
48
+ | 读已存报告与日志证据(字节分页 + SHA-256) | 自动关节推断(A02,`blocked_native`) |
49
+ | 归属校验、代际、操作幂等 | 自动根因回写 SW(A03/A04) |
50
+ | `sim_status` 等只读查询 | 真实物理 PASS 判定(本版恒 `physical_validation=not_run`) |
51
+
52
+ ### 快速自检(不碰 DSH、不碰 SW、不碰 Webots)
53
+ ```powershell
54
+ & $python -B -m unittest discover -s engineering/tests/webots_mcp -p 'test_*.py' # 101 项
55
+ node --test --test-force-exit engineering/plugins/dsh-engineering-ui/test/webots-*.test.mjs
56
+ ```
57
+
58
+ For isolated tests, first create and verify an existing absolute `DSH_STATE_DIR`; explicitly isolate `DSH_HOME`, profile and engineering root. Do not migrate live state or sync/deploy/restart the real installation. Preserve raw evidence and its hash, and distinguish local fixtures, the bounded historical Webots probe, real CAD evidence and unexecuted work in the result.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Auto SolidWorks contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,93 @@
1
+ # -*- coding: utf-8 -*-
2
+ r"""_plugin_paths.py —— 定位 dsh-engineering-ui 插件源码(工作区 / 安装副本都适用)
3
+
4
+ ═══════════════════════════════════════════════════════════════════════════
5
+ 【为什么需要这个模块】
6
+
7
+ 回归测试里多个文件都硬编码了
8
+ os.path.join(HERE, "..", "plugins", "dsh-engineering-ui", "lib", "xxx.js")
9
+
10
+ 这个路径只在【工作区副本】成立:
11
+ <repo>/engineering/tools/ → ../plugins/dsh-engineering-ui/lib/*.js ✅
12
+
13
+ 而在【安装副本】上根本不存在:
14
+ %USERPROFILE%\.dsh\.agent-presetsengineering ools\
15
+ ../plugins/... ❌ 没有这个目录
16
+
17
+ 因为安装时插件被放到了 profile 的 node_modules:
18
+ %USERPROFILE%\.dsh\profiles\<profile>\node_modules\dsh-engineering-ui\
19
+
20
+ 后果:测试在安装副本上一跑就 FileNotFoundError,
21
+ 表现为"回归失败",实际是测试自己的路径假设错了 ——
22
+ 这会掩盖真正的回归问题(谁也不想在 30 个 ❌ 里找那 1 个真的)。
23
+ ═══════════════════════════════════════════════════════════════════════════
24
+ """
25
+ import os
26
+
27
+
28
+ def _candidates():
29
+ """插件 lib 目录的候选位置(按优先级)。"""
30
+ here = os.path.dirname(os.path.abspath(__file__))
31
+ eng_root = os.path.dirname(here) # .../engineering
32
+ out = [
33
+ # ① 工作区布局:<repo>/engineering/plugins/dsh-engineering-ui/lib
34
+ os.path.join(eng_root, "plugins", "dsh-engineering-ui", "lib"),
35
+ # ② 上层工作区(有些布局把 plugins 放在仓库根)
36
+ os.path.join(os.path.dirname(eng_root), "plugins",
37
+ "dsh-engineering-ui", "lib"),
38
+ ]
39
+ # ③ 安装副本:<DSH_HOME>/profiles/<profile>/node_modules/dsh-engineering-ui/lib
40
+ dsh_home = ""
41
+ for k in ("DSH_HOME",):
42
+ v = (os.environ.get(k) or "").strip()
43
+ if v:
44
+ dsh_home = v
45
+ break
46
+ if not dsh_home:
47
+ home = (os.environ.get("USERPROFILE") or os.environ.get("HOME") or "").strip()
48
+ if home and not home.startswith("~"):
49
+ dsh_home = os.path.join(home, ".dsh")
50
+ if dsh_home:
51
+ prof_dir = os.path.join(dsh_home, "profiles")
52
+ try:
53
+ for p in sorted(os.listdir(prof_dir)):
54
+ out.append(os.path.join(prof_dir, p, "node_modules",
55
+ "dsh-engineering-ui", "lib"))
56
+ except Exception:
57
+ pass
58
+ out.append(os.path.join(dsh_home, "node_modules",
59
+ "dsh-engineering-ui", "lib"))
60
+ return out
61
+
62
+
63
+ def plugin_lib_dir():
64
+ """返回存在的插件 lib 目录;都找不到返回 None。"""
65
+ for d in _candidates():
66
+ try:
67
+ if os.path.isdir(d):
68
+ return d
69
+ except Exception:
70
+ continue
71
+ return None
72
+
73
+
74
+ def plugin_file(name):
75
+ """返回插件某个文件(如 'client.js' / 'index.js')的绝对路径;找不到返回 None。"""
76
+ d = plugin_lib_dir()
77
+ if not d:
78
+ return None
79
+ p = os.path.join(d, name)
80
+ return p if os.path.isfile(p) else None
81
+
82
+
83
+ def read_plugin_file(name):
84
+ """读取插件文件内容;找不到返回 None(调用方应据此 skip 而非 fail)。"""
85
+ p = plugin_file(name)
86
+ if not p:
87
+ return None
88
+ try:
89
+ import io
90
+ with io.open(p, encoding="utf-8") as f:
91
+ return f.read()
92
+ except Exception:
93
+ return None