All checks were successful
Build and Test / build (pull_request) Successful in 29m22s
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
191 lines
15 KiB
Markdown
191 lines
15 KiB
Markdown
# Integration Plan
|
|
|
|
Strategy for integrating ztools and Silo as built-in addons while maintaining clear boundaries with FreeCAD core.
|
|
|
|
## Goals
|
|
|
|
1. **Native feel** -- ztools and Silo behave as first-class citizens, not bolted-on addons
|
|
2. **Clean boundaries** -- Clear separation between FreeCAD core, Kindred extensions, and addon code
|
|
3. **Minimal core modifications** -- Preserve FreeCAD's container models (Part, Body, Assembly)
|
|
4. **Maintainability** -- Easy to pull upstream FreeCAD changes without merge conflicts
|
|
5. **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/` for `package.xml` manifests with `<kindred>` extensions
|
|
- Validates version compatibility, resolves dependencies via topological sort
|
|
- Loads addons in priority order (sdk → ztools → silo)
|
|
- Populates `FreeCAD.KindredAddons` registry for runtime introspection
|
|
- Sets up deferred Silo dock panels, origin registration, and update checker
|
|
|
|
**C++ module scaffold** (`App/`, `Gui/`, `CreateGlobal.h`):
|
|
- `CreateApp.so` and `CreateGui.so` shared libraries
|
|
- Currently scaffold-only (no features). Will host `Create::FlipPocket` and other C++ features that need to compile with the application rather than live in `mods/`.
|
|
- 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 implementation
|
|
- `src/Mod/Create/Gui/TaskFlipPocket.cpp` -- Task panel
|
|
- `src/Mod/Create/Gui/ViewProviderFlipPocket.cpp` -- View provider
|
|
- Update `ZTools_EnhancedPocket` to create `Create::FlipPocket` instead 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
|
|
|
|
1. **`Create::` namespace prefix.** All Kindred Create C++ features use this prefix to distinguish them from FreeCAD core.
|
|
|
|
2. **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.
|
|
|
|
3. **Silo server distributed separately.** Users deploy the Silo server independently. Setup instructions live in `mods/silo/README.md`.
|
|
|
|
4. **Version synchronization via submodule pins.** ztools and Silo versions are pinned git submodule commits. Updates are deliberate:
|
|
```bash
|
|
cd mods/ztools && git pull origin main && cd ../..
|
|
git add mods/ztools && git commit -m "Update ztools submodule"
|
|
```
|
|
|
|
5. **Python-first approach.** C++ extensions are deferred until Python cannot achieve the requirement. The AttachExtension approach for datums validated this strategy.
|
|
|
|
6. **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.
|
|
|
|
7. **SDK as adaptation layer.** Addons call `kindred_sdk.*` instead of `FreeCADGui.*` platform internals. This creates a single point of adaptation during upstream rebases — update the SDK wrappers, not every addon.
|
|
|
|
8. **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.
|