Documentation updates: - KNOWN_ISSUES.md: correct #6 (datum handling), resolve #10 (delete_bom_entry) and #11 (silo icons), fix stale formatDate reference, mark completed next steps, add new next steps. - INTEGRATION_PLAN.md: correct ztools SDK migration claim. kc_format.py (#277): - New _manifest_enrich_hook: populates part_uuid from SiloItemId and silo_instance from Silo API URL on every .kc save. - New update_manifest_fields(): public API to update manifest fields in an already-saved .kc ZIP (used for post-upload revision_hash). mods/silo submodule (#276): - New bom_sync.py extraction engine. - Post-commit hooks for BOM sync and manifest revision update. - SSE bom_merged signal + Activity pane handler. - merge_bom_json client method (forward-looking). Refs: #276, #277
15 KiB
Integration Plan
Strategy for integrating ztools and Silo as built-in addons while maintaining clear boundaries with FreeCAD core.
Goals
- Native feel -- ztools and Silo behave as first-class citizens, not bolted-on addons
- 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/) │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ ztools │ │ Silo │ │
│ │ Datum Creator │ │ Open/Save/Commit│ │
│ │ Enhanced Pocket │ │ Part numbering │ │
│ │ Assembly Patterns│ │ Revision control│ │
│ │ Spreadsheet fmt │ │ BOM management │ │
│ └──────────────────┘ └──────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 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. ZTools and Silo operate entirely 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 → ztools → silo)
- Populates
FreeCAD.KindredAddonsregistry for runtime introspection - Sets up deferred Silo dock panels, origin 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.
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). ZTools is no longer a workbench — its commands are injected into native workbench toolbars via the EditingContextResolver and WorkbenchManipulator systems.
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. ztools has not yet been migrated: its package.xml lacks <kindred> metadata and its InitGui.py does not import from kindred_sdk. See KNOWN_ISSUES.md next step #9.
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: Replace the Python boolean-operation workaround in ZTools_EnhancedPocket with a proper Create::FlipPocket C++ feature inheriting from PartDesign::ProfileBased.
Rationale: The current Python implementation creates a standard Pocket then applies 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- Update
ZTools_EnhancedPocketto createCreate::FlipPocketinstead of the workaround
Decision: Deferred. The Python approach is functional for current needs. Revisit when performance or feature-tree integration becomes a problem.
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 ztools, Silo, and SDK automatically.
Implementation: src/Mod/Create/CMakeLists.txt includes install rules for all addons (mods/ztools, mods/silo, mods/sdk) 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.
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. ztools and Silo versions are pinned git submodule commits. Updates are deliberate:
cd mods/ztools && git pull origin main && cd ../.. git add mods/ztools && git commit -m "Update ztools submodule" -
Python-first approach. C++ extensions are deferred until Python cannot achieve the requirement. The AttachExtension approach for datums validated this strategy.
-
Graceful degradation. The addon loader skips addons that fail validation or loading. Each addon load is wrapped in try/except with console logging. The SDK, ztools, and Silo can all 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.