diff --git a/README.md b/README.md index 8cd76eb4c9..1f72357265 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,11 @@ Kindred Create 0.1.5 | FreeCAD 1.2.0 base ## What is Kindred Create? -Kindred Create is a fork of [FreeCAD](https://www.freecad.org) that adds integrated tooling for professional engineering workflows. It ships a context-aware UI system, two addon command sets, a purpose-built dark theme, and a pluggable file origin layer on top of FreeCAD's parametric modeling core. +Kindred Create is a fork of [FreeCAD](https://www.freecad.org) that adds integrated tooling for professional engineering workflows. It ships a context-aware UI system, addon workbenches, a purpose-built dark theme, and a pluggable file origin layer on top of FreeCAD's parametric modeling core. **Editing context system** -- The UI adapts to what you are editing. An `EditingContextResolver` tracks the active document, view, and in-edit object, then shows or hides toolbars automatically. Built-in contexts cover sketcher editing, assembly editing, PartDesign features/bodies, spreadsheets, and idle states. Addons register their own contexts through a Python API. A color-coded breadcrumb bar in the 3D viewport shows the current editing path. -**ztools** -- A command provider that injects velocity-focused tools into FreeCAD's native PartDesign, Assembly, and Spreadsheet workbenches. Adds custom datum creation (planes, axes, points with 15 attachment modes), pattern tools for assemblies, an enhanced pocket with flip-side cutting, and spreadsheet formatting commands. Rather than running as a separate workbench, ztools commands appear contextually via the editing context system. +**Gears** -- A parametric gear generation workbench for creating involute spur gears, helical gears, and other gear profiles directly within FreeCAD assemblies. **Silo** -- A parts lifecycle management system for managing CAD files, part numbers, revisions, and bills of materials across teams. Includes a Go REST API server backed by PostgreSQL and MinIO, with FreeCAD commands for opening, saving, and syncing files directly from the application. A unified origin system integrates Silo file operations (New, Open, Save, Commit, Pull, Push) into the standard File toolbar and menu across all workbenches. Dock panels provide authentication, real-time database activity via SSE, and a custom start page that replaces the default FreeCAD landing. @@ -112,11 +112,11 @@ Addons extend this through the Python API: ### Addon integration -Addons in `mods/` are loaded by a manifest-driven loader (`src/Mod/Create/addon_loader.py`). Each addon provides a `package.xml` with `` extensions declaring version bounds, load priority, and dependencies. The loader resolves dependencies via topological sort and loads addons in order: **sdk** (0) → **ztools** (50) → **silo** (60). +Addons in `mods/` are loaded by a manifest-driven loader (`src/Mod/Create/addon_loader.py`). Each addon provides a `package.xml` with `` extensions declaring version bounds, load priority, and dependencies. The loader resolves dependencies via topological sort and loads addons in order: **sdk** (0) → **gears** (40) → **silo** (60). Addons call platform APIs through the **kindred-addon-sdk** (`mods/sdk/kindred_sdk/`) rather than `FreeCADGui.*` internals directly. The SDK provides stable wrappers for editing contexts, theme tokens, FileOrigin registration, and dock panels. -ztools uses a `WorkbenchManipulator` plus `injectEditingCommands()` to add its tools to PartDesign, Assembly, and Spreadsheet contexts. Silo registers an overlay that adds the "Silo Origin" toolbar whenever the active document contains Silo tracking properties (`SiloItemId`, `SiloPartNumber`). +Silo registers an overlay that adds the "Silo Origin" toolbar whenever the active document contains Silo tracking properties (`SiloItemId`, `SiloPartNumber`). ### Unified origin system @@ -128,20 +128,6 @@ File operations (New, Open, Save, etc.) are abstracted behind a `FileOrigin` int Kindred Create is compatible with standard FreeCAD workflows. The [FreeCAD wiki](https://wiki.freecad.org/Getting_started) covers general usage. -### ztools - -ZTools commands appear automatically in the PartDesign, Assembly, and Spreadsheet toolbars. There is no separate workbench to select. - -**Datum tools** -- A unified datum creator supporting 15 attachment modes for planes, axes, and points. Accessed from the PartDesign toolbar. - -**PartDesign tools** -- Enhanced pocket with face selection and flip-side cutting. Rotated linear pattern. - -**Assembly tools** -- Linear and polar pattern commands for creating component arrays within assemblies. - -**Spreadsheet tools** -- Bold, italic, underline, alignment (left/center/right), background and text color, and a quick-alias command that creates aliases from cell labels. - -See `mods/ztools/` for detailed documentation. - ### Silo Silo requires a running server instance. See `mods/silo/README.md` for server deployment instructions. @@ -187,8 +173,9 @@ create/ │ └── GSL/ # Microsoft Guidelines Support Library ├── mods/ # Kindred addon modules │ ├── sdk/ # Addon SDK — stable API contract (priority 0) -│ ├── ztools/ # ztools command provider (submodule, priority 50) -│ └── silo/ # Silo PLM workbench (submodule, priority 60) +│ ├── gears/ # Gears workbench (submodule, priority 40) +│ ├── silo/ # Silo PLM workbench (submodule, priority 60) +│ └── solver/ # Solver addon (submodule) ├── resources/ # Branding, icons, desktop integration, MIME types ├── package/ # Packaging scripts │ ├── debian/ # .deb build script diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c524bc3a14..aa838700a5 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -20,10 +20,7 @@ FreeCAD startup │ └─ for each addon in order: │ └─ exec(InitGui.py) │ ├─ sdk (priority 0): logs "SDK loaded" - │ ├─ ztools (priority 50): schedules deferred _register() (2000ms) - │ │ ├─ imports ZTools commands - │ │ ├─ installs _ZToolsManipulator (global) - │ │ └─ injects commands into editing contexts + │ ├─ gears (priority 40): registers GearsWorkbench │ └─ silo (priority 60): registers SiloWorkbench │ └─ schedules deferred Silo overlay registration (2500ms) ├─ EditingContextResolver singleton created (MainWindow constructor) @@ -34,7 +31,6 @@ FreeCAD startup ├─ 500ms: _register_kc_format() → .kc file format ├─ 1500ms: _register_silo_origin() → registers Silo FileOrigin ├─ 2000ms: _setup_silo_auth_panel() → "Database Auth" dock - ├─ 2000ms: ZTools _register() → commands + manipulator ├─ 2500ms: Silo overlay registration → "Silo Origin" toolbar overlay ├─ 3000ms: _check_silo_first_start() → settings prompt ├─ 4000ms: _setup_silo_activity_panel() → "Database Activity" dock @@ -65,7 +61,7 @@ The loader (`addon_loader.py`) processes addons in this order: 5. **Load** — execute `Init.py` (console) then `InitGui.py` (GUI) for each addon 6. **Register** — populate `FreeCAD.KindredAddons` registry with addon state -Current load order: **sdk** (0) → **ztools** (50) → **silo** (60) +Current load order: **sdk** (0) → **gears** (40) → **silo** (60) ## Key source layout @@ -98,14 +94,12 @@ mods/sdk/ [dir] Kindred addon SDK — stable API contract │ └── catppuccin-mocha.yaml 26 colors + 14 semantic roles └── Init.py / InitGui.py Minimal log messages -mods/ztools/ [submodule] command provider (not a workbench) - ├── package.xml Manifest (priority 50, depends on sdk) - ├── ztools/InitGui.py Deferred command registration + _ZToolsManipulator - ├── ztools/ztools/ - │ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet - │ ├── datums/core.py Datum creation via Part::AttachExtension - │ └── resources/ Icons (SDK theme tokens), theme utilities - └── CatppuccinMocha/ Theme preference pack (QSS) +mods/gears/ [submodule → gears.git] Gears workbench + ├── package.xml Manifest (priority 40, depends on sdk) + └── ... Parametric gear generation + +mods/solver/ [submodule → solver.git] Solver addon + └── ... Solver plugin support mods/silo/ [submodule → silo-mod.git] FreeCAD workbench ├── freecad/package.xml Manifest (priority 60, depends on sdk) diff --git a/docs/CI_CD.md b/docs/CI_CD.md index 5182f0b230..dccabf36da 100644 --- a/docs/CI_CD.md +++ b/docs/CI_CD.md @@ -72,7 +72,7 @@ Tags containing `rc`, `beta`, or `alpha` are marked as pre-releases. | `build-macos` (Apple Silicon) | `macos-14` | native | `conda-macos-release` | .dmg (arm64) | Disabled | | `build-windows` | `windows-latest` | native | `conda-windows-release` | .exe (NSIS), .7z | Disabled | -Only the Linux build is currently active. macOS and Windows jobs are defined but commented out pending runner availability or cross-compilation support. After `build-linux` succeeds, `publish-release` collects artifacts and creates the Gitea release. +Only the Linux build is currently active. macOS and Windows jobs are defined but commented out — they require self-hosted runners (macOS) or a Windows runner environment that is not yet provisioned. These platforms are deprioritized while the team focuses on Linux stability and the KCSDK rework (#346). Re-enabling them requires registering platform-specific runners and verifying the rattler-build bundle scripts still work with current dependencies. After `build-linux` succeeds, `publish-release` collects artifacts and creates the Gitea release. ### Linux build diff --git a/docs/COMPONENTS.md b/docs/COMPONENTS.md index 0b9a4e778c..4aede60cb3 100644 --- a/docs/COMPONENTS.md +++ b/docs/COMPONENTS.md @@ -1,31 +1,8 @@ # Components -## ztools (command provider) +## Gears workbench -ZTools is no longer a standalone workbench. It registers as a command provider that -injects tools into the appropriate editing contexts via `WorkbenchManipulator` and -the `EditingContextResolver` system. - -**Registered commands (9):** - -| Command | Function | Injected Into | -|---------|----------|---------------| -| `ZTools_DatumCreator` | Create datum planes, axes, points (16 modes) | PartDesign Helper Features | -| `ZTools_DatumManager` | Manage existing datum objects | PartDesign Helper Features | -| `ZTools_EnhancedPocket` | Flip-side pocket (cut outside sketch profile) | PartDesign Modeling Features | -| `ZTools_RotatedLinearPattern` | Linear pattern with incremental rotation | PartDesign Transformation Features | -| `ZTools_AssemblyLinearPattern` | Pattern assembly components linearly | Assembly | -| `ZTools_AssemblyPolarPattern` | Pattern assembly components around axis | Assembly | -| `ZTools_SpreadsheetStyle{Bold,Italic,Underline}` | Text style toggles | Spreadsheet | -| `ZTools_SpreadsheetAlign{Left,Center,Right}` | Cell alignment | Spreadsheet | -| `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` | Colors and alias creation | Spreadsheet | - -**Integration** via `_ZToolsManipulator` (WorkbenchManipulator) and `injectEditingCommands()`: -- Commands are injected into native workbench toolbars (PartDesign, Assembly, Spreadsheet) -- Context toolbar injections ensure commands appear when the relevant editing context is active -- PartDesign menu items inserted after `PartDesign_Boolean` - -**Datum types (7):** offset_from_face, offset_from_plane, midplane, 3_points, normal_to_edge, angled, tangent_to_cylinder. All except tangent_to_cylinder use `Part::AttachExtension` for automatic parametric updates. +Gears (`mods/gears/`) is a default addon providing parametric gear generation. Added as a submodule in the `feat/gears-addon` branch and merged to main. --- @@ -110,10 +87,6 @@ Notable theme customizations beyond standard Catppuccin colors: `silo-auth.svg`, `silo-bom.svg`, `silo-commit.svg`, `silo-info.svg`, `silo-new.svg`, `silo-open.svg`, `silo-pull.svg`, `silo-push.svg`, `silo-save.svg`, `silo.svg` -### Missing icons - -3 command icon names have no corresponding SVG file: `silo-tag`, `silo-rollback`, `silo-status`. The `_icon()` function returns an empty string for these, so `Silo_TagProjects`, `Silo_Rollback`, and `Silo_SetStatus` render without toolbar icons. - ### Palette All silo-* icons use the Catppuccin Mocha color scheme. See `icons/kindred/README.md` for palette specification and icon design standards. diff --git a/docs/INTEGRATION_PLAN.md b/docs/INTEGRATION_PLAN.md index 1a5582ea81..21527fbc92 100644 --- a/docs/INTEGRATION_PLAN.md +++ b/docs/INTEGRATION_PLAN.md @@ -18,11 +18,11 @@ Strategy for integrating ztools and Silo as built-in addons while maintaining cl ├─────────────────────────────────────────────────────────────┤ │ Layer 5: Kindred Addons (mods/) │ │ ┌──────────────────┐ ┌──────────────────┐ │ -│ │ ztools │ │ Silo │ │ -│ │ Datum Creator │ │ Open/Save/Commit│ │ -│ │ Enhanced Pocket │ │ Part numbering │ │ -│ │ Assembly Patterns│ │ Revision control│ │ -│ │ Spreadsheet fmt │ │ BOM management │ │ +│ │ Silo │ │ Gears │ │ +│ │ Open/Save/Commit│ │ Parametric gear │ │ +│ │ Part numbering │ │ generation │ │ +│ │ Revision control│ │ │ │ +│ │ BOM management │ │ │ │ │ └──────────────────┘ └──────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ Layer 4: Kindred Addon SDK (mods/sdk/) │ @@ -91,7 +91,7 @@ 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 `` metadata. Developed and versioned independently as git submodules. Must declare `sdk` to use SDK APIs. +Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`, `InitGui.py`, and `` metadata. Developed and versioned independently as git submodules. Must declare `sdk` to use SDK APIs. Current addons: **silo** (PLM), **gears** (parametric gear generation). --- @@ -101,7 +101,7 @@ Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`, **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 `` 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. +**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. @@ -111,7 +111,7 @@ Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`, **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 `sdk` and uses `kindred_sdk` for overlay registration and theme tokens. ztools has **not yet been migrated**: its `package.xml` lacks `` metadata and its `InitGui.py` does not import from `kindred_sdk`. See KNOWN_ISSUES.md next step #9. +**Migration:** Silo has been migrated to use the SDK (#250) — it declares `sdk` 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 @@ -121,17 +121,16 @@ Pure Python addons with `package.xml` manifests. Self-contained with `Init.py`, ### 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`. +**Goal:** Implement 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. +**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 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. +**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) @@ -192,10 +191,10 @@ FreeCADGui (EditingContextResolver, DockWindowManager, OriginManager, ...) | 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 | — | C++ theme engine | -| 5 | #354 | — | Toolbar provider system (IToolbarProvider) | -| 6 | #355 | — | Menu and action system | -| 7 | #356 | — | Status bar provider + origin migration | +| 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:** @@ -221,15 +220,15 @@ FreeCADGui (EditingContextResolver, DockWindowManager, OriginManager, ...) 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: +4. **Version synchronization via submodule pins.** Addon 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" + cd mods/silo && git pull origin main && cd ../.. + git add mods/silo && git commit -m "Update silo submodule" ``` -5. **Python-first approach.** C++ extensions are deferred until Python cannot achieve the requirement. The AttachExtension approach for datums validated this strategy. +5. **Python-first approach.** C++ extensions are deferred until Python cannot achieve the requirement. -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. +6. **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. 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. diff --git a/docs/KNOWN_ISSUES.md b/docs/KNOWN_ISSUES.md deleted file mode 100644 index 7708b9ec59..0000000000 --- a/docs/KNOWN_ISSUES.md +++ /dev/null @@ -1,90 +0,0 @@ -# Known Issues - -## Issues - -### Critical - -1. ~~**QSS duplication.**~~ Resolved. The canonical QSS lives in `src/Gui/Stylesheets/KindredCreate.qss`. The PreferencePacks copy is now generated at build time via `configure_file()` in `src/Gui/PreferencePacks/CMakeLists.txt`. The unused `resources/preferences/KindredCreate/` directory has been removed. - -2. ~~**WorkbenchManipulator timing.**~~ Resolved. ZTools is no longer a workbench. Commands are registered via a deferred `QTimer.singleShot(2000ms)` in `InitGui.py`, which activates dependent workbenches first, then imports ZTools commands and installs the `_ZToolsManipulator`. The `EditingContextResolver` handles toolbar visibility based on editing context. - -3. ~~**Silo shortcut persistence.**~~ Resolved. `Silo_ToggleMode` removed; file operations now delegate to the selected origin via the unified origin system. - -### High - -4. **Silo authentication not production-hardened.** Local auth (bcrypt) works end-to-end. LDAP (FreeIPA) and OIDC (Keycloak) backends are coded but depend on infrastructure not yet deployed. FreeCAD client has `Silo_Auth` dock panel for login and API token management. Server has session middleware (`alexedwards/scs`), CSRF protection (`nosurf`), and role-based access control (admin/editor/viewer). Migration `009_auth.sql` adds users, api_tokens, and sessions tables. - -5. **No unit tests.** Zero test coverage for ztools and Silo FreeCAD commands. Silo Go backend also lacks tests. - -6. **Assembly solver datum handling is minimal.** `UtilsAssembly.findPlacement()` handles standard shapes (faces, edges, vertices) and `App::Line` origin objects. It does not extract placement from `PartDesign::Plane` or `PartDesign::Point` datum objects — when no element is selected, it returns a default `App.Placement()`. This means assembly joints referencing datum planes/points may produce incorrect placement. - -### Medium - -7. **`Silo_BOM` requires Silo-tracked document.** Depends on `SiloPartNumber` property. Unregistered documents show a warning with no registration path. - -8. **PartDesign menu insertion fragility.** `_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after `PartDesign_Boolean`. If upstream renames this command, insertions silently fail. - -9. **tangent_to_cylinder falls back to manual placement.** TangentPlane MapMode requires a vertex reference not collected by the current UI. - -10. ~~**`delete_bom_entry()` bypasses error normalization.**~~ Resolved. `delete_bom_entry()` uses `self._request("DELETE", ...)` which routes through `SiloClient._request()` with proper error handling. - -11. ~~**Missing Silo icons.**~~ Resolved. All three icons now exist: `silo-tag.svg`, `silo-rollback.svg`, `silo-status.svg` in `mods/silo/freecad/resources/icons/`. - -### Fixed (retain for reference) - -12. **OndselSolver Newton-Raphson convergence.** `NewtonRaphson::isConvergedToNumericalLimit()` compared `dxNorms->at(iterNo)` to itself instead of `dxNorms->at(iterNo - 1)`. This prevented convergence detection on complex assemblies, causing solver exhaustion and "grounded object moved" warnings. Fixed in Kindred fork (`src/3rdParty/OndselSolver`). Needs upstreaming to `FreeCAD/OndselSolver`. - -13. **Assembly solver crash on document restore.** `AssemblyObject::onChanged()` called `updateSolveStatus()` when the Group property changed during document restore, triggering the solver while child objects were still deserializing (SIGSEGV). Fixed with `isRestoring()` and `isPerformingTransaction()` guards at `src/Mod/Assembly/App/AssemblyObject.cpp:143`. - -14. **`DlgSettingsGeneral::applyMenuIconSize` visibility.** The method was `private` but called from `StartupProcess.cpp`. Fixed by moving to `public` (PR #49). Also required `Dialog::` namespace qualifier in `StartupProcess.cpp`. - ---- - -## Incomplete features - -### Silo - -| Feature | Status | Notes | -|---------|--------|-------| -| Authentication | Local auth complete | LDAP/OIDC backends coded, pending infrastructure. Auth dock panel available. | -| CSRF protection | Implemented | `nosurf` library on web form routes | -| File locking | Not implemented | Needed to prevent concurrent edits | -| Odoo ERP integration | Stub only | Returns "not yet implemented" | -| Part number date segments | Unknown | `formatDate()` reference is stale — function not found in codebase | -| Location/inventory APIs | Tables exist, no handlers | | -| CSV import rollback | Not implemented | `bom_handlers.go` | -| SSE event streaming | Implemented | Reconnect logic with exponential backoff | -| Database Activity panel | Implemented | Dock panel showing real-time server events | -| Start panel | Implemented | In-viewport start page with recent files and Silo integration | - -### ztools - -| Feature | Status | Notes | -|---------|--------|-------| -| Tangent-to-cylinder attachment | Manual fallback | No vertex ref in UI | -| Angled datum live editing | Incomplete | AttachmentOffset not updated in panel | -| Assembly pattern undo | Not implemented | | - ---- - -## Next steps - -1. **Authentication hardening** -- Deploy FreeIPA and Keycloak infrastructure. End-to-end test LDAP and OIDC flows. Harden token rotation and session expiry. - -2. **BOM-Assembly bridge** -- Auto-populate Silo BOM from Assembly component links on save. See `docs/BOM_MERGE.md` for specification. - -3. **File locking** -- Pessimistic locks on `Silo_Open` to prevent concurrent edits. Requires server-side lock table and client-side lock display. - -4. ~~**Build system**~~ Done. CMake install rules in `src/Mod/Create/CMakeLists.txt` handle all `mods/` submodules. - -5. **Test coverage** -- Unit tests for ztools datum creation, Silo FreeCAD commands, and Go API endpoints. - -6. ~~**QSS consolidation**~~ Done. Canonical QSS is `src/Gui/Stylesheets/KindredCreate.qss`; PreferencePacks copy generated at build time via `configure_file()`. - -7. **Update notification UI** -- Display in-app notification when a new release is available (issue #30). The update checker backend (`update_checker.py`) runs at startup; notification UI still needed. - -8. **KC file format completion** -- Populate `silo_instance` and `revision_hash` in manifest.json. Implement write-back for history.json, approvals.json, dependencies.json. See `docs/KC_SPECIFICATION.md`. - -9. **ztools SDK migration** -- Add `` metadata to `mods/ztools/package.xml` (load priority, version bounds, SDK dependency). Migrate `InitGui.py` to use `kindred_sdk` APIs for context/overlay registration. - -10. **DAG cross-item edges** -- Assembly constraints referencing geometry in child parts should populate `dag_cross_edges`. Deferred until assembly constraint model is finalized. diff --git a/docs/MULTI_USER_CLIENT.md b/docs/MULTI_USER_CLIENT.md deleted file mode 100644 index 00ac882f03..0000000000 --- a/docs/MULTI_USER_CLIENT.md +++ /dev/null @@ -1,395 +0,0 @@ -# DAG Client Integration Contract - -**Status:** Draft -**Last Updated:** 2026-02-13 - -This document describes what silo-mod and Headless Create runners need to implement to integrate with the Silo dependency DAG and worker system. - ---- - -## 1. Overview - -The DAG system has two client-side integration points: - -1. **silo-mod workbench** (desktop) -- pushes DAG data to Silo on save or revision create. -2. **silorunner + silo-mod** (headless) -- extracts DAGs, validates features, and exports geometry as compute jobs. - -Both share the same Python codebase in the silo-mod repository. Desktop users call the code interactively; runners call it headlessly via `create --console`. - ---- - -## 2. DAG Sync Payload - -Clients push feature trees to Silo via: - -``` -PUT /api/items/{partNumber}/dag -Authorization: Bearer -Content-Type: application/json -``` - -### 2.1 Request Body - -```json -{ - "revision_number": 3, - "nodes": [ - { - "node_key": "Sketch001", - "node_type": "sketch", - "properties_hash": "a1b2c3d4e5f6...", - "metadata": { - "label": "Base Profile", - "constraint_count": 12 - } - }, - { - "node_key": "Pad001", - "node_type": "pad", - "properties_hash": "f6e5d4c3b2a1...", - "metadata": { - "label": "Main Extrusion", - "length": 25.0 - } - } - ], - "edges": [ - { - "source_key": "Sketch001", - "target_key": "Pad001", - "edge_type": "depends_on" - } - ] -} -``` - -### 2.2 Field Reference - -**Nodes:** - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `node_key` | string | yes | Unique within item+revision. Use Create's internal object name (e.g. `Sketch001`, `Pad003`). | -| `node_type` | string | yes | One of: `sketch`, `pad`, `pocket`, `fillet`, `chamfer`, `constraint`, `body`, `part`, `datum`. | -| `properties_hash` | string | no | SHA-256 hex digest of the node's parametric inputs. Used for memoization. | -| `validation_state` | string | no | One of: `clean`, `dirty`, `validating`, `failed`. Defaults to `clean`. | -| `metadata` | object | no | Arbitrary key-value pairs for display or debugging. | - -**Edges:** - -| Field | Type | Required | Description | -|-------|------|----------|-------------| -| `source_key` | string | yes | The node that is depended upon. | -| `target_key` | string | yes | The node that depends on the source. | -| `edge_type` | string | no | One of: `depends_on` (default), `references`, `constrains`. | - -**Direction convention:** Edges point from dependency to dependent. If Pad001 depends on Sketch001, the edge is `source_key: "Sketch001"`, `target_key: "Pad001"`. - -### 2.3 Response - -```json -{ - "synced": true, - "node_count": 15, - "edge_count": 14 -} -``` - ---- - -## 3. Computing properties_hash - -The `properties_hash` enables memoization -- if a node's inputs haven't changed since the last validation, it can be skipped. Computing it: - -```python -import hashlib -import json - -def compute_properties_hash(feature_obj): - """Hash the parametric inputs of a Create feature.""" - inputs = {} - - if feature_obj.TypeId == "Sketcher::SketchObject": - # Hash geometry + constraints - inputs["geometry_count"] = feature_obj.GeometryCount - inputs["constraint_count"] = feature_obj.ConstraintCount - inputs["geometry"] = str(feature_obj.Shape.exportBrep()) - elif feature_obj.TypeId == "PartDesign::Pad": - inputs["length"] = feature_obj.Length.Value - inputs["type"] = str(feature_obj.Type) - inputs["reversed"] = feature_obj.Reversed - inputs["sketch"] = feature_obj.Profile[0].Name - # ... other feature types - - canonical = json.dumps(inputs, sort_keys=True) - return hashlib.sha256(canonical.encode()).hexdigest() -``` - -The exact inputs per feature type are determined by what parametric values affect the feature's geometry. Include anything that, if changed, would require recomputation. - ---- - -## 4. Feature Tree Walking - -To extract the DAG from a Create document: - -```python -import FreeCAD - -def extract_dag(doc): - """Walk a Create document and return nodes + edges.""" - nodes = [] - edges = [] - - for obj in doc.Objects: - # Skip non-feature objects - if not hasattr(obj, "TypeId"): - continue - - node_type = classify_type(obj.TypeId) - if node_type is None: - continue - - nodes.append({ - "node_key": obj.Name, - "node_type": node_type, - "properties_hash": compute_properties_hash(obj), - "metadata": { - "label": obj.Label, - "type_id": obj.TypeId, - } - }) - - # Walk dependencies via InList (objects this one depends on) - for dep in obj.InList: - if hasattr(dep, "TypeId") and classify_type(dep.TypeId): - edges.append({ - "source_key": dep.Name, - "target_key": obj.Name, - "edge_type": "depends_on", - }) - - return nodes, edges - - -def classify_type(type_id): - """Map Create TypeIds to DAG node types.""" - mapping = { - "Sketcher::SketchObject": "sketch", - "PartDesign::Pad": "pad", - "PartDesign::Pocket": "pocket", - "PartDesign::Fillet": "fillet", - "PartDesign::Chamfer": "chamfer", - "PartDesign::Body": "body", - "Part::Feature": "part", - "Sketcher::SketchConstraint": "constraint", - } - return mapping.get(type_id) -``` - ---- - -## 5. When to Push DAG Data - -Push the DAG to Silo in these scenarios: - -| Event | Trigger | Who | -|-------|---------|-----| -| User saves in silo-mod | On save callback | Desktop silo-mod workbench | -| User creates a revision | After `POST /api/items/{pn}/revisions` succeeds | Desktop silo-mod workbench | -| Runner extracts DAG | After `create-dag-extract` job completes | silorunner via `PUT /api/runner/jobs/{id}/dag` | -| Runner validates | After `create-validate` job, push updated validation states | silorunner via `PUT /api/runner/jobs/{id}/dag` | - ---- - -## 6. Runner Entry Points - -silo-mod must provide these Python entry points for headless invocation: - -### 6.1 silo.runner.dag_extract - -Extracts the feature DAG from a Create file and writes it as JSON. - -```python -# silo/runner.py - -def dag_extract(input_path, output_path): - """ - Extract feature DAG from a Create file. - - Args: - input_path: Path to the .kc (Kindred Create) file. - output_path: Path to write the JSON output. - - Output JSON format: - { - "nodes": [...], // Same format as DAG sync payload - "edges": [...] - } - """ - doc = FreeCAD.openDocument(input_path) - nodes, edges = extract_dag(doc) - - with open(output_path, 'w') as f: - json.dump({"nodes": nodes, "edges": edges}, f) - - FreeCAD.closeDocument(doc.Name) -``` - -### 6.2 silo.runner.validate - -Rebuilds all features and reports pass/fail per node. - -```python -def validate(input_path, output_path): - """ - Validate a Create file by rebuilding all features. - - Output JSON format: - { - "valid": true/false, - "nodes": [ - { - "node_key": "Pad001", - "state": "clean", // or "failed" - "message": null, // error message if failed - "properties_hash": "..." - } - ] - } - """ - doc = FreeCAD.openDocument(input_path) - doc.recompute() - - results = [] - all_valid = True - for obj in doc.Objects: - if not hasattr(obj, "TypeId"): - continue - node_type = classify_type(obj.TypeId) - if node_type is None: - continue - - state = "clean" - message = None - if hasattr(obj, "isValid") and not obj.isValid(): - state = "failed" - message = f"Feature {obj.Label} failed to recompute" - all_valid = False - - results.append({ - "node_key": obj.Name, - "state": state, - "message": message, - "properties_hash": compute_properties_hash(obj), - }) - - with open(output_path, 'w') as f: - json.dump({"valid": all_valid, "nodes": results}, f) - - FreeCAD.closeDocument(doc.Name) -``` - -### 6.3 silo.runner.export - -Exports geometry to STEP, IGES, or other formats. - -```python -def export(input_path, output_path, format="step"): - """ - Export a Create file to an external format. - - Args: - input_path: Path to the .kc file. - output_path: Path to write the exported file. - format: Export format ("step", "iges", "stl", "obj"). - """ - doc = FreeCAD.openDocument(input_path) - - import Part - shapes = [obj.Shape for obj in doc.Objects if hasattr(obj, "Shape")] - compound = Part.makeCompound(shapes) - - format_map = { - "step": "STEP", - "iges": "IGES", - "stl": "STL", - "obj": "OBJ", - } - - Part.export([compound], output_path) - FreeCAD.closeDocument(doc.Name) -``` - ---- - -## 7. Headless Invocation - -The `silorunner` binary shells out to Create (with silo-mod installed): - -```bash -# DAG extraction -create --console -e "from silo.runner import dag_extract; dag_extract('/tmp/job/part.kc', '/tmp/job/dag.json')" - -# Validation -create --console -e "from silo.runner import validate; validate('/tmp/job/part.kc', '/tmp/job/result.json')" - -# Export -create --console -e "from silo.runner import export; export('/tmp/job/part.kc', '/tmp/job/output.step', 'step')" -``` - -**Prerequisites:** The runner host must have: -- Headless Create installed (Kindred's fork of FreeCAD) -- silo-mod installed as a Create addon (so `from silo.runner import ...` works) -- No display server required -- `--console` mode is headless - ---- - -## 8. Validation Result Handling - -After a runner completes a `create-validate` job, it should: - -1. Read the result JSON. -2. Push updated validation states via `PUT /api/runner/jobs/{jobID}/dag`: - -```json -{ - "revision_number": 3, - "nodes": [ - {"node_key": "Sketch001", "node_type": "sketch", "validation_state": "clean", "properties_hash": "abc..."}, - {"node_key": "Pad001", "node_type": "pad", "validation_state": "failed", "properties_hash": "def..."} - ], - "edges": [ - {"source_key": "Sketch001", "target_key": "Pad001"} - ] -} -``` - -3. Complete the job via `POST /api/runner/jobs/{jobID}/complete` with the summary result. - ---- - -## 9. SSE Events - -Clients should listen for these events on `GET /api/events`: - -| Event | Payload | When | -|-------|---------|------| -| `dag.updated` | `{item_id, part_number, revision_number, node_count, edge_count}` | After any DAG sync | -| `dag.validated` | `{item_id, part_number, valid, failed_count}` | After validation completes | -| `job.created` | `{job_id, definition_name, trigger, item_id}` | Job auto-triggered or manually created | -| `job.claimed` | `{job_id, runner_id, runner}` | Runner claims a job | -| `job.progress` | `{job_id, progress, message}` | Runner reports progress | -| `job.completed` | `{job_id, runner_id}` | Job finishes successfully | -| `job.failed` | `{job_id, runner_id, error}` | Job fails | -| `job.cancelled` | `{job_id, cancelled_by}` | Job cancelled by user | - ---- - -## 10. Cross-Item Edges - -For assembly constraints that reference geometry in child parts (e.g. a mate constraint between two parts), use the `dag_cross_edges` table. These edges bridge the BOM DAG and the feature DAG. - -Cross-item edges are **not** included in the standard `PUT /dag` sync. They will be managed through a dedicated endpoint in a future iteration once the assembly constraint model in Create/silo-mod is finalized. - -For now, the DAG sync covers intra-item dependencies only. Assembly-level interference detection uses the BOM DAG (`relationships` table) combined with per-item feature DAGs. diff --git a/docs/OVERVIEW.md b/docs/OVERVIEW.md index 046f93a7b8..cb4398f95e 100644 --- a/docs/OVERVIEW.md +++ b/docs/OVERVIEW.md @@ -1,26 +1,30 @@ # Kindred Create -**Last updated:** 2026-02-08 -**Branch:** main @ `cf523f1d87a` -**Kindred Create:** v0.1.0 -**FreeCAD base:** v1.0.0 +**Last updated:** 2026-03-02 +**Branch:** main @ `b0621f9731c` +**Kindred Create:** v0.1.5 +**FreeCAD base:** v1.2.0 ## Documentation | Document | Contents | |----------|----------| | [ARCHITECTURE.md](ARCHITECTURE.md) | Bootstrap flow, source layout, submodules | -| [COMPONENTS.md](COMPONENTS.md) | ztools, Silo, Origin commands, theme, icons | -| [KNOWN_ISSUES.md](KNOWN_ISSUES.md) | Bugs, incomplete features, next steps | +| [COMPONENTS.md](COMPONENTS.md) | Silo, Gears, Origin commands, theme, icons | | [INTEGRATION_PLAN.md](INTEGRATION_PLAN.md) | Architecture layers, integration phases | | [CI_CD.md](CI_CD.md) | Build and release workflows | +| [INTER_SOLVER.md](INTER_SOLVER.md) | Inter-solver communication | +| [DAG_CLIENT_INTEGRATION.md](DAG_CLIENT_INTEGRATION.md) | DAG client integration (draft) | +| [BOM_MERGE.md](BOM_MERGE.md) | Bill of materials merge specification | +| [KC_SPECIFICATION.md](KC_SPECIFICATION.md) | .kc file format specification | ## Submodules | Submodule | Path | Source | Pinned commit | |-----------|------|--------|---------------| -| ztools | `mods/ztools` | `git.kindred-systems.com/forbes/ztools` | `3298d1c` | -| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` | `f9924d3` | +| silo-mod | `mods/silo` | `git.kindred-systems.com/kindred/silo-mod` | `cc6a79f` | +| gears | `mods/gears` | `git.kindred-systems.com/kindred/gears` | `1e26c39` | +| solver | `mods/solver` | `git.kindred-systems.com/kindred/solver` | `cd7f66f` | | OndselSolver | `src/3rdParty/OndselSolver` | `git.kindred-systems.com/kindred/solver` | `fe41fa3` | | GSL | `src/3rdParty/GSL` | `github.com/microsoft/GSL` | `756c91a` | | AddonManager | `src/Mod/AddonManager` | `github.com/FreeCAD/AddonManager` | `01e242e` | @@ -28,4 +32,6 @@ The silo submodule was split from a monorepo into three repos: `silo-client` (shared Python API client), `silo-mod` (FreeCAD workbench, used as Create's submodule), and `silo-calc` (LibreOffice Calc extension). The `silo-mod` repo includes `silo-client` as its own submodule. -OndselSolver is forked from `github.com/FreeCAD/OndselSolver` to carry a Newton-Raphson convergence fix (see [KNOWN_ISSUES.md](KNOWN_ISSUES.md#12)). +OndselSolver is forked from `github.com/FreeCAD/OndselSolver` to carry a Newton-Raphson convergence fix. + +The 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. diff --git a/docs/REPOSITORY_STATE.md b/docs/REPOSITORY_STATE.md deleted file mode 100644 index 79690d9e68..0000000000 --- a/docs/REPOSITORY_STATE.md +++ /dev/null @@ -1,332 +0,0 @@ -# Kindred Create Repository State Report - -**Generated:** 2026-01-31 -**Branch:** main -**Parent repo:** create-0070 @ `364a7057ef` -**Submodules:** -- ztools @ `8d1f195` (ztools-0065, main) -- silo @ `c778825` (silo-0062, main) - ---- - -## Recent Changes (This Session) - -### Assembly Solver Fix -- `610fd43` — PartDesign datum planes (including ZTools datums) now work - correctly as joint references in Assembly. `findPlacement()` in - `src/Mod/Assembly/UtilsAssembly.py` extracts geometry from - `PartDesign::Plane` and `PartDesign::Point` objects instead of returning - zero placements. - -### ZTools Bug Fixes -- `665bdb2` — Three fixes in the ztools submodule: - - Removed `int()` wrapper from `getStandardButtons()` (Qt6/PySide6 - compatibility — `StandardButton` enum is not int-castable). - - Guarded `_setup_ztools_viewprovider()` against C++ ViewProviders - that lack a `Proxy` attribute (`PartDesign::Plane` uses - `ViewProviderDatumPlane`, pure C++). - - Changed `setEditorMode(prop, 2)` to `setPropertyStatus(prop, "Hidden")` - for persistent attachment property hiding across save/reload. - -### ZTools Parametric Datums via AttachExtension -- `2c716b4` — ZTools datum planes now leverage FreeCAD's built-in - `Part::AttachExtension` for automatic parametric updates. Instead of - `MapMode = "Deactivated"` with manual placement, each datum type maps to a - vanilla `MapMode` (`FlatFace`, `ThreePointsPlane`, `NormalToEdge`, etc.) - with appropriate `AttachmentSupport` and `AttachmentOffset`. Datums update - automatically when source geometry changes on recompute. - -### Stylesheet Fixes (Uncommitted — Staged) -- **Tree branch indicators**: Created `branch_closed.svg` and - `branch_open.svg` in `images_dark-light/` with Catppuccin `#cdd6f4` - chevrons. Added `QTreeView::branch` image rules for expand/collapse states. -- **Spinbox/combobox arrows**: Synced all three QSS copies so the CSS - border-triangle arrow fix (previously only in `resources/preferences/`) - now applies at runtime via `src/Gui/Stylesheets/KindredCreate.qss`. -- **Header clipping**: Added `min-height: 20px` to `QHeaderView::section`. -- **QSS sync**: All four copies (`resources/preferences/`, `src/Gui/Stylesheets/`, - `src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`) are now - byte-identical. Merged dock widget padding and spreadsheet cell editor - styling improvements that existed only in the Stylesheets copy. - -### ZTools-PartDesign Merge (Uncommitted — Staged) -- `_ZToolsPartDesignManipulator` in `mods/ztools/ztools/InitGui.py` uses - `Gui.addWorkbenchManipulator()` to inject ZTools commands into PartDesign's - C++ toolbars: - - `ZTools_DatumCreator` + `ZTools_DatumManager` → "Part Design Helper Features" - - `ZTools_EnhancedPocket` → "Part Design Modeling Features" - - `ZTools_RotatedLinearPattern` → "Part Design Transformation Features" - - Same commands also inserted into the Part Design menu after `PartDesign_Boolean`. - -### Silo Enhancements (Uncommitted — Staged) -- **File menu integration**: `SiloMenuManipulator` in `src/Mod/Create/InitGui.py` - injects `Silo_New`, `Silo_Open`, `Silo_Save`, `Silo_Commit`, `Silo_Pull`, - `Silo_Push`, and `Silo_BOM` into the File menu across all workbenches. -- **Toolbar toggle**: `Silo_ToggleMode` checkable command swaps `Ctrl+O/S/N` - between standard FreeCAD file commands and Silo equivalents. Appended to the - global File toolbar via the manipulator. -- **SSL certificate browsing**: Settings dialog now includes a file browser for - custom CA certificates (`SslCertPath` preference). `_get_ssl_context()` loads - the custom cert before system CAs. -- **BOM integration**: Upstream BOM feature (`Silo_BOM` command with tabbed - dialog — BOM + Where Used) merged with local changes and added to the - Create File menu manipulator. - ---- - -## Architecture Overview - -``` -create-0070/ Kindred Create (FreeCAD 1.0+ fork) -├── src/ -│ ├── Mod/ -│ │ ├── Assembly/ Assembly solver (OndselSolver) -│ │ ├── PartDesign/ Part modeling (C++ workbench) -│ │ ├── Sketcher/ 2D constraint sketcher -│ │ ├── Create/ Kindred bootstrap module (Python) -│ │ │ └── InitGui.py Loads ztools+silo, installs manipulators -│ │ └── ... Other FreeCAD modules -│ └── Gui/ -│ ├── Stylesheets/ QSS themes + arrow/branch SVGs -│ ├── PreferencePacks/ Preference pack bundles -│ └── WorkbenchManipulatorPython.cpp Menu/toolbar injection API -├── mods/ -│ ├── ztools/ [submodule] ztools-0065 -│ │ └── ztools/ -│ │ ├── InitGui.py ZToolsWorkbench + PartDesign manipulator -│ │ └── ztools/ -│ │ ├── commands/ Datum, pattern, pocket, assembly, spreadsheet -│ │ ├── datums/core.py Datum creation with AttachExtension -│ │ └── resources/ Icons, theme utilities -│ └── silo/ [submodule] silo-0062 -│ └── pkg/freecad/ -│ ├── InitGui.py SiloWorkbench -│ └── silo_commands.py 12 commands + SiloClient API -└── resources/ - └── preferences/KindredCreate/ Canonical QSS + preference pack -``` - -### Integration Flow - -``` -FreeCAD startup - └─ src/Mod/Create/InitGui.py exec() - ├─ exec(mods/ztools/ztools/InitGui.py) - │ ├─ registers ZToolsWorkbench - │ └─ installs _ZToolsPartDesignManipulator (global) - ├─ exec(mods/silo/pkg/freecad/InitGui.py) - │ └─ registers SiloWorkbench - └─ QTimer.singleShot(2000): - ├─ _setup_silo_menu() - │ └─ installs SiloMenuManipulator (global) - │ ├─ modifyMenuBar: Silo commands in File menu - │ └─ modifyToolBars: Silo_ToggleMode in File toolbar - ├─ _check_silo_first_start() - └─ _setup_silo_activity_panel() -``` - ---- - -## Submodule Status - -### ztools (ztools-0065) - -| Commit | Description | -|--------|-------------| -| `8d1f195` | Add PartDesign WorkbenchManipulator and sync Catppuccin theme | -| `005348b` | Leverage FreeCAD AttachExtension for parametric datum updates | -| `0e95d1c` | Fix Qt6 StandardButton TypeError and C++ ViewProvider Proxy errors | -| `98bd444` | Fix workbench init and spreadsheet syntax errors | - -**Custom commands**: 9 registered -- `ZTools_DatumCreator`, `ZTools_DatumManager` -- `ZTools_RotatedLinearPattern` -- `ZTools_EnhancedPocket` -- `ZTools_AssemblyLinearPattern`, `ZTools_AssemblyPolarPattern` -- `ZTools_SpreadsheetStyle{Bold,Italic,Underline}`, `ZTools_SpreadsheetAlign{Left,Center,Right}`, `ZTools_Spreadsheet{BgColor,TextColor,QuickAlias}` - -**Datum types supported**: offset_from_face, offset_from_plane, midplane, -3_points, normal_to_edge, angled, tangent_to_cylinder - -### silo (silo-0062) - -| Commit | Description | -|--------|-------------| -| `c778825` | Add Silo mode toggle, SSL cert browsing, and BOM menu integration | -| `8c06899` | (upstream) Various fixes | -| `bce7d5a` | Add BOM handling and routes to API and web UI | -| `3a79d89` | feat: add BOM system with API, database repository, and FreeCAD command | -| `8e44ed2` | Fix SIGSEGV: defer document open after dialog close | - -**FreeCAD commands**: 12 registered -- `Silo_Open`, `Silo_New`, `Silo_Save`, `Silo_Commit` -- `Silo_Pull`, `Silo_Push`, `Silo_Info`, `Silo_BOM` -- `Silo_TagProjects`, `Silo_Rollback`, `Silo_SetStatus` -- `Silo_Settings`, `Silo_ToggleMode` - -**API surface**: 38 REST routes covering items, revisions, files, BOM, -projects, schemas, and Odoo integration stubs. See -`mods/silo/docs/REPOSITORY_STATUS.md` for full route table. - -**BOM API methods** (new): -- `get_bom()`, `get_bom_expanded()`, `get_bom_where_used()` -- `add_bom_entry()`, `update_bom_entry()`, `delete_bom_entry()` - ---- - -## Potential Issues - -### Critical - -1. **Three QSS copies can drift again.** The canonical source is - `resources/preferences/KindredCreate/KindredCreate.qss`. The other copies - (`src/Gui/Stylesheets/`, `src/Gui/PreferencePacks/`, `mods/ztools/CatppuccinMocha/`) - must be kept in sync manually. Consider a build step or symlinks to - eliminate duplication. - -2. **WorkbenchManipulator command registration timing.** The - `_ZToolsPartDesignManipulator` appends commands by name (e.g. - `ZTools_DatumCreator`). If the ZTools workbench has not been initialized - (first activation) when the user switches to PartDesign, the commands may - not be registered yet. The `Create/InitGui.py` `exec()` loads the - workbench class but `Initialize()` only runs on first activation. The - manipulator API tolerates missing commands silently (toolbar append - returns without error), but the buttons won't appear until ZTools - initializes. Mitigation: force-activate ZToolsWorkbench during Create - module load, or defer manipulator installation. - -3. **Silo toggle mode shortcut persistence.** `_swap_shortcuts()` stores - original shortcuts in a module-level dict (`_original_shortcuts`). If - FreeCAD crashes with Silo mode ON, the original shortcuts are lost and - standard commands will have no keyboard shortcuts on next launch. Consider - persisting original shortcuts to preferences. - -### High - -4. **Silo has no authentication.** All API endpoints are publicly accessible. - Required before multi-user deployment. See - `mods/silo/docs/REPOSITORY_STATUS.md` for full list. - -5. **No unit tests for silo FreeCAD commands or ztools.** Python code has zero - test coverage. The Go backend also lacks tests per the silo status report. - -6. **Assembly solver `findPlacement()` geometry extraction is minimal.** The - fix at `UtilsAssembly.py:1006` extracts placement from `obj.Shape.Faces[0]` - for `PartDesign::Plane`. This works for planar datums but does not handle - edge cases like empty shapes or non-planar datum objects. - -### Medium - -7. **`Silo_BOM` depends on `get_tracked_object()`** which looks for a - `SiloPartNumber` property on document objects. Documents not registered - with Silo show a warning dialog. The UX could be improved with a - one-click registration flow from the BOM dialog. - -8. **`_ZToolsPartDesignManipulator.modifyMenuBar()` inserts after - `PartDesign_Boolean`.** If upstream FreeCAD renames or removes this - command, the menu insertions silently fail. The toolbar appends (by - toolbar name) are more robust. - -9. **ZTools `plane_tangent_to_cylinder` falls back to manual placement** - because the TangentPlane MapMode requires a vertex reference not currently - collected by the UI. This is the only datum type that does not benefit - from automatic parametric updates. - -10. **Silo `delete_bom_entry()` uses raw `urllib.request`** instead of the - `_request()` helper method on `SiloClient`. This bypasses error - normalization. Should be refactored to use `self._request("DELETE", ...)`. - ---- - -## Feature Stubs and TODOs - -### From silo REPOSITORY_STATUS - -| Feature | Status | Location | -|---------|--------|----------| -| Odoo ERP integration | Stub (returns "not yet implemented") | `internal/odoo/` | -| Part number date segments | Broken (`formatDate()` returns error) | `internal/partnum/generator.go:102` | -| Location/Inventory APIs | Tables exist, no handlers | `migrations/001_initial.sql` | -| File locking | Not implemented | — | -| Authentication/Authorization | Not implemented | — | -| CSRF protection | Not implemented | Web UI only | -| CSV import transaction rollback | Not implemented | `bom_handlers.go` | - -### From ztools - -| Feature | Status | Location | -|---------|--------|----------| -| Tangent-to-cylinder attachment | Manual fallback (no vertex ref) | `datums/core.py` | -| Angled datum live editing | AttachmentOffset rotation not updated in panel | `datum_viewprovider.py` | -| Assembly pattern undo support | Not implemented | `assembly_pattern_commands.py` | - -### From Create integration plan - -| Phase | Feature | Status | -|-------|---------|--------| -| 1 | Addon auto-loading | Done (`src/Mod/Create/InitGui.py`) | -| 2 | Enhanced Pocket as C++ feature | Not started | -| 3 | Datum C++ helpers | Not started (Python AttachExtension approach used instead) | -| 4 | Theme system refinement | Partially done (QSS synced, not moved to Create module) | -| 5 | Silo deep integration | Done (manipulator-based menu/toolbar injection) | -| 6 | Build system integration | Not started | - ---- - -## File Change Summary (Uncommitted) - -### Parent repo (create-0070) - -| File | Change | -|------|--------| -| `resources/preferences/KindredCreate/KindredCreate.qss` | Branch indicators, header min-height, dock/actiongroup improvements, spreadsheet cell editor | -| `src/Gui/Stylesheets/KindredCreate.qss` | Synced with canonical | -| `src/Gui/PreferencePacks/KindredCreate/KindredCreate.qss` | Synced with canonical | -| `src/Gui/Stylesheets/images_dark-light/branch_closed.svg` | New: right-pointing chevron | -| `src/Gui/Stylesheets/images_dark-light/branch_open.svg` | New: down-pointing chevron | -| `src/Mod/Create/InitGui.py` | Expanded SiloMenuManipulator (BOM, full commands, toolbar toggle) | -| `mods/silo` | Submodule pointer updated | -| `mods/ztools` | Submodule pointer updated | - -### ztools submodule (committed + pushed) - -| File | Change | -|------|--------| -| `ztools/InitGui.py` | Added `_ZToolsPartDesignManipulator` | -| `CatppuccinMocha/CatppuccinMocha.qss` | Synced with canonical KindredCreate.qss | - -### silo submodule (committed + pushed) - -| File | Change | -|------|--------| -| `pkg/freecad/silo_commands.py` | SSL cert browsing, `Silo_ToggleMode`, BOM merge | -| `pkg/freecad/InitGui.py` | Added `Silo_ToggleMode` to toolbar | - ---- - -## Silo Integration Path - -Based on `mods/silo/docs/REPOSITORY_STATUS.md` and the existing -`docs/INTEGRATION_PLAN.md`, the integration path forward is: - -### Completed -- Addon auto-loading via `src/Mod/Create/InitGui.py` -- Global File menu injection via `WorkbenchManipulator` -- Toolbar toggle for Silo mode (shortcut swapping) -- SSL certificate configuration for internal CAs -- BOM command integrated into File menu - -### Next Steps -1. **Authentication** — LDAP/FreeIPA integration for multi-user. Silo server - needs auth middleware; FreeCAD client needs credential storage in preferences. -2. **BOM-Assembly bridge** — Auto-populate Silo BOM from FreeCAD Assembly - component links. When a user saves an assembly, extract child part numbers - from `Assembly_InsertLink` objects and sync to Silo BOM. -3. **File locking** — Pessimistic locks on checkout (`Silo_Open`) to prevent - concurrent edits. Requires server-side lock table and client-side - lock-status display. -4. **Status bar integration** — Show current Silo item part number, revision, - and sync status in FreeCAD's status bar. Use - `FreeCADGui.getMainWindow().statusBar()`. -5. **Build system** — CMake install rules for `mods/` submodules so `.deb` - packages include ztools and silo without manual intervention. diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index d129a051d2..d6be66adf3 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -10,7 +10,6 @@ - [Installation](./guide/installation.md) - [Building from Source](./guide/building.md) - [Workbenches](./guide/workbenches.md) - - [ztools](./guide/ztools.md) - [Silo](./guide/silo.md) - [Document Templates](./guide/templates.md) diff --git a/docs/src/guide/ztools.md b/docs/src/guide/ztools.md deleted file mode 100644 index d1d8446257..0000000000 --- a/docs/src/guide/ztools.md +++ /dev/null @@ -1,133 +0,0 @@ -# ztools - -ztools is a pure-Python FreeCAD workbench that consolidates part design, assembly, and sketcher tools into a single unified interface. It is the **default workbench** when Kindred Create launches. - -- **Submodule path:** `mods/ztools/` -- **Source:** `git.kindred-systems.com/forbes/ztools` -- **Stats:** 6,400+ lines of code, 24+ command classes, 33 custom icons, 17 toolbars - -## Commands - -### Datum Creator (`ZTools_DatumCreator`) - -Creates datum geometry (planes, axes, points) with 16 creation modes. The task panel auto-detects the geometry type from your selection and offers appropriate modes. Supports custom naming, spreadsheet linking, and body- or document-level creation. - -### Datum Manager (`ZTools_DatumManager`) - -Manages existing datums. (Stub — planned for Phase 1, Q1 2026.) - -### Enhanced Pocket (`ZTools_EnhancedPocket`) - -Extends FreeCAD's Pocket feature with **Flip Side to Cut** — a SOLIDWORKS-style feature that removes material *outside* the sketch profile rather than inside. Uses a Boolean Common operation internally. Supports all standard pocket types: Dimension, Through All, To First, Up To Face, Two Dimensions. Taper angle is supported for standard pockets (disabled for flipped). - -### Rotated Linear Pattern (`ZTools_RotatedLinearPattern`) - -Creates a linear pattern with incremental rotation per instance. Configure direction, spacing, number of occurrences, and cumulative or per-instance rotation. Source components are automatically hidden. - -### Assembly Linear Pattern (`ZTools_AssemblyLinearPattern`) - -Creates linear patterns of assembly components. Supports multi-component selection, direction vectors, total length or spacing modes, and creation as Links (recommended) or copies. Auto-detects the parent assembly. - -### Assembly Polar Pattern (`ZTools_AssemblyPolarPattern`) - -Creates polar (circular) patterns of assembly components. Supports custom or preset axes (X/Y/Z), full circle or custom angle, center point definition, and creation as Links or copies. - -### Spreadsheet Formatting (9 commands) - -| Command | Action | -|---------|--------| -| `ZTools_SpreadsheetStyleBold` | Toggle bold | -| `ZTools_SpreadsheetStyleItalic` | Toggle italic | -| `ZTools_SpreadsheetStyleUnderline` | Toggle underline | -| `ZTools_SpreadsheetAlignLeft` | Left align | -| `ZTools_SpreadsheetAlignCenter` | Center align | -| `ZTools_SpreadsheetAlignRight` | Right align | -| `ZTools_SpreadsheetBgColor` | Background color picker | -| `ZTools_SpreadsheetTextColor` | Text color picker | -| `ZTools_SpreadsheetQuickAlias` | Auto-create aliases from row/column labels | - -## Datum creation modes - -### Planes (7 modes) - -| Mode | Description | Input | -|------|-------------|-------| -| Offset from Face | Offsets a planar face along its normal | Face + distance (mm) | -| Offset from Plane | Offsets an existing datum plane | Datum plane + distance (mm) | -| Midplane | Plane halfway between two parallel faces | Two parallel faces | -| 3 Points | Plane through three non-collinear points | Three vertices | -| Normal to Edge | Plane perpendicular to an edge at a parameter location | Edge + parameter (0.0–1.0) | -| Angled | Rotates a plane about an edge by a specified angle | Face + edge + angle (degrees) | -| Tangent to Cylinder | Plane tangent to a cylindrical face at an angular position | Cylindrical face + angle (degrees) | - -### Axes (4 modes) - -| Mode | Description | Input | -|------|-------------|-------| -| 2 Points | Axis through two points | Two vertices | -| From Edge | Axis along a linear edge | Linear edge | -| Cylinder Center | Axis along the centerline of a cylinder | Cylindrical face | -| Plane Intersection | Axis at the intersection of two planes | Two non-parallel planes | - -### Points (5 modes) - -| Mode | Description | Input | -|------|-------------|-------| -| At Vertex | Point at a vertex location | Vertex | -| XYZ Coordinates | Point at explicit coordinates | x, y, z (mm) | -| On Edge | Point at a location along an edge | Edge + parameter (0.0–1.0) | -| Face Center | Point at the center of mass of a face | Face | -| Circle Center | Point at the center of a circular or arc edge | Circular edge | - -## PartDesign injection - -ztools registers a `_ZToolsPartDesignManipulator` that hooks into the PartDesign workbench at startup. This injects the following commands into PartDesign's toolbars and menus: - -| PartDesign toolbar | Injected command | -|--------------------|-----------------| -| Part Design Helper Features | `ZTools_DatumCreator`, `ZTools_DatumManager` | -| Part Design Modeling Features | `ZTools_EnhancedPocket` | -| Part Design Transformation Features | `ZTools_RotatedLinearPattern` | - -The manipulator is registered in `InitGui.py` when the Create bootstrap module loads addon workbenches. - -## Directory structure - -``` -mods/ztools/ -├── ztools/ztools/ -│ ├── InitGui.py # Workbench registration + manipulator -│ ├── Init.py # Console initialization -│ ├── commands/ -│ │ ├── datum_commands.py # DatumCreator + DatumManager -│ │ ├── datum_viewprovider.py # ViewProvider + edit panel -│ │ ├── pocket_commands.py # EnhancedPocket + FlippedPocket -│ │ ├── pattern_commands.py # RotatedLinearPattern -│ │ ├── assembly_pattern_commands.py # Linear + Polar assembly patterns -│ │ └── spreadsheet_commands.py # 9 formatting commands -│ ├── datums/ -│ │ └── core.py # 16 datum creation functions -│ └── resources/ # Icons and theme -└── CatppuccinMocha/ # Theme preference pack -``` - -## Internal properties - -ztools stores metadata on feature objects using these properties (preserved for backward compatibility): - -| Property | Purpose | -|----------|---------| -| `ZTools_Type` | Feature type identifier | -| `ZTools_Params` | JSON creation parameters | -| `ZTools_SourceRefs` | JSON source geometry references | - -## Known gaps - -- Datum Manager is a stub — full implementation planned for Q1 2026 -- Datum parameter changes don't recalculate from source geometry yet -- Enhanced Pocket taper angle is disabled for flipped pockets - -## Further reading - -- `mods/ztools/KINDRED_INTEGRATION.md` — integration architecture and migration options -- `mods/ztools/ROADMAP.md` — phased development plan (Q1–Q4 2026)