fyjgtddco/DSH-SW-and-CAD

DSH-SW-and-CAD

机械技术工程师福音!!!专为SW和CAD设计的插件!现在,内置DeepSeek Harness“工程模式”,让DeepSeek Harness以“完成工图”作为第一目标,避免分心,此插件还可以以SW一键转化为CAD图纸,无需任何操作。现在,你只需要说一句命令,就可以去睡觉了,让此插件帮你完成任务吧!

待分类caddeepseek-harnessdeepseek-harness-plugin

🔧 DSH 工程模式 · Engineering Mode

四工位自动化精密加工转台 — 交付完成

面向 CAD / SolidWorks 机械设计的 DeepSeek Harness Agent 预设。 以「完成工图」为唯一目标:需求访谈 → 三维建模 → 有限元校核 → 出图交付, 每一道关键闸门都写在 Python 代码里 —— 不通过,流程走不下去。

📦 长流程产物和日志:https://share.feijipan.com/s/tryFb4AU

一句话:它不是一个"帮你写建模脚本的助手"。 它是一个会自己判断能不能交付的机械设计工程师。

项目值
目标平台DeepSeek Harness 0.2.x(Electron 桌面版 / dsh web)
预设 IDengineering · 显示名「工程模式」· order: 4
UI 插件dsh-engineering-ui v1.2.0
技能7 个
门禁 / 桥接脚本12 个核心脚本 + 14 个物理模块
回归测试30 个 Python + 12 个插件测试
许可MIT

🎬 30 秒看完它怎么干活

工程模式实录:从一句需求到 SolidWorks 建模

真实会话录像,2 倍速播放(原片约 60 秒)。一句「帮我制造一个机械工厂用的机械臂」进去, 出来的是:需求访谈 → 门禁判定 → 拆成多个建模小屋 → 并行驱动 SolidWorks → 汇合总装。 后面每一节,就是这段录像里的一环。


这是什么

DSH 的插件分三个平面,放错位置会互相连坐:

平面位置内容生效方式
宿主层(进程级)profiles/<profile>/cordis.patch.yml权限预设表、全局服务必须重启 DSH
preset 层(会话子作用域)插件 bundle 里的 preset-engineering.patch.yml人设、工具、技能热生效
profile bundleprofiles/<profile>/package.json 的 dependencies + dsh.profile.bundlesUI 插件(客户端半)必须重启 DSH

⛔ 绝对不要把 - id: permission 写进 preset。 @deepseek-ai/dsh-permission-presets 是宿主层进程级服务,preset 里再声明一次 = 重复注册同名服务, loader 直接拒绝,后果是新建会话 / 切预设 / 选模型三件事一起坏。

💡 DSH 0.2.x 不再读取 .agent-presets 目录。 仓库里的 engineering/agent.cordis.yml 只是历史对照,运行时真正加载的是 插件 bundle 声明的那份 preset-engineering.patch.yml。

它能做什么

能力实现
真的驱动 SolidWorks 建模Python win32com,SW 2018 ~ 2025,单位 mm
自己算有限元纯 Python + numpy(2D CST / 3D CTE),可选 Gmsh / CalculiX / Code_Aster / SW Simulation
疲劳与寿命校核Basquin S-N + Marin 修正 + Miner 累积损伤,默认 30 年设计寿命
出工程图三视图 + 等轴测 → .SLDDRW / .DWG / .DXF / .PDF,GB/T 排版规范
图纸几何校验CADX 七项检查(图层 / 图幅 / 线型 / 重叠 / 尺寸链 …)
多零件协作拆分「房间」,子代理串行或并行建模,SW 进程级 FIFO 锁
判断能不能交付材料 / 物理 / 领域 三大防线 + 看图证据 + 台账一致性

三种任务类型(AI 自判,不打扰你)

模式场景执行方式
模式 1单个零件、几何简单单线程直接建模出图
模式 2多零件 / 机构 / 传动系统门禁流水线 + 多子代理「多屋」协作
模式 3用户发来图片 / 截图单线程识图、提尺寸、重建、出图

三种模式共用同一套 SW / CAD / 物理工具链,区别只在要不要走门禁、要不要开子代理。


🧭 并行策略与搭建方式

门禁第 1 步:并行策略 D/E 与搭建方式 A/B/C

门禁启动后的第一件事不是让 AI 直接开画,而是先问你两个互相独立的问题。 这两问写死在 tools/choice_contract.py 里,题面和选项由代码给出,AI 不能改写。

① 并行策略:多屋是排队还是并行

选项含义适合
D部分小屋并行,按波次分批启动零件多、彼此独立、想快
E单小屋串联,一次一个房间零件之间有强耦合、想稳

② 搭建方式:这件事你自己能做主吗

选项含义交互强度
A完全自主搭建,AI 自主决策关键尺寸与材料几乎不打扰你
B部分自主,关键节点询问中等
C步步确认,每个零件建模前都出参数表给你确认最严,全程把关

C 模式是代码级强制的:每件零件必须单独提问、单独得到答复, 由主对话执行 mode_gate.py confirm-part <房间> <零件> 才能写入授权令牌。 沿用上一件零件的确认会被拒绝,并记进 violations.json。

选定之后

python "<根>\tools\workflow_gate.py" select C,E

写法很宽松,以下全部等价:select C,E / select C E / select "C, E" / select c e / select --choice C --parallel E。

select 会把结论当场写进 workflow_state.json,并与 mode_state.json 自动对齐 —— 不会出现两个命令读到相反结论的情况。


☑️ 需求是怎么问出来的

工程模式的第一条纪律:不猜参数。 材料、公差、配合类型、载荷来源,不确定就必须问你 —— 但也不是一股脑把几十道题全砸过来。

先定「问多细」

门禁第 2 步只问一个问题:本次任务要不要严格把关参数?

你的回答题数区间说明
强需求(严格校核)10 ~ 50 题载荷、尺寸、公差、材料都要有设计依据
不强 / 精简5 ~ 10 题先出大致结构,细节按工程经验定

区间由 mode2_flow.validate_question_budget() 强制:超上限直接拒绝, 收尾时未达下限同样拒绝交付 —— 既不许敷衍,也不许审问到死。

再决定「什么时候问哪一题」

按需提问:分析到缺口时才提问,而不是开局把题全抛出来

旧做法是开局把候选题目全部抛出,用户答到手软。 现在改成按需提问:AI 先沿十阶段往下推,推到某个阶段发现缺信息,才问那一题,并写明理由。

🆕 十阶段不再由主对话自己跑:它由一个真实子代理「总计子代理」推进 (开工先 analyst-bind 绑定自己的 sessionId),主对话只负责编排与建小屋。 主对话若自己调 begin-stage 会被 ANALYST_ACTOR_REQUIRED 拒绝。

十阶段设计流水线(顺序即契约,跳阶段会被拒):

TaskUnderstanding      任务理解      结构化 TaskSpec:目标 / 环境 / 载荷 / 约束 / 未知量
FunctionalDecomposition 功能分解      FunctionTree:子功能 + 输入输出 + 依赖
PhysicsReasoning       物理推导      运动 / 力 / 转矩 / 能量 / 自由度 + 假定
PrincipleSynthesis     工作原理探索  多个候选原理 + 淘汰理由
MechanismSynthesis     机构综合      MechanismGraph:构件 + 连接 + 自由度
RecursivePartReasoning 递归零件推导  PartRequirementGraph:每个零件为何存在
PartSynthesis          零件设计与选型 标准件 / 自定义件 + 几何与接口定义
EngineeringValidation  工程验证      PASS / FAIL / UNKNOWN + 证据
DesignIteration        自主迭代      回退位置 + 版本 + 未解决问题
ExplainableDesignOutput 可解释输出    完整设计报告 + 可追溯性

提问必须挂在已经推进到的阶段上:

# 1) 先推进阶段(必须按序)
python "<根>\tools\workflow_gate.py" mode2 begin-stage TaskUnderstanding
# 2) 真的缺信息了,才问 —— 且必须写明理由
python "<根>\tools\workflow_gate.py" mode2 ask "使用场合是什么" --stage TaskUnderstanding --reason "决定材料与防护等级"

阶段没 begin-stage 就提问 → 拒绝;无理由提问 → 拒绝。 这就是「不许开局把题全抛出去」的机器判据。

回答完还要落盘(answer-question)—— 题目一旦有答复,挂在它上面的阶段产物会立刻标 stale, 必须用新的产物重做那一段才能继续,防止下游拿着过期参数去建模。


📏 载荷只有一个来源

曾经踩过一个很典型的坑:门禁按 1000 N 估算、physics 按 100 N 校核 —— 两套数值,报告当然对不上。

现在载荷只有一条通路:

门禁问答 ──落盘──> tools/load_cases/gate_load_case.json ──读取──> 有限元 / 疲劳
规则说明
优先读用户写的数值「100N」「10kg」「0.1kN」会被直接识别为额定载荷
冲击只是系数出现冲击 / 动态关键词,只放大动载系数,不改额定值
落盘即真相额定载荷 = magnitude_n,physics 严禁另写数值
估算必须复核返回 load_is_estimate=true 时,AI 必须先向你确认才能继续

👥 子代理:主对话只编排,分析交给「总计子代理」

子代理三栏工作区:建模小屋并行跑 SolidWorks,实时可见

装配体不是一个大脚本能画完的。工程模式把它拆成若干房间, 每个房间一个子代理,房间之间靠 SW 进程锁排队 —— 而不是靠人盯着。

三层角色

角色干什么边界
主对话(大屋)问答、编排、建小屋、收尾不自己跑十阶段;只能调根会话命令
总计子代理analyst-bind 后跑十阶段分析、按需提问、决定房间编制只有它能写阶段与编制
建模小屋 + 总理子代理各自建模;总理同波监工、收上报、校验相邻尺寸只做本房间

房间数量不再固定 3 个:由总计子代理按分析结论登记(1 ~ 24 个), 每个房间必须写清 parts(负责哪些零件)与 why(为什么需要它)。 set-subagent-plan --decided-by 总计子代理 是硬要求,别人署名直接判越权。

波次

波次房间干什么
第 1 波建模小屋 1..N + 总理子代理并行建模;总理与建模同波启动,长生命周期监工
第 2 波总装与验证只有第 1 波全部 room-end 后才允许开始
第 3 波工程图输出总装完成后出三视图 / 剖视 / 标注

SW 是单实例,所以有一个进程级 FIFO 锁

机制行为
排队谁先请求谁先用,队列保留;返回 sw_busy 就等 90 秒重试同一条命令
公平轮转有人排队时,单房间最多连续 3 条命令或独占 180 秒,超出强制让位(防饿死)
心跳子代理每 60 秒续一次,但已降级为辅助证据
清场每波开始前 close-all,确认没有残留的 SLDWORKS.EXE

判活只认看板,不认心跳

python "<根>\tools\mode_gate.py" room-board --json

room-board 给每个房间一个一等状态,外加 safe_to_restart 与 next_action:

状态含义能不能重启
starting刚建,宽限期内否
running正常干活中 —— 不许说"没反应"否
waiting_sw在 SW 队列里正常等锁,不是死了否(严禁判死)
idle平台侧活着,当前没有可观察动作否
unbound平台侧活着但忘了 subagent-assign否,补绑定即可,禁止 reset
done / failed已收工 / 已失败按需 recover
dead真的没了是 —— 唯一允许 recover/restart 的状态

旧实现的六态分类会把排队等锁的屋子误判成死,于是主对话重启一个其实活着的屋, 两个子代理抢同一份 SW 文件。现在 waiting_sw 是一等状态,看板直接给 safe_to_restart=false。

两条禁令 + 一个例外

  1. 小屋不许越权:建模小屋不能调 mode_gate / workflow_gate / list_agents / subagent_fork,只做本房间的建模与验证。 唯一例外是总计子代理 —— 它只能用 mode2_flow.py 的阶段 / 提问 / 编制命令, 以及 ask_user.py 提问桥。
  2. 根会话命令不外借:init / provide_context / select / confirm-assembly / recover / restart / reset 只许主对话调用,子代理调一律返回 ROOT_SESSION_REQUIRED。

这两条都在代码里按 sessionId 校验,不是提示词约定 —— 越权不是"不应该",是调不通。

小屋自己不会提问,所以有桥

DSH 不允许子代理直接向用户提问(userQuestions.ask() 会校验 agents.roots(), 子代理必抛 DELEGATED_CALLER)。ask_user.py 把问题登记到本小屋 → 卡片出现在右侧面板 → 原地阻塞轮询直到你作答 → 答案以 tool_result 回到提问方。全程不结束回合。


🛡️ 三大防线:本项目的核心

这是它和「普通 CAD 助手」最大的区别:质量校验不是建议,是硬门禁。

#防线凭据判不通过的依据
①材料每个 .sldprt 旁的 <零件>.SLDPRT.material.json缺凭据 / 密度 = 1000(水)/ 跨标准静默替代
②物理reports/<房间>.physics.jsonoverall == FAIL,或静力过了但寿命不够
③领域reports/<房间>.domain.json存在 CRITICAL 违规(按 GB/T 规则库判)

四个强制点(走到就得过)

sw_bridge.py run                 → ① 材料
mode_gate.py room-end <房间>      → ①②③(该房间)+ 看图证据
workflow_gate.py confirm-assembly → ①②③(全部建模房间)
workflow_gate.py select (收尾)  → ①②③(全任务)

凭据为什么伪造不了

凭据由宿主进程签名:HMAC-SHA256,密钥只存在宿主内存里,绝不落盘。 Python 侧不持有密钥,签名与验签都得请求宿主; 宿主不可用时不是"放行",而是 fail-closed —— 无法验签即视为未通过。

所以哪怕 AI 能读写工程模式目录里的所有文件,也写不出一份能验签的凭据。 宿主自己会读磁盘上的真实报告再签,调用方没法让它为"不存在的运行"背书。

签名有效期默认 24 小时(DSH_DEFENSE_SIG_TTL_MS 可覆盖)。 早先设成 10 分钟时,只要一个房间里零件保存跨度超过 10 分钟, room-end 就必然失败 —— 多零件装配等于永远过不了门。

还有一道「你得亲眼看过」

建模房间下线前,本房间产出过的每个零件都必须留下经核实的看图证据: 截图真实存在、非 0 字节、闭环判定 PASS。缺任何一件 → VISUAL_EVIDENCE_REQUIRED,拒绝下线。

唯一合法绕行(且必定留痕)

python mode_gate.py room-end "<房间>" --force   # 显式强制
$env:DSH_DEFENSE_BYPASS = 1                     # 环境变量

两条路都会写进 reports/defense_bypass.json —— 绝不静默放行。


🔬 物理在环(FEA + 疲劳)

建模不是终点。每个房间都要出一份物理校核报告,FAIL 或寿命不足就拒绝下线。

求解器的降级链

按本机装了什么自动降级,没有外部 FEA 软件也照样算:

级别后端依赖
L0解析解(梁理论)无
L1纯 Python FEA(numpy CST 三角形 / CTE 四面体)numpy
L2Gmsh + CalculiX可选安装
L3Gmsh + Code_Aster可选安装
L4Gmsh + Elmer可选安装
L5SolidWorks Simulation APISW Premium 许可

疲劳是必过项,不是加分项

  • 方法:Basquin S-N + Marin 修正(ka/kb/kc/kd/ke)+ Goodman / Soderberg / Gerber 平均应力修正 + Miner 线性累积损伤
  • 每次 solve_fea 之后自动追加,结论并入 gates 与 overall
  • 静力过了但寿命不够 → 直接 FAIL,不再误判为 PASS
  • 默认按 30 年设计寿命;铝合金按无真实疲劳极限处理(5 × 10⁸ 次条件极限)

一个闸口只归一层管

同一个闸口 ID 曾出现几何层与 FEA 层给出相反结论的情况。现在 physics/simulation_report.py 用 GATE_OWNER 给每个闸口声明唯一归属层,聚合时只采信归属层:

闸口归属
DESIGN_SPACE / CONNECTIVITY / WALL_THICKNESS几何层
SAFETY_FACTOR / MAX_DISPLACEMENT / FATIGUE / MESH_QUALITYFEA 层

📐 从模型到图纸

建模阶段只做三件事:草图完全定义 → 特征建模 → 圆角倒角孔。 然后是一条固定链路:run → drawing → dwg → show,出图后截图验收。

python "<根>\tools\sw_bridge.py" run <建模脚本.py>       # 画零件
python "<根>\tools\sw_bridge.py" drawing <零件>          # 出 .slddrw
python "<根>\tools\sw_bridge.py" dwg <零件>              # 导 DWG(AutoCAD 可编辑)
python "<根>\tools\sw_bridge.py" show                    # 截图看一眼

工程图含三视图(前 / 俯 / 右)+ 等轴测,导出 .SLDDRW / .DWG / .DXF / .PDF。

排版是硬规则,出界即不合格

画布归一 1.0 × 1.0,原点左下,各纸型同比例。

规则值
安全区(0.05, 0.05) ~ (0.95, 0.95),唯一合法区域
标题栏禁区(0.80, 0.90) ~ (1.00, 1.00)
主视 / 俯视(0.30, 0.72) / (0.30, 0.28)
右视 / 等轴测(0.75, 0.72) / (0.75, 0.28)
投影关系主俯同 x(长对正),主右同 y(高平齐)
视图间距任意两视图 ≥ 35 mm(约 0.04)

宁可升纸型,也不许越界。轴类零件画中心线(点划线),特征交界画分界线,禁边线重合。

两个不商量的小事

  1. 命名必须中文:DSH_ + 中文名,例如 DSH_关节轴.sldprt。
  2. 默认材料 Q235:new_part() 就赋材,杜绝「密度恒为 1000(水)」导致的整条校核失真。

🖥️ 界面:三栏工作区

UI 插件 dsh-engineering-ui 只在工程模式下生效,可在设置里关掉。

区域内容
主对话(约 3/4)DSH 原生会话区,检测到子代理时自动收窄
中间竖排频道每个子代理一个按钮,绿点 = 运行中,点击切换右侧屏幕
右侧工作区(约 1/4)所选子代理的实时输出、工具调用与参数、运行状态、可直接作答的提问卡片

没有子代理时三栏全部隐藏,回到全宽聊天。

设置页「工程模式」分区

  • 工程环境检查:换电脑后一键扫 Python / pywin32 / numpy / ezdxf / shapely / SolidWorks / AutoCAD / 交付目录 / 跨机残留设置,逐项给绿黄红和一行修复建议;
  • 生成修复提示词:用本机实测结果现场生成一段提示词,直接发给新对话让它自己查、自己装;
  • 连接区:SW / CAD 连接探测与启动,状态落 connection_state.json,AI 与设置页共读同一份;
  • 显示页开关:可把右侧子代理面板交回 DSH 官方。

📦 安装

环境要求

项要求
系统Windows(SolidWorks / AutoCAD 自动化依赖 win32com)
DSH0.2.x(Electron 桌面版或 dsh web)
Python3.8+ 64 位,需 pywin32;物理校核另需 numpy
可选ezdxf + shapely(DXF 几何校验)、Pillow(看图)、Gmsh / CalculiX(高阶 FEA)
软件SolidWorks 2018 ~ 2025;AutoCAD(仅出 DWG 时需要)

一键安装(DSH 0.2.x)

cd <本仓库>
.\install-0.2.0.ps1
# 只装指定 profile:
.\install-0.2.0.ps1 -Profile web,desktop

脚本会做四件事:

  1. 把 engineering/tools 复制到 ~/.dsh/.agent-presets/engineering/tools(门禁脚本);
  2. 把 engineering/skills 复制到 ~/.dsh/skills(技能);
  3. 把 UI 插件复制进每个 profile 的 node_modules,并登记进 package.json (dependencies + dsh.profile.bundles);
  4. 写入宿主层 cordis.patch.yml(权限三档),绝不覆盖已有 patch。

⚠️ 装完必须重启 DSH。宿主层与插件 host 半都是进程级配置,热更新无效。 只改客户端半(lib/client.js)时,刷新页面即可。

改了代码之后

仓库里的 engineering/ 是源码,DSH 真正加载的是安装副本。改完要同步:

.\sync-to-dsh.ps1 -DryRun     # 先看要动哪些文件
.\sync-to-dsh.ps1             # 实际同步(逐个备份 .bak-sync-<时间戳>)
python engineering\tools\verify_sync.py   # 逐文件 SHA-256 比对,确认真的同步了

运行时状态文件(mode_state.json / workflow_state.json / sw_state.json / connection_state.json / settings.json)是会话现场数据,同步时会被跳过 —— 不要手动覆盖,否则流程会误判。


⌨️ 命令速查

门禁的入口全是命令行脚本,不是 DSH 工具。 历史文档里出现过的 workflow-gate-init 这类"工具名"在本环境并不存在,照抄会失败。

$T = "<工程模式根目录>\tools"   # 含 mode_gate.py 与 workflow_gate.py 的那个目录
python "$T\_root.py"            # 不确定根目录?先跑这个自检

workflow_gate.py — 门禁大脑

子命令用途
init "<任务>"初始化任务,返回第 1 步(模式确认 + 并行策略 D/E + 搭建方式 A/B/C)
provide_context "<回答>"推进状态机,需调用 3 次(模式确认 → 需求强度 → 汇总估算)
select C,E锁定搭建方式与并行策略
confirm-assembly "<清单>"第 1 波完成后确认总装
check-part / verify-ownership零件归属校验 / 总装前去重核对
status / gate-summary / check状态 / 总览 / 是否允许建模
recover / restart <房间> / reset恢复卡住 / 重做房间 / 清空重来
mode2 <子命令>十阶段契约:begin-stage / ask / prime-report / prime-verify …
stage-status / pre-delivery阶段进度 / 交付前总闸

除 status / gate-summary 这类只读命令外,只许根会话调用; 子代理调 init / select / reset 会拿到 ROOT_SESSION_REQUIRED。

mode_gate.py — 房间状态机 + SW 锁

类别子命令
看板(权威)room-board [--room X] [--json] — 八态 + safe_to_restart + next_action
房间room-start / room-end / room-fail / room-status / room-report / room-report-read
SW 锁sw-request / sw-wait / sw-release / sw-status / sw-proc / lock-doctor / close-all
子代理subagent-assign(每次 fork 后必做) / subagent-free / subagent-status / whoami
心跳room-heartbeat(辅助证据) / room-heartbeat-check
授权confirm-part <房间> <零件>(C 模式) / room-artifact
看护sw-guard-start / sw-guard-stop / sw-guard-status(CPU / 内存 > 85% 立刻关 SW)
维护doctor / rooms-reset / stale-artifacts / residue-check / platform-refresh

mode2_flow.py — 十阶段 / 编制 / 总理

子命令用途
analyst-bind / analyst-status总计子代理绑定自己的 sessionId / 查看是否已绑定
begin-stage / mark-stage-done按序推进阶段 / 登记产物(只认总计子代理身份)
ask / answer-question / refresh-stage按需提问 / 落盘答复 / 重做过期阶段
set-subagent-plan --rooms-json ... --decided-by 总计子代理登记本轮房间编制
prime-board / prime-report / check-consistency监工看板 / 收上报 / 相邻尺寸一致性
prime-verify / export-docx / pre-delivery统一核实 / 汇总 docx / 交付前总闸

其他脚本

脚本用途
defense_gate.py check-room <房间> / check-task三大防线自查
sw_bridge.py <命令>SW 桥接(run / drawing / dwg / physics-* / conn-* / cad-*)
physics_bridge.py <子命令>物理验证 CLI(validate-case / optimize / fatigue / validate-domain)
visual_check.py gate --part <零件> --expect <json>看图闭环校核
ask_user.py --room <房间> --child <id> ...子代理阻塞式提问
part_registry.py零件台账:相邻尺寸一致性 / SHA-256 防篡改 / 导出 docx
settings.py report / env_check.py probe本机设置 / 环境自检

🗂️ 目录结构

DSH-SW-and-CAD-main/
├── README.md                     # 本文件
├── assets/gifs/                  # 四段实录动图
├── install-0.2.0.ps1             # DSH 0.2.x 安装(装进所有 profile)
├── install.ps1 / install.sh      # DSH 0.1.x 安装(Win / macOS-Linux)
├── sync-to-dsh.ps1               # 源码 -> 安装副本同步
├── patch-incompatible.ps1        # 第三方插件 peer range 修补
├── RUNNING_WORKFLOW.md           # 源码级全链路追踪(从一条消息到一次 COM 调用)
├── engineering/                  # ★ 预设本体
│   ├── preset.yml                # 显示元数据
│   ├── agent.cordis.yml          # 历史清单(运行时不加载,仅对照)
│   ├── README.md                 # 架构与门禁细节(更技术向)
│   ├── skills/                   # 8 个技能
│   │   ├── mode-selection/       # 强制入口:模式选择 + 门禁流程
│   │   ├── assembly-orchestration/ # 多屋编排
│   │   ├── cad-workflow/         # AutoCAD 工作流
│   │   ├── sw-design/            # SW 设计 + GB/T 制图
│   │   ├── solidworks-bridge/    # SW 桥接
│   │   ├── sw-to-cad/            # SW -> CAD
│   │   ├── physics-in-loop/      # 物理在环
│   │   └── webots-simulation/    # Webots 仿真(可选,见 docs/webots-mcp)
│   ├── tools/                    # ★ Python 工具链
│   │   ├── workflow_gate.py      # 门禁大脑
│   │   ├── mode_gate.py          # 房间状态机 + SW 锁 + room-board
│   │   ├── mode2_flow.py         # 十阶段契约 / 编制 / 总理
│   │   ├── defense_gate.py       # 三大防线
│   │   ├── sw_bridge.py          # SW 桥接执行器
│   │   ├── swapi.py              # 高层建模 API
│   │   ├── part_registry.py      # 零件台账 + 一致性校验
│   │   ├── visual_check.py       # 看图闭环
│   │   ├── webots_env.py         # ★ Webots 仿真可用性自检(只读)
│   │   ├── webots_mcp/           # ★ Webots MCP server / 转换 / 证据(可选)
│   │   ├── physics/              # 物理子系统(FEA / 疲劳 / 规则库)
│   │   ├── physics/rules/        # GB/T 规则包
│   │   ├── load_cases/           # 载荷工况(gate_load_case.json)
│   │   ├── reports/              # 防线凭据 + 房间报告
│   │   └── test_regression_*.py  # 31 个回归测试
│   └── plugins/dsh-engineering-ui/  # UI 插件
│       ├── lib/index.js          # Host 半(HTTP 路由 / 提问桥接 / 防线签名)
│       ├── lib/client.js         # 浏览器半(三栏工作区)
│       ├── lib/defense-sign.js   # HMAC 凭据签名
│       ├── lib/job-wait-guard.js # ★ job_output 长等待守卫(防"卡死",见下)
│       ├── preset-engineering.patch.yml  # ★ 运行时真正加载的人设
│       ├── lib/webots.js         # ★ Webots 只读宿主门(归属校验 + 4 条路由)
│       └── test/                 # 15 个插件测试
├── profiles/                     # 宿主层 patch 模板
└── third-party-patched/          # 打过补丁的第三方插件

动手改之前先读 engineering/README.md:那里记着每个历史 bug 的现场现象 / 根因 / 修复判据, 很多看起来"多余"的代码,是为了防止某个已经踩过两次的坑复发。


🤖 Webots 仿真(可选,默认关闭)

接入的是官方交付补丁 f04ac75a(86 文件:engineering/tools/webots_mcp/ 的 MCP server、 转换器、证据读取器 + 12 份契约文档 + 测试)。它是外围承载,不是物理核心 —— 原生 SW 导出、关节推断、自动回写与真实物理判定仍未实现,状态里会明写 core_ready=false / CALIBRATION_REQUIRED。

它挂在主流程的哪个位置

不是第四种模式。仿真发生在模型已经存在之后:

Mode 1/2/3 判定 → 门禁 → 建模 → 三大防线 → 出图
                                     ↘ (可选)Webots 仿真 → 报告/证据 → 只读回看

它消费 select 建立的 task/room 身份,所以必须在 select 之后、room-end 之前跑; 房间收尾后没有合法身份,只读接口会返回 CONTEXT_UNAVAILABLE。

三个入口

入口用法
自检(先跑这个)python "<根>\tools\webots_env.py" --json → 看 sim_available / blocking
桥接命令sw_bridge.py sim-status / sim-env / sim-list / sim-report(不连 SW、不取 SW 锁)
MCP 工具mcp__webots__sim_status / sim_launch / sim_job / sim_report / sim_evidence …(需 DSH_WEBOTS_ENABLE=1)

宿主侧新开了 4 条只读 GET 路由(webots-context / -report / -evidence / -attribute), 走的是和 conn-state 同一套 guardRoute(loopback + Origin 校验 + 限流)。

⚠️ 设置页「连接区」里那块「▶ Webots 仿真报告与证据(只读)」已按用户要求移除(2026-11-05)。 组件(EngWebotsPanel / EngWebotsSnapshot / EngWebotsReport)仍保留并导出, 供子代理工作区或后续版本复用;要接回设置页只需恢复一行 h(EngWebotsPanel, {})。

启用(缺一即视为未启用,不是"坏了")

$env:DSH_WEBOTS_ENABLE     = '1'
$env:DSH_WEBOTS_PYTHON     = '<绝对路径>\python.exe'    # 已装 webots_mcp/requirements.txt
$env:DSH_WEBOTS_INPUT_ROOT = '<已存在的只读输入根>'
$env:DSH_STATE_DIR         = '<已存在的绝对 state 目录>'
$env:DSH_ENGINEERING_ROOT  = '<工程模式根>\engineering'
$env:WEBOTS_HOME           = 'D:\Webots'
# 可选:$env:DSH_WEBOTS_RUNTIME_CONFIG = '<绝对路径>\runtime.json'

依赖安装(一次性):

python -m venv $env:USERPROFILE\.dsh\engineering-webots\venv
& $env:USERPROFILE\.dsh\engineering-webots\venv\Scripts\python.exe -m pip install -r engineering\tools\webots_mcp\requirements.txt

边界(必须保留在报告里)

能做不能做
离线把零件捕获转成 URDF + PROTO(urdf2webots 2025.0.0)原生 SW→URDF 的坐标/惯量标定(A01)
读已存报告与日志证据(字节分页 + SHA-256)自动关节推断(A02)
归属校验 / 代际 / 操作幂等自动根因回写 SW(A03/A04)
sim_status 等只读查询真实物理 PASS 判定(恒 physical_validation=not_run)

fake / fixture / synthetic / 静态校验 / 空接触 都不等于物理 PASS; OUTCOME_UNKNOWN 禁止重发动作。详见 engineering/docs/webots-mcp/。

🩹 防"卡死":job_output 长等待守卫

2026-10-31 事故:job_output { wait: true, timeout_ms: 270000 } 静默阻塞数分钟, GUI 毫无反馈 → 用户以为 DSH 死机 → 强制退出 → 退出瞬间所有插件 fiber 失活 → cannot get required service "jobs" in inactive context → turn/end{interrupted},整轮对话作废。 完整复盘见 docs/DSH卡死事故分析_job_output阻塞.md。

修复分两层,两层都装才完整:

层位置生效方式
宿主层plugins/dsh-engineering-ui/lib/job-wait-guard.js(经官方 ctx.on('tools/execute') 接线)装进 profile 后重启 DSH
仓库层preset-engineering.patch.yml 人设 + 各 SKILL + ask_user.py热生效(同步到安装副本即可)

宿主层做两件事:

  1. 把长等待切成 ≤45s 的窗口:到点就返回"仍在运行"(正常成功结果,不是失败)—— GUI 保持响应,用户随时能打断,模型也不会把整轮挂在等待上;
  2. 把上下文失活异常降级成 JOB_CONTEXT_LOST 工具错误(isError=true + 操作指引), 不再让框架异常冒到 turn 级把整轮打断。

安装 / 重装(DSH 每次升级都会覆盖安装目录,升级后重跑一次即可):

.\install-job-wait-guard.ps1 -DryRun     # 先看会动哪些文件
.\install-job-wait-guard.ps1            # 装进每个 profile(逐文件 .bak-guard-时间戳)
.\install-job-wait-guard.ps1 -Verify     # 只核对
环境变量默认作用
DSH_ENG_JOB_WAIT_GUARD开设 0 关闭守卫
DSH_ENG_JOB_WAIT_MAX_MS45000单次等待窗口上限(最小 5000)

回归:node --test engineering\plugins\dsh-engineering-ui\test\job-wait-guard.test.mjs(6/6)。

仓库层还改了提示词本身(BUG-A1-①)

旧人设里有一句「必须等后台 job 时:单次 sleep ≤30s,timeout_ms ≤30000,宁可多轮短等」—— 这句把"轮询"写成了等待的第一选择,实测被照抄成单轮 477 次 sleep(30)、轮询 4 小时 02 分 (占墙钟 66%),期间零产物。现已改写为:

  • 禁止用 time.sleep / Start-Sleep 轮询等子代理、等房间、等 SW 锁;
  • 只准用阻塞原语:mode_gate.py wait-rooms "<房间>" --timeout 900 / mode_gate.py room-board --wait 900 / mode_gate.py sw-wait <房间> --timeout 90;
  • 确实没有原语时(如等一个 sw_bridge run 的后台 job 收尾)才允许短 sleep, 且同一等待目标连续不得超过 3 次;
  • 等待期间允许结束回合,格式固定为 [WAITING] 在等:…;判据:room-board state=…;唤醒条件:… (该终止态由 Host 半实现,现阶段须自己写清摘要;房间已是 done/failed/dead 时必须先处置, 禁止用它掩盖"其实已经完事")。

工具输出乱码:先重跑,再下结论(BUG-A6)

人设里新增铁律:工具输出里出现 U+FFFD / � 时禁止据此下结论, 必须补上 $env:PYTHONIOENCODING='utf-8'; $env:PYTHONUTF8='1' 重跑, 或用 read 工具直接读磁盘原文核对(磁盘上的 .json/.md 不经控制台代码页)。 注入式根治在插件 lib/index.js 的宿主半,人设层只做流程约束。


⚠️ 已知限制

  1. 强依赖 Windows + 已装好的 SolidWorks。SW / CAD 自动化走 COM,macOS 与 Linux 上只能跑非建模部分。
  2. 没装 SolidWorks 的机器上,SW 相关行为无法验证(massprops、GetBodyBox 等)。
  3. CADX 的重叠检查依赖 ezdxf + shapely,两者缺失时该项自动跳过 —— 别把它当成"已通过"。
  4. 铝合金按无真实疲劳极限处理(用 5 × 10⁸ 次条件极限),校核偏保守。
  5. 规则库是元数据注册表 + 适用性提示:具体机读数值仍需从标准原文提取; BLOCKER / CRITICAL 类规则必须人工复核,不可由 AI 自动放行。
  6. 部分文件是 UTF-8 with BOM。Windows PowerShell 5.1 的 Get-Content 会按 ANSI 解码, 读中文 JSON 容易报「传入的对象无效」。用 python -c "..." 或 DSH 的 read 工具读。
  7. 四段动图合计约 13 MB,GitHub 首屏加载会慢一些;介意的话可以换成压缩版或外链。

📜 版本历史

提交 / 日期说明
2026-10-28总计子代理真实化(analyst-bind + 身份校验)+ 总理子代理同波启动与监工 + room-board 状态可信化(waiting_sw / unbound)+ 子代理禁令(ROOT_SESSION_REQUIRED)+ 插件自动平台登记
e12d665为移动端 DSH Go 做适配性调整
fe671a3mode2_flow 与防御门控完善,新增回归测试与物理运行记录
b2a11b1已适配 DSH 0.2.1-rc.2
578818e模式二流程改造:十阶段契约 + 总理核实 + 看图闭环 + SW 双路看护
eb55f4a适配 DSH 0.2.0 桌面版(bundle 路径、desktop profile、三栏 UI)
d2e6828工程工作流更新:技能、mode gate、插件、SW 桥接改进

English

DSH Engineering Mode is an Agent Preset for DeepSeek Harness, built for CAD / SolidWorks mechanical design. Its single goal is a finished engineering drawing.

What makes it different from a chat assistant that writes CAD scripts: