Files
FreeCADWasmDev/docs/WEB_IMPLEMENTATION_FIRST_STRATEGY.md
wangdequan 9a7c4f0335 Save FreeCAD Web workspace sources and user validation evidence
IFC native binding remains incomplete; preserve accurate test results.
2026-09-15 22:01:58 +08:00

8.7 KiB
Raw Blame History

FreeCAD Web 实现优先移植策略

2026-09-08 当前调度与上下文规则以 WEB_DELIVERY_CONTEXT_PLAN.md 为准:优先复用已有成果交付工作区、文档、建模和文件闭环;当前业务结果确认是必须步骤,不受下方历史“验证后置”条款禁止。完整 API/Full Parity/浏览器矩阵仍不在每个小批次重复执行,全部业务范围保留。

决策

当前执行目标从“逐条 API 先取得 evidence 再推进”切换为“先完成用户可操作的 Web 功能链,使用过程中发现问题再定点修复”。

这不是删除 FreeCAD 源程序,也不是允许静态结果或假实现。所有实际计算、Document、对象、格式、Python 和持久化行为仍必须来自 freecad-source 构建出的 WASM/native dispatcher;变化的是调度顺序和完成判据:

  • 不再以 apiExposed 作为实现阶段的主进度;
  • 不在每个小批次之后运行 focused gate、完整 API gate、Full Parity gate 或 Chrome 矩阵;
  • 只在需要启动/链接目标时做最小的构建、类型、资源和入口检查;
  • 浏览器使用中出现真实问题时,生成一个最小复现和修复记录,再对受影响功能链定点处理;
  • 完整验证保留为后置工作,不得把未验证内容写成 pass。

13,386 的审计结论

13,386 不是“FreeCAD 全部用户功能”的数量,也不是 Web 必须创建的 13,386 个公开函数。

  1. 扫描器解析了 1,546 个 .py/.pyi 文件,跳过 233 个 test-like 文件和 4 个语法无法解析的文件。去重前命中 14,709 个节点(class 2,201、function 3,047、method 9,461)。
  2. docs/format-api-inventory.json 的成品清单是 13,385 条:class 2,053、function 2,380、method 8,952,覆盖 29 个模块。生成器用 (module, kind, name) 做 setdefault,实际折叠了 1,324 个源码节点、涉及 362 个冲突 key;所以成品“无重复”是去重算法的结果,不表示源码没有同名定义。
  3. docs/p6/python-api-manifest.json 目前是 13,386 条,多出的 1 条是 py:Part:function:makeBox。它来自 C++ Python binding AppPartPy.cpp 的专门 gate,不在当前只扫描 .py/.pyi 的 AST inventory 中。因此这是“源码 Python inventory + 手工补入的 C++ binding”,不是同一口径的全量数字。
  4. inventory 不覆盖完整 C++ Python 注册、导入/别名、继承所得 API、动态命令或嵌套定义;同时把所有不以下划线开头的实现函数都视为 public,可能把内部 helper 算成 API。因此它既会漏计,也会过计。
  5. Import/App/SCL_output/config_control_design.py 单文件约 1,007 条记录,是 fedex 生成的 STEP/EXPRESS schema 类和规则,不等于 1,007 个用户界面功能。
  6. 按路径/名称做保守的 GUI 线索统计约 3,647 条(27.2%),其中 TaskPanel、ViewProvider、Command、Gui 路径高度重叠;这些能力在无头 WASM 中需要 React 交互等价物,不应直接当作可暴露 Python 函数。
  7. 目前 restricted 和 not_implemented 主要表示运行时边界或尚未建立 typed fixture,不表示对应的 Web 用户功能永远不存在。

因此,13,386 应保留为“可追溯源符号索引”,不能继续作为移植队列长度、页面数量或功能完成率分母。实现阶段必须另建 capability 口径。

四层状态模型

层 文件/来源 作用 是否阻断实现
源符号索引 docs/format-api-inventory.json、docs/p6/python-api-manifest.json 保留源码身份、模块、family、tier 和证据路径 否
功能能力注册 docs/current/feature-capability-registry.json 记录一个用户功能链对应的 command、Worker、WASM 模块和涉及 API 否
实现回执 docs/current/implementation-first-registry.json 记录已完成接线/构建的批次,防止同一批重复领取 否
使用问题 docs/current/runtime-issue-ledger.json 用户或运行时发现问题的最小复现、首错、修复和重新部署范围 仅阻断受影响功能

API manifest 的 disposition 只有在明确的后置验证阶段才更新。实现回执不能把 planned 伪装成 exposed,也不能因为一个功能链已可用就关闭所有相关 API 记录。

新的实现顺序

按用户可观察工作流推进,每个工作流内部仍批量复用一个 fc_web_dispatch_json({cmd,args})、一个 Facade/Worker 和一个独立 WASM 模块:

  1. 核心工作区:创建/打开/保存 Document、对象树、属性编辑、选择、重算、Undo/Redo、恢复。
  2. 建模主链:Part 基本体、布尔/变换、PartDesign 特征、Sketcher 几何和约束。
  3. 视图交互:Three.js 场景、选择高亮、相机、显示模式、属性面板和导航。
  4. 文件链:FCStd、STEP/IGES/BREP/STL/OBJ/SVG/DXF/IFC 等实际可用的 import/export 路由。
  5. 工程工作台:TechDraw、Mesh、Fem、BIM/IFC、Assembly、CAM、Measure。
  6. 扩展和长尾:Python family、插件、模板、辅助工作台和可明确映射的 GUI 命令。

每条工作流先完成“入口 → native handler → Worker → React 页面 → 错误恢复”的连续路径,再扩展同一路径的 API 别名。禁止为每个符号单独创建 WASM export、Worker 或页面。

Desktop command 使用生成式通道:workbench-command-matrix.json 提供命令身份和源码位置,生成器从 native FC_WEB_DESKTOP_COMMAND(...) 或 QStringList 注册中确定实现所有者,并产出 desktop-command-routes.json。React DesktopCommandDispatcher 依据该索引选择 family-batch 或 direct-command transport,模块 Worker 按需加载对应独立 WASM。结果必须从请求参数和真实 BREP/mesh/Document 数据计算,不能在 React/Facade 维护逐命令固定参数、fixture 或结果;跨工作台出现的同名命令复用 canonical 实现。

Workbench.cpp 中带子项的 MenuItem/ToolBarItem.setCommand() 是导航容器,不是可执行命令。生成器通过后续 *item << ... 或 add...(*item) 关系自动识别,并生成 ui-container route,由 React 呈现菜单/工具栏分组;只有叶子命令进入 WASM 实现队列。这样不会为了 Constraints、Dimensions、Boolean 等分组标题制造假的 native handler。

为了避免 Emscripten 无增量最终链接带来的重复成本,外层 pipeline 在构建前刷新 capability registry。只要当前批次还有一个 selected ID 缺少 native registration、family Facade/Worker 或 React 通用入口,就以 implementation_incomplete 返回且不构建。静态接线全部完成后只构建一次。构建缓存从 build.ninja 解析当前 target 的 object→source 映射,不因同模块其它 probe 改动失效。

回合规则

  • 外层 planner 可以继续使用 API manifest 选择源码输入,但实现回执负责去重;已经有回执的记录不再次领取,除非 runtime issue 明确重新打开。
  • Codex 回合只做源码判断、接线、依赖补充、WASM 构建和资源同步;不要主动运行 focused gate 或完整验证。
  • 若源码没有可用 native handler,只登记 native_source_required/blocked_native_dependency,继续领取其它功能链;不生成假的 JS 结果。
  • 构建只针对变更目标使用 -j8(或 FREECAD_BUILD_JOBS),并保留独立模块 artifact 和动态加载 manifest;不合并 WASM。
  • 构建失败只修复首错一次;无法从本地源码解决时记录 issue,立即转到下一个不受影响的功能链。
  • 使用阶段的错误处理流程是:记录 request/args/source revision/artifact hash → 定点复现 → 最小修复 → 重新构建受影响模块 → 更新 issue 状态。不要触发全量验证。

观察到问题时使用以下入口写入定点队列;scheduler 会因 ledger 指纹变化自动领取对应 capability:

python3 tools/record_runtime_issue.py 'Part:part.createRecompute' \
  --args-json '{"schema":"...","module":"Part"}' \
  --error '实际观察到的首错或错误行为'

新的进度口径

状态页必须同时显示 featureCapabilities、implementationReceipts、apiExposed、apiClassified、runtimeIssues 和 fullParity。capability 总量由动态发现的 Web command 与源码盘点的桌面 Qt/Gui command 合并生成;后者只有得到 Web route、Worker、React 入口和参数化 native registration 后才能写实现回执。具体数量始终读取 registry,不在执行规则中固化。apiExposed 仅表示已有运行时 evidence 的源符号,不能代表 Web 功能完成率。

最终 Full Parity 仍需要用户明确触发的集中验证;实现优先阶段不得用“暂不验证”宣布项目完成,也不得因验证缺失阻断继续实现。