Root documentation: - README.md: add Datums description, update addon load order and SDK references, fix project structure tree, update issue reporting guidance - CONTRIBUTING.md: update submodule table (remove ztools, add gears/datums/solver), fix QSS guidance (single canonical source, not three copies) - docs/ARCHITECTURE.md: update bootstrap flow (5 addons, split deferred timers between Create core and Silo addon), update load order and source layout - docs/COMPONENTS.md: add Datums and Solver sections, update Gears description, fix Silo origin registration reference - docs/KNOWN_ISSUES.md: create missing file referenced by CLAUDE.md and CONTRIBUTING.md - docs/INTEGRATION_PLAN.md: update layer 5 diagram, fix load order references, update Phase 6 install rules, fix Layer 2/3/5 descriptions - docs/OVERVIEW.md: add datums submodule entry - docs/UPSTREAM.md: update Phase 1 directory table and Phase 4 submodule list mdBook documentation (docs/src/): - SUMMARY.md: replace dead architecture/ links with existing reference pages, remove deleted silo-server files, add new silo-server pages - introduction.md: rewrite — replace ztools with current addons (Silo, Gears, Datums, KCSDK), update version to v0.1.5/FreeCAD 1.2.0 - guide/getting-started.md: update first-run addon list - guide/installation.md: update verification console output - guide/workbenches.md: rewrite — replace ztools with Gears, Datums, Solver - guide/building.md: update submodule table, fix error message guidance - development/contributing.md: fix scope example and issue reporting - development/repo-structure.md: rewrite — add SDK, datums, gears, solver, reference/ folder; update submodule and key files tables - development/writing-an-addon.md: fix priority range table - reference/create-module-bootstrap.md: rewrite — reflect addon_loader system, split deferred timers between Create core and Silo addon - reference/datum-creator.md: update from ZTools to datums addon paths and naming - reference/glossary.md: add KCSDK entry, update FreeCAD version, remove ztools entry, update repository URLs table
17 KiB
Integration Plan
Strategy for integrating Kindred addons as built-in components while maintaining clear boundaries with FreeCAD core.
Goals
- Native feel -- Addons behave as first-class citizens, not bolted-on extras
- Clean boundaries -- Clear separation between FreeCAD core, Kindred extensions, and addon code
- Minimal core modifications -- Preserve FreeCAD's container models (Part, Body, Assembly)
- Maintainability -- Easy to pull upstream FreeCAD changes without merge conflicts
- Extensibility -- Architecture supports future Kindred-specific features
Architecture layers
┌─────────────────────────────────────────────────────────────┐
│ Kindred Create Application │
├─────────────────────────────────────────────────────────────┤
│ Layer 5: Kindred Addons (mods/) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Silo │ │ Gears │ │ Datums │ │ Solver │ │
│ │ PLM/VCS │ │ Gear gen │ │ Datum │ │ Assembly │ │
│ │ BOM mgmt │ │ │ │ creator │ │ research │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Layer 4: Kindred Addon SDK (mods/sdk/) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Stable API contract: context, theme, origin, dock ││
│ │ Isolates addons from FreeCADGui.* platform internals ││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ Layer 3: Kindred Create Module (src/Mod/Create/) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Python: manifest-driven addon loader, Silo integration ││
│ │ C++: CreateApp / CreateGui libraries (feature scaffold)││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ Layer 2: FreeCAD Python API │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ FreeCAD, FreeCADGui, Part, PartDesign, Sketcher, ││
│ │ Assembly, WorkbenchManipulator ││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ Layer 1: FreeCAD Core (C++) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ App::Document, Part::Feature, PartDesign::Body, etc. ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
Boundary definitions
Layer 1: FreeCAD Core -- do not modify
FreeCAD's fundamental data structures: PartDesign::Body, PartDesign::Pocket, Part::Feature, App::Document, Sketcher::SketchObject. Modifying these creates merge conflicts with upstream and risks breaking FCStd file compatibility.
Layer 2: FreeCAD Python API -- use as-is
The Python API provides everything needed for feature creation, command registration, and geometry access. Addons operate through this layer. Stable FreeCAD APIs (Gui.addCommand(), Gui.addWorkbench(), Gui.addWorkbenchManipulator()) are called directly -- they do not need SDK wrappers.
Layer 3: Kindred Create Module -- src/Mod/Create/
The Create module serves two roles:
Python bootstrap (Init.py, InitGui.py, addon_loader.py):
- Scans
mods/forpackage.xmlmanifests with<kindred>extensions - Validates version compatibility, resolves dependencies via topological sort
- Loads addons in priority order (sdk → solver → gears → datums → silo)
- Populates
FreeCAD.KindredAddonsregistry for runtime introspection - Sets up deferred .kc format registration and update checker
C++ module scaffold (App/, Gui/, CreateGlobal.h):
CreateApp.soandCreateGui.soshared libraries- Currently scaffold-only (no features). Will host
Create::FlipPocketand other C++ features that need to compile with the application rather than live inmods/. - Follows the Assembly module pattern (
PyMOD_INIT_FUNC,Py::ExtensionModule)
Layer 4: Kindred Addon SDK -- mods/sdk/
The SDK is a pure-Python package that provides stable wrappers around Kindred-specific platform APIs. Addons import from kindred_sdk instead of calling FreeCADGui.* platform internals directly. This creates a single adaptation point during upstream rebases.
SDK modules:
context— editing context registration (register_context,register_overlay,inject_commands, etc.)theme— YAML-driven palette system (get_theme_tokens,load_palette,Palette)origin— FileOrigin registration (register_origin,unregister_origin)dock— deferred dock panel helper (register_dock_panel)compat— version detection (create_version,freecad_version)
The SDK is loaded first (priority 0) and has no dependencies.
Layer 5: Kindred Addons -- mods/
Pure Python addons with package.xml manifests. Self-contained with Init.py, InitGui.py, and <kindred> metadata. Developed and versioned independently as git submodules. Must declare <dependency>sdk</dependency> to use SDK APIs. Current addons: solver (assembly research), gears (parametric gear generation), datums (unified datum creator), silo (PLM).
Phase status
Phase 1: Addon auto-loading -- DONE
Implementation: src/Mod/Create/addon_loader.py implements manifest-driven loading with dependency resolution. Replaces the original exec()-based approach. Each addon provides a package.xml with <kindred> extensions specifying version bounds, load priority, and dependencies.
Default workbench: PartDesignWorkbench (set in PreferencePacks/KindredCreate/KindredCreate.cfg).
Registry: FreeCAD.KindredAddons provides runtime introspection — .loaded() returns addon names and states, .get(name) returns manifest data, .contexts() lists registered editing contexts.
Phase 1.5: Addon SDK -- DONE
Goal: Provide a stable API contract between the Create platform and addons, isolating addons from FreeCADGui.* platform internals that may change during upstream rebases.
Implementation: mods/sdk/kindred_sdk/ package with wrappers for editing contexts, theme tokens, FileOrigin registration, and dock panel creation. YAML-driven palette system (palettes/catppuccin-mocha.yaml) replaces hardcoded color dicts that were duplicated across 5+ locations.
Migration: Silo has been migrated to use the SDK (#250) — it declares <dependency>sdk</dependency> and uses kindred_sdk for overlay registration and theme tokens. Gears also depends on the SDK. The former ztools addon was removed from the build (#344) and archived to reference/ztools/ (#345) as part of the UI/UX rework (#346); its commands will be reimplemented through the KCSDK system.
Phase 1.75: C++ module scaffold -- DONE
Goal: Establish src/Mod/Create/App/ and src/Mod/Create/Gui/ so Kindred-specific C++ features have a proper build target.
Implementation: CreateApp.so and CreateGui.so shared libraries following the Assembly module pattern. Currently scaffold-only — no features registered. The existing Python bootstrap continues working alongside the C++ module.
Phase 2: Enhanced Pocket as C++ feature -- NOT STARTED
Goal: Implement a proper Create::FlipPocket C++ feature inheriting from PartDesign::ProfileBased.
Rationale: The former ztools Python implementation created a standard Pocket then applied a boolean Common. A native feature would integrate properly with the feature tree, support undo/redo correctly, and perform better on complex geometry.
Scope:
src/Mod/Create/App/FeatureFlipPocket.cpp-- Feature implementationsrc/Mod/Create/Gui/TaskFlipPocket.cpp-- Task panelsrc/Mod/Create/Gui/ViewProviderFlipPocket.cpp-- View provider
Decision: Deferred. The former Python approach was functional. Revisit as part of the KCSDK-driven command reimplementation (#346).
Phase 3: Datum C++ helpers -- NOT STARTED (SUPERSEDED)
Original goal: Create C++ geometry helper functions for datum calculations.
Current state: The Python implementation now uses FreeCAD's built-in Part::AttachExtension for automatic parametric updates. Each datum type maps to a native MapMode (FlatFace, ThreePointsPlane, NormalToEdge, etc.) with appropriate AttachmentSupport and AttachmentOffset. This eliminates the need for custom geometry calculations.
Decision: Superseded by the AttachExtension approach. Only tangent_to_cylinder still uses manual placement (requires a vertex reference not currently collected by the UI).
Phase 4: Theme system -- DONE
Goal: Theme applies consistently at startup regardless of active workbench.
Current state: The Catppuccin Mocha theme is set as the default via the KindredCreate preference pack. The canonical QSS lives in src/Gui/Stylesheets/KindredCreate.qss. The PreferencePacks copy is generated at build time via configure_file() in src/Gui/PreferencePacks/CMakeLists.txt.
Theme colors are now centralized in the SDK's YAML palette (mods/sdk/kindred_sdk/palettes/catppuccin-mocha.yaml). Addons use kindred_sdk.theme.get_theme_tokens() instead of hardcoding color dicts. The SDK provides a Palette class for programmatic access to colors and semantic roles.
Phase 5: Silo deep integration -- DONE
Goal: Silo commands available globally, not just in the Silo workbench.
Implementation: The unified origin system (FileOrigin, OriginManager, OriginSelectorWidget) in src/Gui/ delegates all file operations (New/Open/Save) to the selected origin. Standard commands (Std_New, Std_Open, Std_Save) and origin commands (Origin_Commit, Origin_Pull, Origin_Push, Origin_Info, Origin_BOM) are built into the File toolbar and menu. The Silo workbench no longer has its own toolbar — it only provides a menu with admin/management commands.
Dock panels: Database Auth (2000ms), Database Activity (4000ms), and Start Panel panels are created via deferred QTimers using kindred_sdk.register_dock_panel(). The Activity panel displays real-time server events via SSE with automatic reconnection. The Start Panel provides an in-viewport landing page with recent files and Silo integration.
Phase 6: Build system integration -- DONE
Goal: CMake install rules for mods/ submodules so packages include all addons automatically.
Implementation: src/Mod/Create/CMakeLists.txt includes install rules for all addons (mods/sdk, mods/solver, mods/gears, mods/datums, mods/silo) and the C++ module scaffold (App/, Gui/). Build-time code generation: version.py.in → version.py via configure_file().
CI/CD status: Release workflows (.gitea/workflows/release.yml) build for Linux (AppImage + .deb), macOS (DMG for Intel + Apple Silicon), and Windows (.exe NSIS installer + .7z archive). Builds run on public runners in dockerized mode. Releases are triggered by v* tags. See docs/CI_CD.md for details.
Phase 7: KCSDK — C++-backed SDK module -- IN PROGRESS
Goal: Replace the pure-Python SDK wrappers with a C++ shared library (libKCSDK.so) and pybind11 bindings (kcsdk.so). This gives addons a stable, typed API with proper GIL safety and enables future C++ addon development without Python.
Architecture:
Python Addons (silo, future addons, ...)
|
kindred_sdk (mods/sdk/) <- convenience layer (try kcsdk, fallback FreeCADGui)
|
kcsdk.so (pybind11 module) <- C++ API bindings
|
KCSDK (C++ shared library) <- SDKRegistry + provider interfaces
|
FreeCADGui (EditingContextResolver, DockWindowManager, OriginManager, ...)
Sub-phases:
| # | Issue | Status | Description |
|---|---|---|---|
| 1 | #350 | DONE | Scaffold KCSDK library + kcsdk pybind11 module |
| 2 | #351 | DONE | Migrate editing context API to kcsdk |
| 3 | #352 | DONE | Panel provider system (IPanelProvider) |
| 4 | #353 | DONE | C++ theme engine |
| 5 | #354 | DONE | Toolbar provider system (IToolbarProvider) |
| 6 | #355 | DONE | Menu and action system |
| 7 | #356 | DONE | Status bar provider + origin migration |
| 8 | #357 | — | Deprecation cleanup + SDK v1.0.0 |
Key files:
src/Gui/SDK/— C++ library (KCSDKGlobal.h, Types.h, SDKRegistry, IPanelProvider, WidgetBridge)src/Gui/SDK/bindings/— pybind11 module (kcsdk_py.cpp, PyIPanelProvider, PyProviderHolder)mods/sdk/kindred_sdk/— Python wrappers with kcsdk/legacy fallback
Design decisions:
- No Qt in public C++ API —
Types.husesstd::string,std::vector,std::function. Qt conversion happens internally inSDKRegistry.cpp. - GIL-safe Python callables — Python callbacks stored via
std::make_shared<py::object>withpy::gil_scoped_acquirebefore every invocation. - PySide widget bridging —
WidgetBridge::toQWidget()converts PySide QWidget objects to C++QWidget*viaGui::PythonWrapper(Shiboken). - Provider pattern — Interfaces like
IPanelProviderenable addons to register factories. The registry callscreate_widget()once and manages the lifecycle throughDockWindowManager.
Design decisions
-
Create::namespace prefix. All Kindred Create C++ features use this prefix to distinguish them from FreeCAD core. -
No upstream contribution. Kindred Create is a standalone product. This allows divergent design decisions without upstream coordination. Category 3 bug fixes (see
UPSTREAM.md) may be upstreamed to reduce patch burden. -
Silo server distributed separately. Users deploy the Silo server independently. Setup instructions live in
mods/silo/README.md. -
Version synchronization via submodule pins. Addon versions are pinned git submodule commits. Updates are deliberate:
cd mods/silo && git pull origin main && cd ../.. git add mods/silo && git commit -m "Update silo submodule" -
Python-first approach. C++ extensions are deferred until Python cannot achieve the requirement.
-
Graceful degradation. The addon loader skips addons that fail validation or loading. Each addon load is wrapped in try/except with console logging. Any addon can be absent without breaking the bootstrap.
-
SDK as adaptation layer. Addons call
kindred_sdk.*instead ofFreeCADGui.*platform internals. This creates a single point of adaptation during upstream rebases — update the SDK wrappers, not every addon. -
Manifest-driven loading. Addons declare version bounds, dependencies, and load priority in
package.xml<kindred>extensions. This replaces hardcoded load lists and enables third-party addons in the future.