subagent transcript

session 17f09f89 · workflow wf_77616857
delegated task
GOAL: Produce a CONCRETE roadmap to FULL FreeCAD desktop feature parity for the FreeCAD->WebAssembly port. Be evidence-based: grep/read the actual sou
▸ Magik
GOAL: Produce a CONCRETE roadmap to FULL FreeCAD desktop feature parity for the FreeCAD->WebAssembly port. Be evidence-based: grep/read the actual sources, don't reason from general FreeCAD knowledge alone. Cite file paths. CURRENT STATE (verified working in the browser build): - FreeCAD 26.3.0dev compiled to wasm. Toolchain: emscripten 4.0.12, ASYNCIFY, JS-exceptions, **single-thread (NO pthreads, QT_FEATURE_thread=-1)**, static CPython 3.14, static Qt 6.11.1 (asyncify), static OCCT, static Coin3D. **NO dlopen** — every C-extension is registered via PyImport_AppendInittab in generated src/Main/WasmInittab*.cpp. **NO subprocess/QProcess, NO threads, NO native OS dialogs.** Browser file I/O via upload/download (deploy/index.html). FreeCAD.wasm ~243MB. - 3D viewport RENDERS (offscreen FBO + QPainter blit; Coin3D/OpenGL via WebGL). - **PySide6 FULLY WORKS**: QtCore+QtGui+QtWidgets bindings + shiboken runtime + signals/slots; `from PySide import QtGui` compat shim works; `Gui.getMainWindow()` returns a real PySide6 QMainWindow (shiboken wrapInstance); Python macro scripting drives geometry + GUI. - Workbenches LIVE (7): Part, PartDesign, Sketcher, Surface, Spreadsheet, Material (+None/Start). Measure + Import modules built-in. - Built-in C-extensions (inittab): Import, ImportGui, Materials, MatGui, Measure, MeasureGui, Part, PartGui, PartDesign, PartDesignGui, Sketcher, SketcherGui, Spreadsheet, SpreadsheetGui, StartGui, Surface, SurfaceGui. - MISSING modules (present in src/Mod but NOT built/registered): Draft, BIM, CAM, Fem, Mesh, MeshPart, Points, TechDraw, Assembly, Plot, Show, OpenSCAD, Web, Inspection, ReverseEngineering, Robot, JtReader, Help, AddonManager, Test, Tux, TemplatePyMod. PATHS: - FreeCAD source: /home/magik6k/lcad-wasm/freecad-port/FreeCAD (src/Mod/<WB>, src/Gui, src/App). Each module has CMakeLists.txt, App/ (C++), Gui/ (C++), and often a Python workbench tree (Init.py/InitGui.py + *.py). - wasm build tree: /opt/toolchains/src/freecad-gui-build (CMakeCache.txt, build.ninja, src/Main/WasmInittab*.cpp). - deploy: /home/magik6k/lcad-wasm/freecad-port/deploy (index.html = browser file I/O + boot; *.data = packaged FS). - The module-enablement pipeline already used for the live modules: add C-ext to inittab (RegName=CInitSuffix form via FREECAD_WASM_EXTRA_PY_MODULES + the SHARED->STATIC rewrite in FreeCAD/CMakeLists.txt:91-107), package the module's Python tree onto the wasm FS via file_packager (freecad-mods.data), drop unbuildable OCCT deps, fix dependency gates. - External-tool deps that are a problem in wasm: Fem (calculix/gmsh solvers via subprocess), BIM (ifcopenshell, needs building for wasm + network for downloads), CAM (post-processors), AddonManager (git/network), OpenSCAD (external openscad binary), Web (QtWebEngine — almost certainly not portable). For each thing you assess, classify wasm-viability: WORKS (already), EASY (module-enable pipeline, no hard blocker), MEDIUM (needs a dep built for wasm or a moderate workaround), HARD (needs a wasm-native re-architecture e.g. web worker/fetch/browser API), BLOCKED (fundamentally not portable — say why + what a degraded fallback looks like). Give a rough effort (S/M/L/XL) and cite evidence (CMakeLists deps, Init.py imports, subprocess/QProcess/network usage grep). You are the roadmap synthesizer. Six research agents investigated the parity dimensions. Merge their findings into ONE concrete, phased, dependency-ordered roadmap to full FreeCAD desktop parity in wasm. Requirements: - Order phases by value/effort and dependencies (quick wins first, hard-blocked items flagged honestly). - Each phase: clear goal, the specific items/workbenches/features it delivers, effort, what it depends on, risks. - Call out QUICK WINS (module-enable-pipeline workbenches with no hard blocker — likely Draft, Mesh, Points, TechDraw). - Be HONEST about HARD BLOCKERS (Fem solvers/subprocess, BIM/ifcopenshell+network, Web/QtWebEngine, AddonManager/git, threading) — give the mitigation or the degraded fallback, and a verdict (achievable / partial / not-in-browser). - Give a rough current parity % and a realistic end-state (what "full parity" can and cannot mean in a browser). - recommendedNext = the single best next action. De-duplicate and resolve any disagreements between agents (prefer evidence-cited claims). RESEARCH FINDINGS (JSON): [ { "dimension": "Workbench inventory & classification (every module in src/Mod) — master gap inventory for the FreeCAD→wasm parity roadmap", "worksNow": [ "LIVE C++ workbenches compiled & in inittab: Part, PartDesign, Sketcher, Surface, Spreadsheet, Material, Measure, Import (verified in /opt/toolchains/src/freecad-gui-build/build.ninja — only these src/Mod/*/App|Gui targets configured)", "Show module is already enabled: BUILD_SHOW:BOOL=ON in CMakeCache.txt and its Python tree is packaged (/Mod/Show appears in deploy/freecad-mods.data.js). It is a pure-Python visibility-automation helper (no workbench UI), so it 'works now' as a library dependency", "pivy (Coin3D Python bindings) is packaged (/Mod/pivy in deploy/freecad.data.js) — the Python-side scene-graph layer Draft/other WBs rely on is present", "In-tree 3rdParty deps that unblock several modules are already present in the source tree: src/3rdParty/salomesmesh (SMESH for Fem/MeshPart), src/3rdParty/OndselSolver (Assembly solver), src/3rdParty/libE57Format (Points), src/Mod/CAM/libarea (CAM area-native). libE57Format is even configured in the wasm build tree (/opt/toolchains/src/freecad-gui-build/src/3rdParty/libE57Format)" ], "keyRisks": [ "numpy / matplotlib / scipy are NOT ported/packaged (confirmed absent from all three deploy/*.data.js manifests). This blocks Plot outright and degrades any BIM report/schedule and a handful of Draft/Fem utilities. Porting numpy to this no-pthread wasm/CPython3.14 target is itself a non-trivial sub-project.", "External-process solvers are a hard wall under the NO-subprocess constraint: Fem (g …
Fable
thinking
I've got all the research findings from the six agents, so now I'm synthesizing everything into a roadmap. I should do a quick verification of the key claims—particularly around pivy not being built and the Mesh dependencies—but the research is already comprehensive enough that I can move forward with minimal additional checks.
Fable
I have comprehensive research findings from six agents. Let me verify a few load-bearing claims before synthesizing.
Fable
⚙ Bash {"command": "cd /opt/toolchains/src/freecad-gui-build 2>/dev/null && echo \"=== pivy in build.ninja ===\" && grep -c pivy build.ninja 2>/dev/null; echo \"=== Mesh targets ===\" && grep -oE \"src/Mod/(Mesh|Draft|Points|TechDraw)[^ ]*\" build…
tool result
=== pivy in build.ninja ===
0
=== Mesh targets ===
=== _coin in inittab ===
src/Main/WasmInittab.cpp:0
src/Main/WasmInittabGui.cpp:0
zshexit:1: parameter HISTDB_FD does not contain a file descriptor
Fable
⚙ Bash {"command": "cd /home/magik6k/lcad-wasm/freecad-port/FreeCAD 2>/dev/null && echo \"=== Draft pivy guard ===\" && grep -n \"pivy\" src/Mod/Draft/InitGui.py | head; echo \"=== Mesh QtConcurrent ===\" && grep -rn \"QtConcurrent\" src/Mod/Mesh/…
tool result
=== Draft pivy guard ===
57:            from pivy import coin
=== Mesh QtConcurrent ===
src/Mod/Mesh/App/Core/Curvature.cpp:31:#include <QtConcurrentMap>
src/Mod/Mesh/App/Core/Curvature.cpp:86:            = QtConcurrent::mapped(mySegment, std::bind(&FacetCurvature::Compute, &face, sp::_1));
=== IDBFS in index.html ===
0
zshexit:1: parameter HISTDB_FD does not contain a file descriptor
Fable
thinking
I've verified the key findings across the codebase—pivy isn't built, Draft's InitGui has proper import guards, Mesh relies on QtConcurrent for threading, and there's a persistence gap without IDBFS support. Now I'm ready to synthesize these into a structured roadmap.

Looking at the disagreements between agents: Draft's viability hinges on pivy._coin availability (MEDIUM/L priority, not EASY as initially thought), pivy._coin itself is the critical linchpin that should sequence first, and MeshPart becomes EASY-MEDIUM once Mesh is resolved. QtConcurrent usage across Mesh, Points, and TechDraw needs a serial fallback patch since the module may not be available in the WASM environment. Persisten  …
Fable
All load-bearing claims verified: pivy `_coin` is not built (0 refs in build.ninja, none in inittab), Draft's `InitGui.py:57` hard-gates on `from pivy import coin`, Mesh's `Curvature.cpp:86` uses `QtConcurrent::mapped` (needs the serial patch), and `index.html` has zero IDBFS/syncfs (persistence gap confirmed). The research findings are internally consistent. Synthesizing now.
Fable
⚙ StructuredOutput {"__unparsedToolInput": {"raw": "{\"executiveSummary\": \"The wasm port already runs FreeCAD's core solid-modeling stack (Part/PartDesign/Sketcher/Surface/Spreadsheet/Measure/Import) with a working 3D viewport, full PySide6, STEP/IGES/BREP/…
tool result
<tool_use_error>InputValidationError: StructuredOutput was called with input that could not be parsed as JSON.
You sent (first 200 of 23004 bytes): {"executiveSummary": "The wasm port already runs FreeCAD's core solid-modeling stack (Part/PartDesign/Sketcher/Surface/Spreadsheet/Measure/Import) with a working 3D viewport, full PySide6, STEP/IGES/B
Common causes: unescaped backslashes in file paths (use / or \\), unescaped control characters, or truncated output. Retry with valid JSON.</tool_use_e  …[truncated]
Fable
thinking
I should pass the structured object directly to StructuredOutput instead of wrapping it in a string.
Fable
I passed the wrong shape. Let me call it directly with structured fields.
Fable
⚙ StructuredOutput {"executiveSummary": "The wasm port already runs FreeCAD's core solid-modeling stack (Part/PartDesign/Sketcher/Surface/Spreadsheet/Measure/Import) with a working 3D viewport, full PySide6, STEP/IGES/BREP/glTF/FCStd I/O, and the full cross-c…
tool result
Structured output provided successfully