代码评审报告_V1.0_20260828.md 43 KB

PCB轴向磁通电机自动化仿真系统 — 全量代码评审报告

内容
报告版本 V1.0
评审日期 2026-08-28
评审范围 src/scripts/web/backend/web/frontend/src/、部署配置(Dockerfile / docker-compose.yml / nginx.conf / deploy.ps1 / .gitignore)、文档-代码一致性
排除范围 axial_mag_pull-master/torqrippswap-master/(第三方参考案例)、DRSS V16.html(参考文件)
评审方法 10 个并行分区静态评审 + 只读检查命令(ASCII 扫描、git ls-files / check-ignore、密钥模式搜索、端点逐一核对)。未启动 Motor-CAD、未运行动态仿真
评审重点 ① 核心闭环(边界条件→方案→仿真→结果→AI分析→经验库)正确性;② GUI 稳定性 / 美观度 / 交互逻辑(本地 PySide6 + Web 前端)

一、总体结论

项目骨架是健康的:双系统解耦架构清晰,本地端↔Web端 17 个 API 端点逐一核实全部真实存在且签名匹配;工程纪律(纯 ASCII、参数回读校验、每点基线重载、逐点落盘、生成物不入库)在 src/ 主链路上基本逐条落地;src/solver_core.pysrc/scan_engine.pyscripts/robust_motorcad.py 的工程素养中上。

但存在三类系统性问题,与"Phase 1/2/3 全部完成"的宣称有明确差距:

  1. 核心闭环"通而数据错":多处双份硬编码契约已发生漂移(指标 key 清单、状态枚举、保真度语义),不报错、只产错数据;task_executor.py 会在仿真失败时静默注入 mock 假数据并标记 status="ok" 上报——一旦触发,经验库和 AI 分析闭环被污染且无任何告警。
  2. AI 相关页面/模块明显未经验证:Web 前端 8 个 AI 页面中,7 个页面中文 UI 全是 \uXXXX 字面乱码、8 处 axios 响应未取 .data 导致功能全废——任何一次手工冒烟都会暴露,说明这批代码写完即提交、零联调;后端 AI 闭环的"六类收敛判据"实际只执行四类、转矩目标比较方向写反、L0 预筛选在最常见输入下"空跑即通过"。
  3. 稳定性短板集中在长时运行路径:后端 BatchScheduler 存在必现死锁(调用取消接口即冻结整个后端);本地 GUI 运行中关窗即崩、求解无超时无断线重连;自适应闭环状态全在内存、重启即丢。

建议:先按第八章 P0 清单修复(约 15 项,多数改动机械、收益巨大),再将 README/设计文档的状态描述校准到可验证的实现现状。


二、🔴 错误 / 必须修复(28 项)

A. 核心闭环数据完整性(最优先)

# 位置 问题 建议
A1 web/backend/app/routers/plans.py:200-205 vs src/solver_core.py:32-159 upload-results 指标清单双份硬编码已漂移:后端硬编码的 tmax_nm/tmin_nm/ripple_abs_nm/power_factor 在本地端 METRIC_KEYS 中不存在(死配置);本地端实际产出的 ripple_nm/back_emf_thd_pct/em_power_w/shaft_speed_rpm 不在后端清单中,上传时被误分类为 params——4 项指标静默丢失、参数表被污染,经验库和相似检索基于错位数据运行 消除双份硬编码:以 solver_core.METRIC_KEYS 为单一事实源生成后端常量,或上传时在 CSV/manifest 中声明列语义
A2 scripts/task_executor.py:282-289 仿真失败后静默回退 mock 假数据并标 status="ok"_run_simulation_point 捕获任何异常后调用父类 mock 实现,伪造的 tavg_nm/efficiency_pct 通过 report_results 上报 Web 端,与真实数据无法区分——电机没算,经验库却记了一条"成功"结果 失败必须标 status="failed" 并记录真实错误;mock 仅由显式开关启用并在结果中强制标注 source:"mock"
A3 scripts/task_executor.py:291-323 Motor-CAD 实例管理三大铁律全违反MotorCAD() 未传 open_new_instance=True、无 set_visible(True)、扫描点之间不重载基线(参数跨点污染)、无弹窗抑制 该类应直接复用 RobustMotorCADSolver,不要另写裸 pymotorcad 调用
A4 scripts/task_executor.py:304-311 回读校验被 except Exception: pass 完全架空:set→get→比对不一致抛出的 RuntimeError 被静默吞掉,执行流继续求解。比不写校验更危险——给人"已做校验"的假象,实际零防护 去掉外层 try/except,让 mismatch 异常上传播并标记该点 failed
A5 scripts/task_executor.py:299 附带 _run_motorcadget_variable("Torque_Avg"/"Efficiency"/"Total_Losses") 取结果——这三个变量名在全仓库(知识库、solver_core、探测记录)无任何出处,几乎必然抛异常(然后触发 A2 的 mock 回退) 结果提取复用 solver_core 的导出文件解析路径
A6 web/backend/app/routers/adaptive.py + 全仓库 自适应闭环缺本地执行桥:README 宣称"AI驱动自适应仿真闭环就绪",但「拿批次点→驱动 Motor-CAD→回传结果」在仓库中没有任何执行者(api_client / GUI / task_executor 均不感知 /api/adaptive),闭环只能人工逐步调 API;且 loop 状态存于内存 dict(adaptive_loop.py:368),后端重启即全部丢失 本地端增加 adaptive 模式执行器(轮询 next-batch → ScanEngine 执行 → report-results);loop 状态持久化到 SQLite
A7 src/gui/main.py:296, 565-600, 655-660, 723-729 GUI 的 self._plan 从不更新_start_scanplan = self._build_plan() 是局部变量,从未回写。_on_finished 写经验库时 plan_id/topology/model_path 永远是启动默认值——用户改了模型改了方案,经验库记录全部挂在默认方案名下,静默污染"经验库积累"核心闭环 _start_scan 校验通过后 self._plan = plan;或改用 worker 携带的 plan
A8 src/api_client.py:153-155(根源 _request() :52-53) delete_experience() 删除成功时必然抛异常:后端 DELETE 返回 204 空响应体,_request() 对所有成功响应无条件 json.loads(resp.read()),空 body 抛 JSONDecodeError 且不被现有 except 捕获——每次成功删除都以异常告终 _request() 先读 body,为空返回 None:raw = resp.read(); return json.loads(raw) if raw else None

B. 稳定性 / 崩溃

# 位置 问题 建议
B1 web/backend/app/services/batch_scheduler.py:69-71, 106-115, 158-159 BatchScheduler 必现死锁get_next_task()/cancel_task()with self._lock 内调 _notify_callbacks(),后者第一行调 get_statistics() 再次 with self._lock——threading.Lock() 非可重入,永久死锁,即使没有任何回调注册也触发。该路径经 POST /api/monitor/cancel/{task_id} 暴露,死锁发生在事件循环线程上,整个后端冻结 _notify_callbacks() 移到锁外(参考 complete_task 的正确写法),或改用 threading.RLock()
B2 src/gui/main.py(无 closeEvent)+ :790 扫描运行中关闭窗口 → QThread 被强制销毁崩溃 + 无退出路径:关窗时 worker 仍在运行则 QThread: Destroyed while thread is still running 直接 terminate 崩溃、Motor-CAD 进程被遗弃;setQuitOnLastWindowClosed(False) 且无托盘/退出菜单——关窗后进程变无界面僵尸,只能任务管理器强杀 重写 closeEvent:worker 运行中弹确认框,worker.cancel() + worker.wait(超时) 后再关;移除 setQuitOnLastWindowClosed(False) 或补托盘退出入口
B3 src/gui/main.py:156-160, 464, 508-520 变量表格输入非数字即触发全局崩溃弹窗get_variables() 对单元格直接 float(text) 无 try/except,而 itemChanged 在每次按键编辑完成时触发 _update_estimate()——用户输入 "1.""abc" 等中间态时 ValueError 一路抛到全局 excepthook,正常打字就反复收到"程序错误"弹窗 get_variables() 逐行 try/except 并带行号报错;_update_estimate 解析失败显示 "Points: (invalid input)";_start_scan 先捕获解析异常用 QMessageBox 指出具体单元格
B4 src/gui/main.py:85-107 GUI 路径 Motor-CAD 进程泄漏ScanWorker.run()solver.disconnect() 只在成功路径执行;ScanEngine 的 FATAL 异常 re-raise 后 disconnect 被跳过,Motor-CAD 进程(含 license 占用)可能长期残留。对比 run_scan.py:191-193run_single.py:145-147 都正确使用了 finally,GUI 主链路反而没有 connect 之后的逻辑包入 try/finally,finally 中调 disconnect()
B5 scripts/robust_motorcad.py:608-612 run_single_point 提前 return 导致失败点不落盘、不进结果集:采样点/网格组合不兼容时函数在 try 块内直接 return result,跳过第 680-681 行的 _all_results.append_write_result_to_disk——该失败点彻底消失,违反"失败点记录错误并继续、结果逐点落盘"纪律 提前 return 改为设置状态后走正常收尾路径,保证 append/落盘必达
B6 scripts/robust_motorcad.py:336-345 point_timeout 参数是死代码:构造函数接收 point_timeout=300 但全文无使用;do_magnetic_calculation() 同步阻塞,Motor-CAD 卡死则脚本永久阻塞,重试机制不会触发。docstring 宣称"Per-point timeout + retry",属于宣称的安全特性缺失 用子线程+join(timeout) 或 Job Object 实现真实超时;或删除参数并修正文档
B7 scripts/task_executor.py:66-79, 242-262 本地文件兜底模式下任务被无限重复执行requests 未安装时走 _scan_local_task_filesexecute_task 完成后不删除/重命名文件也不回写状态——下一个轮询周期(5 秒后)同一批任务再次执行,无限循环 执行后重命名为 *_task.done.json 或回写 status:"completed" 并扫描时过滤

C. AI 闭环逻辑错误(宣称功能失真)

# 位置 问题 建议
C1 web/backend/app/services/result_analyst.py:355-360 转矩目标比较方向写反:"越高越好"用子串匹配 "torque" in metric,但实际指标键是 tavg_nm(不含 "torque")→ 转矩被当作"越低越好",取 min 作为 best 且 min <= target 几乎恒真——转矩目标比较永远 pass 且展示最差值,闭环验收判据失真 建立显式 metric→direction 映射表(可复用 analytics.py 的 METRIC_DEFS),不要用子串猜测
C2 web/backend/app/services/result_analyst.py:369-395 "六类收敛判据"只有四类真正执行check_optimum_stabilitycheck_surrogate_error 全仓库无调用方。后果:① 4 项通过即报 "converged"(2 项从未评估);② 置信评分按 total=6 折算,收敛贡献上限被压到 4/6,A 级在数学上更难达到,置信等级被系统性低估。API 文档宣称 "Six convergence criteria checks" 与实现不符 真正接入另两个判据,或把 total 改为 4 并修正文档
C3 web/backend/app/services/l0_prescreening.py:368-376 L0 预筛选"空跑即通过"feasible = failed == 0,而所有检查项都以 if params.get("xxx") is not None 触发——典型输入(speed_rpm/current_a/target_torque_nm)下 0 项检查运行、total_checks=0、却返回 feasible=True。L0 作为闭环第一道闸门在最常见场景下形同虚设 增加最低覆盖判定(如 total_checks >= 3)或覆盖率字段,覆盖率为 0 时标记"未知"并转 warning
C4 web/backend/app/services/feasibility_search.py:303 信任域锚点无视优化方向:激活信任域时恒取 max(...)objective_direction="minimize"(损耗/成本类目标)时信任域锚定在最差可行点上,70% 候选围绕最差点采样 按 objective_direction 选 max/min
C5 web/backend/app/services/feasibility_search.py:398-426 信任域中心不随新最优点迁移report_result 更新 best_feasible_point 但从不更新 trust_region_center,中心永久锚定在激活时的旧最优点 is_better 为真且信任域已激活时同步迁移中心(经典信任域标准做法)

D. Web 前端致命缺陷(详见第六章专题)

# 位置 问题 建议
D1 TaskManager.vue:6PlanGenerator.vue:6,14,18L0Prescreen.vueAdaptiveOptimize.vueResultAnalysis.vueFidelityCalibration.vueExperienceEnhance.vueConfidenceBadge.vue:3(共 8 文件) Vue 模板中大量使用 \uXXXX 转义,浏览器原样显示为字面乱码——这是把".py 必须纯 ASCII"的纪律错误套用到 .vue 模板上(模板文本节点不做 JS 字符串转义)。7 个 AI 页面的全部中文 UI 文本都是乱码。注意:{{ }} 插值和绑定表达式里的转义是 JS 求值,那些是对的,可保留 ASCII 纪律仅针对 .py/.ps1.vue 直接写 UTF-8 中文,把模板静态文本中的 \uXXXX 全部还原
D2 api/index.ts:3-7 + 8 处调用点 axios 响应未取 .data,半数页面拿不到数据:无响应拦截器,以下页面直接把响应包装对象当业务数据用——TaskManager(任务列表永远为空)、MonitorDashboard(统计卡片恒为 0)、L0Prescreen(恒显示"不可行"+渲染抛 TypeError)、PlanGenerator、ResultAnalysis、FidelityCalibration、AdaptiveOptimize(创建后状态卡不显示)、ExperienceEnhance(后续 URL 变成 /loops/undefined/... 必失败)。这些页面功能上完全不可用 根治:api/index.ts 加响应拦截器 r => r.data 并全库统一写法;或逐处补 .data。二选一,必须统一
D3 AdvancedVisualization.vue:209-213 ECharts 动态导入写错mod.default 在 ECharts 5(纯 ESM)中为 undefined,echarts 恒 undefined,四个图表永远不渲染且无任何用户可见报错 改为 echarts = mod 或像 Dashboard.vue 一样静态 import * as echarts;导入失败应 ElMessage 提示
D4 AdvancedVisualization.vue:308-333, 243-272 「参数敏感性热力图」和「收敛轨迹」是伪造数据:热力图 X/Y 轴硬编码 P1..P6/Q1..Q5,数据按取模随意填格,与真实扫描参数毫无关系,标题却写"参数敏感性热力图";收敛轨迹把任意数据机械分组模拟出并不存在的"优化收敛过程"——在仿真优化工具里属于产生错误结论的图表 热力图改为真实参数轴+指标分桶聚合(Dashboard 的敏感性图是正确做法可复用);收敛轨迹接真实 adaptive 批次数据或显著标注"示意图"

E. 部署 / 安全

# 位置 问题 建议
E1 Dockerfile:16 + 根目录无 .dockerignore 含真实密钥的 .env 会被烤入 Docker 镜像层COPY web/backend/ .web/backend/.env(内含真实 KIMI_API_KEY)复制进镜像,密钥永久存在于镜像层。同时整个仓库(.git、node_modules、5 份 .mot)都进构建上下文 新增 .dockerignore(至少含 .env.gitnode_modulesoutput/*.mot*.db);已构建过的镜像应视为已泄露,建议轮换 API Key
E2 docker-compose.yml:19 + web/backend/app/config.py:17 KIMI_API_KEY 空值屏蔽挂载 .env 中的真实密钥:宿主机未设该变量时 compose 注入空字符串环境变量;config.py 的加载逻辑 if key and key not in os.environ 把空字符串也算"已存在"——挂载的 .env 真实密钥永远不会被加载,Docker 部署下 AI 功能静默失效 删除 compose 中该行完全依赖挂载 .env,或改为 ${KIMI_API_KEY:?must be set};同时 config.py 跳过空值环境变量
E3 Dockerfile:22 + docker-compose.yml:17 容器内 SQLite 无持久化卷:数据库落在容器内 /app/afm_sim.db,compose 只挂载了 output/ 和 models/——docker-compose down 或重建后经验案例、任务记录、AI 调用日志全部丢失,这恰恰是项目核心资产 增加卷映射(如 ./web/backend/data:/app/data)并将 DB 路径指向挂载点
E4 web/backend/app/main.py:9-37 + deploy.ps1:117 + Dockerfile:34 API 完全无认证,且部署脚本引导绑定 0.0.0.0:13 个路由(任务下发、AI 调用、删除、报告下载)无鉴权;/api/ai/chat 是开放的 Kimi 付费 API 代理且 ChatRequest 对 max_tokens 无上限。默认 127.0.0.1 安全,但 deploy.ps1 和 Dockerfile 均为 --host 0.0.0.0——局域网任何机器可调用付费接口、取消任务、删除数据 至少加共享 Token 中间件(X-API-Key);ChatRequest 加 max_tokens 上界;文档明确绑定边界

F. 功能缺陷 / 纪律冲突

# 位置 问题 建议
F1 src/scan_engine.py:170-183 断点续扫(checkpoint resume)是死代码run() 每次用毫秒时间戳生成全新 run_dir 和 CSV 文件名,随后 _load_completed_indices(csv_path) 读的是刚生成名字、必然不存在的文件——completed 永远为空,"跳过已完成点"逻辑永远不会触发。8 小时扫描第 7 小时崩溃时将全部重来 增加 resume_from: Path 参数,恢复时定位已有 scan_results_*.csv 读取完成索引并追加写入
F2 web/backend/app/models/simulation_plan.py:27 + routers/projects.py:88-96 + database.py:8-12 删除项目不产生级联,留下孤儿数据:docstring 承诺"Delete a project and all its plans/results",但 backref 无 delete-orphan 级联,且 SQLite 未开 PRAGMA foreign_keys=ON——删除项目后其 plans/results 全部残留,仍可访问、下载、上传结果 relationship 显式配置 cascade="all, delete-orphan";engine 加 event listener 开启外键
F3 web/backend/app/services/plan_generator.py:36,60,62,269,271result_analyst.py:274,444experience_enhancer.py:41,65 3 个 web 端 .py 文件内嵌中文字符串,违反纯 ASCII 铁律(AGENTS.md 硬性约束第 1 条"违者返工")。src/ 和 scripts/ 全部合规,唯独这 3 个文件违规(plan_generator 达 117 处) 中文 prompt 抽取到 web/backend/prompts/ 模板文件(代码已有 _load_prompt() 外置机制),或做 \uXXXX 转义
F4 src/gui/main.py:572-589 Git preflight 与工程纪律直接冲突:AGENTS.md 要求"不满足时拒绝启动扫描",实现却是弹窗"Continue anyway?"可绕过;except Exception: pass 还把"非 Git 仓库/HEAD 无效/git 不存在"全部静默放行 项目层面裁决:改代码为硬拒绝(推荐),或改纪律并在 manifest 记录 git HEAD + dirty 标志保证可追溯
F5 web/backend/app/routers/plans.py:145-171 GET 请求带写副作用:两个 download 端点在 GET 中把 status 改为 executing 并 commit——前端预览、浏览器重试、健康探测都可能意外推动状态机,且无回退路径 状态迁移改为显式 POST /{plan_id}/start-execution,download 只读

三、🟡 风险 / 需注意(按子系统分组,共 40+ 项)

3.1 Motor-CAD 仿真核心(src/solver_core.py、scan_engine.py)

  1. 求解无超时、无断线重连solver_core.py:393-399):do_magnetic_calculation() 无超时,一次挂死整个扫描永久卡住,GUI 取消无效;Motor-CAD 进程中途崩溃后扫描会"带病跑完"产出大量无意义 FAILED。scripts/robust_motorcad.py:379-382 已有现成重建实例逻辑未回流。建议:单点看门狗超时 + 连续 N 点同阶段失败时触发重连。
  2. 回读校验容差严于 float32 精度solver_core.py:380):rel_tol=1e-8 小于 float32 机器精度(1.19e-7),大绝对值参数(3000 rpm、150 A)可能间歇性误判 FAILED。合规但接近物理极限,建议按值量级分档容差并在失败日志输出绝对/相对偏差。
  3. pick_metric 前缀模糊匹配可能静默绑错字段solver_core.py:268-276):双向 startswith 宽松匹配 + dict 序遍历 section,命中顺序不稳定,必需指标"存在但数值错误"仍标 OK 进经验库。建议模糊命中打标 metrics_source="fuzzy" 并显式警告,或收紧为单向匹配+section 优先级。
  4. 编码回退链 latin-1 永不失败solver_core.py:208-216):cp1252 文件若字节序列恰好合法 GBK 会先被误解码,字段名静默乱码。建议解码后做启发式校验(是否出现 ; 分隔和可 float 行),全乱码继续尝试下一编码。
  5. 环境变量回退未检查 ANSYSLMD_LICENSE_FILEsolver_core.py:326-342):知识库记载其缺失导致 ~30s 静默退出,建议 connect 前探测并提前明确报错。
  6. manifest 未记录 git commit hashscan_engine.py:188-202):建议写入 git rev-parse HEAD,保证运行目录可追溯到确切代码版本。

3.2 方案 Schema / 经验库 / API 客户端(src/)

  1. upload_results 会静默清空该方案全部已有结果plans.py:192-193):后端先 DELETE 再插入,客户端无提示——误传部分结果 CSV 会覆盖丢失完整历史。建议支持 mode=replace|append,且先完整解析校验再删除旧数据(当前顺序:先删后解析,坏 CSV 抛 ValueError 时旧数据已清)。
  2. find_similar 对目标值为 0 的参数维度静默跳过experience_db.py:185-189):0 是斜极角等参数的合法常见取值,skew_angle=15 的案例会被误判"相似"。
  3. recommend_next_round 建议区间下界被强制钳到 0experience_db.py:297):对可取负值的参数(电流角、斜极角)错误截断负向探索空间。
  4. 本地与 Web 端相似案例算法语义不一致experience_db.py:160-196 vs analytics.py:119-159):同一组参数两端检索结果和排序不同,闭环结论无法互相印证。建议以 Web 端为权威。
  5. SQLite 连接管理脆弱experience_db.py:55-58):无 WAL、无 timeout、无线程保护;GUI 长写入可致同步脚本 database is locked。建议开 WAL + timeout=30
  6. 本地经验库无去重experience_db.py:71-136):同一 CSV 导入两次产生双份记录,扭曲统计推荐。
  7. validate() 不查变量重名plan_schema.py:195-210):同名 ScanVariable 后者静默覆盖前者,产出大量参数完全相同的冗余点,浪费每点数分钟的求解时间。from_dict 对未知/拼错字段静默丢弃("toplogy" 拼错静默回落默认值)。
  8. cases 字段定义并序列化但全项目无人消费plan_schema.py:79-98):Web 端若按契约下发多工况 cases,本地端静默忽略——下发方以为仿真了多工况,实际只扫变量笛卡尔积,契约语义断裂。
  9. api_client 无重试、超时写死 30sapi_client.py:26,51-58):结果回传单点失败即断链;URL 查询参数未编码(f-string 拼接);错误处理假设响应恒为 JSON/UTF-8。
  10. plan_id 秒级时间戳可能碰撞plan_schema.py:119 + plans.py:19-20):SP-%Y%m%d-%H%M%S 同秒创建两个方案即撞唯一键,客户端收到裸 500。AI 批量闭环同秒多方案是现实可能。建议追加随机后缀 + 全局 IntegrityError→409 处理器。

3.3 本地脚本与测试(scripts/)

  1. robust_motorcad.py 是孤岛代码:除测试外无任何模块 import 它,850 行健壮性投入(重试/重连/preflight/弹窗恢复)空转,实际仿真全走 solver_core——两套求解器并行演化必然发散。建议二选一合并
  2. preflight 把"非管理员"和"非默认安装路径"判为硬失败robust_motorcad.py:503-514):硬编码 C:\ANSYS_Motor-CAD,而本机装在 D 盘——preflight 在本机必然 FAIL。应降级为 warning。
  3. _parse_export 宣称"E-Magnetics 优先"实为"行序先到先得"robust_motorcad.py:740-786):无 section 概念;且 replace(",", ".") 会把千分位 "1,234.5" 变成 "1.234.5" 静默丢弃数值。
  4. 重试策略对确定性错误也重试 3 次robust_motorcad.py:650-667):变量名不存在、写回 mismatch 每次结果必然相同仍重试;float(val) 强转使字符串型参数(材料名等)直接判失败。
  5. CSV 表头按第一个点的 params 动态生成robust_motorcad.py:792-818):后续点参数集不同则列错位。建议预生成键并集表头或 DictWriter。
  6. 三个 test 文件全是"展示性"测试test_api_client.py 在 pytest 收集期就发真实网络请求且恒报 PASSED 无任何断言;test_p4_acceptance.py 约 2/3 是"文件存在"假测试且 pytest 下失败不上报;test_robust_solver.py 无论成败都返回 0。真实断言覆盖率接近零——最该补的是 _parse_export 用样例 CSV 的离线单元测试。
  7. run_scan.py--skip-git-check 是纪律后门:bypass 时无任何痕迹留存,建议在 manifest/log 显式记录。
  8. scan_airgap.json 相对路径按 CWD 解析:从项目根以外目录执行即报"Model file not found",应相对配置文件所在目录解析。

3.4 Web 后端 API 层

  1. Session 泄漏routers/ai.py:50-55,71-79 手动管理会话无 try/finally;task_manager.py 7 处 db = next(get_db()) 从不关闭——且 CPython 下生成器被 GC 回收后 finally 立刻执行 close,后续 ORM 操作实际运行在已关闭 Session 上(SQLAlchemy 静默重开连接,"碰巧能用")。统一改 with SessionLocal() as db:
  2. 内存态全局对象无淘汰无锁routers/search.py:12-13_search_instancesadaptive_loop.py_loops——进程重启全丢、只增不减(内存泄漏)、线程池并发读写无锁。建议容量上限+LRU+Lock,中期落盘。
  3. experience.py 用裸 dict 接收请求体tags 传字符串时 ",".join 逐字符拼接成 "t,a,g,1,,,..." 静默损坏数据;应定义 Pydantic 模型。
  4. upload-results 输入防护缺失:文件无大小限制(内存 DoS);非数值行抛 ValueError 裸 500;上传后无条件置 plan.status="completed"(全部行 FAILED 也标完成)。
  5. 状态字段自由字符串无枚举PlanUpdate.status 任意字符串可写入,状态机因拼写差异静默失效。建议 Literal[...] 约束。
  6. except Exception 把内部错误原文回客户端(adaptive/tasks/ai_plan/analysis 十余处):暴露文件路径、SQL 片段、Kimi 错误细节。
  7. N+1 查询list_projects/list_plans 列表页 50 条产生 50~100 次额外 SQL 往返。
  8. 列表分页参数无上限 + analytics 全表加载/analytics/experience/stats/experience/similar 全表载入内存,经验库增长后单请求 O(n) 内存。
  9. 任务通道结果不进 SimulationResulttask_manager.py:191-209):report_results 只写 task 目录 results.json,analytics/经验导入/AI 分析全部看不到任务通道数据——双通道数据割裂。
  10. 结果状态约定两个子系统不一致:scan_engine 用 "OK"/"FAILED"、task_executor 用 "ok"/"failed"、experience_enhancer 用 feasible 布尔;analytics 只认大写 "OK"——闭环结果流入分析时被静默过滤,前端得到空图。全仓库统一状态枚举
  11. report_generator 数据形状与 TaskManager 输出不匹配report_generator.py:60,74,88):"参数"与"逐点结果"章节恒为空表。
  12. 失败点污染分析样本adaptive_loop.py:215-223):status≠ok 的点仍进入 min/max/mean、收敛判据、AI 输入统计。
  13. 闭环收敛完全依赖信任域收缩adaptive_loop.py:295-314):result_analyst 算出的收敛判据/置信等级只用于展示,不影响循环终止;信任域未激活时只能靠预算耗尽停止。
  14. task_name 直接拼目录路径task_manager.py:60):"../x" 可路径穿越;同秒同名任务目录互相覆盖。
  15. 调度器总进度可超 100%batch_scheduler.py:124-131):分母不含已完成任务点数。
  16. report_results/update_progress 无状态机防护:已取消任务可被"复活"为 completed;progress_data 读-改-写无锁存在丢失更新。

3.5 AI 闭环算法(services/)

  1. 规则引擎与 L0 物理限值互相矛盾rule_engine.py:48 vs l0_prescreening.py:82):气隙 0.2 vs 0.3mm、磁钢 40 vs 20mm——两个模块各自维护一份"物理事实",规则引擎推荐的范围注定被 L0 判不可行。硬限值应收敛到单一事实源
  2. L0 限值与设计方案文档不一致:设计文档写"电流密度 ≤ 12 A/mm²"代码用 15;"磁钢厚度 ≤ 轴向长度×0.4"约束完全缺失;min_via_diameter_mm 是死限值(定义了从不检查)。
  3. _validate_plan 不校验扫描变量名plan_generator.py:196-225):web 侧 magnet_thickness_mm(示例 3-8mm,显然是轴向厚度)与 Motor-CAD 的 Magnet_Thickness(径向深度 13mm)语义歧义——若下游按名字字面映射会把 3-8mm 写进径向深度,几何直接错误且回读校验能过。校验层需要变量名白名单+轴向/径向语义标注
  4. 扫描点数估算在 min≥max 时产生非正 total_pointsplan_generator.py:217-222):追加了 issue 但没 continue,后续预算告警全部基于错误数字。
  5. select_next_batch 返回空批次时不置停滞状态feasibility_search.py:340-396):上层可能无限空转。连续 N 次空批次应置 "stalled"
  6. "checkpoint support"只有导出没有恢复feasibility_search.py:474-503):无 import_state;导出还缺 objective_metric/direction、rng 内部状态——断点续跑无法实现,种子可复现性在恢复点断裂。
  7. 保真度等级语义三方矛盾schema_v2.py:25-31 vs result_analyst.py:20-26 vs README.md:68):result_analyst 把 L3 标为"3D FEA (Motor-CAD)"——概念错误,Motor-CAD 不是 3D FEA 工具;bias_pct 按错误映射参与校准,修正值物理上不可信。README 宣称 L2/L3/L4 已完成,但全仓库无任何 Maxwell/JMAG 集成代码,属过度宣称。
  8. Kimi API 客户端细节ai_client.py):对 400 也退避重试;429 不读 Retry-After;data.get("choices",[{}])[0] 空列表时 IndexError;硬约束解析遇 "efficiency_pct >= 92%" 这类非数值抛 ValueError 未捕获。

四、🟢 优化建议(精选)

代码卫生

  • 清理未使用 import:solver_core.py:17-18(csv/json)、scan_engine.py:17(time)、gui/main.py:24-31(QTimer/QFont/QComboBox 等 7 项)。
  • gui/main.py:275 死代码(恒为 black 的 placeholder + 函数体内 import QColor)。
  • solver_core.py:351-364 disconnect 前重载基线是多余开销(quit 本就不保存)。
  • main.py:40 @app.on_event("startup") 已 deprecated,改 lifespan;datetime.utcnow 全面弃用改 datetime.now(timezone.utc)
  • experience_db.py:129-135 逐行 commit 改单事务批量;plan_id 前后端统一加随机后缀。

经验库 / 分析

  • 本地 experience/experience.db 默认路径锚定项目根而非 CWD(experience_db.py:52plan_schema.py:200-201)。
  • feasibility_search.py:443 收敛阈值 0.001 是绝对量纲,换 objective_metric 后灵敏度完全不同,改相对阈值。
  • experience_enhancer.py:107 注释声称 "random 10" 抽样未实现。
  • batch_scheduler.py:166-174 每点全量写 JSON 状态文件,磁盘 IO 频繁,建议节流。

部署

  • Dockerfile 无 USER 指令(root 运行);compose 残留死配置(version:"3.8" 废弃、未使用的 named volume);nginx 缺安全响应头(X-Content-Type-Optionsclient_max_body_size)。
  • deploy.ps1:103 生成的 .env 带 UTF-8 BOM,config.py 用 utf-8(非 utf-8-sig)解析——首行 key 静默损坏的定时炸弹,两边都修。
  • .gitignore 建议加全局 *.db + *.db-journal;明确 书籍与论文/MotorCAD软件教程及故障处理防范/ 两个大目录的入库策略;根目录与 models/ 重复的 .mot 模型(共 5 份 526KB)只保留一份。
  • reports.py:47 文件名未 os.path.basename 净化(当前被路由挡住,纵深防御);:32 把服务器绝对路径返回客户端。

文档

  • README 项目结构清单过时(routers 列 5 个实际 13 个,scripts 缺 task_executor/robust_motorcad)。
  • 设计方案第 5 章接口契约与实现漂移(§5.3 写 POST 实际 GET;§5.1 富结构 vs 实现扁平 V1 子集)——建议增加"实现现状 vs 目标契约"对照表。

五、文档-代码一致性专项

# 位置 矛盾
1 README.md:99 快速开始命令直接报错:写 python scripts/run_scan.py --plan ...,脚本只接受 --config/--var,新用户照抄第一条命令即失败
2 README.md:41-62 vs :244-247 同一文件自相矛盾:里程碑表标 P2-M3/M4/M5、P3-M1~M5 全部 ✅ 完成,末尾路线图同一批项标 🔲 待开始
3 README.md:68 + :10 能力过度宣称:L2(2D FEA)/L3/L4 列为已完成核心能力,全仓库无任何 Maxwell/JMAG 集成;"自适应闭环就绪"但无本地执行桥(A6)
4 docs/P3-评审响应与更新计划.md vs result_analyst.py 宣称"六类收敛判据"实际四类生效(C2)
5 plans.py 注释 docstring 示例 SP-20260827-001(带序号)实现无序号

闭环链路核验结论:主链路(plans 通道)接口骨架成立——download→plan_schema 解析→扫描→upload→入库各环节端点真实存在、CSV 编码契约(utf-8-sig)一致、download 多余字段被 from_dict 正确忽略。但有三个断点:指标 key 清单漂移(A1)、任务通道数据不进 SimulationResult(3.4-33)、自适应闭环无本地执行桥(A6)。


六、重点专题:GUI 评审(本地 PySide6 + Web 前端)

6.1 本地 GUI(src/gui/main.py,801 行)

总体:结构清晰、分层合理(Worker/表格/日志/主窗分离),线程模型主干正确(Motor-CAD 全部在 QThread 子线程,通信全走 Signal/Slot),样式表做工在工业软件里属中上。但有 4 个必须修的问题(A7、B2、B3、F4,见上)和以下交互/稳定性风险:

交互逻辑风险

  • ScanWorker._cancel 标志设置了却从未被读取(main.py:77-107):connect 阶段(30s+)点 Stop 无效,扫描照常全量执行。
  • Stop 后状态机不完整(:613-617):stop_btn 仍可重复点击,状态栏停在 "Stopping...";若 engine 挂死永不返回,按钮状态机永久卡死。
  • 失败弹窗直接展示完整 traceback(:673-675):几十行 Python 堆栈弹给电机工程师看。弹窗应只给摘要,traceback 留日志区或折叠 "Show Details"。
  • Git preflight 在主线程同步 subprocess.check_output 无超时(:576-579):git 挂起则整个 GUI 冻结。加 timeout=10
  • 无扫描点数爆炸保护(:508-520):多变量笛卡尔积可轻易产生数千点(数天),只有估算时间显示,无超阈值确认。
  • 删除变量行后估算标签不刷新(:464 只连了 itemChanged,removeRow 不触发)。

美观度与细节

  • 结果表表头用内部 key(tavg_nm)而非友好标签——METRIC_LABELS import 了却全文未用(:38, 188)。
  • 三个彩色按钮各自内联重复样式表(:376-411),建议抽常量/统一 QSS。
  • resize(1400,900) 未设 minimumSize,拖小后表格列挤没;splitter 比例硬编码,建议 QSettings 保存/恢复窗口几何。
  • 结果表无排序、无"导出 CSV / 打开输出目录"按钮(结果 CSV 实际已落盘,可达性差)。
  • 全英文 UI 是 ASCII 纪律的合理结果;如需中文界面建议走 Qt .ts 翻译文件而非硬编码。

6.2 Web 前端(web/frontend/src,约 20 文件)

总体:路由/布局/API 分层清晰,Element Plus + ECharts 选型得当,Dashboard.vue 是质量标杆(图表生命周期、空态、加载态、联动都正确)。但 4 个 🔴(D1-D4)证明 AI 相关 8 个页面从未真正跑通过。修复 D1/D2 后还必须处理:

交互逻辑

  • AI 接口 30s 超时很可能不够(api/index.ts:5):方案生成/结果分析/经验提取都是 LLM 调用,建议 AI 类请求单独 timeout: 120000
  • 错误提示只显示 e.message:FastAPI 的 detail 被吞,用户只见 "Request failed with status code: 500"。响应拦截器统一提取 err.response?.data?.detail
  • 顶栏「后端已连接」硬编码假状态(MainLayout.vue:65):后端挂了也显示绿色。应轮询 health 接口。
  • TaskManager 无自动刷新(:210):盯执行的核心页面全靠手动刷新,而 MonitorDashboard 已有 5s 轮询范式——有活跃任务时应启动轮询。
  • 经验库搜索框每次击键都发请求且关键词根本没发给后端(ExperienceList.vue:48):请求纯属浪费,客户端 computed 过滤已是响应式的。
  • 路由无 404 catch-all;菜单高亮在详情页丢失(精确匹配应改前缀匹配)。
  • 假成功按钮:PlanGenerator savePlan 是 stub 却弹"方案已保存(开发中)"成功提示(ExperienceEnhance 同样)——未实现功能应禁用或标"即将上线",不能给成功反馈。
  • Dashboard 清空方案选择后图表渲染到已卸载 DOM(Dashboard.vue:233-243):再次选择时图表空白。selectedPlan 变 null 时 dispose 并置 null。
  • AdvancedVisualization 4 个 ECharts 实例从不 dispose 无 resize 监听(内存泄漏,同项目 Dashboard 做法正确,两种标准)。

美观度

  • 中英混杂:ProjectDetail Create Plan ({{estimatedPoints}} points)、ExperienceList 编辑弹窗全英文、Imported x cases——P2 补丁做过全面中文化,这批 AI 页面又退化了。
  • 字体栈缺中文回退(style.css:9 无 PingFang SC / Microsoft YaHei)。
  • 响应式缺失:侧栏固定 220px 不可折叠;el-row 固定 :span 未配 :xs/:sm/:md,窄屏严重挤压。
  • PlanDetail 结果表列硬编码 8 个指标,新指标无法显示——应按 results[0].metrics 动态生成列。
  • TypeScript 类型安全形同虚设:ref<any>/res: any 泛滥让 vue-tsc 完全拦不住字段错误——D2 那种低级 bug 正是 any 的直接后果。至少为核心实体定义 interface。

七、已验证合规项(正面结论)

  • ASCII 合规src/scripts/、web 后端 routers/schemas/models、deploy.ps1 全部纯 ASCII ✅(仅 3 个 services 文件违规,见 F3;.vue 文件的"合规"方式用错了,见 D1)
  • 仓库卫生git ls-files 确认无 .env*.dbdist/output/node_modules*.log 被跟踪;.gitignore 覆盖全面 ✅(此前怀疑的 .env 入库不成立——.env 未入 Git,但会进 Docker 镜像,见 E1)
  • 硬编码密钥:全仓搜索 sk-/Bearer/password/secret/token 模式,未发现真实密钥;API Key 统一走环境变量 ✅
  • SQL 注入 / 命令注入:web 后端全部走 SQLAlchemy 参数化,无拼接 SQL、无 subprocess 调用;experience_db.py 全部参数化绑定 ✅
  • Motor-CAD 纪律(src 主链路):open_new_instance=True、set_visible(True)、MessageDisplayState=2、每点 load_from_file、回读校验抛 RuntimeError 标 FAILED 继续、逐点 writerow+flush、原始 .mot 只读(全文件无 save 调用)✅
  • 参数语义:rule_engine 注册表中 Magnet_Length=轴向厚度、Magnet_Thickness=径向深度(特意标注 "NOT radial depth")、RMSCurrent 口径,与知识库完全一致;全 src/ 未发现写 PeakCurrent ✅
  • API 契约骨架:api_client 调用的 17 个端点在后端逐一核实全部存在,HTTP 方法/路径/参数/请求体/multipart 字段名/响应键均匹配 ✅;README "32 个 P3 API 端点"实测恰好 32 ✅
  • 算法数学正确性:LHS 采样(区间分配+维内打乱+种子固定 42)、Pearson(var=0 保护)、Pareto 支配逻辑、相似案例归一化距离、预算记账(L0 拒绝不占预算)均实现正确 ✅
  • 前端部分页面:Dashboard 图表 dispose/resize/空态/加载态正确;删除操作均有确认框;vite 代理配置正确 ✅

八、修复优先级路线图

P0 — 立即修(阻断核心闭环正确性 / 数据完整性 / 必现崩溃)

顺序 预估工作量
1 A2+A3+A4+A5 task_executor 重构(复用 RobustMotorCADSolver,禁 mock 静默回退) 0.5 天
2 A1 upload-results 指标清单单一事实源 0.5 天
3 A7 GUI self._plan 不更新 10 分钟
4 A8 api_client 204 空响应 10 分钟
5 B1 BatchScheduler 死锁 30 分钟
6 D1+D2 前端乱码 + axios .data(改动机械、收益巨大) 0.5 天
7 C1 转矩方向映射表、C2 收敛判据接入或改 total、C3 L0 覆盖率判定 1 天
8 B3 输入校验崩溃、B4 GUI finally disconnect 0.5 天

P1 — 本周内(稳定性与部署)

  • B2 closeEvent + 退出路径;B5 robust 提前 return;B6/B7 超时死代码与无限重复执行
  • F2 级联删除 + SQLite 外键;F5 GET 写副作用拆分
  • E1 .dockerignore + 轮换已泄露的 API Key;E2 空值屏蔽;E3 SQLite 持久卷;E4 共享 Token
  • F3 中文 prompt 外置;F4 Git preflight 裁决(改代码或改纪律,二选一)
  • C4/C5 信任域两个 bug;D3/D4 前端图表修复;3.1-1 求解超时+重连
  • A6 自适应闭环本地执行桥(决定"闭环就绪"是否名副其实)
  • 3.4-34 状态枚举全仓库统一;3.4-25 Session 管理统一

P2 — 迭代打磨

  • 其余 🟡 项(契约对齐、去重、分页上限、N+1、checkpoint 真正实现)
  • 测试体系重建:_parse_export 离线单测优先,三个假测试文件改写
  • 文档校准:README 路线图/快速开始/能力宣称、设计方案第 5 章契约对照表
  • 前端:类型定义、轮询、404、响应式、中文化补齐

九、给项目决策层的三个问题

  1. Git preflight 到底"拒绝"还是"提醒"? AGENTS.md 写拒绝、GUI 实现是可绕过——改代码还是改纪律,需要裁决(建议:硬拒绝 + manifest 记录 HEAD/dirty)。
  2. robust_motorcad.pysolver_core.py 两套求解器谁合并谁? 850 行健壮性投入目前空转,task_executor 又在写第三套裸调用——建议收敛为一套。
  3. ASCII 纪律是否豁免 web/backend? 3 个 services 文件已大量违规(内嵌中文 prompt)。建议不豁免、走 prompts 外置;若豁免需修改 AGENTS.md 并加 CI 检查边界。注意:此纪律不适用于 .vue 文件,前端的乱码恰恰是误用的结果。

本报告所有发现均有代码位置证据支撑;评审为静态分析,未运行动态仿真,涉及 Motor-CAD 实际行为的结论以知识库与代码逻辑推断为准。修复后建议对每个 P0 项做针对性验证(尤其是 D1/D2 修复后对 8 个 AI 页面做一次完整手工联调)。