feat(addon-system): add <kindred> package.xml extensions and schema docs
Some checks failed
Build and Test / build (pull_request) Failing after 2m59s

Add <kindred> elements to ztools (priority=50) and silo (priority=60)
package.xml files declaring min_create_version, load_priority,
pure_python, and context metadata.

Fix addon_loader.py topological sort to use level-by-level processing
with (priority, name) sorting within each level, replacing
static_order() which did not guarantee deterministic ordering.

Add docs/src/development/package-xml-schema.md documenting the full
field reference, schema example, and backward compatibility notes.

Closes #252
This commit is contained in:
2026-02-16 14:21:27 -06:00
parent 60ceb47e4f
commit 98d1877472
5 changed files with 123 additions and 5 deletions

View File

@@ -28,6 +28,7 @@
- [Repository Structure](./development/repo-structure.md)
- [Build System](./development/build-system.md)
- [Gui Module Build](./development/gui-build-integration.md)
- [Package.xml Schema Extensions](./development/package-xml-schema.md)
# Silo Server

View File

@@ -0,0 +1,109 @@
# Package.xml Schema Extensions
Kindred Create extends FreeCAD's standard `package.xml` addon manifest with a `<kindred>` element. This element provides metadata for the manifest-driven addon loader: version compatibility, load ordering, dependency declarations, and editing context registration.
The `<kindred>` element is ignored by FreeCAD's AddonManager and stock module loader. Addons with this element remain compatible with upstream FreeCAD.
## Field reference
| Field | Parsed by loader | Required | Default | Description |
|---|---|---|---|---|
| `min_create_version` | Yes | No | *(none)* | Minimum Kindred Create version. Addon is skipped if the running version is lower. |
| `max_create_version` | Yes | No | *(none)* | Maximum Kindred Create version. Addon is skipped if the running version is higher. |
| `load_priority` | Yes | No | `100` | Integer. Lower values load first. Used as a secondary sort after dependency resolution. |
| `dependencies` | Yes | No | *(none)* | List of addon names (by `<name>` in their `package.xml`) that must load before this one. |
| `sdk_version` | No | No | *(none)* | Required kindred-addon-sdk version. Reserved for future use when the SDK is available. |
| `pure_python` | No | No | `true` | If `false`, the addon requires compiled C++ components. Informational. |
| `contexts` | No | No | *(none)* | Editing contexts this addon registers or injects into. Informational. |
Fields marked "Parsed by loader" are read by `addon_loader.py` and affect load behavior. Other fields are informational metadata for tooling and documentation.
## Schema
```xml
<kindred>
<min_create_version>0.1.0</min_create_version>
<max_create_version>1.0.0</max_create_version>
<sdk_version>0.1.0</sdk_version>
<load_priority>100</load_priority>
<pure_python>true</pure_python>
<dependencies>
<dependency>sdk</dependency>
<dependency>other-addon</dependency>
</dependencies>
<contexts>
<context id="partdesign.body" action="inject"/>
<context id="sketcher.edit" action="register"/>
<context id="*" action="overlay"/>
</contexts>
</kindred>
```
All child elements are optional. An empty `<kindred/>` element is valid and signals that the addon is Kindred-aware with all defaults.
### Version fields
`min_create_version` and `max_create_version` are compared against the running Kindred Create version using semantic versioning (major.minor.patch). If the running version falls outside the declared range, the addon is skipped with a warning in the report view.
### Load priority
When multiple addons have no dependency relationship, `load_priority` determines their relative order. Lower values load first. Suggested ranges:
| Range | Use |
|---|---|
| 0-9 | SDK and core infrastructure |
| 10-49 | Foundation addons that others may depend on |
| 50-99 | Standard addons |
| 100+ | Optional or late-loading addons |
### Dependencies
Each `<dependency>` names another addon by its `<name>` element in `package.xml`. The loader resolves load order using topological sort. If a dependency is not found among discovered addons, the dependent addon is skipped.
### Contexts
The `<contexts>` element documents which editing contexts the addon interacts with. The `action` attribute describes the type of interaction:
| Action | Meaning |
|---|---|
| `inject` | Addon injects commands into this context's toolbars |
| `register` | Addon registers this as a new context |
| `overlay` | Addon registers an overlay that may apply across contexts |
A wildcard `id="*"` indicates the addon's overlay applies universally (matched by a condition function rather than a specific context ID).
## Example: complete package.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<package format="1" xmlns="https://wiki.freecad.org/Package_Metadata">
<name>MyAddon</name>
<description>Example Kindred Create addon</description>
<version>0.2.0</version>
<maintainer email="dev@example.com">Developer</maintainer>
<license>LGPL-2.1-or-later</license>
<url type="repository">https://git.example.com/myaddon</url>
<content>
<workbench>
<classname>MyAddonWorkbench</classname>
<subdirectory>./</subdirectory>
</workbench>
</content>
<kindred>
<min_create_version>0.1.0</min_create_version>
<load_priority>80</load_priority>
<pure_python>true</pure_python>
<contexts>
<context id="partdesign.body" action="inject"/>
</contexts>
</kindred>
</package>
```
## Backward compatibility
- The `<kindred>` element sits outside `<content>` and is not part of FreeCAD's package.xml specification. FreeCAD's `App.Metadata` C++ parser and the AddonManager's Python `MetadataReader` both ignore unknown elements.
- An addon installed in stock FreeCAD will work normally; the `<kindred>` extensions are simply unused.
- The Kindred Create loader works with or without the `<kindred>` element. Addons that omit it load with no version constraints and default priority (100).