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

83 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```sh
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 仍需要用户明确触发的集中验证;实现优先阶段不得用“暂不验证”宣布项目完成,也不得因验证缺失阻断继续实现。