▸ Magik
MISSION: push the FreeCAD->WebAssembly port from its current state toward the ~80% browser-parity ceiling in one coordinated effort. You are ONE agent in a parallel swarm; do ONLY your assigned slice and return a precise spec the integrator will apply. The integrator (main loop) owns the single shared FreeCAD cmake reconfigure + ninja build + link; YOU DO NOT run the FreeCAD build.
TOOLCHAIN / ENV: run `source /home/magik6k/lcad-wasm/env.sh` first (sets emsdk 4.0.12 + EM_CONFIG + the libclang-21->22 shim). Tools: emcc/em++/emar/emnm, host swig 4.4.1, host python 3.14, cmake, ninja. Constraints: emscripten single-thread (NO pthreads, QT_FEATURE_thread=-1), NO dlopen (static inittab), NO subprocess/QProcess, ASYNCIFY + JS-exceptions, static CPython 3.14 + Qt 6.11.1 asyncify + OCCT + Coin3D. `-lidbfs.js` is ALREADY in the link options.
PATHS:
- FreeCAD source (git repo, branch wasm-parity-push): /home/magik6k/lcad-wasm/freecad-port/FreeCAD (src/Mod/<WB>, src/Gui, src/App, src/3rdParty, src/Main/CMakeLists.txt)
- wasm build tree: /opt/toolchains/src/freecad-gui-build (CMakeCache.txt, build.ninja) — READ ONLY for you; do not build here.
- deploy: /home/magik6k/lcad-wasm/freecad-port/deploy (index.html, boot.py, *.data). Working M3 build is backed up in deploy-m3-backup/.
- pyside-port build dir for sublib archives: /home/magik6k/lcad-wasm/pyside-port/build/<name>
- Qt asyncify wasm: /opt/toolchains/qt-asyncify/6.11.1/wasm_singlethread ; python-wasm: /opt/toolchains/python-wasm (include/python3.14, lib) ; ICU: /opt/toolchains/icu-wasm
HOW MODULES GET ENABLED (the proven pipeline — return these as DATA, do not edit the shared files yourself except your own module's source):
1. Cache flag: BUILD_<WB>=ON (cmake -D). Enabling it makes src/Mod/<WB>/CMakeLists build the <WB> and <WB>Gui STATIC libs (top-level CMakeLists.txt:91-107 rewrites SHARED/MODULE->STATIC under EMSCRIPTEN). In-tree 3rdParty deps (libE57Format, OndselSolver, libarea, Coin) build within this same tree when their consuming module is enabled.
2. inittab + link: the integrator adds a block to src/Main/CMakeLists.txt of the form
if(BUILD_MESH)
list(APPEND FREECAD_WASM_PY_MODULES Mesh)
list(APPEND FREECAD_WASM_PY_GUI_MODULES MeshGui)
endif()
FREECAD_WASM_PY_MODULES entries are BOTH registered in the inittab (PyImport_AppendInittab("<name>", PyInit_<name>)) AND linked. Some modules build "_<Name>.a" and register the dotted/underscore name (e.g. PartDesign target -> _PartDesign, PartDesign/__init__.py does 'import _PartDesign'). Determine the exact PyInit symbol + registered name for YOUR module by reading its App/Gui CMakeLists (OUTPUT_NAME / target name) and its Init.py/__init__.py import.
3. External prebuilt archives (only pivy._coin) go in FREECAD_WASM_EXTRA_LINK_LIBS (a -Wl,--start-group;...;-Wl,--end-group list) + an inittab entry via FREECAD_WASM_EXTRA_PY_MODULES ("RegName=CInitSuffix", e.g. "PySide6.QtCore=QtCore").
4. Python trees: modules ship a Python workbench tree (src/Mod/<WB>/*.py, InitGui.py) that must be packaged onto the wasm FS at /freecad/Mod/<WB> via emscripten file_packager into a supplementary .data loaded by index.html. List the tree path + mount; the integrator packs it.
Current live inittab modules: Import,ImportGui,Materials,MatGui,Measure,MeasureGui,Part,PartGui,_PartDesign,PartDesignGui,Sketcher,SketcherGui,Spreadsheet,SpreadsheetGui,StartGui,Surface,SurfaceGui + PySide6.QtCore/QtGui/QtWidgets=QtCore/QtGui/QtWidgets + shiboken6.Shiboken=Shiboken.
Current FREECAD_WASM_EXTRA_PY_MODULES: "shiboken6.Shiboken=Shiboken;PySide6.QtCore=QtCore;PySide6.QtGui=QtGui;PySide6.QtWidgets=QtWidgets".
SINGLE-THREAD PATCHING: QtConcurrent/QThreadPool/std::async/std::thread do not work under QT_FEATURE_thread=-1. Convert to synchronous: QtConcurrent::blockingMapped(seq,fn)->serial std::transform; QtConcurrent::mapped -> serial loop; QtConcurrent::run(fn)+QFutureWatcher -> call fn() inline then invoke the finished handler directly. Preserve behavior. Patch ONLY your module's own source files (disjoint from other agents). Cite exact file:line.
RETURN A PRECISE SPEC. Be concrete and evidence-based (grep/read the real files). Do NOT run the FreeCAD reconfigure/ninja. Apply source patches (Edit) only within your assigned files.
You are the INTEGRATION SYNTHESIZER. The swarm built sublibs, patched module sources, and authored P0 glue. Merge everything into ONE tiered integration manifest the main loop will execute as a single reconfigure per tier. Tiers: T0=P0 (persistence+filedialog+exports), T1=Mesh/Points/MeshPart/Inspection/DXF/small-modules, T2=pivy._coin+Draft+Show, T3=TechDraw/Assembly/CAM. For each tier list: the exact -DBUILD_*=ON cmake flags, the src/Main/CMakeLists.txt blocks to insert (dedup), the EXTRA_PY_MODULES entries, the EXTRA_LINK_LIBS additions (pivy archive etc.), the Python trees to package (src->mount), and the browser probes. Note which sublibs built (ok) vs failed (so the integrator skips failed ones — e.g. if pivy._coin failed, T2 Draft is blocked). List ALL patched files (so the integrator can git-commit + review). Give the integrationOrder and global risks. recommendation = how to sequence for maximum landed value given what built.
SWARM OUTPUT (JSON):
sublibs: [
{
"name": "pivy._coin",
"ok": true,
"howBuilt": "Reproduced the pivy CMake SWIG->compile path by hand (script saved at /home/magik6k/lcad-wasm/pyside-port/build/pivy-coin/build.sh). (1) HOST swig 4.4.1: `swig -c++ -python -includeall -D__PIVY__ -I<pivy_root> -I<pivy_root>/fake_headers -I<coin/include src> -I<coin/include generated> -I<interfaces> -outdir OUT -o OUT/coin_wrap.cxx interfaces/coin.i`. The pivy swigified-header mechanism was already primed (install_helpers.py had run: pivy/Inventor/*.h carry the `#ifdef __PIVY__ %include Inventor/X.i` block), so no pre-step needed. Include ORDER matters: pivy_root + fake_headers must precede coin includes so the swigified shadows win. `-py3` from the stock …
Fable
thinking
I'm understanding my role as the integration synthesizer—I need to consolidate all the swarm outputs into a single tiered integration manifest and return it through StructuredOutput. Looking at the schema, I need to structure tiers with properties like tier number, name, modules, cmake flags, expected results, and optional fields for cmake blocks, Python modules, link libraries, and Python source trees.
I also need to capture sublibs with their status and optional archive paths, patched files, integration order, global risks, and a final recommendation. Let me do some quick verification checks on the sublib archives and the current CMakeLists.txt structure to ensure accuracy before generati …