Files
create/docs/KC_SPECIFICATION.md
forbes d7b532255b
Some checks failed
Build and Test / build (pull_request) Has been cancelled
feat(icons): add icon theming infrastructure with Catppuccin color remapping
- Remove hand-crafted kindred-icons/ in favor of auto-generated themed icons
- Add icons/mappings/ with FCAD.csv (Tango palette) and kindred.csv (Catppuccin Mocha)
- Add icons/retheme.py script to remap upstream FreeCAD SVG colors
- Generate icons/themed/ with 1,595 themed SVGs (45,300 color replacements)
- BitmapFactory loads icons/themed/ as highest priority before default icons
- 157-color mapping covers the full Tango palette, interpolating between
  4 luminance anchors per color family

Regenerate: python3 icons/retheme.py
2026-02-15 20:34:22 -06:00

23 KiB
Raw Blame History

.kc File Format Specification

Version: 1.0-draft Date: February 2026 Status: Specification — Not Started

The .kc format is Kindred Create's native file format. It is a strict superset of FreeCAD's .fcstd format — every .kc file is a valid .fcstd file with an additional silo/ directory containing platform metadata. This design preserves full interoperability with vanilla FreeCAD while enabling Silo integration, version control, compute job attachment, and engineering workflow features.


1. Design Principles

Superset, not fork. A .kc file can be renamed to .fcstd and opened in unmodified FreeCAD. FreeCAD ignores unknown entries in the ZIP archive, so the silo/ directory is invisible to the base document loader. This means upstream FreeCAD merges never break the format.

Silo metadata is a snapshot. The silo/ directory carries a point-in-time copy of server-side state. The Silo server is authoritative. When a .kc file is opened while connected to Silo, the client checks for newer revisions. Offline edits are reconciled on reconnect by comparing revision hashes in silo/manifest.json.

Incremental adoption. Not every silo/ file needs to be populated. The format grows as Silo modules ship. A minimal .kc file only requires silo/manifest.json. All other entries are optional and introduced by their respective modules.

Round-trip safety. FreeCAD's save routine writes only the entries it knows about (Document.xml, GuiDocument.xml, .brp files, thumbnails/). It does not delete unknown entries from the ZIP. The silo/ directory survives FreeCAD save cycles without corruption.


2. Archive Structure

A .kc file is a ZIP archive. Its contents are organized into two zones: the standard FreeCAD zone (inherited as-is) and the Kindred zone (silo/).

part.kc (ZIP archive)
│
│   ── FreeCAD Standard Zone ──────────────────────────
│
├── Document.xml              # Feature tree, parameters, object definitions
├── GuiDocument.xml           # Visual state (colors, visibility, camera)
├── *.brp                     # BREP geometry cache (one per shape)
├── thumbnails/
│   └── Thumbnail.png         # FreeCAD-generated preview
│
│   ── Kindred Zone ───────────────────────────────────
│
└── silo/
    ├── manifest.json          # Identity, origin, revision, schema version
    ├── metadata.json          # Custom schema fields, tags, lifecycle state
    ├── history.json           # Local revision log (lightweight)
    ├── approvals.json         # ECO / approval state snapshot
    ├── dependencies.json      # Assembly link references by Silo UUID
    ├── macros/                # Embedded macro references or inline scripts
    ├── inspection/            # GD&T annotations, tolerance data, CMM linkage
    ├── jobs/                  # Compute job YAML definitions
    │   └── default.yaml
    └── thumbnails/            # Silo-generated renderings (separate from FreeCAD's)

3. FreeCAD Standard Zone

These entries are identical to a standard .fcstd file. Kindred Create does not modify their structure or semantics.

Entry Description
Document.xml Serialized feature tree. Contains all object definitions, parametric properties, sketch geometry, constraints, and inter-object references. This is the canonical representation of the model.
GuiDocument.xml View provider state: object colors, visibility flags, camera position, display modes. Not required for geometry reconstruction.
*.brp OpenCASCADE BREP files. One per shape object. These are a derived cache — they can be regenerated from Document.xml by recomputing the feature tree.
thumbnails/Thumbnail.png FreeCAD's built-in thumbnail, generated on save. 128×128 PNG by default.

The BREP files are binary and not diffable. Document.xml is XML and structurally diffable (see Silo's Intelligent FCStd Diffing module). GuiDocument.xml is XML but rarely relevant to version control.


4. Kindred Zone (silo/)

All Kindred-specific data lives under silo/. Each entry is described below with its schema, lifecycle, and owning module.

4.1 silo/manifest.json — Required

The only mandatory silo/ entry. Identifies this file within the Silo ecosystem.

{
  "kc_version": "1.0",
  "silo_instance": "https://silo.example.com",
  "part_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "revision_hash": "a1b2c3d4e5f6",
  "created_at": "2026-02-13T19:00:00Z",
  "modified_at": "2026-02-13T20:30:00Z",
  "created_by": "joseph"
}
Field Type Description
kc_version string .kc schema version. Used for forward-compatible migrations.
silo_instance string URL of the originating Silo server. Null for offline-created files.
part_uuid UUID Globally unique identifier assigned by Silo. Survives renames and moves.
revision_hash string Hash of the last committed revision. Used for offline reconciliation.
created_at ISO 8601 Timestamp of initial .kc creation.
modified_at ISO 8601 Timestamp of last save.
created_by string Username of the creating user.

4.2 silo/metadata.json — Optional

Custom schema field values, lifecycle state, and tags. Driven by Silo's user-customizable schema engine.

{
  "schema": "mechanical-part-v2",
  "lifecycle": "released",
  "tags": ["structural", "aluminum"],
  "fields": {
    "category": "bracket",
    "material": "6061-T6",
    "finish": "anodized",
    "weight_kg": 0.34,
    "project": "PRJ-042"
  }
}

The schema field references a schema definition stored on the Silo server. Field names, types, and validation rules are defined by that schema. The client renders form fields dynamically based on the schema descriptor fetched from GET /api/schemas/{schema_name}/form.

4.3 silo/history.json — Optional

Lightweight local revision log. The full history lives server-side; this is a portable subset for offline reference.

{
  "revisions": [
    {
      "revision": 3,
      "hash": "a1b2c3d4e5f6",
      "author": "joseph",
      "timestamp": "2026-02-13T20:30:00Z",
      "comment": "Added fillet to mounting holes",
      "status": "released"
    },
    {
      "revision": 2,
      "hash": "f6e5d4c3b2a1",
      "author": "joseph",
      "timestamp": "2026-02-12T14:00:00Z",
      "comment": "Initial geometry",
      "status": "draft"
    }
  ]
}

Revisions are listed newest-first. This file is append-only during local editing and reconciled with the server on commit.

4.4 silo/approvals.json — Optional

Snapshot of engineering change order (ECO) and approval workflow state. Server-authoritative — this is a read cache for offline display.

{
  "eco": "ECO-2026-047",
  "state": "pending_review",
  "approvers": [
    {
      "user": "jane.smith",
      "role": "design_lead",
      "status": "approved",
      "timestamp": "2026-02-13T16:00:00Z"
    },
    {
      "user": "bob.jones",
      "role": "quality",
      "status": "pending",
      "timestamp": null
    }
  ]
}

4.5 silo/dependencies.json — Optional

Assembly link references stored by Silo UUID rather than filesystem path. This decouples assembly structure from local file layout.

{
  "links": [
    {
      "uuid": "660e8400-e29b-41d4-a716-446655440001",
      "label": "Base Plate",
      "part_number": "KC-BRK-0042",
      "revision": 2,
      "quantity": 1,
      "relationship": "component"
    },
    {
      "uuid": "770e8400-e29b-41d4-a716-446655440002",
      "label": "M6 Socket Head Cap Screw",
      "part_number": "KC-HDW-0108",
      "revision": 1,
      "quantity": 4,
      "relationship": "component"
    }
  ]
}

When opening an assembly .kc, the Silo workbench resolves UUIDs to local file paths. Missing dependencies trigger a download prompt if the Silo connection is active.

4.6 silo/macros/ — Optional

Embedded macro references or inline Python scripts bound to this part. Files in this directory are registered with Create's macro system on document open.

silo/macros/
├── on_save.py              # Hook: runs before save
├── generate_drawing.py     # Utility: creates a drawing from this part
└── manifest.json           # Macro metadata and execution triggers

Macro manifest:

{
  "macros": [
    {
      "file": "on_save.py",
      "trigger": "pre_save",
      "description": "Validates wall thickness before save"
    },
    {
      "file": "generate_drawing.py",
      "trigger": "manual",
      "description": "Generate 3-view drawing with BOM table"
    }
  ]
}

4.7 silo/inspection/ — Optional

GD&T annotations, tolerance data, and CMM device linkage metadata. Structure TBD pending Tier 5 Quality module specification.

Provisional layout:

silo/inspection/
├── gdt_annotations.json    # GD&T callouts linked to face/edge references
├── tolerance_stack.json    # Statistical tolerance analysis results
└── cmm_program.json        # CMM program reference and measurement linkage

4.8 silo/jobs/ — Optional

Compute job YAML definitions attached to this part. These feed into Silo's job queue infrastructure (Tier 3). A part can carry multiple job definitions for different compute workloads.

# silo/jobs/default.yaml
kind: silo/job
version: 1
metadata:
  part: bracket-assembly-v3
  trigger: on-commit
spec:
  tasks:
    - name: constraint-check
      runner:
        labels: [cpu, ondsel-solver]
      image: kindred/solver-runner:latest
      timeout: 300s
    - name: appearance-render
      runner:
        labels: [gpu, render]
      image: kindred/render-runner:latest
      depends_on: [constraint-check]
      resources:
        vram: 8Gi

Job YAMLs use the runner label system described in the Silo Job Queue specification. The trigger field determines when the job executes: on-commit (every Silo commit), on-release (lifecycle transition to released), or manual (user-initiated).

4.9 silo/thumbnails/ — Optional

Silo-generated renderings, separate from FreeCAD's built-in thumbnails/Thumbnail.png. These are produced by the Headless Create module (Tier 1) and may include multiple views or higher-resolution images.

silo/thumbnails/
├── isometric.png           # Default isometric view
├── front.png               # Front orthographic
├── top.png                 # Top orthographic
└── exploded.png            # Exploded assembly view (assemblies only)

Thumbnail generation policy (single canonical vs. multi-view) is configurable at the Silo instance level.


5. Interoperability

5.1 FCStd → .kc (Import / Promotion)

When a user opens an .fcstd file in Kindred Create, it loads normally through FreeCAD's standard document loader. The file can be "promoted" to .kc through either of two paths:

Manual promotion: User selects File → Save As → .kc. Create generates silo/manifest.json with a new UUID and prompts for schema field selection if connected to Silo.

Silo-triggered promotion: User commits an .fcstd to Silo via the Silo workbench. Silo assigns a UUID, generates the silo/ directory with defaults, and returns a .kc to the client. Subsequent saves default to .kc.

In both cases, no data in the FreeCAD standard zone is modified. The promotion is purely additive.

5.2 .kc → FCStd (Export / Demotion)

File → Export As → .fcstd strips the entire silo/ directory. The resulting file is a valid .fcstd with no Kindred-specific content. This is the recommended path for sharing files with vanilla FreeCAD users.

5.3 Vanilla FreeCAD Behavior

If a .kc file is renamed to .fcstd and opened in vanilla FreeCAD:

  • The document loads normally. Document.xml, GuiDocument.xml, and BREP files are read as expected.
  • The silo/ directory is ignored (unknown ZIP entries are silently skipped).
  • On save, FreeCAD writes its standard entries. The silo/ directory survives the save because FreeCAD does not delete unknown ZIP entries.
  • Caveat: If FreeCAD rewrites the ZIP from scratch (rather than updating in-place), the silo/ directory may be lost. Testing confirms that FreeCAD 1.0+ preserves unknown entries, but this behavior should be monitored across upstream releases.

6. Client Implementation Layers

Implementation in the Create client is organized into four layers, each independently deliverable.

Layer 1: Format Registration (C++)

Register .kc as a recognized file type in FreeCAD's application framework.

Scope:

  • src/App/Application.cpp — register .kc extension alongside .fcstd in the file type map. Both extensions route to the same openDocument() path since the ZIP internals are structurally identical.
  • src/Gui/FileDialog.cpp — add .kc to open/save/export dialogs. New documents default to .kc. "Save As" offers both .kc and .fcstd.
  • src/App/Document.cpp — on save-as-.fcstd, strip the silo/ directory from the ZIP. On save-as-.kc, ensure the silo/ directory exists (create manifest.json with defaults if missing).
  • Platform integration — .kc MIME type registration, file association on Linux (.desktop file / XDG), macOS (Info.plist), and Windows (registry / NSIS installer).

Risk: Low. FreeCAD already ignores unknown ZIP entries. This layer is purely file dialog and post-save ZIP manipulation.

Acceptance criteria:

  • .kc files open in Create without errors.
  • "Save As .fcstd" produces a valid .fcstd with no silo/ directory.
  • "Save As .kc" produces a ZIP with at minimum silo/manifest.json.
  • Double-clicking a .kc file on all platforms opens Create.

Layer 2: Silo Metadata Layer (Python)

A KindredDocument class in src/Mod/Create/ that wraps the loaded App::Document and manages the silo/ directory contents.

Scope:

  • src/Mod/Create/KindredDocument.py (new) — load/save logic for all silo/ entries.
  • src/Mod/Create/InitGui.py — connect to App::Document signals (signalSaveDocument, signalRestoreDocument) to trigger metadata load/save.

Behavior by operation:

Operation Action
Open .kc Parse all silo/ entries. Expose metadata as properties on the document.
Open .fcstd No-op — no silo/ directory present. KindredDocument is inactive.
Save .kc Serialize current metadata into silo/ before FreeCAD writes the ZIP.
Save .fcstd Skip metadata serialization. Strip silo/ if present.
Promote .fcstd.kc Generate silo/manifest.json with new UUID. Prompt for schema fields.

Behavior by silo/ entry:

Entry On open On save On promote
manifest.json Read instance origin, UUID, revision, schema version Update modified_at and revision_hash Generate with new UUID
metadata.json Load schema fields, tags, lifecycle Serialize current state Generate with defaults from selected schema
history.json Load local revision log Append entry if dirty Initialize empty
approvals.json Load ECO/approval snapshot Pass-through (server authoritative) Initialize empty
dependencies.json Resolve assembly links by UUID Update from current assembly link objects Generate from assembly link scan
macros/ Register embedded macros Serialize bound macros Empty directory
inspection/ Load GD&T / tolerance data Serialize annotations Empty directory
jobs/ Load job definitions for display Serialize job YAML edits Empty directory
thumbnails/ Load Silo-rendered previews No-op (server generates these) Empty directory

Risk: Medium. Signal timing relative to FreeCAD's ZIP write must be tested carefully to ensure silo/ entries are written before the archive is finalized.

Acceptance criteria:

  • Opening a .kc with populated silo/metadata.json surfaces schema fields in the Create UI.
  • Saving a .kc persists metadata changes across close/reopen cycles.
  • Promoting an .fcstd to .kc assigns a UUID and creates silo/manifest.json.

Layer 3: Silo Workbench Integration (Python)

The Silo workbench (mods/silo/) connects .kc files to the live Silo server.

Scope:

  • Commit to Silo — reads silo/manifest.json for the part UUID, uploads the .kc via REST. Silo extracts and indexes the silo/ metadata server-side.
  • Checkout from Silo — downloads a .kc with fully populated silo/ directory. KindredDocument hydrates metadata on open.
  • Dependency resolutionsilo/dependencies.json stores assembly references by UUID. On opening an assembly, the workbench resolves UUIDs to local paths or triggers downloads for missing components.
  • Offline reconciliation — on reconnect, compare manifest.json revision hashes. Server wins on conflict unless the user explicitly forces a local override. Display a diff summary before reconciliation.

Risk: Medium. Depends on Silo server API endpoints existing for each metadata type. Can be built incrementally — start with commit/checkout of the full .kc blob, then add granular metadata sync per module.

Acceptance criteria:

  • Commit/checkout round-trips a .kc without metadata loss.
  • Assembly checkout resolves all dependencies.json UUIDs to local files.
  • Offline edits reconcile cleanly when connection is restored.

Layer 4: Compute Job Attachment (Python)

UI for managing silo/jobs/ YAML definitions. Ties into Silo's Tier 3 compute modules.

Scope:

  • Task panel in the Silo workbench for viewing, editing, and attaching job YAMLs.
  • Job trigger configuration (on-commit, on-release, manual).
  • Status display for running/completed jobs (fetched from Silo server).

Risk: Low (UI-only on the client side). Depends on Silo job queue infrastructure being operational.

Acceptance criteria:

  • Users can attach a job YAML to a .kc file via the UI.
  • Job status is visible in the Silo workbench panel.

7. Implementation Sequence

Layers are ordered by dependency and risk:

  1. Layer 1 (Format Registration) — Small C++ diff. Low risk. Immediately lets users open/save .kc files even without Silo running. No functional behavior beyond file association.

  2. Layer 2 (Metadata Layer) — Bulk of the work. Develop incrementally: start with manifest.json only, add other silo/ entries as their respective Silo modules come online.

  3. Layer 3 (Silo Integration) — Requires Silo server API endpoints. Build commit/checkout first, add granular metadata sync as modules mature.

  4. Layer 4 (Job Attachment) — Deferred until Silo Tier 3 (Job Queue + Compute modules) is operational. The silo/jobs/ directory sits empty until then.

This sequence ensures Create is backwards-compatible with .fcstd at every step. The .kc format grows incrementally as Silo modules ship, matching the tiered dependency structure in the platform roadmap.


8. Version Migration

The kc_version field in silo/manifest.json tracks the schema version. When the .kc spec evolves:

  • Additive changes (new optional silo/ entries): No migration needed. Older files simply lack the new entries.
  • Breaking changes (renamed fields, restructured entries): A migration function in KindredDocument upgrades silo/ contents on open. The original file is preserved until the user explicitly saves.
  • Version floor: Create refuses to open .kc files with a kc_version newer than it supports, displaying an "update Create" message.

9. Security Considerations

Macro execution: silo/macros/ scripts execute with full FreeCAD Python API access. Files from untrusted sources should prompt the user before macro registration. A configurable trust policy (always trust from this Silo instance / never auto-execute / prompt each time) is exposed in Create preferences.

Job YAML injection: silo/jobs/ YAMLs specify container images and resource requests. The Silo server validates job definitions against an allowlist of approved images and resource limits before dispatching. The client does not execute jobs directly.

Metadata tampering: silo/manifest.json contains the revision hash. On commit, Silo validates the hash against its own records. Tampered manifests are rejected with a conflict error requiring re-checkout.


10. Open Questions

  1. FreeCAD ZIP rewrite behavior — Confirm that FreeCAD 1.0+ preserves unknown ZIP entries on save across all platforms. If not, the silo/ directory must be re-injected post-save via a signal hook.

  2. Thumbnail policy — Single canonical isometric thumbnail vs. configurable multi-view renders. Impacts silo/thumbnails/ size and Headless Create compute cost.

  3. Offline metadata authority — How much of silo/metadata.json (particularly lifecycle state) can be modified offline? Current proposal: lifecycle transitions require server confirmation; field edits are permitted offline and reconciled on commit.

  4. Assembly dependency depth — Should silo/dependencies.json be recursive (full assembly tree) or single-level (direct children only)? Single-level is simpler; recursive enables full offline assembly loading.

  5. Macro sandboxing — Is a restricted execution environment for silo/macros/ feasible within FreeCAD's Python runtime, or is trust-based policy the only practical option?


Appendix A: MIME Type and File Association

Property Value
Extension .kc
MIME type application/x-kindred-create
UTI (macOS) com.kindred-systems.create.document
Magic bytes PK (ZIP header, offset 0) + silo/manifest.json entry present
Icon Kindred Create document icon (from icons/kindred/ asset set)

Appendix B: Glossary

Term Definition
.fcstd FreeCAD Standard file format. ZIP containing Document.xml, GuiDocument.xml, BREP cache, and thumbnails.
.kc Kindred Create file format. Superset of .fcstd with a silo/ directory.
BREP Boundary Representation. OpenCASCADE geometry format stored as .brp files. Derived cache, regenerable from Document.xml.
Promotion Converting an .fcstd to .kc by adding a silo/ directory with at minimum manifest.json.
Demotion Converting a .kc to .fcstd by stripping the silo/ directory.
Reconciliation Process of merging offline .kc edits with server-side state on reconnect.
Schema A Silo-defined template specifying which metadata fields exist for a given part category.

Appendix C: References