Files
create/docs/INTEGRATION_PLAN.md
forbes 0bc03ea421
All checks were successful
Build and Test / build (pull_request) Successful in 29m22s
feat: BOM auto-extraction and manifest field population (#276, #277)
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
2026-02-19 12:37:24 -06:00

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.